//----------------------------------------------------------------------- void PagingLandScapeOctree::_unref(const bool removeChildren) { --mNumNodes; if (removeChildren) { //remove null children PagingLandScapeOctree *child; for (unsigned int i = 0; i < 2; i++) { for (unsigned int j = 0; j < 2; j++) { for (unsigned int k = 0; k < 2; k++) { child = mChildren[ i ][ j ][ k ]; if (child && !child->hasChildren()) { mSceneMgr->deleteOctree(child); mChildren[ i ][ j ][ k ] = 0; } } } } } if (mParent != 0) { mParent->_unref(mNumNodes == 0); } };
//----------------------------------------------------------------------- void SWTraversal::onTree(PagingLandScapeOctree & n, VisibleObjectsBoundsInfo * const visibleBounds) { if(occlusion.mCurrentCam->isVisible(n.getCullBoundingBox ())) { #ifdef _VISIBILITYDEBUG occlusion.traversed_nodes_cnt++; n.getNodeData (occlusion.mCurrentCam)->viewFrustumVisible = true; #endif //_VISIBILITYDEBUG const bool isitVisible = isVisible(n); if (isitVisible) { traverseChildren (n, visibleBounds); } #ifdef _VISIBILITYDEBUG n.getNodeData (occlusion.mCurrentCam)->queryVisible = isitVisible; #endif //_VISIBILITYDEBUG } #ifdef _VISIBILITYDEBUG else { occlusion.traversed_nodes_cnt++; n.getNodeData (occlusion.mCurrentCam)->viewFrustumVisible = false; occlusion.frustum_culled_nodes_cnt++; } #endif //_VISIBILITYDEBUG }
//----------------------------------------------------------------------- void SWTraversal::traverseChildren(PagingLandScapeOctree & node, VisibleObjectsBoundsInfo * const visibleBounds) { FrontToBackNodeSorterPriorityQueue myStack = FrontToBackNodeSorterPriorityQueue(FrontToBackNodeSorterOperator (camPos)); //assert (node.getNodeData (occlusion.mCurrentCam)->viewFrustumVisible); if (!node.mNodes.empty()) { PagingLandScapeOctreeNodeList::const_iterator it = node.mNodes.begin(); while (it != node.mNodes.end()) { myStack.push(*it); ++it; } } PagingLandScapeOctree *n = node.mChildren[ 0 ][ 0 ][ 0 ]; if (n && n->hasChildren()) myStack.push (n); n = node.mChildren[ 1 ][ 0 ][ 0 ]; if (n && n->hasChildren()) myStack.push (n); n = node.mChildren[ 0 ][ 1 ][ 0 ]; if (n && n->hasChildren()) myStack.push (n); n = node.mChildren[ 1 ][ 1 ][ 0 ]; if (n && n->hasChildren()) myStack.push (n); n = node.mChildren[ 0 ][ 0 ][ 1 ]; if (n && n->hasChildren()) myStack.push (n); n = node.mChildren[ 1 ][ 0 ][ 1 ]; if (n && n->hasChildren()) myStack.push (n); n = node.mChildren[ 0 ][ 1 ][ 1 ]; if (n && n->hasChildren()) myStack.push (n); n = node.mChildren[ 1 ][ 1 ][ 1 ]; if (n && n->hasChildren()) myStack.push (n); //traverse nearer child first while (!myStack.empty ()) { OcclusionElement& nstacked = *myStack.top (); myStack.pop (); nstacked.traversal(*this, visibleBounds); } }
//----------------------------------------------------------------------- void CHCTraversal::onTree(PagingLandScapeOctree& node, VisibleObjectsBoundsInfo * const visibleBounds) const { #ifdef _VISIBILITYDEBUG assert (node.getNodeData (occlusion.mCurrentCam)->viewFrustumVisible); occlusion.traversed_nodes_cnt++; #endif //_VISIBILITYDEBUG if (!node.mNodes.empty()) { PagingLandScapeOctreeNodeList::iterator it = node.mNodes.begin(); while (it != node.mNodes.end()) { stack.push (*it); ++it; } } PagingLandScapeOctree *n = node.mChildren[ 0 ][ 0 ][ 0 ]; if (n && n->hasChildren()) stack.push(n); n = node.mChildren[ 1 ][ 0 ][ 0 ]; if (n && n->hasChildren()) stack.push(n); n = node.mChildren[ 0 ][ 1 ][ 0 ]; if (n && n->hasChildren()) stack.push(n); n = node.mChildren[ 1 ][ 1 ][ 0 ]; if (n && n->hasChildren()) stack.push(n); n = node.mChildren[ 0 ][ 0 ][ 1 ]; if (n && n->hasChildren()) stack.push(n); n = node.mChildren[ 1 ][ 0 ][ 1 ]; if (n && n->hasChildren()) stack.push(n); n = node.mChildren[ 0 ][ 1 ][ 1 ]; if (n && n->hasChildren()) stack.push(n); n = node.mChildren[ 1 ][ 1 ][ 1 ]; if (n && n->hasChildren()) stack.push(n); }
//----------------------------------------------------------------------- void TreeOverlayDebug::onTree(PagingLandScapeOctree& n, VisibleObjectsBoundsInfo * const visibleBounds) const { SimpleRenderable * const s = n.getRectangle2d(mScnMrg); if (n.getNodeData (occlusion.mCurrentCam)->viewFrustumVisible) { if (n.getNodeData (occlusion.mCurrentCam)->queryVisible) { s->setMaterial ("BaseWhiteNoLightNoDepthCheck"); occlusion.mCurrentRenderQueue->addRenderable (s, s->getRenderQueueGroup ()); traverseChildren (n, visibleBounds); } else { s->setMaterial ("BaseRedNoLightNoDepthCheck"); occlusion.mCurrentRenderQueue->addRenderable (s, s->getRenderQueueGroup ()); } } else { s->setMaterial ("BaseGreenNoLightNoDepthCheck"); occlusion.mCurrentRenderQueue->addRenderable (s, s->getRenderQueueGroup ()); } }
//----------------------------------------------------------------------- void Traversal::traverseChildren(PagingLandScapeOctree& node, VisibleObjectsBoundsInfo * const visibleBounds) { // hasLocalChildren if (!node.mNodes.empty()) { //Add stuff to be rendered; PagingLandScapeOctreeNodeList::iterator it = node.mNodes.begin(); PagingLandScapeOctreeNodeList::iterator itEnd = node.mNodes.end(); while (it != itEnd) { (*it)->traversal (*this, visibleBounds); ++it; } } PagingLandScapeOctree *n = node.mChildren[ 0 ][ 0 ][ 0 ]; if (n && n->hasChildren()) n->traversal (*this, visibleBounds); n = node.mChildren[ 1 ][ 0 ][ 0 ]; if (n && n->hasChildren()) n->traversal (*this, visibleBounds); n = node.mChildren[ 0 ][ 1 ][ 0 ]; if (n && n->hasChildren()) n->traversal (*this, visibleBounds); n = node.mChildren[ 1 ][ 1 ][ 0 ]; if (n && n->hasChildren()) n->traversal (*this, visibleBounds); n = node.mChildren[ 0 ][ 0 ][ 1 ]; if (n && n->hasChildren()) n->traversal (*this, visibleBounds); n = node.mChildren[ 1 ][ 0 ][ 1 ]; if (n && n->hasChildren()) n->traversal (*this, visibleBounds); n = node.mChildren[ 0 ][ 1 ][ 1 ]; if (n && n->hasChildren()) n->traversal (*this, visibleBounds); n = node.mChildren[ 1 ][ 1 ][ 1 ]; if (n && n->hasChildren()) n->traversal (*this, visibleBounds); }
//----------------------------------------------------------------------- PagingLandScapeOctree *PagingLandScapeOctree::_getChildWhereBoxFits(const AxisAlignedBox &box, PagingLandScapeOctreeSceneManager *scn) { /** It's assumed the the given box has already been proven to fit into * a child. Since it's a loose PagingLandScapeOctree, only the centers need to be * compared to find the appropriate node. */ const Vector3 &octantMax = mBox.getMaximum(); const Vector3 &octantMin = mBox.getMinimum(); const Vector3 octCenter = octantMin + mHalfSize; const Vector3 ncenter = box.getMaximum().midPoint(box.getMinimum()); //ember change: We'll remove this assertion since it seems to trigger sometimes when stuff are placed really close to the boundaries, probably caused be precision issues // assert (octantMax.x >= ncenter.x && octantMax.y >= ncenter.y && octantMax.z >= ncenter.z && // octantMin.x <= ncenter.x && octantMin.y <= ncenter.y && octantMin.z <= ncenter.z); unsigned int x; if (ncenter.x > octCenter.x) x = 1; else x = 0; unsigned int y; if (ncenter.y > octCenter.y) y = 1; else y = 0; unsigned int z; if (ncenter.z > octCenter.z) z = 1; else z = 0; if (mChildren[ x ][ y ][ z ] == 0) { Vector3 min, max; if (x == 0) { min.x = octantMin.x; max.x = octCenter.x; } else { min.x = octCenter.x; max.x = octantMax.x; } if (y == 0) { min.y = octantMin.y; max.y = octCenter.y; } else { min.y = octCenter.y; max.y = octantMax.y; } if (z == 0) { min.z = octantMin.z; max.z = octCenter.z; } else { min.z = octCenter.z; max.z = octantMax.z; } #ifdef _DEBUG std::cout << "new Child\n"; #endif PagingLandScapeOctree *newChild = scn->getNewOctree(); newChild->setParent (this); newChild->setSceneManager(scn); newChild->setBoundingBox(min, max); assert (max.x >= ncenter.x && max.y >= ncenter.y && max.z >= ncenter.z && min.x <= ncenter.x && min.y <= ncenter.y && min.z <= ncenter.z); scn->registeredNodeInCamera (newChild); #ifdef _VISIBILITYDEBUG newChild ->setDebugCorners(scn); #endif //_VISIBILITYDEBUG mChildren[x][y][z] = newChild; } return mChildren[x][y][z]; }
//----------------------------------------------------------------------- PagingLandScapeOctree *PagingLandScapeOctree::_getCullChildWhereBoxFits(const AxisAlignedBox &box, PagingLandScapeOctreeSceneManager *scn) { /** It's assumed the the given box has already been proven to fit into * a child. Since it's a loose PagingLandScapeOctree, only the centers need to be * compared to find the appropriate node. */ const Vector3 octCenter = mCullBox.getMinimum() + mCullHalfSize; const Vector3 ncenter = box.getMaximum().midPoint(box.getMinimum()); unsigned int x; if (ncenter.x > octCenter.x) x = 1; else x = 0; unsigned int y; if (ncenter.y > octCenter.y) y = 1; else y = 0; unsigned int z; if (ncenter.z > octCenter.z) z = 1; else z = 0; if (mChildren[ x ][ y ][ z ] == 0) { const Vector3 &octantMax = mBox.getMaximum(); const Vector3 &octantMin = mBox.getMinimum(); Vector3 min, max; if (x == 0) { min.x = octantMin.x; max.x = octCenter.x; } else { min.x = octCenter.x; max.x = octantMax.x; } if (y == 0) { min.y = octantMin.y; max.y = octCenter.y; } else { min.y = octCenter.y; max.y = octantMax.y; } if (z == 0) { min.z = octantMin.z; max.z = octCenter.z; } else { min.z = octCenter.z; max.z = octantMax.z; } PagingLandScapeOctree *newChild = scn->getNewOctree(); newChild->setParent (this); newChild->setSceneManager(scn); newChild ->setBoundingBox(min, max); scn->registeredNodeInCamera (newChild); #ifdef _VISIBILITYDEBUG newChild ->setDebugCorners(scn); #endif //_VISIBILITYDEBUG mChildren[x][y][z] = newChild; } return mChildren[x][y][z]; }