[59] | 1 | #include "OgreVisibilityOctreeSceneManager.h"
|
---|
[74] | 2 | #include "OgreVisibilityOptionsManager.h"
|
---|
[59] | 3 | #include <OgreMath.h>
|
---|
| 4 | #include <OgreIteratorWrappers.h>
|
---|
| 5 | #include <OgreRenderSystem.h>
|
---|
| 6 | #include <OgreCamera.h>
|
---|
[92] | 7 | #include <OgreLogManager.h>
|
---|
[118] | 8 | #include <OgreStringConverter.h>
|
---|
[59] | 9 |
|
---|
[118] | 10 |
|
---|
[59] | 11 | namespace Ogre {
|
---|
| 12 |
|
---|
| 13 | //-----------------------------------------------------------------------
|
---|
| 14 | VisibilityOctreeSceneManager::VisibilityOctreeSceneManager(
|
---|
[87] | 15 | GtpVisibility::VisibilityManager *visManager)
|
---|
[112] | 16 | :
|
---|
| 17 | mVisibilityManager(visManager),
|
---|
[118] | 18 | mIsDepthPass(false),
|
---|
[112] | 19 | mShowVisualization(false),
|
---|
| 20 | mRenderNodesForViz(false),
|
---|
[118] | 21 | mRenderNodesContentForViz(false),
|
---|
[114] | 22 | mVisualizeCulledNodes(false),
|
---|
[115] | 23 | mSkipTransparents(false),
|
---|
[120] | 24 | mDelayRenderTransparents(true),
|
---|
| 25 | mUseDepthPass(true)
|
---|
[59] | 26 | {
|
---|
[120] | 27 | mHierarchyInterface = new OctreeHierarchyInterface(this, mDestRenderSystem);
|
---|
[94] | 28 |
|
---|
[59] | 29 | //mDisplayNodes = true;
|
---|
[86] | 30 | //mShowBoundingBoxes = true;
|
---|
| 31 | //mShowBoxes = true;
|
---|
[87] | 32 |
|
---|
[96] | 33 | // TODO: find reasonable value for max depth
|
---|
| 34 | mMaxDepth = 50;
|
---|
[59] | 35 | }
|
---|
| 36 | //-----------------------------------------------------------------------
|
---|
[119] | 37 | void VisibilityOctreeSceneManager::InitDepthPass()
|
---|
[115] | 38 | {
|
---|
| 39 | MaterialPtr depthMat = MaterialManager::getSingleton().getByName("Visibility/DepthPass");
|
---|
| 40 |
|
---|
| 41 | if (depthMat.isNull())
|
---|
| 42 | {
|
---|
| 43 | // Init
|
---|
| 44 | depthMat = MaterialManager::getSingleton().create(
|
---|
| 45 | "Visibility/DepthPass",
|
---|
| 46 | ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
|
---|
| 47 |
|
---|
[118] | 48 | mDepthPass = depthMat->getTechnique(0)->getPass(0);
|
---|
[115] | 49 | mDepthPass->setColourWriteEnabled(false);
|
---|
| 50 | mDepthPass->setDepthWriteEnabled(true);
|
---|
| 51 | mDepthPass->setLightingEnabled(false);
|
---|
| 52 | }
|
---|
| 53 | else
|
---|
| 54 | {
|
---|
| 55 | mDepthPass = depthMat->getTechnique(0)->getPass(0);
|
---|
| 56 | }
|
---|
| 57 | }
|
---|
| 58 | //-----------------------------------------------------------------------
|
---|
[59] | 59 | VisibilityOctreeSceneManager::~VisibilityOctreeSceneManager()
|
---|
| 60 | {
|
---|
[120] | 61 | if (mHierarchyInterface)
|
---|
| 62 | {
|
---|
| 63 | delete mHierarchyInterface;
|
---|
| 64 | mHierarchyInterface = NULL;
|
---|
| 65 | }
|
---|
[59] | 66 | }
|
---|
| 67 | //-----------------------------------------------------------------------
|
---|
[118] | 68 | Pass *VisibilityOctreeSceneManager::setPass(Pass* pass)
|
---|
[59] | 69 | {
|
---|
[118] | 70 | // setting vertex program is not efficient
|
---|
[120] | 71 | Pass *usedPass = ((mIsDepthPass && pass->getDepthWriteEnabled() && !pass->hasVertexProgram()) ? mDepthPass : pass);
|
---|
| 72 |
|
---|
| 73 | /*
|
---|
[119] | 74 | // set depth fill pass only if depth write enabled
|
---|
| 75 | Pass *usedPass = (mIsDepthPass && pass->getDepthWriteEnabled() ? mDepthPass : pass);
|
---|
[118] | 76 |
|
---|
[120] | 77 | if (mIsDepthPass && pass->hasVertexProgram())
|
---|
| 78 | {
|
---|
| 79 | // set vertex program of current pass to depth pass
|
---|
| 80 | mDepthPass->setVertexProgram(pass->getVertexProgramName());
|
---|
| 81 |
|
---|
| 82 | if (mDepthPass->hasVertexProgram())
|
---|
[118] | 83 | {
|
---|
[120] | 84 | const GpuProgramPtr& prg = mDepthPass->getVertexProgram();
|
---|
| 85 | // Load this program if not done already
|
---|
| 86 | if (!prg->isLoaded())
|
---|
| 87 | prg->load();
|
---|
| 88 | // Copy params
|
---|
| 89 | mDepthPass->setVertexProgramParameters(pass->getVertexProgramParameters());
|
---|
[118] | 90 | }
|
---|
| 91 | else if (mDepthPass->hasVertexProgram())
|
---|
| 92 | {
|
---|
| 93 | mDepthPass->setVertexProgram("");
|
---|
| 94 | }
|
---|
[120] | 95 | }*/
|
---|
[118] | 96 |
|
---|
[120] | 97 | SceneManager::setPass(usedPass);
|
---|
[118] | 98 |
|
---|
| 99 | return usedPass;
|
---|
| 100 | }
|
---|
| 101 | //-----------------------------------------------------------------------
|
---|
| 102 | void VisibilityOctreeSceneManager::ShowVisualization(Camera *cam)
|
---|
| 103 | {
|
---|
| 104 | // add player camera for visualization purpose
|
---|
| 105 | try {
|
---|
| 106 | Camera *c;
|
---|
| 107 | if ((c = getCamera("PlayerCam")) != NULL)
|
---|
| 108 | {
|
---|
| 109 | getRenderQueue()->addRenderable(c);
|
---|
| 110 | }
|
---|
| 111 | }
|
---|
| 112 | catch(...)
|
---|
| 113 | {
|
---|
| 114 | // ignore
|
---|
| 115 | }
|
---|
| 116 | for (BoxList::iterator it = mBoxes.begin(); it != mBoxes.end(); ++it)
|
---|
| 117 | {
|
---|
| 118 | getRenderQueue()->addRenderable(*it);
|
---|
| 119 | }
|
---|
| 120 | if (mRenderNodesForViz || mRenderNodesContentForViz)
|
---|
| 121 | {
|
---|
| 122 | // change node material so it is better suited for visualization
|
---|
| 123 | MaterialPtr nodeMat = MaterialManager::getSingleton().getByName("Core/NodeMaterial");
|
---|
| 124 | nodeMat->setAmbient(1, 1, 0);
|
---|
| 125 | nodeMat->setLightingEnabled(true);
|
---|
| 126 | nodeMat->getTechnique(0)->getPass(0)->removeAllTextureUnitStates();
|
---|
| 127 |
|
---|
| 128 | for (NodeList::iterator it = mVisible.begin(); it != mVisible.end(); ++it)
|
---|
| 129 | {
|
---|
| 130 |
|
---|
| 131 | if (mRenderNodesForViz)
|
---|
| 132 | {
|
---|
| 133 | getRenderQueue()->addRenderable(*it);
|
---|
| 134 | // addbounding boxes instead of node itself
|
---|
| 135 | //(*it)->_addBoundingBoxToQueue(getRenderQueue());
|
---|
| 136 | }
|
---|
| 137 | if (mRenderNodesContentForViz)
|
---|
| 138 | {
|
---|
| 139 | (*it)->_addToRenderQueue(cam, getRenderQueue(), false);
|
---|
| 140 | }
|
---|
| 141 | }
|
---|
| 142 | }
|
---|
[103] | 143 |
|
---|
[118] | 144 | }
|
---|
| 145 | //-----------------------------------------------------------------------
|
---|
| 146 | void VisibilityOctreeSceneManager::_findVisibleObjects(Camera* cam, bool onlyShadowCasters)
|
---|
| 147 | {
|
---|
| 148 | //-- show visible scene nodes and octree bounding boxes from last frame
|
---|
| 149 | if (mShowVisualization)
|
---|
| 150 | {
|
---|
| 151 | ShowVisualization(cam);
|
---|
| 152 | }
|
---|
| 153 | else
|
---|
[115] | 154 | {
|
---|
[118] | 155 | mVisible.clear();
|
---|
| 156 | mBoxes.clear();
|
---|
| 157 |
|
---|
| 158 | // if there is no depth pass =>
|
---|
| 159 | // we interleave identification and rendering of objects
|
---|
| 160 | // in _renderVisibibleObjects
|
---|
| 161 |
|
---|
| 162 | // only shadow casters will be rendered in shadow texture pass
|
---|
| 163 | mHierarchyInterface->SetOnlyShadowCasters(onlyShadowCasters);
|
---|
| 164 | }
|
---|
| 165 | }
|
---|
| 166 | //-----------------------------------------------------------------------
|
---|
| 167 | void VisibilityOctreeSceneManager::_renderVisibleObjects()
|
---|
| 168 | {
|
---|
[119] | 169 | // create material for depth pass
|
---|
| 170 | InitDepthPass();
|
---|
| 171 |
|
---|
[118] | 172 | // visualization: apply standard rendering
|
---|
| 173 | if (mShowVisualization)
|
---|
| 174 | {
|
---|
[115] | 175 | OctreeSceneManager::_renderVisibleObjects();
|
---|
| 176 | return;
|
---|
| 177 | }
|
---|
| 178 |
|
---|
[118] | 179 |
|
---|
[87] | 180 | //-- hierarchical culling
|
---|
| 181 | // the objects of different layers (e.g., background, scene,
|
---|
| 182 | // overlay) must be identified and rendered one after another
|
---|
| 183 |
|
---|
[118] | 184 | bool leaveTransparentsInQueue = mDelayRenderTransparents && !mUseDepthPass;
|
---|
| 185 |
|
---|
| 186 | // possible two cameras (one for culling, one for rendering)
|
---|
| 187 | mHierarchyInterface->InitFrame(mOctree, mCameraInProgress,
|
---|
| 188 | mCullCamera ? getCamera("CullCamera") : NULL,
|
---|
| 189 | leaveTransparentsInQueue);
|
---|
| 190 |
|
---|
| 191 | // call initframe to reset culling manager stats
|
---|
| 192 | mVisibilityManager->GetCullingManager()->InitFrame(mVisualizeCulledNodes);
|
---|
| 193 |
|
---|
[115] | 194 | mSkipTransparents = false;
|
---|
| 195 |
|
---|
[118] | 196 | //-- render background, in case there is one
|
---|
[59] | 197 | clearSpecialCaseRenderQueues();
|
---|
| 198 | addSpecialCaseRenderQueue(RENDER_QUEUE_BACKGROUND);
|
---|
| 199 | addSpecialCaseRenderQueue(RENDER_QUEUE_SKIES_EARLY);
|
---|
[118] | 200 | setSpecialCaseRenderQueueMode(SceneManager::SCRQM_INCLUDE);
|
---|
[59] | 201 |
|
---|
[87] | 202 | SceneManager::_renderVisibleObjects();
|
---|
| 203 |
|
---|
[118] | 204 |
|
---|
[59] | 205 | #ifdef GTP_VISIBILITY_MODIFIED_OGRE
|
---|
[115] | 206 | _deleteRenderedQueueGroups(false);
|
---|
[59] | 207 | #endif
|
---|
| 208 |
|
---|
| 209 | //-- render visible objects (i.e., all but overlay)
|
---|
| 210 | clearSpecialCaseRenderQueues();
|
---|
[118] | 211 | addSpecialCaseRenderQueue(RENDER_QUEUE_SKIES_LATE);
|
---|
[59] | 212 | addSpecialCaseRenderQueue(RENDER_QUEUE_OVERLAY);
|
---|
| 213 | setSpecialCaseRenderQueueMode(SceneManager::SCRQM_EXCLUDE);
|
---|
[115] | 214 |
|
---|
[118] | 215 | // transparents are skipped from hierarchical rendering
|
---|
| 216 | // => they need sorting, thus we render them afterwards
|
---|
[115] | 217 | mSkipTransparents = mDelayRenderTransparents;
|
---|
[59] | 218 |
|
---|
[118] | 219 | // set state for depth pass
|
---|
| 220 | mIsDepthPass = mUseDepthPass;
|
---|
| 221 |
|
---|
[100] | 222 | /**
|
---|
| 223 | * the hierarchical culling algorithm
|
---|
[118] | 224 | * for depth pass: will just find objects and update depth buffer
|
---|
| 225 | * for delayed rendering: will render all but transparents
|
---|
[100] | 226 | **/
|
---|
[115] | 227 |
|
---|
[59] | 228 | mVisibilityManager->ApplyVisibilityCulling();
|
---|
[115] | 229 |
|
---|
| 230 | //-- now we can savely render all remaining objects, e.g., transparents, overlay
|
---|
| 231 | mSkipTransparents = false;
|
---|
[59] | 232 |
|
---|
| 233 | clearSpecialCaseRenderQueues();
|
---|
| 234 | SceneManager::_renderVisibleObjects();
|
---|
[92] | 235 |
|
---|
[118] | 236 | // for depth pass: add visible nodes found with the visibility culling
|
---|
| 237 | if (mUseDepthPass)
|
---|
[120] | 238 | {
|
---|
[118] | 239 | for (NodeList::iterator it = mVisible.begin(); it != mVisible.end(); ++it)
|
---|
[120] | 240 | {
|
---|
[118] | 241 | (*it)->_addToRenderQueue(mCameraInProgress, getRenderQueue(), false);
|
---|
[120] | 242 | }
|
---|
[118] | 243 | mIsDepthPass = false;
|
---|
[120] | 244 | }
|
---|
[118] | 245 | mSkipTransparents = false;
|
---|
[100] | 246 |
|
---|
[118] | 247 | //-- now we can render all remaining queue objects
|
---|
| 248 | // for depth pass: all
|
---|
| 249 | // for delayed rendering: transparents, overlay
|
---|
| 250 | clearSpecialCaseRenderQueues();
|
---|
| 251 | SceneManager::_renderVisibleObjects();
|
---|
[114] | 252 |
|
---|
[120] | 253 | WriteLog(); // write out stats
|
---|
[59] | 254 | }
|
---|
| 255 | //-----------------------------------------------------------------------
|
---|
| 256 | void VisibilityOctreeSceneManager::_updateSceneGraph(Camera* cam)
|
---|
| 257 | {
|
---|
| 258 | mVisibilityManager->GetCullingManager()->SetHierarchyInterface(mHierarchyInterface);
|
---|
| 259 | mHierarchyInterface->SetRenderSystem(mDestRenderSystem);
|
---|
| 260 |
|
---|
| 261 | #ifdef GTP_VISIBILITY_MODIFIED_OGRE
|
---|
| 262 | mHierarchyInterface->SetNumOctreeNodes(mNumOctreeNodes);
|
---|
| 263 | #endif
|
---|
| 264 | OctreeSceneManager::_updateSceneGraph(cam);
|
---|
| 265 | }
|
---|
| 266 | //-----------------------------------------------------------------------
|
---|
| 267 | bool VisibilityOctreeSceneManager::setOption(const String & key, const void * val)
|
---|
| 268 | {
|
---|
[115] | 269 | if (key == "UseDepthPass")
|
---|
[87] | 270 | {
|
---|
[115] | 271 | mUseDepthPass = (*static_cast<const bool *>(val));
|
---|
[87] | 272 | return true;
|
---|
| 273 | }
|
---|
[100] | 274 | if (key == "ShowVisualization")
|
---|
| 275 | {
|
---|
| 276 | mShowVisualization = (*static_cast<const bool *>(val));
|
---|
| 277 | return true;
|
---|
| 278 | }
|
---|
[112] | 279 | if (key == "RenderNodesForViz")
|
---|
| 280 | {
|
---|
[114] | 281 | mRenderNodesForViz = (*static_cast<const bool *>(val));
|
---|
[112] | 282 | return true;
|
---|
| 283 | }
|
---|
[118] | 284 | if (key == "RenderNodesContentForViz")
|
---|
| 285 | {
|
---|
| 286 | mRenderNodesContentForViz = (*static_cast<const bool *>(val));
|
---|
| 287 | return true;
|
---|
| 288 | }
|
---|
[112] | 289 | if (key == "SkyBoxEnabled")
|
---|
| 290 | {
|
---|
| 291 | mSkyBoxEnabled = (*static_cast<const bool *>(val));
|
---|
| 292 | return true;
|
---|
| 293 | }
|
---|
| 294 | if (key == "SkyPlaneEnabled")
|
---|
| 295 | {
|
---|
| 296 | mSkyPlaneEnabled = (*static_cast<const bool *>(val));
|
---|
| 297 | return true;
|
---|
| 298 | }
|
---|
| 299 | if (key == "SkyDomeEnabled")
|
---|
| 300 | {
|
---|
| 301 | mSkyDomeEnabled = (*static_cast<const bool *>(val));
|
---|
| 302 | return true;
|
---|
| 303 | }
|
---|
| 304 | if (key == "VisualizeCulledNodes")
|
---|
| 305 | {
|
---|
| 306 | mVisualizeCulledNodes = (*static_cast<const bool *>(val));
|
---|
| 307 | return true;
|
---|
| 308 | }
|
---|
[115] | 309 | if (key == "DelayRenderTransparents")
|
---|
| 310 | {
|
---|
| 311 | mDelayRenderTransparents = (*static_cast<const bool *>(val));
|
---|
| 312 | return true;
|
---|
| 313 | }
|
---|
[74] | 314 | return VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface).
|
---|
| 315 | setOption(key, val) || OctreeSceneManager::setOption(key, val);
|
---|
[59] | 316 | }
|
---|
| 317 | //-----------------------------------------------------------------------
|
---|
| 318 | bool VisibilityOctreeSceneManager::getOption(const String & key, void *val)
|
---|
| 319 | {
|
---|
[74] | 320 | if (key == "NumHierarchyNodes")
|
---|
| 321 | {
|
---|
| 322 | * static_cast<unsigned int *>(val) = (unsigned int)mNumOctreeNodes;
|
---|
| 323 | return true;
|
---|
| 324 | }
|
---|
| 325 |
|
---|
| 326 | return VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface).
|
---|
| 327 | getOption(key, val) && OctreeSceneManager::getOption(key, val);
|
---|
[59] | 328 | }
|
---|
| 329 | //-----------------------------------------------------------------------
|
---|
| 330 | bool VisibilityOctreeSceneManager::getOptionValues(const String & key, StringVector &refValueList)
|
---|
| 331 | {
|
---|
| 332 | return OctreeSceneManager::getOptionValues( key, refValueList );
|
---|
| 333 | }
|
---|
| 334 | //-----------------------------------------------------------------------
|
---|
| 335 | bool VisibilityOctreeSceneManager::getOptionKeys(StringVector & refKeys)
|
---|
| 336 | {
|
---|
[74] | 337 | return VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface).
|
---|
[103] | 338 | getOptionKeys (refKeys) || OctreeSceneManager::getOptionKeys(refKeys);
|
---|
[59] | 339 | }
|
---|
| 340 | //-----------------------------------------------------------------------
|
---|
| 341 | void VisibilityOctreeSceneManager::setVisibilityManager(GtpVisibility::VisibilityManager *visManager)
|
---|
| 342 | {
|
---|
| 343 | mVisibilityManager = visManager;
|
---|
| 344 | }
|
---|
| 345 | //-----------------------------------------------------------------------
|
---|
| 346 | GtpVisibility::VisibilityManager *VisibilityOctreeSceneManager::getVisibilityManager()
|
---|
| 347 | {
|
---|
| 348 | return mVisibilityManager;
|
---|
| 349 | }
|
---|
[93] | 350 | //-----------------------------------------------------------------------
|
---|
[92] | 351 | void VisibilityOctreeSceneManager::WriteLog()
|
---|
| 352 | {
|
---|
| 353 | std::stringstream d;
|
---|
[59] | 354 |
|
---|
[120] | 355 | d << "Depth pass: " << StringConverter::toString(mUseDepthPass) << ", "
|
---|
| 356 | << "Delay transparents: " << StringConverter::toString(mDelayRenderTransparents) << ", "
|
---|
| 357 | << "Use optimization: " << StringConverter::toString(mHierarchyInterface->GetUseOptimization()) << ", "
|
---|
| 358 | << "Algorithm type: " << mVisibilityManager->GetCullingManagerType() << "\n"
|
---|
[118] | 359 | << "Hierarchy nodes: " << mNumOctreeNodes << ", "
|
---|
| 360 | << "Traversed nodes: " << mHierarchyInterface->GetNumTraversedNodes() << ", "
|
---|
[92] | 361 | << "Rendered nodes: " << mHierarchyInterface->GetNumRenderedNodes() << ", "
|
---|
| 362 | << "Query culled nodes: " << mVisibilityManager->GetCullingManager()->GetNumQueryCulledNodes() << ", "
|
---|
| 363 | << "Frustum culled nodes: " << mVisibilityManager->GetCullingManager()->GetNumFrustumCulledNodes() << ", "
|
---|
| 364 | << "Queries issued: " << mVisibilityManager->GetCullingManager()->GetNumQueriesIssued() << "\n";
|
---|
[120] | 365 | /*<< "avg. FPS: " << mCurrentViewport->getTarget()->getAverageFPS() << ", "
|
---|
| 366 | << "best FPS: " << mCurrentViewport->getTarget()->getBestFPS() << ", "
|
---|
| 367 | << "worst FPS: " << mCurrentViewport->getTarget()->getWorstFPS() << ", "
|
---|
| 368 | << "best frame time: " << mCurrentViewport->getTarget()->getBestFrameTime() << ", "
|
---|
| 369 | << "worst frame time: " << mCurrentViewport->getTarget()->getWorstFrameTime() << "\n";*/
|
---|
[92] | 370 |
|
---|
| 371 | LogManager::getSingleton().logMessage(d.str());
|
---|
| 372 | }
|
---|
[118] | 373 | //-----------------------------------------------------------------------
|
---|
| 374 | void VisibilityOctreeSceneManager::renderObjects(const RenderPriorityGroup::TransparentRenderablePassList& objs,
|
---|
| 375 | bool doLightIteration, const LightList* manualLightList)
|
---|
| 376 | {
|
---|
| 377 | if (!mSkipTransparents)
|
---|
| 378 | {
|
---|
| 379 | OctreeSceneManager::renderObjects(objs, doLightIteration, manualLightList);
|
---|
| 380 | }
|
---|
| 381 | }
|
---|
| 382 |
|
---|
[59] | 383 | } // namespace Ogre |
---|