#include "OgreVisibilityOctreeSceneManager.h" #include "OgreVisibilityOptionsManager.h" #include #include #include #include #include #include namespace Ogre { //----------------------------------------------------------------------- VisibilityOctreeSceneManager::VisibilityOctreeSceneManager( GtpVisibility::VisibilityManager *visManager) : mVisibilityManager(visManager), mRenderDepthPass(false), mShowVisualization(false), mRenderNodesForViz(false), mRenderNodesContentForViz(false), mVisualizeCulledNodes(false), mDelayRenderTransparents(true), mUseDepthPass(true), mSkipTransparents(false) { mHierarchyInterface = new OctreeHierarchyInterface(this, mDestRenderSystem); //mDisplayNodes = true; //mShowBoundingBoxes = true; //mShowBoxes = true; // TODO: find reasonable value for max depth mMaxDepth = 50; } //----------------------------------------------------------------------- void VisibilityOctreeSceneManager::InitDepthPass() { MaterialPtr depthMat = MaterialManager::getSingleton().getByName("Visibility/DepthPass"); if (depthMat.isNull()) { // Init depthMat = MaterialManager::getSingleton().create( "Visibility/DepthPass", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); mDepthPass = depthMat->getTechnique(0)->getPass(0); mDepthPass->setColourWriteEnabled(false); mDepthPass->setDepthWriteEnabled(true); mDepthPass->setLightingEnabled(false); } else { mDepthPass = depthMat->getTechnique(0)->getPass(0); } } //----------------------------------------------------------------------- VisibilityOctreeSceneManager::~VisibilityOctreeSceneManager() { if (mHierarchyInterface) { delete mHierarchyInterface; mHierarchyInterface = NULL; } } //----------------------------------------------------------------------- Pass *VisibilityOctreeSceneManager::setPass(Pass* pass) { // setting vertex program is not efficient Pass *usedPass = ((mRenderDepthPass && pass->getDepthWriteEnabled() && !pass->hasVertexProgram()) ? mDepthPass : pass); /* // set depth fill pass only if depth write enabled Pass *usedPass = (mRenderDepthPass && pass->getDepthWriteEnabled() ? mDepthPass : pass); if (mRenderDepthPass && pass->hasVertexProgram()) { // set vertex program of current pass to depth pass mDepthPass->setVertexProgram(pass->getVertexProgramName()); if (mDepthPass->hasVertexProgram()) { const GpuProgramPtr& prg = mDepthPass->getVertexProgram(); // Load this program if not done already if (!prg->isLoaded()) prg->load(); // Copy params mDepthPass->setVertexProgramParameters(pass->getVertexProgramParameters()); } else if (mDepthPass->hasVertexProgram()) { mDepthPass->setVertexProgram(""); } }*/ SceneManager::setPass(usedPass); return usedPass; } //----------------------------------------------------------------------- void VisibilityOctreeSceneManager::PrepareVisualization(Camera *cam) { // add player camera for visualization purpose try { Camera *c; if ((c = getCamera("PlayerCam")) != NULL) { getRenderQueue()->addRenderable(c); } } catch(...) { // ignore } for (BoxList::iterator it = mBoxes.begin(); it != mBoxes.end(); ++it) { getRenderQueue()->addRenderable(*it); } if (mRenderNodesForViz || mRenderNodesContentForViz) { // change node material so it is better suited for visualization MaterialPtr nodeMat = MaterialManager::getSingleton().getByName("Core/NodeMaterial"); nodeMat->setAmbient(1, 1, 0); nodeMat->setLightingEnabled(true); nodeMat->getTechnique(0)->getPass(0)->removeAllTextureUnitStates(); for (NodeList::iterator it = mVisible.begin(); it != mVisible.end(); ++it) { if (mRenderNodesForViz) { getRenderQueue()->addRenderable(*it); // addbounding boxes instead of node itself //(*it)->_addBoundingBoxToQueue(getRenderQueue()); } if (mRenderNodesContentForViz) { (*it)->_addToRenderQueue(cam, getRenderQueue(), false); } } } } //----------------------------------------------------------------------- void VisibilityOctreeSceneManager::_findVisibleObjects(Camera* cam, bool onlyShadowCasters) { //-- show visible scene nodes and octree bounding boxes from last frame if (mShowVisualization) { PrepareVisualization(cam); } else { mVisible.clear(); mBoxes.clear(); // if there is no depth pass => // we interleave identification and rendering of objects // in _renderVisibibleObjects // only shadow casters will be rendered in shadow texture pass mHierarchyInterface->SetOnlyShadowCasters(onlyShadowCasters); } } //----------------------------------------------------------------------- void VisibilityOctreeSceneManager::_renderVisibleObjects() { // create material for depth pass InitDepthPass(); // visualization: apply standard rendering if (mShowVisualization) { OctreeSceneManager::_renderVisibleObjects(); return; } //-- hierarchical culling // the objects of different layers (e.g., background, scene, // overlay) must be identified and rendered one after another bool leaveTransparentsInQueue = mDelayRenderTransparents && !mUseDepthPass; // possible two cameras (one for culling, one for rendering) mHierarchyInterface->InitFrame(mOctree, mCameraInProgress, mCullCamera ? getCamera("CullCamera") : NULL, leaveTransparentsInQueue); // reset culling manager stats mVisibilityManager->GetCullingManager()->InitFrame(mVisualizeCulledNodes); mSkipTransparents = false; //-- render background, in case there is one clearSpecialCaseRenderQueues(); addSpecialCaseRenderQueue(RENDER_QUEUE_BACKGROUND); addSpecialCaseRenderQueue(RENDER_QUEUE_SKIES_EARLY); setSpecialCaseRenderQueueMode(SceneManager::SCRQM_INCLUDE); SceneManager::_renderVisibleObjects(); #ifdef GTP_VISIBILITY_MODIFIED_OGRE _deleteRenderedQueueGroups(); #endif //-- render visible objects (i.e., all but overlay) clearSpecialCaseRenderQueues(); addSpecialCaseRenderQueue(RENDER_QUEUE_SKIES_LATE); addSpecialCaseRenderQueue(RENDER_QUEUE_OVERLAY); setSpecialCaseRenderQueueMode(SceneManager::SCRQM_EXCLUDE); // transparents are skipped from hierarchical rendering // => they need sorting, thus we render them afterwards mSkipTransparents = mDelayRenderTransparents; // set state for depth pass mRenderDepthPass = mUseDepthPass; /** * the hierarchical culling algorithm * for depth pass: will just find objects and update depth buffer * for delayed rendering: will render all but transparents **/ mVisibilityManager->ApplyVisibilityCulling(); //-- now we can savely render all remaining objects, e.g., transparents, overlay mSkipTransparents = false; clearSpecialCaseRenderQueues(); SceneManager::_renderVisibleObjects(); // for depth pass: add visible nodes found with the visibility culling if (mUseDepthPass) { for (NodeList::iterator it = mVisible.begin(); it != mVisible.end(); ++it) { (*it)->_addToRenderQueue(mCameraInProgress, getRenderQueue(), false); } mRenderDepthPass = false; } mSkipTransparents = false; //-- now we can render all remaining queue objects // for depth pass: all // for delayed rendering: transparents, overlay clearSpecialCaseRenderQueues(); OctreeSceneManager::_renderVisibleObjects(); WriteLog(); // write out stats } //----------------------------------------------------------------------- void VisibilityOctreeSceneManager::_updateSceneGraph(Camera* cam) { mVisibilityManager->GetCullingManager()->SetHierarchyInterface(mHierarchyInterface); mHierarchyInterface->SetRenderSystem(mDestRenderSystem); #ifdef GTP_VISIBILITY_MODIFIED_OGRE mHierarchyInterface->SetNumOctreeNodes(mNumOctreeNodes); #endif OctreeSceneManager::_updateSceneGraph(cam); } //----------------------------------------------------------------------- bool VisibilityOctreeSceneManager::setOption(const String & key, const void * val) { if (key == "UseDepthPass") { mUseDepthPass = (*static_cast(val)); return true; } if (key == "PrepareVisualization") { mShowVisualization = (*static_cast(val)); return true; } if (key == "RenderNodesForViz") { mRenderNodesForViz = (*static_cast(val)); return true; } if (key == "RenderNodesContentForViz") { mRenderNodesContentForViz = (*static_cast(val)); return true; } if (key == "SkyBoxEnabled") { mSkyBoxEnabled = (*static_cast(val)); return true; } if (key == "SkyPlaneEnabled") { mSkyPlaneEnabled = (*static_cast(val)); return true; } if (key == "SkyDomeEnabled") { mSkyDomeEnabled = (*static_cast(val)); return true; } if (key == "VisualizeCulledNodes") { mVisualizeCulledNodes = (*static_cast(val)); return true; } if (key == "DelayRenderTransparents") { mDelayRenderTransparents = (*static_cast(val)); return true; } return VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface). setOption(key, val) || OctreeSceneManager::setOption(key, val); } //----------------------------------------------------------------------- bool VisibilityOctreeSceneManager::getOption(const String & key, void *val) { if (key == "NumHierarchyNodes") { * static_cast(val) = (unsigned int)mNumOctreeNodes; return true; } return VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface). getOption(key, val) && OctreeSceneManager::getOption(key, val); } //----------------------------------------------------------------------- bool VisibilityOctreeSceneManager::getOptionValues(const String & key, StringVector &refValueList) { return OctreeSceneManager::getOptionValues( key, refValueList ); } //----------------------------------------------------------------------- bool VisibilityOctreeSceneManager::getOptionKeys(StringVector & refKeys) { return VisibilityOptionsManager(mVisibilityManager, mHierarchyInterface). getOptionKeys (refKeys) || OctreeSceneManager::getOptionKeys(refKeys); } //----------------------------------------------------------------------- void VisibilityOctreeSceneManager::setVisibilityManager(GtpVisibility::VisibilityManager *visManager) { mVisibilityManager = visManager; } //----------------------------------------------------------------------- GtpVisibility::VisibilityManager *VisibilityOctreeSceneManager::getVisibilityManager() { return mVisibilityManager; } //----------------------------------------------------------------------- void VisibilityOctreeSceneManager::WriteLog() { std::stringstream d; d << "Depth pass: " << StringConverter::toString(mUseDepthPass) << ", " << "Delay transparents: " << StringConverter::toString(mDelayRenderTransparents) << ", " << "Use optimization: " << StringConverter::toString(mHierarchyInterface->GetUseOptimization()) << ", " << "Algorithm type: " << mVisibilityManager->GetCullingManagerType() << "\n" << "Hierarchy nodes: " << mNumOctreeNodes << ", " << "Traversed nodes: " << mHierarchyInterface->GetNumTraversedNodes() << ", " << "Rendered nodes: " << mHierarchyInterface->GetNumRenderedNodes() << ", " << "Query culled nodes: " << mVisibilityManager->GetCullingManager()->GetNumQueryCulledNodes() << ", " << "Frustum culled nodes: " << mVisibilityManager->GetCullingManager()->GetNumFrustumCulledNodes() << ", " << "Queries issued: " << mVisibilityManager->GetCullingManager()->GetNumQueriesIssued() << "\n"; /*<< "avg. FPS: " << mCurrentViewport->getTarget()->getAverageFPS() << ", " << "best FPS: " << mCurrentViewport->getTarget()->getBestFPS() << ", " << "worst FPS: " << mCurrentViewport->getTarget()->getWorstFPS() << ", " << "best frame time: " << mCurrentViewport->getTarget()->getBestFrameTime() << ", " << "worst frame time: " << mCurrentViewport->getTarget()->getWorstFrameTime() << "\n";*/ LogManager::getSingleton().logMessage(d.str()); } //----------------------------------------------------------------------- void VisibilityOctreeSceneManager::renderObjects(const RenderPriorityGroup::TransparentRenderablePassList& objs, bool doLightIteration, const LightList* manualLightList) { if (!mSkipTransparents) { OctreeSceneManager::renderObjects(objs, doLightIteration, manualLightList); } } } // namespace Ogre