#include "OgreOcclusionCullingSceneTraverser.h" #include "OgreMath.h" #include "OgreIteratorWrappers.h" #include "OgreCamera.h" #include "OgreHardwareOcclusionQuery.h" #include "OgreSolidHalfBoundingBox.h" #include namespace Ogre { //----------------------------------------------------------------------- SceneTraverser::OcclusionCullingSceneTraverser(SceneManager *sm, RenderSystem *rsys): mFrameId(1), mDistanceQueue(NULL), mVisibilityThreshold(0), mCurrentTestIdx(0), mNumSceneNodes(0), mNumTraversedNodes(0), mNumQueryCulledNodes(0), mNumFrustumCulledNodes(0), mNumRenderedNodes(0),mNumRenderedGeometry(0), mSceneManager(sm), mRenderSystem(rsys), mSceneRoot(NULL) { mHalfBoundingBox[0] = mHalfBoundingBox[1] = 0; } //----------------------------------------------------------------------- SceneTraverser::~OcclusionCullingSceneTraverser() { if(mHalfBoundingBox[0]) delete mHalfBoundingBox[0]; if(mHalfBoundingBox[1]) delete mHalfBoundingBox[1]; deleteQueries(); if(mDistanceQueue) delete mDistanceQueue; //SceneManager::~SceneManager(); } //----------------------------------------------------------------------- void SceneTraverser::traverseNode( Camera *cam, HierarchyNode *node ) { mNumTraversedNodes ++; if(node->numAttachedObjects() > 0) { renderSceneNode(cam, node); } // internal node: add children to priority queue for further processing Node::ChildNodeIterator it = node->getChildIterator(); while (it.hasMoreElements()) { SceneNode* sceneChild = static_cast(it.getNext()); mDistanceQueue->push(sceneChild); } } //----------------------------------------------------------------------- void SceneTraverser::renderSceneNode( Camera *cam, HierarchyNode *node ) { if(node->lastRendered() != node->lastVisited()) { node->setLastRendered(node->lastVisited()); mNumRenderedNodes ++; mSceneManager->_renderSceneNode(cam, node); } } //----------------------------------------------------------------------- void SceneTraverser::setSceneManager( SceneManager *sm ) { mSceneManager = sm; } //----------------------------------------------------------------------- void SceneTraverser::setRenderSystem( RenderSystem *rsys ) { mRenderSystem = rsys; } //----------------------------------------------------------------------- bool SceneTraverser::isLeaf( SceneNode *node ) { return (node->numChildren() == 0); } //----------------------------------------------------------------------- void SceneTraverser::pullUpVisibility(SceneNode *node ) { while(node && !node->isNodeVisible()) { node->setNodeVisible(true); node = node->getParentSceneNode(); } } //----------------------------------------------------------------------- void SceneTraverser::deleteQueries( void ) { for(unsigned int i=0; i < (unsigned int)mOcclusionQueries.size(); ++i) delete mOcclusionQueries[i]; mOcclusionQueries.clear(); } //----------------------------------------------------------------------- void SceneTraverser::renderBoundingBox( AxisAlignedBox *box ) { // Render two halfes of the bounding box (using triangle fans) for(int half = 0; half < 2; half ++) { static Matrix4 xform[256]; //TODO: this should be full bounding box SolidHalfBoundingBox *halfbox = getSolidHalfBoundingBox(half); halfbox->setupBoundingBox(*box); /*mRenderSystem->_setWorldMatrix(Matrix4::IDENTITY); halfbox->getWorldTransforms(xform); int numMatrices = halfbox->getNumWorldTransforms(); if (numMatrices > 1) { mRenderSystem->_setWorldMatrices(xform, numMatrices); } else { mRenderSystem->_setWorldMatrix(*xform); } mRenderSystem->setClipPlanes(halfbox->getClipPlanes()); static RenderOperation ro; mSceneManager->useRenderableViewProjMode(halfbox); halfbox->getRenderOperation(ro); ro.srcRenderable = halfbox; mRenderSystem->_render(ro);*/ mSceneManager->myrenderSingleObject(getSolidHalfBoundingBox(half), getSolidHalfBoundingBox(half)->getTechnique()->getPass(0), true); } } //----------------------------------------------------------------------- SolidHalfBoundingBox *SceneTraverser::getSolidHalfBoundingBox( int half ) { if(!mHalfBoundingBox[half]) mHalfBoundingBox[half] = new SolidHalfBoundingBox(half == 1); return mHalfBoundingBox[half]; } //----------------------------------------------------------------------- void OcclusionCullingSceneTraverser::setNumSceneNodes(int num) { mNumSceneNodes = num; } //----------------------------------------------------------------------- void SceneTraverser::setSceneRoot(SceneNode *root) { mSceneRoot = root; } //----------------------------------------------------------------------- void SceneTraverser::initDistanceQueue(Camera *cam) { mDistanceQueue = new PriorityQueue(myless(cam)); mDistanceQueue->push(mSceneRoot); } //----------------------------------------------------------------------- HardwareOcclusionQuery *SceneTraverser::getNextOcclusionQuery(void) { if(mCurrentTestIdx == mOcclusionQueries.size()) { mOcclusionQueries.push_back(mRenderSystem->createHardwareOcclusionQuery()); } return mOcclusionQueries[mCurrentTestIdx ++]; } //----------------------------------------------------------------------- bool OcclusionCullingSceneTraverser::setOption( const String & key, const void * val ) { if ( key == "Algorithm" ) { mCurrentAlgorithm = * static_cast < const int * > ( val ); return true; } if ( key == "Threshold" ) { mVisibilityThreshold = * static_cast < const int * > ( val ); return true; } return false; } //----------------------------------------------------------------------- bool SceneTraverser::getOption( const String & key, void *val ) { if ( key == "Algorithm" ) { * static_cast < int * > ( val ) = mCurrentAlgorithm; return true; } if ( key == "Threshold" ) { * static_cast < unsigned int * > ( val ) = mVisibilityThreshold; return true; } if ( key == "NumSceneNodes" ) { * static_cast < unsigned int * > ( val ) = mNumSceneNodes; return true; } if ( key == "NumTraversedNodes" ) { * static_cast < unsigned int * > ( val ) = mNumTraversedNodes; return true; } if ( key == "NumQueryCulledNodes" ) { * static_cast < unsigned int * > ( val ) = mNumQueryCulledNodes; return true; } if ( key == "NumFrustumCulledNodes" ) { * static_cast < unsigned int * > ( val ) = mNumFrustumCulledNodes; return true; } if ( key == "NumRenderedNodes" ) { * static_cast < unsigned int * > ( val ) = mNumRenderedNodes; return true; } return false; } //----------------------------------------------------------------------- bool SceneTraverser::getOptionKeys( StringVector & refKeys ) { refKeys.push_back( "Algorithm" ); refKeys.push_back( "Threshold" ); refKeys.push_back( "NumSceneNodes" ); refKeys.push_back( "NumTraversedNodes" ); refKeys.push_back( "NumQueryCulledNodes" ); refKeys.push_back( "NumFrustumCulledNodes" ); refKeys.push_back( "mNumRenderedGeometry" ); return true; } }