- Timestamp:
- 03/29/05 08:21:37 (20 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/VUT/OcclusionCullingSceneManager/src/OgreOcclusionCullingSceneManager.cpp
r31 r32 13 13 14 14 //----------------------------------------------------------------------- 15 OcclusionCullingSceneManager::OcclusionCullingSceneManager(): 16 mFrameId(1), mDistanceQueue(NULL), mVisibilityThreshold(0), mCurrentTestIdx(0), 17 mQueryMode(MODE_RENDER), mNumSceneNodes(0), mCurrentAlgorithm(RENDER_COHERENT), 18 mNumTraversedNodes(0), mNumQueryCulledNodes(0), mNumFrustumCulledNodes(0), mNumRenderedGeometry(0) 19 { 20 mHalfBoundingBox[0] = mHalfBoundingBox[1] = 0; 15 OcclusionCullingSceneManager::OcclusionCullingSceneManager() 16 { 21 17 } 22 18 //----------------------------------------------------------------------- 23 void OcclusionCullingSceneManager::_findVisibleObjects( Camera* cam, bool onlyShadowCasters)19 void OcclusionCullingSceneManager::_findVisibleObjects( Camera* cam, bool onlyShadowCasters ) 24 20 { 25 // empty because we have to find in _renderVisibleObjects21 // empty because we have to find objects in _renderVisibleObjects 26 22 } 27 23 //----------------------------------------------------------------------- 28 OcclusionCullingSceneManager::~OcclusionCullingSceneManager() 29 { 30 if(mHalfBoundingBox[0]) delete mHalfBoundingBox[0]; 31 if(mHalfBoundingBox[1]) delete mHalfBoundingBox[1]; 32 33 deleteQueries(); 34 //SceneManager::~SceneManager(); 24 void OcclusionCullingSceneManager::_renderVisibleObjects( void ) 25 { 26 mSceneTraverser.renderScene(mCameraInProgress, mSceneRoot); 35 27 } 36 28 //----------------------------------------------------------------------- 37 void OcclusionCullingSceneManager::_renderVisibleObjects(void) 38 { 39 mNumTraversedNodes = 0; 40 mNumQueryCulledNodes = 0; 41 mNumFrustumCulledNodes = 0; 42 mNumRenderedGeometry = 0; 43 44 mDistanceQueue = new PriorityQueue(myless<SceneNode *>(mCameraInProgress)); 45 mDistanceQueue->push(mSceneRoot); 46 mCurrentTestIdx = 0; 47 //renderZPass(); 48 49 switch(mCurrentAlgorithm) 50 { 51 case RENDER_CULL_FRUSTUM: 52 renderCullFrustum(); 53 break; 54 case RENDER_STOP_AND_WAIT: 55 renderStopAndWait(); 56 break; 57 case RENDER_COHERENT: 58 renderCoherentWithQueue(); 59 break; 60 default: 61 renderCullFrustum(); 62 break; 63 } 64 65 delete mDistanceQueue; 66 67 mFrameId ++; 68 } 69 //----------------------------------------------------------------------- 70 void OcclusionCullingSceneManager::renderZPass() 29 /*void OcclusionCullingSceneManager::renderZPass() 71 30 { 72 31 traverseNode(mSceneRoot); 73 } 32 }*/ 74 33 //----------------------------------------------------------------------- 75 void OcclusionCullingSceneManager:: renderCoherentWithQueue()34 void OcclusionCullingSceneManager::_updateSceneGraph( Camera* cam ) 76 35 { 77 QueryQueue queryQueue; 78 79 //-- PART 1: process finished occlusion queries 80 while(!mDistanceQueue->empty() || !queryQueue.empty()) 81 { 82 while(!queryQueue.empty() && 83 ((queryQueue.front().second)->resultAvailable() || mDistanceQueue->empty())) 84 { 85 SceneNode *node = queryQueue.front().first; 86 HardwareOcclusionQuery *query = queryQueue.front().second; 87 88 queryQueue.pop(); 89 90 // wait until result available 91 unsigned int visiblePixels; 92 query->pullOcclusionQuery(&visiblePixels); 93 94 if(visiblePixels > mVisibilityThreshold) 95 { 96 pullUpVisibility(node); 97 traverseNode(node); 98 } 99 else 100 { 101 mNumQueryCulledNodes ++; 102 } 103 } 104 105 //-- PART 2: hierarchical traversal 106 if(!mDistanceQueue->empty()) 107 { 108 SceneNode *node = mDistanceQueue->top(); 109 mDistanceQueue->pop(); 110 111 if(mCameraInProgress->isVisible(node->_getWorldAABB())) 112 { 113 // identify previously visible nodes 114 bool wasVisible = node->isNodeVisible() && (node->lastVisited() == mFrameId - 1); 115 116 // identify nodes that we cannot skip queries for 117 bool leafOrWasInvisible = !wasVisible || isLeaf(node); 118 119 // reset node's visibility classification 120 node->setNodeVisible(false); 121 122 // update node's visited flag 123 node->setLastVisited(mFrameId); 124 125 // skip testing previously visible interior nodes 126 if(leafOrWasInvisible) 127 { 128 HardwareOcclusionQuery *query = issueOcclusionQuery(node, wasVisible); 129 queryQueue.push(query_pair(node, query)); 130 } 131 132 // always traverse a node if it was visible 133 if(wasVisible) 134 { 135 traverseNode(node); 136 } 137 } 138 else 139 { 140 mNumFrustumCulledNodes ++; 141 } 142 } 143 } 144 } 145 //----------------------------------------------------------------------- 146 void OcclusionCullingSceneManager::renderCullFrustum() 147 { 148 while(!mDistanceQueue->empty()) 149 { 150 SceneNode *node = mDistanceQueue->top(); 151 mDistanceQueue->pop(); 152 153 // interesting for visualization purpose 154 node->setNodeVisible(false); 155 156 if(mCameraInProgress->isVisible(node->_getWorldAABB())) 157 { 158 // update node's visited flag 159 node->setLastVisited(mFrameId); 160 node->setNodeVisible(true); 161 traverseNode(node); 162 } 163 else 164 { 165 mNumFrustumCulledNodes ++; 166 } 167 } 168 } 169 //----------------------------------------------------------------------- 170 void OcclusionCullingSceneManager::renderStopAndWait() 171 { 172 while(!mDistanceQueue->empty()) 173 { 174 SceneNode *node = mDistanceQueue->top(); 175 mDistanceQueue->pop(); 36 mSceneTraverser.preprocess(); 176 37 177 // interesting for the visualization178 node->setNodeVisible(false);179 node->setLastVisited(mFrameId);180 181 if(mCameraInProgress->isVisible(node->_getWorldAABB()))182 {183 HardwareOcclusionQuery *query = issueOcclusionQuery(node, false);184 185 unsigned int visiblePixels;186 // wait if result not available187 query->pullOcclusionQuery(&visiblePixels);188 189 // node visible190 if(visiblePixels > mVisibilityThreshold)191 {192 traverseNode(node);193 }194 else195 {196 mNumQueryCulledNodes ++;197 }198 }199 else200 {201 mNumFrustumCulledNodes ++;202 }203 }204 }205 //-----------------------------------------------------------------------206 HardwareOcclusionQuery *OcclusionCullingSceneManager::issueOcclusionQuery(SceneNode *node, bool wasVisible)207 {208 // change state so the bounding box gets not actually rendered on the screen209 setRenderingMode(MODE_QUERY);210 211 // get next available test id212 HardwareOcclusionQuery *query = mOcclusionQueries[mCurrentTestIdx++];213 214 query->beginOcclusionQuery();215 216 /*217 static RenderOperation ro;218 useRenderableViewProjMode(&box);219 box.getRenderOperation(ro);220 ro.srcRenderable = &box;221 mDestRenderSystem->_render(ro);222 */223 224 renderBoundingBox(node);225 226 query->endOcclusionQuery();227 228 return query;229 }230 231 //-----------------------------------------------------------------------232 void OcclusionCullingSceneManager::setRenderingMode(int mode)233 {234 // avoid unnecessary state changes235 if(mode != mQueryMode)236 {237 bool enabled = (mode == MODE_RENDER);238 239 mDestRenderSystem->_setColourBufferWriteEnabled(enabled,240 enabled, enabled, enabled);241 mDestRenderSystem->_setDepthBufferWriteEnabled(enabled);242 mDestRenderSystem->setLightingEnabled(enabled);243 mQueryMode = mode;244 }245 }246 //-----------------------------------------------------------------------247 void OcclusionCullingSceneManager::traverseNode(SceneNode *node)248 {249 mNumTraversedNodes ++;250 251 if(node->numAttachedObjects() > 0)252 {253 render(node);254 }255 256 // internal node: add children to priority queue for further processing257 Node::ChildNodeIterator it = node->getChildIterator();258 259 while (it.hasMoreElements())260 {261 SceneNode* sceneChild = static_cast<SceneNode*>(it.getNext());262 mDistanceQueue->push(sceneChild);263 }264 }265 //-----------------------------------------------------------------------266 void OcclusionCullingSceneManager::render(SceneNode *node)267 {268 setRenderingMode(MODE_RENDER);269 270 //HACK (too slow)271 node->_findVisibleObjects(mCameraInProgress, getRenderQueue(), false,272 mDisplayNodes, false);273 SceneManager::_renderVisibleObjects();274 getRenderQueue()->clear();275 }276 //-----------------------------------------------------------------------277 void OcclusionCullingSceneManager::_updateSceneGraph(Camera* cam)278 {279 unsigned int numnodes = countSceneNodes(mSceneRoot);280 281 //-- initialise occlusion queries.282 if(numnodes != mNumSceneNodes)283 {284 deleteQueries();285 286 mNumSceneNodes = numnodes;287 288 for(unsigned int i=0; i < mNumSceneNodes; i++)289 {290 mOcclusionQueries.push_back(mDestRenderSystem->createHardwareOcclusionQuery());291 }292 }293 294 38 SceneManager::_updateSceneGraph(cam); 295 }296 //-----------------------------------------------------------------------297 unsigned int OcclusionCullingSceneManager::countSceneNodes(SceneNode *node)298 {299 unsigned int result = 1;300 301 Node::ChildNodeIterator it = node->getChildIterator();302 303 while (it.hasMoreElements())304 {305 SceneNode* sceneChild = static_cast<SceneNode*>(it.getNext());306 result += countSceneNodes(sceneChild);307 }308 309 return result;310 }311 //-----------------------------------------------------------------------312 bool OcclusionCullingSceneManager::isLeaf(SceneNode *node)313 {314 return (node->numChildren() == 0);315 }316 //-----------------------------------------------------------------------317 void OcclusionCullingSceneManager::pullUpVisibility(SceneNode *node)318 {319 while(!node->isNodeVisible())320 {321 node->setNodeVisible(true);322 323 if(node != mSceneRoot)324 node = static_cast<SceneNode *>(node->getParent());325 }326 }327 //-----------------------------------------------------------------------328 void OcclusionCullingSceneManager::deleteQueries()329 {330 for(unsigned int i=0; i < mNumSceneNodes; i++)331 delete mOcclusionQueries[i];332 333 mOcclusionQueries.clear();334 }335 //-----------------------------------------------------------------------336 void OcclusionCullingSceneManager::renderBoundingBox(SceneNode *node)337 {338 // Render two halfes of the bounding box (using triangle fans)339 for(int half=0; half < 2; half ++)340 {341 getSolidHalfBoundingBox(half)->setupBoundingBox(node->_getWorldAABB());342 SceneManager::renderSingleObject(getSolidHalfBoundingBox(half),343 getSolidHalfBoundingBox(half)->getTechnique()->getPass(0), false);344 }345 }346 //-----------------------------------------------------------------------347 SolidHalfBoundingBox *OcclusionCullingSceneManager::getSolidHalfBoundingBox(int half)348 {349 if(!mHalfBoundingBox[half])350 mHalfBoundingBox[half] = new SolidHalfBoundingBox(half == 1);351 352 return mHalfBoundingBox[half];353 39 } 354 40 //----------------------------------------------------------------------- 355 41 bool OcclusionCullingSceneManager::setOption( const String & key, const void * val ) 356 42 { 357 if ( key == "Algorithm" ) 358 { 359 mCurrentAlgorithm = * static_cast < const int * > ( val ); 360 return true; 361 } 362 if ( key == "Threshold" ) 363 { 364 mCurrentAlgorithm = * static_cast < const int * > ( val ); 365 return true; 366 } 367 43 mSceneTraverser.setOption(key, val); 44 368 45 return SceneManager::setOption( key, val ); 369 46 } … … 371 48 bool OcclusionCullingSceneManager::getOption( const String & key, void *val ) 372 49 { 373 if ( key == "Algorithm" ) 374 { 375 * static_cast < int * > ( val ) = mCurrentAlgorithm; 376 return true; 377 } 378 if ( key == "Threshold" ) 379 { 380 * static_cast < unsigned int * > ( val ) = mVisibilityThreshold; 381 return true; 382 } 383 if ( key == "NumSceneNodes" ) 384 { 385 * static_cast < unsigned int * > ( val ) = mNumSceneNodes; 386 return true; 387 } 388 if ( key == "NumTraversedNodes" ) 389 { 390 * static_cast < unsigned int * > ( val ) = mNumTraversedNodes; 391 return true; 392 } 393 if ( key == "NumQueryCulledNodes" ) 394 { 395 * static_cast < unsigned int * > ( val ) = mNumQueryCulledNodes; 396 return true; 397 } 398 if ( key == "NumFrustumCulledNodes" ) 399 { 400 * static_cast < unsigned int * > ( val ) = mNumFrustumCulledNodes; 401 return true; 402 } 403 50 mSceneTraverser.getOption(key, val); 51 404 52 return SceneManager::getOption( key, val ); 405 53 } … … 413 61 { 414 62 SceneManager::getOptionKeys( refKeys ); 63 415 64 refKeys.push_back( "Algorithm" ); 416 65 refKeys.push_back( "Threshold" );
Note: See TracChangeset
for help on using the changeset viewer.