00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00025
00026 #include "glc_octreenode.h"
00027
00028 bool GLC_OctreeNode::m_useBoundingSphere= true;
00029
00030 GLC_OctreeNode::GLC_OctreeNode(const GLC_BoundingBox& boundingBox, GLC_OctreeNode* pParent)
00031 : m_BoundingBox(boundingBox)
00032 , m_pParent(pParent)
00033 , m_Children()
00034 , m_3DViewInstanceSet()
00035 , m_Empty(true)
00036 {
00037
00038
00039 }
00040
00041 GLC_OctreeNode::GLC_OctreeNode(const GLC_OctreeNode& octreeNode, GLC_OctreeNode* pParent)
00042 : m_BoundingBox(octreeNode.m_BoundingBox)
00043 , m_pParent(pParent)
00044 , m_Children()
00045 , m_3DViewInstanceSet(octreeNode.m_3DViewInstanceSet)
00046 , m_Empty(octreeNode.m_Empty)
00047 {
00048 if (!octreeNode.m_Children.isEmpty())
00049 {
00050 const int size= octreeNode.m_Children.size();
00051 for (int i= 0; i < size; ++i)
00052 {
00053 m_Children.append(new GLC_OctreeNode(*(octreeNode.m_Children.at(i)), this));
00054 }
00055 }
00056 }
00057
00058 GLC_OctreeNode::~GLC_OctreeNode()
00059 {
00060 const int size= m_Children.size();
00061 for (int i= 0; i < size; ++i)
00062 {
00063 delete m_Children.at(i);
00064 }
00065 }
00066
00067 bool GLC_OctreeNode::intersectionWithBoundingSphereUsed()
00068 {
00069 return m_useBoundingSphere;
00070 }
00071
00072 QSet<GLC_3DViewInstance*> GLC_OctreeNode::setOfIntersectedInstances(const GLC_BoundingBox& bBox)
00073 {
00074 QSet<GLC_3DViewInstance*> instanceSet;
00075 if (intersect(bBox))
00076 {
00077 QSet<GLC_3DViewInstance*>::iterator iInstance= m_3DViewInstanceSet.begin();
00078 while (m_3DViewInstanceSet.constEnd() != iInstance)
00079 {
00080 if ((*iInstance)->boundingBox().intersect(bBox))
00081 {
00082 instanceSet << *(iInstance);
00083 }
00084 ++iInstance;
00085 }
00086 const int childCount= m_Children.size();
00087 for (int i= 0; i < childCount; ++i)
00088 {
00089 instanceSet.unite(m_Children[i]->setOfIntersectedInstances(bBox));
00090 }
00091 }
00092
00093 return instanceSet;
00094 }
00096
00098
00099 void GLC_OctreeNode::addChildren()
00100 {
00101 Q_ASSERT(m_Children.isEmpty());
00102 Q_ASSERT(!m_BoundingBox.isEmpty());
00103
00104 const double xLower= m_BoundingBox.lowerCorner().x();
00105 const double yLower= m_BoundingBox.lowerCorner().y();
00106 const double zLower= m_BoundingBox.lowerCorner().z();
00107
00108 const double xUpper= m_BoundingBox.upperCorner().x();
00109 const double dX= (xUpper - xLower) / 2.0;
00110 const double yUpper= m_BoundingBox.upperCorner().y();
00111 const double dY= (yUpper - yLower) / 2.0;
00112 const double zUpper= m_BoundingBox.upperCorner().z();
00113 const double dZ= (zUpper - zLower) / 2.0;
00114
00115
00116
00117 GLC_Point3d lower;
00118 GLC_Point3d upper;
00119 GLC_OctreeNode* pOctreeNode= NULL;
00120
00121 {
00122 lower.setVect(xLower, yLower, zLower);
00123 upper.setVect(xLower + dX, yLower + dY, zLower + dZ);
00124 GLC_BoundingBox box(lower, upper);
00125 pOctreeNode= new GLC_OctreeNode(box, this);
00126 m_Children.append(pOctreeNode);
00127 }
00128 {
00129 lower.setVect(xLower + dX, yLower, zLower);
00130 upper.setVect(xUpper, yLower + dY, zLower + dZ);
00131 GLC_BoundingBox box(lower, upper);
00132 pOctreeNode= new GLC_OctreeNode(box, this);
00133 m_Children.append(pOctreeNode);
00134 }
00135 {
00136 lower.setVect(xLower + dX, yLower + dY, zLower);
00137 upper.setVect(xUpper, yUpper, zLower + dZ);
00138 GLC_BoundingBox box(lower, upper);
00139 pOctreeNode= new GLC_OctreeNode(box, this);
00140 m_Children.append(pOctreeNode);
00141 }
00142 {
00143 lower.setVect(xLower, yLower + dY, zLower);
00144 upper.setVect(xLower + dX, yUpper, zLower + dZ);
00145 GLC_BoundingBox box(lower, upper);
00146 pOctreeNode= new GLC_OctreeNode(box, this);
00147 m_Children.append(pOctreeNode);
00148 }
00149 {
00150 lower.setVect(xLower, yLower, zLower + dZ);
00151 upper.setVect(xLower + dX, yLower + dY, zUpper);
00152 GLC_BoundingBox box(lower, upper);
00153 pOctreeNode= new GLC_OctreeNode(box, this);
00154 m_Children.append(pOctreeNode);
00155 }
00156 {
00157 lower.setVect(xLower + dX, yLower, zLower + dZ);
00158 upper.setVect(xUpper, yLower + dY, zUpper);
00159 GLC_BoundingBox box(lower, upper);
00160 pOctreeNode= new GLC_OctreeNode(box, this);
00161 m_Children.append(pOctreeNode);
00162 }
00163 {
00164 lower.setVect(xLower + dX, yLower + dY, zLower + dZ);
00165 upper.setVect(xUpper, yUpper, zUpper);
00166 GLC_BoundingBox box(lower, upper);
00167 pOctreeNode= new GLC_OctreeNode(box, this);
00168 m_Children.append(pOctreeNode);
00169 }
00170 {
00171 lower.setVect(xLower, yLower + dY, zLower + dZ);
00172 upper.setVect(xLower + dX, yUpper, zUpper);
00173 GLC_BoundingBox box(lower, upper);
00174 pOctreeNode= new GLC_OctreeNode(box, this);
00175 m_Children.append(pOctreeNode);
00176 }
00177 }
00178
00179
00180 void GLC_OctreeNode::addInstance(GLC_3DViewInstance* pInstance, int depth)
00181 {
00182 m_Empty= false;
00183 const GLC_BoundingBox instanceBox= pInstance->boundingBox();
00184
00185 if (intersect(instanceBox))
00186 {
00187 if (0 == depth)
00188 {
00189 m_3DViewInstanceSet.insert(pInstance);
00190 }
00191 else
00192 {
00193 if (m_Children.isEmpty())
00194 {
00195
00196 addChildren();
00197 }
00198 QVector<bool> childIntersect(8);
00199 bool allIntersect= true;
00200 bool currentIntersect= false;
00201 for (int i= 0; i < 8; ++i)
00202 {
00203 currentIntersect= m_Children.at(i)->intersect(instanceBox);
00204 allIntersect= allIntersect && currentIntersect;
00205 childIntersect[i]= currentIntersect;
00206 }
00207 if (allIntersect)
00208 {
00209 m_3DViewInstanceSet.insert(pInstance);
00210 }
00211 else
00212 {
00213 for (int i= 0; i < 8; ++i)
00214 {
00215 if (childIntersect[i])
00216 {
00217 m_Children[i]->addInstance(pInstance, depth - 1);
00218 }
00219 }
00220 }
00221 }
00222
00223 }
00224 }
00225
00226
00227 void GLC_OctreeNode::updateViewableInstances(const GLC_Frustum& frustum, QSet<GLC_3DViewInstance*>* pInstanceSet)
00228 {
00229
00230 bool firstCall= false;
00231
00232 if (NULL == pInstanceSet)
00233 {
00234 pInstanceSet= new QSet<GLC_3DViewInstance*>();
00235 firstCall= true;
00236 }
00237
00238
00239 GLC_Frustum::Localisation nodeLocalisation= frustum.localizeBoundingBox(m_BoundingBox);
00240 if (nodeLocalisation == GLC_Frustum::OutFrustum)
00241 {
00242 disableViewFlag(pInstanceSet);
00243 }
00244 else if (nodeLocalisation == GLC_Frustum::InFrustum)
00245 {
00246 unableViewFlag(pInstanceSet);
00247 }
00248 else
00249 {
00250 QSet<GLC_3DViewInstance*>::iterator iInstance= m_3DViewInstanceSet.begin();
00251 while (m_3DViewInstanceSet.constEnd() != iInstance)
00252 {
00253
00254 if (!pInstanceSet->contains(*iInstance))
00255 {
00256 GLC_3DViewInstance* pCurrentInstance= (*iInstance);
00257
00258 GLC_Frustum::Localisation instanceLocalisation= frustum.localizeBoundingBox(pCurrentInstance->boundingBox());
00259
00260 if (instanceLocalisation == GLC_Frustum::OutFrustum)
00261 {
00262 pCurrentInstance->setViewable(GLC_3DViewInstance::NoViewable);
00263 }
00264 else if (instanceLocalisation == GLC_Frustum::InFrustum)
00265 {
00266 pInstanceSet->insert(pCurrentInstance);
00267 pCurrentInstance->setViewable(GLC_3DViewInstance::FullViewable);
00268 }
00269 else
00270 {
00271 pInstanceSet->insert(pCurrentInstance);
00272 pCurrentInstance->setViewable(GLC_3DViewInstance::PartialViewable);
00273
00274 GLC_Matrix4x4 instanceMat= pCurrentInstance->matrix();
00275 const int size= pCurrentInstance->numberOfBody();
00276 for (int i= 0; i < size; ++i)
00277 {
00278
00279 GLC_BoundingBox geomBox= pCurrentInstance->geomAt(i)->boundingBox();
00280 GLC_Point3d center(instanceMat * geomBox.center());
00281 double radius= geomBox.boundingSphereRadius() * instanceMat.scalingX();
00282 GLC_Frustum::Localisation geomLocalisation= frustum.localizeSphere(center, radius);
00283
00284 pCurrentInstance->setGeomViewable(i, geomLocalisation != GLC_Frustum::OutFrustum);
00285 }
00286 }
00287 }
00288
00289 ++iInstance;
00290 }
00291 const int size= m_Children.size();
00292 for (int i= 0; i < size; ++i)
00293 {
00294 m_Children.at(i)->updateViewableInstances(frustum, pInstanceSet);
00295 }
00296 }
00297 if (firstCall) delete pInstanceSet;
00298 }
00299
00300
00301 void GLC_OctreeNode::removeEmptyChildren()
00302 {
00303 NodeList::iterator iList= m_Children.begin();
00304 while(m_Children.constEnd() != iList)
00305 {
00306 GLC_OctreeNode* pCurrentChild= *iList;
00307 if (pCurrentChild->isEmpty())
00308 {
00309 delete pCurrentChild;
00310 iList= m_Children.erase(iList);
00311 }
00312 else
00313 {
00314 pCurrentChild->removeEmptyChildren();
00315 if (pCurrentChild->isEmpty())
00316 {
00317 delete pCurrentChild;
00318 iList= m_Children.erase(iList);
00319 }
00320 else ++iList;
00321 }
00322 }
00323
00324 if (m_Children.isEmpty() && (NULL != m_pParent))
00325 {
00326 if (1 == m_3DViewInstanceSet.size())
00327 {
00328 m_pParent->m_3DViewInstanceSet.insert(*(m_3DViewInstanceSet.begin()));
00329 m_3DViewInstanceSet.clear();
00330 }
00331 m_Empty= m_3DViewInstanceSet.isEmpty();
00332 }
00333 }
00334
00335 void GLC_OctreeNode::useBoundingSphereIntersection(bool use)
00336 {
00337 m_useBoundingSphere= use;
00338 }
00339
00340 void GLC_OctreeNode::unableViewFlag(QSet<GLC_3DViewInstance*>* pInstanceSet)
00341 {
00342 QSet<GLC_3DViewInstance*>::iterator iInstance= m_3DViewInstanceSet.begin();
00343 while (m_3DViewInstanceSet.constEnd() != iInstance)
00344 {
00345 if (!pInstanceSet->contains(*iInstance))
00346 {
00347 (*iInstance)->setViewable(GLC_3DViewInstance::FullViewable);
00348 pInstanceSet->insert(*iInstance);
00349 }
00350
00351 ++iInstance;
00352 }
00353 const int size= m_Children.size();
00354 for (int i= 0; i < size; ++i)
00355 {
00356 m_Children.at(i)->unableViewFlag(pInstanceSet);
00357 }
00358 }
00359
00360
00361 void GLC_OctreeNode::disableViewFlag(QSet<GLC_3DViewInstance*>* pInstanceSet)
00362 {
00363 QSet<GLC_3DViewInstance*>::iterator iInstance= m_3DViewInstanceSet.begin();
00364 while (m_3DViewInstanceSet.constEnd() != iInstance)
00365 {
00366 if (!pInstanceSet->contains(*iInstance))
00367 (*iInstance)->setViewable(GLC_3DViewInstance::NoViewable);
00368
00369 ++iInstance;
00370 }
00371 const int size= m_Children.size();
00372 for (int i= 0; i < size; ++i)
00373 {
00374 m_Children.at(i)->disableViewFlag(pInstanceSet);
00375 }
00376 }
00377