Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

OgreSceneManager.cpp

Go to the documentation of this file.
00001 /*
00002 -----------------------------------------------------------------------------
00003 This source file is part of OGRE
00004     (Object-oriented Graphics Rendering Engine)
00005 For the latest info, see http://ogre.sourceforge.net/
00006 
00007 Copyright © 2000-2002 The OGRE Team
00008 Also see acknowledgements in Readme.html
00009 
00010 This program is free software; you can redistribute it and/or modify it under
00011 the terms of the GNU Lesser General Public License as published by the Free Software
00012 Foundation; either version 2 of the License, or (at your option) any later
00013 version.
00014 
00015 This program is distributed in the hope that it will be useful, but WITHOUT
00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
00018 
00019 You should have received a copy of the GNU Lesser General Public License along with
00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
00022 http://www.gnu.org/copyleft/lesser.txt.
00023 -----------------------------------------------------------------------------
00024 */
00025 #include "OgreStableHeaders.h"
00026 
00027 #include "OgreSceneManager.h"
00028 
00029 #include "OgreCamera.h"
00030 #include "OgreRenderSystem.h"
00031 #include "OgreMeshManager.h"
00032 #include "OgreMesh.h"
00033 #include "OgreSubMesh.h"
00034 #include "OgreEntity.h"
00035 #include "OgreSubEntity.h"
00036 #include "OgreLight.h"
00037 #include "OgreMath.h"
00038 #include "OgreControllerManager.h"
00039 #include "OgreMaterialManager.h"
00040 #include "OgreAnimation.h"
00041 #include "OgreAnimationTrack.h"
00042 #include "OgreRenderQueueSortingGrouping.h"
00043 #include "OgreOverlay.h"
00044 #include "OgreOverlayManager.h"
00045 #include "OgreStringConverter.h"
00046 #include "OgreRenderQueueListener.h"
00047 #include "OgreBillboardSet.h"
00048 #include "OgrePass.h"
00049 #include "OgreTechnique.h"
00050 #include "OgreTextureUnitState.h"
00051 #include "OgreException.h"
00052 #include "OgreLogManager.h"
00053 
00054 // This class implements the most basic scene manager
00055 
00056 #include <cstdio>
00057 
00058 namespace Ogre {
00059 
00060     SceneManager::SceneManager()
00061     {
00062         // Root scene node
00063         mSceneRoot = new SceneNode(this, "root node");
00064 
00065         // No sky by default
00066         mSkyPlaneEnabled = false;
00067         mSkyBoxEnabled = false;
00068         mSkyDomeEnabled = false;
00069 
00070         // init sky
00071         mSkyPlaneEntity = 0;
00072         uint i;
00073         for (i = 0; i < 6; ++i)
00074         {
00075             mSkyBoxEntity[i] = 0;
00076         }
00077         for (i = 0; i < 5; ++i)
00078         {
00079             mSkyDomeEntity[i] = 0;
00080         }
00081         mSkyPlaneNode = 0;
00082         mSkyDomeNode = 0;
00083         mSkyBoxNode = 0;
00084 
00085 
00086         // No fog
00087         mFogMode = FOG_NONE;
00088 
00089         mDisplayNodes = false;
00090 
00091       mShowBoundingBoxes = false;
00092     }
00093 
00094     SceneManager::~SceneManager()
00095     {
00096         clearScene();
00097         delete mSceneRoot;
00098     }
00099 
00100     //-----------------------------------------------------------------------
00101     Camera* SceneManager::createCamera(const String& name)
00102     {
00103         Camera *c = new Camera(name, this);
00104         mCameras.insert(CameraList::value_type(name, c));
00105 
00106 
00107         return c;
00108     }
00109 
00110     //-----------------------------------------------------------------------
00111     Camera* SceneManager::getCamera(const String& name)
00112     {
00113         CameraList::iterator i = mCameras.find(name);
00114         if (i == mCameras.end())
00115         {
00116             return 0;
00117         }
00118         else
00119         {
00120             return i->second;
00121         }
00122     }
00123 
00124     //-----------------------------------------------------------------------
00125     void SceneManager::removeCamera(Camera *cam)
00126     {
00127         // Find in list
00128         CameraList::iterator i = mCameras.begin();
00129         for (; i != mCameras.end(); ++i)
00130         {
00131             if (i->second == cam)
00132             {
00133                 mCameras.erase(i);
00134                 delete cam;
00135                 break;
00136             }
00137         }
00138 
00139     }
00140 
00141     //-----------------------------------------------------------------------
00142     void SceneManager::removeCamera(const String& name)
00143     {
00144         // Find in list
00145         CameraList::iterator i = mCameras.find(name);
00146         if (i != mCameras.end())
00147         {
00148             delete i->second;
00149             mCameras.erase(i);
00150         }
00151 
00152     }
00153 
00154     //-----------------------------------------------------------------------
00155     void SceneManager::removeAllCameras(void)
00156     {
00157 
00158         CameraList::iterator i = mCameras.begin();
00159         for (; i != mCameras.end(); ++i)
00160         {
00161             delete i->second;
00162         }
00163         mCameras.clear();
00164     }
00165 
00166     //-----------------------------------------------------------------------
00167     Light* SceneManager::createLight(const String& name)
00168     {
00169         Light *l = new Light(name);
00170         mLights.insert(SceneLightList::value_type(name, l));
00171         return l;
00172     }
00173 
00174     //-----------------------------------------------------------------------
00175     Light* SceneManager::getLight(const String& name)
00176     {
00177         SceneLightList::iterator i = mLights.find(name);
00178         if (i == mLights.end())
00179         {
00180             return 0;
00181         }
00182         else
00183         {
00184             return i->second;
00185         }
00186     }
00187 
00188     //-----------------------------------------------------------------------
00189     void SceneManager::removeLight(Light *l)
00190     {
00191         // Find in list
00192         SceneLightList::iterator i = mLights.begin();
00193         for (; i != mLights.end(); ++i)
00194         {
00195             if (i->second == l)
00196             {
00197                 mLights.erase(i);
00198                 delete l;
00199                 break;
00200             }
00201         }
00202 
00203     }
00204 
00205     //-----------------------------------------------------------------------
00206     void SceneManager::removeLight(const String& name)
00207     {
00208         // Find in list
00209         SceneLightList::iterator i = mLights.find(name);
00210         if (i != mLights.end())
00211         {
00212             delete i->second;
00213             mLights.erase(i);
00214         }
00215 
00216     }
00217 
00218     //-----------------------------------------------------------------------
00219     void SceneManager::removeAllLights(void)
00220     {
00221 
00222         SceneLightList::iterator i = mLights.begin();
00223         for (; i != mLights.end(); ++i)
00224         {
00225             delete i->second;
00226         }
00227         mLights.clear();
00228     }
00229     //-----------------------------------------------------------------------
00230     bool SceneManager::lightLess::operator()(const Light* a, const Light* b) const
00231     {
00232         return a->tempSquareDist < b->tempSquareDist;
00233     }
00234     //-----------------------------------------------------------------------
00235     void SceneManager::_populateLightList(const Vector3& position, LightList& destList)
00236     {
00237         // Really basic trawl of the lights, then sort
00238         destList.clear();
00239 
00240         SceneLightList::iterator i, iend;
00241         iend = mLights.end();
00242         for (i = mLights.begin(); i != iend; ++i)
00243         {
00244             Light* lt = i->second;
00245             if (lt->isVisible())
00246             {
00247                 if (lt->getType() == Light::LT_DIRECTIONAL)
00248                 {
00249                     // No distance
00250                     lt->tempSquareDist = 0.0f;
00251                     destList.push_back(lt);
00252                 }
00253                 else
00254                 {
00255                     // Calc squared distance
00256                     lt->tempSquareDist = (lt->getDerivedPosition() - position).squaredLength();
00257                     // only add in-range lights
00258                     Real range = lt->getAttenuationRange();
00259                     if (lt->tempSquareDist <= (range * range))
00260                     {
00261                         destList.push_back(lt);
00262                     }
00263                 }
00264             }
00265         }
00266 
00267         // Sort
00268         std::sort(destList.begin(), destList.end(), lightLess());
00269 
00270 
00271     }
00272     //-----------------------------------------------------------------------
00273     Entity* SceneManager::createEntity(const String& entityName, PrefabType ptype)
00274     {
00275         switch (ptype)
00276         {
00277         case PT_PLANE:
00278             return createEntity(entityName, "Prefab_Plane");
00279 
00280             break;
00281         }
00282 
00283         return 0;
00284     }
00285 
00286     //-----------------------------------------------------------------------
00287     Entity* SceneManager::createEntity(
00288         const String& entityName,
00289         const String& meshName )
00290     {
00291         // Check name not used
00292         EntityList::iterator it = mEntities.find( entityName );
00293         if( it != mEntities.end() )
00294         {
00295             Except(
00296                 Exception::ERR_DUPLICATE_ITEM,
00297                 "An entity with the name " + entityName + " already exists",
00298                 "SceneManager::createEntity" );
00299         }
00300 
00301         // Get mesh (load if required)
00302         Mesh* pMesh = MeshManager::getSingleton().load( meshName );
00303 
00304         // Create entity
00305         Entity* e = new Entity( entityName, pMesh, this );
00306 
00307         // Add to internal list
00308         mEntities[entityName] = e; //.insert(EntityList::value_type(entityName, e));
00309 
00310         return e;
00311     }
00312 
00313     //-----------------------------------------------------------------------
00314     Entity* SceneManager::getEntity(const String& name)
00315     {
00316         EntityList::iterator i = mEntities.find(name);
00317         if (i == mEntities.end())
00318         {
00319             return 0;
00320         }
00321         else
00322         {
00323             return i->second;
00324         }
00325     }
00326 
00327     //-----------------------------------------------------------------------
00328     void SceneManager::removeEntity(Entity *cam)
00329     {
00330         // Find in list
00331         EntityList::iterator i = mEntities.begin();
00332         for (; i != mEntities.end(); ++i)
00333         {
00334             if (i->second == cam)
00335             {
00336                 mEntities.erase(i);
00337                 delete cam;
00338                 break;
00339             }
00340         }
00341 
00342     }
00343 
00344     //-----------------------------------------------------------------------
00345     void SceneManager::removeEntity(const String& name)
00346     {
00347         // Find in list
00348         EntityList::iterator i = mEntities.find(name);
00349         if (i != mEntities.end())
00350         {
00351             delete i->second;
00352             mEntities.erase(i);
00353         }
00354 
00355     }
00356 
00357     //-----------------------------------------------------------------------
00358     void SceneManager::removeAllEntities(void)
00359     {
00360 
00361         EntityList::iterator i = mEntities.begin();
00362         for (; i != mEntities.end(); ++i)
00363         {
00364             delete i->second;
00365         }
00366         mEntities.clear();
00367     }
00368     //-----------------------------------------------------------------------
00369     void SceneManager::clearScene(void)
00370     {
00371         // Delete all SceneNodes, except root that is
00372         for (SceneNodeList::iterator i = mSceneNodes.begin();
00373             i != mSceneNodes.end(); ++i)
00374         {
00375             delete i->second;
00376         }
00377         mSceneNodes.clear();
00378 
00379         // Clear root node of all children
00380         mSceneRoot->removeAllChildren();
00381         mSceneRoot->detachAllObjects();
00382 
00383         // Delete all entities
00384         for (EntityList::iterator ei = mEntities.begin();
00385             ei != mEntities.end(); ++ei)
00386         {
00387             delete ei->second;
00388         }
00389         mEntities.clear();
00390 
00391         // Delete all Cameras
00392         for (CameraList::iterator ci = mCameras.begin();
00393             ci != mCameras.end(); ++ci)
00394         {
00395             delete ci->second;
00396         }
00397         mCameras.clear();
00398 
00399         // Delete all BillboardSets
00400         for (BillboardSetList::iterator bi = mBillboardSets.begin();
00401             bi != mBillboardSets.end(); ++bi)
00402         {
00403             delete bi->second;
00404         }
00405         mBillboardSets.clear();
00406         // Clear lights
00407         removeAllLights();
00408 
00409         // Clear animations
00410         destroyAllAnimations();
00411 
00412         // Remove sky nodes since they've been deleted
00413         mSkyBoxNode = mSkyPlaneNode = mSkyDomeNode = 0;
00414         mSkyBoxEnabled = mSkyPlaneEnabled = mSkyDomeEnabled = false; 
00415 
00416     }
00417 
00418     //-----------------------------------------------------------------------
00419     Material* SceneManager::createMaterial(const String& name)
00420     {
00421         // Create using MaterialManager
00422         Material* m = (Material*)MaterialManager::getSingleton().create(name);
00423 
00424 
00425         return m;
00426     }
00427     //-----------------------------------------------------------------------
00428     Material* SceneManager::getDefaultMaterialSettings(void)
00429     {
00430         return Material::mDefaultSettings;
00431     }
00432     //-----------------------------------------------------------------------
00433     Material* SceneManager::getMaterial(const String& name)
00434     {
00435         return (Material*)MaterialManager::getSingleton().getByName(name);
00436     }
00437 
00438     //-----------------------------------------------------------------------
00439     Material* SceneManager::getMaterial(int handle)
00440     {
00441         return static_cast<Material*>(
00442             MaterialManager::getSingleton().getByHandle(handle));
00443     }
00444     //-----------------------------------------------------------------------
00445     SceneNode* SceneManager::createSceneNode(void)
00446     {
00447         SceneNode* sn = new SceneNode(this);
00448         mSceneNodes[sn->getName()] = sn;
00449         return sn;
00450     }
00451     //-----------------------------------------------------------------------
00452     SceneNode* SceneManager::createSceneNode(const String& name)
00453     {
00454         SceneNode* sn = new SceneNode(this, name);
00455         mSceneNodes[sn->getName()] = sn;
00456         return sn;
00457     }
00458     //-----------------------------------------------------------------------
00459     void SceneManager::destroySceneNode(const String& name)
00460     {
00461         SceneNodeList::iterator i = mSceneNodes.find(name);
00462 
00463         if (i == mSceneNodes.end())
00464         {
00465             Except(Exception::ERR_ITEM_NOT_FOUND, "SceneNode '" + name + "' not found.",
00466                 "SceneManager::destroySceneNode");
00467         }
00468 
00469         delete i->second;
00470         mSceneNodes.erase(i);
00471     }
00472     //-----------------------------------------------------------------------
00473     SceneNode* SceneManager::getRootSceneNode(void) const
00474     {
00475         return mSceneRoot;
00476     }
00477     //-----------------------------------------------------------------------
00478     SceneNode* SceneManager::getSceneNode(const String& name) const
00479     {
00480         SceneNodeList::const_iterator i = mSceneNodes.find(name);
00481 
00482         if (i == mSceneNodes.end())
00483         {
00484             Except(Exception::ERR_ITEM_NOT_FOUND, "SceneNode '" + name + "' not found.",
00485                 "SceneManager::getSceneNode");
00486         }
00487 
00488         return i->second;
00489         
00490     }
00491     //-----------------------------------------------------------------------
00492     void SceneManager::setPass(Pass* pass)
00493     {
00494         static bool lastUsedVertexProgram = false;
00495         static bool lastUsedFragmentProgram = false;
00496 
00497         // TEST
00498         /*
00499         LogManager::getSingleton().logMessage("BEGIN PASS " + StringConverter::toString(pass->getIndex()) + 
00500             " of " + pass->getParent()->getParent()->getName());
00501         */
00502 
00503         if (pass->hasVertexProgram())
00504         {
00505             mDestRenderSystem->bindGpuProgram(pass->getVertexProgram()->_getBindingDelegate());
00506             // bind parameters later since they can be per-object
00507             lastUsedVertexProgram = true;
00508         }
00509         else
00510         {
00511             // Unbind program?
00512             if (lastUsedVertexProgram)
00513             {
00514                 mDestRenderSystem->unbindGpuProgram(GPT_VERTEX_PROGRAM);
00515                 lastUsedVertexProgram = false;
00516             }
00517             // Set fixed-function vertex parameters
00518 
00519             // Set surface reflectance properties, only valid if lighting is enabled
00520             if (pass->getLightingEnabled())
00521             {
00522                 mDestRenderSystem->_setSurfaceParams( 
00523                     pass->getAmbient(), 
00524                     pass->getDiffuse(), 
00525                     pass->getSpecular(), 
00526                     pass->getSelfIllumination(), 
00527                     pass->getShininess() );
00528             }
00529 
00530             // Dynamic lighting enabled?
00531             mDestRenderSystem->setLightingEnabled(pass->getLightingEnabled());
00532         }
00533 
00534         // Using a fragment program?
00535         if (pass->hasFragmentProgram())
00536         {
00537             mDestRenderSystem->bindGpuProgram(
00538                 pass->getFragmentProgram()->_getBindingDelegate());
00539             // bind parameters later since they can be per-object
00540             lastUsedFragmentProgram = true;
00541         }
00542         else
00543         {
00544             // Unbind program?
00545             if (lastUsedFragmentProgram)
00546             {
00547                 mDestRenderSystem->unbindGpuProgram(GPT_FRAGMENT_PROGRAM);
00548                 lastUsedFragmentProgram = false;
00549             }
00550 
00551             // Set fixed-function fragment settings
00552 
00553             // Fog (assumes we want pixel fog which is the usual)
00554             // New fog params can either be from scene or from material
00555             FogMode newFogMode;
00556             ColourValue newFogColour;
00557             Real newFogStart, newFogEnd, newFogDensity;
00558             if (pass->getFogOverride())
00559             {
00560                 // New fog params from material
00561                 newFogMode = pass->getFogMode();
00562                 newFogColour = pass->getFogColour();
00563                 newFogStart = pass->getFogStart();
00564                 newFogEnd = pass->getFogEnd();
00565                 newFogDensity = pass->getFogDensity();
00566             }
00567             else
00568             {
00569                 // New fog params from scene
00570                 newFogMode = mFogMode;
00571                 newFogColour = mFogColour;
00572                 newFogStart = mFogStart;
00573                 newFogEnd = mFogEnd;
00574                 newFogDensity = mFogDensity;
00575             }
00576             mDestRenderSystem->_setFog(
00577                 newFogMode, newFogColour, newFogDensity, newFogStart, newFogEnd);
00578 
00579         }
00580 
00581         // The rest of the settings are the same no matter whether we use programs or not
00582 
00583         // Set scene blending
00584         mDestRenderSystem->_setSceneBlending(
00585             pass->getSourceBlendFactor(), pass->getDestBlendFactor());
00586 
00587 
00588         // Texture unit settings
00589         
00590         Pass::TextureUnitStateIterator texIter =  pass->getTextureUnitStateIterator();
00591         size_t unit = 0;
00592         while(texIter.hasMoreElements())
00593         {
00594             TextureUnitState* pTex = texIter.getNext();
00595             mDestRenderSystem->_setTextureUnitSettings(unit, *pTex);
00596             ++unit;
00597         }
00598         // Disable remaining texture units
00599         mDestRenderSystem->_disableTextureUnitsFrom(pass->getNumTextureUnitStates());
00600 
00601         // Set up non-texture related material settings
00602         // Depth buffer settings
00603         mDestRenderSystem->_setDepthBufferFunction(pass->getDepthFunction());
00604         mDestRenderSystem->_setDepthBufferCheckEnabled(pass->getDepthCheckEnabled());
00605         mDestRenderSystem->_setDepthBufferWriteEnabled(pass->getDepthWriteEnabled());
00606         mDestRenderSystem->_setDepthBias(pass->getDepthBias());
00607         // Set colour write mode
00608         // Right now we only use on/off, not per-channel
00609         bool colWrite = pass->getColourWriteEnabled();
00610         mDestRenderSystem->_setColourBufferWriteEnabled(colWrite, colWrite, colWrite, colWrite);
00611         // Culling mode
00612         mDestRenderSystem->_setCullingMode(pass->getCullingMode());
00613         // Shading
00614         mDestRenderSystem->setShadingType(pass->getShadingMode());
00615 
00616     }
00617     //-----------------------------------------------------------------------
00618     void SceneManager::_renderScene(Camera* camera, Viewport* vp, bool includeOverlays)
00619     {
00620         mCameraInProgress = camera;
00621         mCamChanged = true;
00622 
00623 
00624         // Set the viewport
00625         setViewport(vp);
00626 
00627         // Tell params about camera
00628         mAutoParamDataSource.setCurrentCamera(camera);
00629 
00630         // Tell params about current ambient light
00631         mAutoParamDataSource.setAmbientLightColour(mAmbientLight);
00632 
00633 
00634         // Update the scene
00635         _applySceneAnimations();
00636         _updateSceneGraph(camera);
00637 
00638         // Auto-track camera if required
00639         camera->_autoTrack();
00640 
00641         if (camera->isReflected())
00642         {
00643             mDestRenderSystem->setInvertVertexWinding(true);
00644         }
00645         else
00646         {
00647             mDestRenderSystem->setInvertVertexWinding(false);
00648         }
00649 
00650         // Clear the render queue
00651         mRenderQueue.clear();
00652 
00653         // Parse the scene and tag visibles
00654         _findVisibleObjects(camera);
00655         // Add overlays, if viewport deems it
00656         if (vp->getOverlaysEnabled())
00657         {
00658             OverlayManager::getSingleton()._queueOverlaysForRendering(camera, &mRenderQueue, vp);
00659         }
00660         // Queue skies
00661         _queueSkiesForRendering(camera);
00662 
00663 
00664 
00665         // Don't do view / proj here anymore
00666         // Checked per renderable now, although only changed when required
00667         //mDestRenderSystem->_setViewMatrix(camera->getViewMatrix());
00668         //mDestRenderSystem->_setProjectionMatrix(camera->getProjectionMatrix());
00669 
00670         mDestRenderSystem->_beginGeometryCount();
00671         // Begin the frame
00672         mDestRenderSystem->_beginFrame();
00673 
00674         // Set rasterisation mode
00675         mDestRenderSystem->_setRasterisationMode(camera->getDetailLevel());
00676 
00677         // Update controllers (after begineFrame since some are frameTime dependent)
00678         ControllerManager::getSingleton().updateAllControllers();
00679 
00680         // Render scene content (only entities in this SceneManager, no world geometry)
00681         _renderVisibleObjects();
00682 
00683 
00684         
00685         
00686         
00687 
00688         // End frame
00689         mDestRenderSystem->_endFrame();
00690 
00691         // Notify camera or vis faces
00692         camera->_notifyRenderedFaces(mDestRenderSystem->_getFaceCount());
00693 
00694 
00695 
00696     }
00697 
00698 
00699     //-----------------------------------------------------------------------
00700     void SceneManager::_setDestinationRenderSystem(RenderSystem* sys)
00701     {
00702         mDestRenderSystem = sys;
00703     }
00704 
00705 
00706     //-----------------------------------------------------------------------
00707     void SceneManager::setWorldGeometry(const String& filename)
00708     {
00709         // This default implementation cannot handle world geometry
00710         Except(Exception::ERR_INVALIDPARAMS,
00711             "World geometry is not supported by the generic SceneManager.",
00712             "SceneManager::setWorldGeometry");
00713     }
00714 
00715     //-----------------------------------------------------------------------
00716     bool SceneManager::materialLess::operator() (const Material* x, const Material* y) const
00717     {
00718         // If x transparent and y not, x > y (since x has to overlap y)
00719         if (x->isTransparent() && !y->isTransparent())
00720         {
00721             return false;
00722         }
00723         // If y is transparent and x not, x < y
00724         else if (!x->isTransparent() && y->isTransparent())
00725         {
00726             return true;
00727         }
00728         else
00729         {
00730             // Otherwise don't care (both transparent or both solid)
00731             // Just arbitrarily use pointer
00732             return x < y;
00733         }
00734 
00735     }
00736 
00737     //-----------------------------------------------------------------------
00738     void SceneManager::setSkyPlane(
00739         bool enable,
00740         const Plane& plane,
00741         const String& materialName,
00742         Real gscale,
00743         Real tiling,
00744         bool drawFirst,
00745         Real bow)
00746     {
00747         mSkyPlaneEnabled = enable;
00748         if (enable)
00749         {
00750             String meshName = "SkyPlane";
00751             mSkyPlane = plane;
00752 
00753             Material* m = getMaterial(materialName);
00754             if (!m)
00755             {
00756                 Except(Exception::ERR_INVALIDPARAMS, 
00757                     "Sky plane material '" + materialName + "' not found.",
00758                     "SceneManager::setSkyPlane");
00759             }
00760             // Make sure the material doesn't update the depth buffer
00761             m->setDepthWriteEnabled(false);
00762             // Ensure loaded
00763             m->load();
00764 
00765             mSkyPlaneDrawFirst = drawFirst;
00766 
00767             // Set up the plane
00768             Mesh* planeMesh = (Mesh*)MeshManager::getSingleton().getByName(meshName);
00769             if (planeMesh)
00770             {
00771                 // Destroy the old one
00772                 MeshManager::getSingleton().unload(planeMesh);
00773                 delete planeMesh;
00774             }
00775 
00776             // Create up vector
00777             Vector3 up = plane.normal.crossProduct(Vector3::UNIT_X);
00778             if (up == Vector3::ZERO)
00779                 up = plane.normal.crossProduct(-Vector3::UNIT_Z);
00780 
00781             // Create skyplane
00782             if( bow > 0 )
00783             {
00784                 // Build a curved skyplane
00785                 planeMesh = MeshManager::getSingleton().createCurvedPlane(meshName, plane, gscale * 100, gscale * 100, gscale * bow * 100, 6, 6, false, 1, tiling, tiling, up);
00786             }
00787             else
00788             {
00789                 planeMesh = MeshManager::getSingleton().createPlane(meshName, plane, gscale * 100, gscale * 100, 1, 1, false, 1, tiling, tiling, up);
00790             }
00791 
00792             // Create entity 
00793             if (mSkyPlaneEntity)
00794             {
00795                 // destroy old one, do it by name for speed
00796                 removeEntity(meshName);
00797             }
00798             // Create, use the same name for mesh and entity
00799             mSkyPlaneEntity = createEntity(meshName, meshName);
00800             mSkyPlaneEntity->setMaterialName(materialName);
00801 
00802             // Create node and attach
00803             if (!mSkyPlaneNode)
00804             {
00805                 mSkyPlaneNode = createSceneNode(meshName + "Node");
00806             }
00807             else
00808             {
00809                 mSkyPlaneNode->detachAllObjects();
00810             }
00811             mSkyPlaneNode->attachObject(mSkyPlaneEntity);
00812 
00813         }
00814     }
00815     //-----------------------------------------------------------------------
00816     void SceneManager::setSkyBox(
00817         bool enable,
00818         const String& materialName,
00819         Real distance,
00820         bool drawFirst,
00821         const Quaternion& orientation )
00822     {
00823         mSkyBoxEnabled = enable;
00824         if (enable)
00825         {
00826             Material* m = getMaterial(materialName);
00827             if (!m)
00828             {
00829                 Except(Exception::ERR_INVALIDPARAMS, 
00830                     "Sky box material '" + materialName + " not found.",
00831                     "SceneManager::setSkyBox");
00832             }
00833             // Make sure the material doesn't update the depth buffer
00834             m->setDepthWriteEnabled(false);
00835             // Ensure loaded
00836             m->load();
00837             // Also clamp texture, don't wrap (otherwise edges can get filtered)
00838             m->getBestTechnique()->getPass(0)->getTextureUnitState(0)->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
00839 
00840 
00841             mSkyBoxDrawFirst = drawFirst;
00842 
00843             // Create node 
00844             if (!mSkyBoxNode)
00845             {
00846                 mSkyBoxNode = createSceneNode("SkyBoxNode");
00847             }
00848             else
00849             {
00850                 mSkyBoxNode->detachAllObjects();
00851             }
00852 
00853             MaterialManager& matMgr = MaterialManager::getSingleton();
00854             // Set up the box (6 planes)
00855             for (int i = 0; i < 6; ++i)
00856             {
00857                 Mesh* planeMesh = createSkyboxPlane((BoxPlane)i, distance, orientation);
00858                 String entName = "SkyBoxPlane" + StringConverter::toString(i);
00859 
00860                 // Create entity 
00861                 if (mSkyBoxEntity[i])
00862                 {
00863                     // destroy old one, do it by name for speed
00864                     removeEntity(entName);
00865                 }
00866                 mSkyBoxEntity[i] = createEntity(entName, planeMesh->getName());
00867                 // Have to create 6 materials, one for each frame
00868                 // Used to use combined material but now we're using queue we can't split to change frame
00869                 // This doesn't use much memory because textures aren't duplicated
00870                 Material* boxMat = (Material*)matMgr.getByName(entName);
00871                 if (!boxMat)
00872                 {
00873                     // Create new by clone
00874                     boxMat = m->clone(entName);
00875                     boxMat->load();
00876                 }
00877                 else
00878                 {
00879                     // Copy over existing
00880                     m->copyDetailsTo(boxMat);
00881                     boxMat->load();
00882                 }
00883                 // Set active frame
00884                 boxMat->getBestTechnique()->getPass(0)->getTextureUnitState(0)
00885                     ->setCurrentFrame(i);
00886 
00887                 mSkyBoxEntity[i]->setMaterialName(boxMat->getName());
00888 
00889                 // Attach to node
00890                 mSkyBoxNode->attachObject(mSkyBoxEntity[i]);
00891             } // for each plane
00892 
00893         }
00894 
00895     }
00896     //-----------------------------------------------------------------------
00897     void SceneManager::setSkyDome(
00898         bool enable,
00899         const String& materialName,
00900         Real curvature,
00901         Real tiling,
00902         Real distance,
00903         bool drawFirst,
00904         const Quaternion& orientation )
00905     {
00906         mSkyDomeEnabled = enable;
00907         if (enable)
00908         {
00909             Material* m = getMaterial(materialName);
00910             if (!m)
00911             {
00912                 Except(Exception::ERR_INVALIDPARAMS, 
00913                     "Sky dome material '" + materialName + " not found.",
00914                     "SceneManager::setSkyDome");
00915             }
00916             // Make sure the material doesn't update the depth buffer
00917             m->setDepthWriteEnabled(false);
00918             // Ensure loaded
00919             m->load();
00920 
00921             mSkyDomeDrawFirst = drawFirst;
00922 
00923             // Create node 
00924             if (!mSkyDomeNode)
00925             {
00926                 mSkyDomeNode = createSceneNode("SkyDomeNode");
00927             }
00928             else
00929             {
00930                 mSkyDomeNode->detachAllObjects();
00931             }
00932 
00933             // Set up the dome (5 planes)
00934             for (int i = 0; i < 5; ++i)
00935             {
00936                 Mesh* planeMesh = createSkydomePlane((BoxPlane)i, curvature, tiling, distance, orientation);
00937 
00938                 String entName = "SkyDomePlane" + StringConverter::toString(i);
00939 
00940                 // Create entity 
00941                 if (mSkyDomeEntity[i])
00942                 {
00943                     // destroy old one, do it by name for speed
00944                     removeEntity(entName);
00945                 }
00946                 mSkyDomeEntity[i] = createEntity(entName, planeMesh->getName());
00947                 mSkyDomeEntity[i]->setMaterialName(m->getName());
00948 
00949                 // Attach to node
00950                 mSkyDomeNode->attachObject(mSkyDomeEntity[i]);
00951             } // for each plane
00952 
00953         }
00954     }
00955     //-----------------------------------------------------------------------
00956     Mesh* SceneManager::createSkyboxPlane(
00957         BoxPlane bp,
00958         Real distance,
00959         const Quaternion& orientation )
00960     {
00961         Plane plane;
00962         String meshName;
00963         Vector3 up;
00964 
00965         meshName = "SkyBoxPlane_";
00966         // Set up plane equation
00967         plane.d = distance;
00968         switch(bp)
00969         {
00970         case BP_FRONT:
00971             plane.normal = Vector3::UNIT_Z;
00972             up = Vector3::UNIT_Y;
00973             meshName += "Front";
00974             break;
00975         case BP_BACK:
00976             plane.normal = -Vector3::UNIT_Z;
00977             up = Vector3::UNIT_Y;
00978             meshName += "Back";
00979             break;
00980         case BP_LEFT:
00981             plane.normal = Vector3::UNIT_X;
00982             up = Vector3::UNIT_Y;
00983             meshName += "Left";
00984             break;
00985         case BP_RIGHT:
00986             plane.normal = -Vector3::UNIT_X;
00987             up = Vector3::UNIT_Y;
00988             meshName += "Right";
00989             break;
00990         case BP_UP:
00991             plane.normal = -Vector3::UNIT_Y;
00992             up = Vector3::UNIT_Z;
00993             meshName += "Up";
00994             break;
00995         case BP_DOWN:
00996             plane.normal = Vector3::UNIT_Y;
00997             up = -Vector3::UNIT_Z;
00998             meshName += "Down";
00999             break;
01000         }
01001         // Modify by orientation
01002         plane.normal = orientation * plane.normal;
01003         up = orientation * up;
01004 
01005 
01006         // Check to see if existing plane
01007         MeshManager& mm = MeshManager::getSingleton();
01008         Mesh* planeMesh = (Mesh*)mm.getByName(meshName);
01009         if(planeMesh)
01010         {
01011             // destroy existing
01012             mm.unload(planeMesh);
01013             delete planeMesh;
01014         }
01015         // Create new
01016         Real planeSize = distance * 2;
01017         const int BOX_SEGMENTS = 1;
01018         planeMesh = mm.createPlane(meshName, plane, planeSize, planeSize, BOX_SEGMENTS, BOX_SEGMENTS, false, 1, 1, 1, up);
01019 
01020         //planeMesh->_dumpContents(meshName);
01021 
01022         return planeMesh;
01023 
01024     }
01025     //-----------------------------------------------------------------------
01026     Mesh* SceneManager::createSkydomePlane(
01027         BoxPlane bp,
01028         Real curvature,
01029         Real tiling,
01030         Real distance,
01031         const Quaternion& orientation )
01032     {
01033 
01034         Plane plane;
01035         String meshName;
01036         Vector3 up;
01037 
01038         meshName = "SkyDomePlane_";
01039         // Set up plane equation
01040         plane.d = distance;
01041         switch(bp)
01042         {
01043         case BP_FRONT:
01044             plane.normal = Vector3::UNIT_Z;
01045             up = Vector3::UNIT_Y;
01046             meshName += "Front";
01047             break;
01048         case BP_BACK:
01049             plane.normal = -Vector3::UNIT_Z;
01050             up = Vector3::UNIT_Y;
01051             meshName += "Back";
01052             break;
01053         case BP_LEFT:
01054             plane.normal = Vector3::UNIT_X;
01055             up = Vector3::UNIT_Y;
01056             meshName += "Left";
01057             break;
01058         case BP_RIGHT:
01059             plane.normal = -Vector3::UNIT_X;
01060             up = Vector3::UNIT_Y;
01061             meshName += "Right";
01062             break;
01063         case BP_UP:
01064             plane.normal = -Vector3::UNIT_Y;
01065             up = Vector3::UNIT_Z;
01066             meshName += "Up";
01067             break;
01068         case BP_DOWN:
01069             // no down
01070             return 0;
01071         }
01072         // Modify by orientation
01073         plane.normal = orientation * plane.normal;
01074         up = orientation * up;
01075 
01076         // Check to see if existing plane
01077         MeshManager& mm = MeshManager::getSingleton();
01078         Mesh* planeMesh = (Mesh*)mm.getByName(meshName);
01079         if(planeMesh)
01080         {
01081             // destroy existing
01082             mm.unload(planeMesh);
01083             delete planeMesh;
01084         }
01085         // Create new
01086         Real planeSize = distance * 2;
01087         const int BOX_SEGMENTS = 16;
01088         planeMesh = mm.createCurvedIllusionPlane(meshName, plane, planeSize, planeSize, curvature, 
01089             BOX_SEGMENTS, BOX_SEGMENTS, false, 1, tiling, tiling, up, orientation, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY, HardwareBuffer::HBU_STATIC_WRITE_ONLY, 
01090             false, false);
01091 
01092         //planeMesh->_dumpContents(meshName);
01093 
01094         return planeMesh;
01095 
01096     }
01097 
01098 
01099     //-----------------------------------------------------------------------
01100     void SceneManager::_updateSceneGraph(Camera* cam)
01101     {
01102         // Cascade down the graph updating transforms & world bounds
01103         // In this implementation, just update from the root
01104         // Smarter SceneManager subclasses may choose to update only
01105         //   certain scene graph branches
01106         mSceneRoot->_update(true, false);
01107 
01108 
01109     }
01110     //-----------------------------------------------------------------------
01111     void SceneManager::_findVisibleObjects(Camera* cam)
01112     {
01113         // Tell nodes to find, cascade down all nodes
01114         mSceneRoot->_findVisibleObjects(cam, &mRenderQueue, true, mDisplayNodes);
01115 
01116     }
01117     //-----------------------------------------------------------------------
01118     void SceneManager::_renderVisibleObjects(void)
01119     {
01120         int render_count = 0;
01121         // Render each separate queue
01122         RenderQueue::QueueGroupIterator queueIt = mRenderQueue._getQueueGroupIterator();
01123 
01124         // NB only queues which have been created are rendered, no time is wasted
01125         //   parsing through non-existent queues (even though there are 10 available)
01126 
01127         while (queueIt.hasMoreElements())
01128         {
01129             // Get queue group id
01130             RenderQueueGroupID qId = queueIt.peekNextKey();
01131             RenderQueueGroup* pGroup = queueIt.getNext();
01132 
01133 
01134             bool repeatQueue = false;
01135             do // for repeating queues
01136             {
01137                 // Fire queue started event
01138                 if (fireRenderQueueStarted(qId))
01139                 {
01140                     // Someone requested we skip this queue
01141                     continue;
01142                 }
01143 
01144                 // Iterate through priorities
01145                 RenderQueueGroup::PriorityMapIterator groupIt = pGroup->getIterator();
01146 
01147                 while (groupIt.hasMoreElements())
01148                 {
01149                     render_count++;
01150                     RenderPriorityGroup* pPriorityGrp = groupIt.getNext();
01151 
01152                     // Sort the queue first
01153                     pPriorityGrp->sort(mCameraInProgress);
01154 
01155 
01156 
01157                     // ----- SOLIDS LOOP -----
01158                     RenderPriorityGroup::SolidRenderablePassMap::iterator ipass, ipassend;
01159                     ipassend = pPriorityGrp->mSolidPasses.end();
01160                     for (ipass = pPriorityGrp->mSolidPasses.begin(); ipass != ipassend; ++ipass)
01161                     {
01162                         // Fast bypass if this group is now empty
01163                         if (ipass->second->empty()) continue;
01164                         // For solids, we try to do each pass in turn
01165                         setPass(ipass->first);
01166                         RenderPriorityGroup::RenderableList* rendList = ipass->second;
01167                         RenderPriorityGroup::RenderableList::const_iterator irend, irendend;
01168                         irendend = rendList->end();
01169                         for (irend = rendList->begin(); irend != irendend; ++irend)
01170                         {
01171                             // Render a single object, this will set up auto params if required
01172                             renderSingleObject(*irend, ipass->first);
01173                         }
01174                     } 
01175 
01176                     // ----- TRANSPARENT LOOP -----
01177                     // This time we render by Z, not by pass
01178                     // The mTransparentObjects set needs to be ordered first
01179                     // Render each non-transparent entity in turn, grouped by material
01180                     RenderPriorityGroup::TransparentRenderablePassList::iterator itrans, itransend;
01181 
01182                     itransend = pPriorityGrp->mTransparentPasses.end();
01183                     for (itrans = pPriorityGrp->mTransparentPasses.begin(); 
01184                         itrans != itransend; ++itrans)
01185                     {
01186                         // For transparents, we have to accept that we can't sort entirely by pass
01187                         setPass(itrans->pass);
01188                         renderSingleObject(itrans->renderable, itrans->pass);
01189                     }
01190                 }// for each priority
01191             
01192                 // Fire queue ended event
01193                 if (fireRenderQueueEnded(qId))
01194                 {
01195                     // Someone requested we repeat this queue
01196                     repeatQueue = true;
01197                 }
01198                 else
01199                 {
01200                     repeatQueue = false;
01201                 }
01202             } while (repeatQueue);
01203 
01204         } // for each queue group
01205     }
01206     //-----------------------------------------------------------------------
01207     void SceneManager::renderSingleObject(Renderable* rend, Pass* pass)
01208     {
01209         static Matrix4 xform[256];
01210         unsigned short numMatrices;
01211         static bool normalisedNormals = false;
01212         static SceneDetailLevel camDetailLevel = mCameraInProgress->getDetailLevel();
01213         static SceneDetailLevel lastDetailLevel = camDetailLevel;
01214         static RenderOperation ro;
01215         static LightList localLightList;
01216 
01217         if (pass->isProgrammable())
01218         {
01219             // Tell auto params object about the renderable change
01220             mAutoParamDataSource.setCurrentRenderable(rend);
01221             pass->_updateAutoParamsNoLights(mAutoParamDataSource);
01222         }
01223         
01224         // Set world transformation
01225         rend->getWorldTransforms(xform);
01226         numMatrices = rend->getNumWorldTransforms();
01227         if (numMatrices > 1)
01228         {
01229             mDestRenderSystem->_setWorldMatrices(xform, numMatrices);
01230         }
01231         else
01232         {
01233             mDestRenderSystem->_setWorldMatrix(*xform);
01234         }
01235 
01236         // Issue view / projection changes if any
01237         useRenderableViewProjMode(rend);
01238 
01239         // Reissue any texture gen settings which are dependent on view matrix
01240         Pass::TextureUnitStateIterator texIter =  pass->getTextureUnitStateIterator();
01241         size_t unit = 0;
01242         while(texIter.hasMoreElements())
01243         {
01244             TextureUnitState* pTex = texIter.getNext();
01245             if (pTex->hasViewRelativeTextureCoordinateGeneration())
01246             {
01247                 mDestRenderSystem->_setTextureUnitSettings(unit, *pTex);
01248             }
01249             ++unit;
01250         }
01251 
01252 
01253         // Sort out normalisation
01254         bool thisNormalise = rend->getNormaliseNormals();
01255         if (thisNormalise != normalisedNormals)
01256         {
01257             mDestRenderSystem->setNormaliseNormals(thisNormalise);
01258             normalisedNormals = thisNormalise;
01259         }
01260 
01261         // Set up the solid / wireframe override
01262         SceneDetailLevel reqDetail = rend->getRenderDetail();
01263         if (reqDetail != lastDetailLevel || reqDetail != camDetailLevel)
01264         {
01265             if (reqDetail > camDetailLevel)
01266             {
01267                 // only downgrade detail; if cam says wireframe we don't go up to solid
01268                 reqDetail = camDetailLevel;
01269             }
01270             mDestRenderSystem->_setRasterisationMode(reqDetail);
01271             lastDetailLevel = reqDetail;
01272 
01273         }
01274 
01275         // Set up rendering operation
01276         rend->getRenderOperation(ro);
01277         ro.srcRenderable = rend;
01278 
01279         // Here's where we issue the rendering operation to the render system
01280         // Note that we may do this once per light, therefore it's in a loop
01281         // and the light parameters are updated once per traversal through the
01282         // loop
01283         const LightList& rendLightList = rend->getLights();
01284         bool iteratePerLight = pass->getRunOncePerLight();
01285         size_t numIterations = iteratePerLight ? rendLightList.size() : 1;
01286         const LightList* pLightListToUse;
01287         for (size_t i = 0; i < numIterations; ++i)
01288         {
01289             // Determine light list to use
01290             if (iteratePerLight)
01291             {
01292                 // Change the only element of local light list to be
01293                 // the light at index i
01294                 localLightList.clear();
01295                 // Check whether we need to filter this one out
01296                 if (pass->getRunOnlyForOneLightType() && 
01297                     pass->getOnlyLightType() != rendLightList[i]->getType())
01298                 {
01299                     // Skip
01300                     continue;
01301                 }
01302 
01303                 localLightList.push_back(rendLightList[i]);
01304                 pLightListToUse = &localLightList;
01305             }
01306             else
01307             {
01308                 // Use complete light list
01309                 pLightListToUse = &rendLightList;
01310             }
01311 
01312             // Do we need to update GPU program parameters?
01313             if (pass->isProgrammable())
01314             {
01315                 // Update any automatic gpu params for lights
01316                 // Other bits of information will have to be looked up
01317                 mAutoParamDataSource.setCurrentLightList(pLightListToUse);
01318                 pass->_updateAutoParamsLightsOnly(mAutoParamDataSource);
01319                 // NOTE: We MUST bind parameters AFTER updating the autos
01320                 // TEST
01321                 /*
01322                 LogManager::getSingleton().logMessage("BIND PARAMS FOR " + 
01323                     pass->getParent()->getParent()->getName());
01324                 */
01325                 if (pass->hasVertexProgram())
01326                 {
01327                     mDestRenderSystem->bindGpuProgramParameters(GPT_VERTEX_PROGRAM, 
01328                         pass->getVertexProgramParameters());
01329                 }
01330                 if (pass->hasFragmentProgram())
01331                 {
01332                     mDestRenderSystem->bindGpuProgramParameters(GPT_FRAGMENT_PROGRAM, 
01333                         pass->getFragmentProgramParameters());
01334                 }
01335             }
01336             // Do we need to update light states? 
01337             // Only do this if fixed-function vertex lighting applies
01338             if (pass->getLightingEnabled() && !pass->hasVertexProgram())
01339             {
01340                 mDestRenderSystem->_useLights(*pLightListToUse, pass->getMaxSimultaneousLights());
01341             }
01342             // issue the render op      
01343             mDestRenderSystem->_render(ro);
01344         } // possibly iterate per light
01345     }
01346     //-----------------------------------------------------------------------
01347     void SceneManager::setAmbientLight(const ColourValue& colour)
01348     {
01349         mAmbientLight = colour;
01350         mDestRenderSystem->setAmbientLight(colour.r, colour.g, colour.b);
01351     }
01352     //-----------------------------------------------------------------------
01353     const ColourValue& SceneManager::getAmbientLight(void) const
01354     {
01355         return mAmbientLight;
01356     }
01357     //-----------------------------------------------------------------------
01358     ViewPoint SceneManager::getSuggestedViewpoint(bool random)
01359     {
01360         // By default return the origin
01361         ViewPoint vp;
01362         vp.position = Vector3::ZERO;
01363         vp.orientation = Quaternion::IDENTITY;
01364         return vp;
01365     }
01366     //-----------------------------------------------------------------------
01367     void SceneManager::setFog(FogMode mode, const ColourValue& colour, Real density, Real start, Real end)
01368     {
01369         mFogMode = mode;
01370         mFogColour = colour;
01371         mFogStart = start;
01372         mFogEnd = end;
01373         mFogDensity = density;
01374     }
01375     //-----------------------------------------------------------------------
01376     FogMode SceneManager::getFogMode(void) const
01377     {
01378         return mFogMode;
01379     }
01380     //-----------------------------------------------------------------------
01381     const ColourValue& SceneManager::getFogColour(void) const
01382     {
01383         return mFogColour;
01384     }
01385     //-----------------------------------------------------------------------
01386     Real SceneManager::getFogStart(void) const
01387     {
01388         return mFogStart;
01389     }
01390     //-----------------------------------------------------------------------
01391     Real SceneManager::getFogEnd(void) const
01392     {
01393         return mFogEnd;
01394     }
01395     //-----------------------------------------------------------------------
01396     Real SceneManager::getFogDensity(void) const
01397     {
01398         return mFogDensity;
01399     }
01400     //-----------------------------------------------------------------------
01401     BillboardSet* SceneManager::createBillboardSet(const String& name, unsigned int poolSize)
01402     {
01403         BillboardSet* set = new BillboardSet( name, poolSize );
01404         mBillboardSets[name] = set;//.insert(BillboardSetList::value_type(name, set));
01405 
01406         return set;
01407     }
01408     //-----------------------------------------------------------------------
01409     BillboardSet* SceneManager::getBillboardSet(const String& name)
01410     {
01411         BillboardSetList::iterator i = mBillboardSets.find(name);
01412         if (i == mBillboardSets.end())
01413         {
01414             return 0;
01415         }
01416         else
01417         {
01418             return i->second;
01419         }
01420     }
01421     //-----------------------------------------------------------------------
01422     void SceneManager::removeBillboardSet(BillboardSet* set)
01423     {
01424         // Find in list
01425         BillboardSetList::iterator i = mBillboardSets.begin();
01426         for (; i != mBillboardSets.end(); ++i)
01427         {
01428             if (i->second == set)
01429             {
01430                 mBillboardSets.erase(i);
01431                 delete set;
01432                 break;
01433             }
01434         }
01435 
01436     }
01437     //-----------------------------------------------------------------------
01438     void SceneManager::removeBillboardSet(const String& name)
01439     {
01440         // Find in list
01441         BillboardSetList::iterator i = mBillboardSets.find(name);
01442         if (i != mBillboardSets.end())
01443         {
01444             delete i->second;
01445             mBillboardSets.erase(i);
01446         }
01447     }
01448     //-----------------------------------------------------------------------
01449     void SceneManager::setDisplaySceneNodes(bool display)
01450     {
01451         mDisplayNodes = display;
01452     }
01453     //-----------------------------------------------------------------------
01454     Animation* SceneManager::createAnimation(const String& name, Real length)
01455     {
01456         Animation* pAnim = new Animation(name, length);
01457         mAnimationsList[name] = pAnim;
01458         return pAnim;
01459     }
01460     //-----------------------------------------------------------------------
01461     Animation* SceneManager::getAnimation(const String& name) const
01462     {
01463         AnimationList::const_iterator i = mAnimationsList.find(name);
01464         if (i == mAnimationsList.end())
01465         {
01466             Except(Exception::ERR_ITEM_NOT_FOUND, 
01467                 "Cannot find animation with name " + name, 
01468                 "SceneManager::getAnimation");
01469         }
01470         return i->second;
01471     }
01472     //-----------------------------------------------------------------------
01473     void SceneManager::destroyAnimation(const String& name)
01474     {
01475         AnimationList::iterator i = mAnimationsList.find(name);
01476         if (i == mAnimationsList.end())
01477         {
01478             Except(Exception::ERR_ITEM_NOT_FOUND, 
01479                 "Cannot find animation with name " + name, 
01480                 "SceneManager::getAnimation");
01481         }
01482 
01483         // Free memory
01484         delete i->second;
01485 
01486         mAnimationsList.erase(i);
01487 
01488     }
01489     //-----------------------------------------------------------------------
01490     void SceneManager::destroyAllAnimations(void)
01491     {
01492         AnimationList::iterator i;
01493         for (i = mAnimationsList.begin(); i != mAnimationsList.end(); ++i)
01494         {
01495             // destroy
01496             delete i->second;
01497         }
01498         mAnimationsList.clear();
01499     }
01500     //-----------------------------------------------------------------------
01501     AnimationState* SceneManager::createAnimationState(const String& animName)
01502     {
01503         if (mAnimationStates.find(animName) != mAnimationStates.end())
01504         {
01505             Except(Exception::ERR_DUPLICATE_ITEM, 
01506                 "Cannot create, AnimationState already exists: "+animName, 
01507                 "SceneManager::createAnimationState");
01508         }
01509 
01510         // Get animation, this will throw an exception if not found
01511         Animation* anim = getAnimation(animName);
01512 
01513         // Create new state
01514         AnimationState newState(animName, 0, anim->getLength());
01515 
01516         // Record it
01517         std::pair<AnimationStateSet::iterator, bool> retPair = 
01518             mAnimationStates.insert(AnimationStateSet::value_type(animName, newState));
01519 
01520         // Check boolean return
01521         if (retPair.second)
01522         {
01523             // insert was OK
01524             // Get pointer from iterator in pair
01525             return &(retPair.first->second);
01526         }
01527         else
01528         {
01529             // Problem
01530             // Not because of duplicate item, that's checked for above
01531             Except(Exception::ERR_INTERNAL_ERROR, "Unexpected error creating new animation state.",
01532                 "SceneManager::createAnimationState");
01533         }
01534 
01535 
01536     }
01537     //-----------------------------------------------------------------------
01538     AnimationState* SceneManager::getAnimationState(const String& animName) 
01539     {
01540         AnimationStateSet::iterator i = mAnimationStates.find(animName);
01541 
01542         if (i == mAnimationStates.end())
01543         {
01544             Except(Exception::ERR_ITEM_NOT_FOUND, 
01545                 "Cannot locate animation state for animation " + animName,
01546                 "SceneManager::getAnimationState");
01547         }
01548 
01549         return &(i->second);
01550 
01551     }
01552     //-----------------------------------------------------------------------
01553     void SceneManager::destroyAnimationState(const String& name)
01554     {
01555         AnimationStateSet::iterator i = mAnimationStates.find(name);
01556 
01557         if (i == mAnimationStates.end())
01558         {
01559             Except(Exception::ERR_ITEM_NOT_FOUND, 
01560                 "Cannot locate animation state for animation " + name,
01561                 "SceneManager::destroyAnimationState");
01562         }
01563 
01564         mAnimationStates.erase(i);
01565 
01566 
01567     }
01568     //-----------------------------------------------------------------------
01569     void SceneManager::destroyAllAnimationStates(void)
01570     {
01571         mAnimationStates.clear();
01572     }
01573     //-----------------------------------------------------------------------
01574     void SceneManager::_applySceneAnimations(void)
01575     {
01576         AnimationStateSet::const_iterator i, iend;
01577 
01578         i = mAnimationStates.begin();
01579         iend = mAnimationStates.end();
01580     
01581         for (;i != iend; ++i)
01582         {
01583             if (i->second.getEnabled())
01584             {
01585                 Animation* anim = getAnimation(i->second.getAnimationName());
01586 
01587                 // Reset any nodes involved
01588                 // NB this excludes blended animations
01589                 const Animation::TrackList& trackList = anim->_getTrackList();
01590                 Animation::TrackList::const_iterator ti, tend;
01591                 ti = trackList.begin();
01592                 tend = trackList.end();
01593                 for (;ti != tend; ++ti)
01594                 {
01595                     Node* nd = ti->second->getAssociatedNode();
01596                     nd->resetToInitialState();
01597                 }
01598 
01599 
01600                 // Apply the animation
01601                 anim->apply(i->second.getTimePosition(), i->second.getWeight());
01602             }
01603         }
01604 
01605 
01606     }
01607     //---------------------------------------------------------------------
01608     void SceneManager::manualRender(RenderOperation* rend, 
01609         Pass* pass, Viewport* vp, const Matrix4& worldMatrix, 
01610         const Matrix4& viewMatrix, const Matrix4& projMatrix) 
01611     {
01612         mDestRenderSystem->_setViewport(vp);
01613         mDestRenderSystem->_setWorldMatrix(worldMatrix);
01614         mDestRenderSystem->_setViewMatrix(viewMatrix);
01615         mDestRenderSystem->_setProjectionMatrix(projMatrix);
01616 
01617         mDestRenderSystem->_beginFrame();
01618 
01619         setPass(pass);
01620         mDestRenderSystem->_render(*rend);
01621 
01622         mDestRenderSystem->_endFrame();
01623         
01624     }
01625     //---------------------------------------------------------------------
01626     Overlay* SceneManager::createOverlay(const String& name, ushort zorder)
01627     {
01628         /*
01629         // check not existing
01630         OverlayList::iterator i = mOverlays.find(name);
01631         if (i != mOverlays.end())
01632         {
01633             Except(Exception::ERR_DUPLICATE_ITEM, 
01634                 "An overlay named " + name + " already exists.",
01635                 "SceneManager::createOverlay");
01636         }
01637         Overlay *newOverlay = new Overlay(name, zorder);
01638 
01639         mOverlays.insert(OverlayList::value_type(name, newOverlay));
01640         return newOverlay;
01641         */
01642 
01643         Overlay* newOverlay = (Overlay*)OverlayManager::getSingleton().create(name);
01644         newOverlay->setZOrder(zorder);
01645         return newOverlay;
01646 
01647 
01648 
01649     }
01650     //---------------------------------------------------------------------
01651     Overlay* SceneManager::getOverlay(const String& name)
01652     {
01653         /*
01654         OverlayList::iterator i = mOverlays.find(name);
01655         if (i == mOverlays.end())
01656         {
01657             Except(Exception::ERR_ITEM_NOT_FOUND, 
01658                 "An overlay named " + name + " cannot be found.",
01659                 "SceneManager::getOverlay");
01660         }
01661 
01662         return i->second;
01663         */
01664         Overlay* ret = (Overlay*)OverlayManager::getSingleton().getByName(name);
01665         if (!ret)
01666         {
01667             Except(Exception::ERR_ITEM_NOT_FOUND, 
01668                 "An overlay named " + name + " cannot be found.",
01669                 "SceneManager::getOverlay");
01670         }
01671 
01672         return ret;
01673 
01674     }
01675     //---------------------------------------------------------------------
01676     void SceneManager::destroyOverlay(const String& name)
01677     {
01678         /*
01679         OverlayList::iterator i = mOverlays.find(name);
01680         if (i == mOverlays.end())
01681         {
01682             Except(Exception::ERR_ITEM_NOT_FOUND, 
01683                 "An overlay named " + name + " cannot be found.",
01684                 "SceneManager::destroyOverlay");
01685         }
01686 
01687         delete i->second;
01688         mOverlays.erase(i);
01689         */
01690         Overlay* pOver = (Overlay*)OverlayManager::getSingleton().getByName(name);
01691         if (!pOver)
01692         {
01693             Except(Exception::ERR_ITEM_NOT_FOUND, 
01694                 "An overlay named " + name + " cannot be found.",
01695                 "SceneManager::destroyOverlay");
01696         }
01697         OverlayManager::getSingleton().unload(pOver);
01698         delete pOver;
01699 
01700     }
01701     //---------------------------------------------------------------------
01702     void SceneManager::destroyAllOverlays(void)
01703     {
01704         /*
01705         OverlayList::iterator i, iend;
01706         iend = mOverlays.end();
01707         for (i = mOverlays.begin(); i != iend; ++i)
01708         {
01709             delete i->second;
01710         }
01711         mOverlays.clear();
01712         */
01713         OverlayManager::getSingleton().unloadAndDestroyAll();
01714 
01715 
01716     }
01717     //---------------------------------------------------------------------
01718     void SceneManager::useRenderableViewProjMode(Renderable* pRend)
01719     {
01720         // Check view matrix
01721         static bool lastViewWasIdentity = false;
01722         bool useIdentityView = pRend->useIdentityView();
01723         if (useIdentityView && (mCamChanged || !lastViewWasIdentity))
01724         {
01725             // Using identity view now, change it
01726             mDestRenderSystem->_setViewMatrix(Matrix4::IDENTITY);
01727             lastViewWasIdentity = true;
01728         }
01729         else if (!useIdentityView && (mCamChanged || lastViewWasIdentity))
01730         {
01731             // Coming back to normal from identity view
01732             mDestRenderSystem->_setViewMatrix(mCameraInProgress->getViewMatrix());
01733             lastViewWasIdentity = false;
01734         }
01735         
01736         static bool lastProjWasIdentity = false;
01737         bool useIdentityProj = pRend->useIdentityProjection();
01738 
01739         if (useIdentityProj && (mCamChanged || !lastProjWasIdentity))
01740         {
01741             mDestRenderSystem->_setProjectionMatrix(Matrix4::IDENTITY);
01742 
01743             lastProjWasIdentity = true;
01744         }
01745         else if (!useIdentityProj && (mCamChanged || lastProjWasIdentity))
01746         {
01747             // Coming back from flat projection
01748             mDestRenderSystem->_setProjectionMatrix(mCameraInProgress->getProjectionMatrix());
01749             lastProjWasIdentity = false;
01750         }
01751 
01752         mCamChanged = false;
01753 
01754     }
01755 
01756     //---------------------------------------------------------------------
01757     void SceneManager::_queueSkiesForRendering(Camera* cam)
01758     {
01759         // Update nodes
01760         // Translate the box by the camera position (constant distance)
01761         if (mSkyPlaneNode)
01762         {
01763             // The plane position relative to the camera has already been set up
01764             mSkyPlaneNode->setPosition(cam->getDerivedPosition());
01765         }
01766 
01767         if (mSkyBoxNode)
01768         {
01769             mSkyBoxNode->setPosition(cam->getDerivedPosition());
01770         }
01771 
01772         if (mSkyDomeNode)
01773         {
01774             mSkyDomeNode->setPosition(cam->getDerivedPosition());
01775         }
01776 
01777         RenderQueueGroupID qid;
01778         if (mSkyPlaneEnabled)
01779         {
01780             qid = mSkyPlaneDrawFirst? 
01781                         RENDER_QUEUE_1 : RENDER_QUEUE_9;
01782             mRenderQueue.addRenderable(mSkyPlaneEntity->getSubEntity(0), qid, RENDERABLE_DEFAULT_PRIORITY);
01783         }
01784 
01785         uint plane;
01786         if (mSkyBoxEnabled)
01787         {
01788             qid = mSkyBoxDrawFirst? 
01789                         RENDER_QUEUE_1 : RENDER_QUEUE_9;
01790 
01791             for (plane = 0; plane < 6; ++plane)
01792             {
01793                 mRenderQueue.addRenderable(
01794                     mSkyBoxEntity[plane]->getSubEntity(0), qid, RENDERABLE_DEFAULT_PRIORITY);
01795             }
01796         }
01797 
01798         if (mSkyDomeEnabled)
01799         {
01800             qid = mSkyDomeDrawFirst? 
01801                         RENDER_QUEUE_1 : RENDER_QUEUE_9;
01802 
01803             for (plane = 0; plane < 5; ++plane)
01804             {
01805                 mRenderQueue.addRenderable(
01806                     mSkyDomeEntity[plane]->getSubEntity(0), qid, RENDERABLE_DEFAULT_PRIORITY);
01807             }
01808         }
01809     }
01810     //---------------------------------------------------------------------
01811     void SceneManager::addRenderQueueListener(RenderQueueListener* newListener)
01812     {
01813         mRenderQueueListeners.push_back(newListener);
01814     }
01815     //---------------------------------------------------------------------
01816     void SceneManager::removeRenderQueueListener(RenderQueueListener* delListener)
01817     {
01818         RenderQueueListenerList::iterator i, iend;
01819         iend = mRenderQueueListeners.end();
01820         for (i = mRenderQueueListeners.begin(); i != iend; ++i)
01821         {
01822             if (*i == delListener)
01823             {
01824                 mRenderQueueListeners.erase(i);
01825                 break;
01826             }
01827         }
01828 
01829     }
01830     //---------------------------------------------------------------------
01831     bool SceneManager::fireRenderQueueStarted(RenderQueueGroupID id)
01832     {
01833         RenderQueueListenerList::iterator i, iend;
01834         bool skip = false;
01835 
01836         iend = mRenderQueueListeners.end();
01837         for (i = mRenderQueueListeners.begin(); i != iend; ++i)
01838         {
01839             (*i)->renderQueueStarted(id, skip);
01840         }
01841         return skip;
01842     }
01843     //---------------------------------------------------------------------
01844     bool SceneManager::fireRenderQueueEnded(RenderQueueGroupID id)
01845     {
01846         RenderQueueListenerList::iterator i, iend;
01847         bool repeat = false;
01848 
01849         iend = mRenderQueueListeners.end();
01850         for (i = mRenderQueueListeners.begin(); i != iend; ++i)
01851         {
01852             (*i)->renderQueueEnded(id, repeat);
01853         }
01854         return repeat;
01855     }
01856     //---------------------------------------------------------------------
01857     void SceneManager::setViewport(Viewport* vp)
01858     {
01859         // Set viewport in render system
01860         mDestRenderSystem->_setViewport(vp);
01861     }
01862     //---------------------------------------------------------------------
01863     void SceneManager::showBoundingBoxes(bool bShow) 
01864     {
01865         mShowBoundingBoxes = bShow;
01866     }
01867     //---------------------------------------------------------------------
01868     bool SceneManager::getShowBoundingBoxes() const
01869     {
01870         return mShowBoundingBoxes;
01871     }
01872     //---------------------------------------------------------------------
01873     AxisAlignedBoxSceneQuery* 
01874     SceneManager::createAABBQuery(const AxisAlignedBox& box, unsigned long mask)
01875     {
01876         DefaultAxisAlignedBoxSceneQuery* q = new DefaultAxisAlignedBoxSceneQuery(this);
01877         q->setQueryMask(mask);
01878         return q;
01879     }
01880     //---------------------------------------------------------------------
01881     SphereSceneQuery* 
01882     SceneManager::createSphereQuery(const Sphere& sphere, unsigned long mask)
01883     {
01884         DefaultSphereSceneQuery* q = new DefaultSphereSceneQuery(this);
01885         q->setQueryMask(mask);
01886         return q;
01887     }
01888     //---------------------------------------------------------------------
01889     RaySceneQuery* 
01890     SceneManager::createRayQuery(const Ray& ray, unsigned long mask)
01891     {
01892         DefaultRaySceneQuery* q = new DefaultRaySceneQuery(this);
01893         q->setQueryMask(mask);
01894         return q;
01895     }
01896     //---------------------------------------------------------------------
01897     IntersectionSceneQuery* 
01898     SceneManager::createIntersectionQuery(unsigned long mask)
01899     {
01900         
01901         DefaultIntersectionSceneQuery* q = new DefaultIntersectionSceneQuery(this);
01902         q->setQueryMask(mask);
01903         return q;
01904     }
01905     //---------------------------------------------------------------------
01906     void SceneManager::destroyQuery(SceneQuery* query)
01907     {
01908         delete query;
01909     }
01910     //---------------------------------------------------------------------
01911     DefaultIntersectionSceneQuery::DefaultIntersectionSceneQuery(SceneManager* creator)
01912         : IntersectionSceneQuery(creator)
01913     {
01914         // No world geometry results supported
01915         mSupportedWorldFragments.insert(SceneQuery::WFT_NONE);
01916     }
01917     //---------------------------------------------------------------------
01918     DefaultIntersectionSceneQuery::~DefaultIntersectionSceneQuery()
01919     {
01920     }
01921     //---------------------------------------------------------------------
01922     void DefaultIntersectionSceneQuery::execute(IntersectionSceneQueryListener* listener)
01923     {
01924         // TODO: BillboardSets? Will need per-billboard collision most likely
01925         // Entities only for now
01926         SceneManager::EntityList::const_iterator a, b, theEnd;
01927         theEnd = mParentSceneMgr->mEntities.end();
01928         int numEntities;
01929         // Loop a from first to last-1
01930         a = mParentSceneMgr->mEntities.begin();
01931         numEntities = (uint)mParentSceneMgr->mEntities.size();
01932         for (int i = 0; i < (numEntities - 1); ++i, ++a)
01933         {
01934             // Skip if a does not pass the mask
01935             if (! (a->second->getQueryFlags() & mQueryMask))
01936                 continue;
01937 
01938             // Loop b from a+1 to last
01939             b = a;
01940             for (++b; b != theEnd; ++b)
01941             {
01942                 // Apply mask to b (both must pass)
01943                 if (b->second->getQueryFlags() & mQueryMask)
01944                 {
01945                     const AxisAlignedBox& box1 = a->second->getWorldBoundingBox();
01946                     const AxisAlignedBox& box2 = b->second->getWorldBoundingBox();
01947 
01948                     if (box1.intersects(box2))
01949                     {
01950                         listener->queryResult(a->second, b->second);
01951                     }
01952                 }
01953 
01954             }
01955         }
01956     }
01957     //---------------------------------------------------------------------
01958     DefaultAxisAlignedBoxSceneQuery::
01959     DefaultAxisAlignedBoxSceneQuery(SceneManager* creator)
01960     : AxisAlignedBoxSceneQuery(creator)
01961     {
01962         // No world geometry results supported
01963         mSupportedWorldFragments.insert(SceneQuery::WFT_NONE);
01964     }
01965     //---------------------------------------------------------------------
01966     DefaultAxisAlignedBoxSceneQuery::~DefaultAxisAlignedBoxSceneQuery()
01967     {
01968     }
01969     //---------------------------------------------------------------------
01970     void DefaultAxisAlignedBoxSceneQuery::execute(SceneQueryListener* listener)
01971     {
01972         // TODO: BillboardSets? Will need per-billboard collision most likely
01973         // Entities only for now
01974         SceneManager::EntityList::const_iterator i, iEnd;
01975         iEnd = mParentSceneMgr->mEntities.end();
01976         for (i = mParentSceneMgr->mEntities.begin(); i != iEnd; ++i)
01977         {
01978             if (mAABB.intersects(i->second->getWorldBoundingBox()))
01979             {
01980                 listener->queryResult(i->second);
01981             }
01982         }
01983     }
01984     //---------------------------------------------------------------------
01985     DefaultRaySceneQuery::
01986     DefaultRaySceneQuery(SceneManager* creator) : RaySceneQuery(creator)
01987     {
01988         // No world geometry results supported
01989         mSupportedWorldFragments.insert(SceneQuery::WFT_NONE);
01990     }
01991     //---------------------------------------------------------------------
01992     DefaultRaySceneQuery::~DefaultRaySceneQuery()
01993     {
01994     }
01995     //---------------------------------------------------------------------
01996     void DefaultRaySceneQuery::execute(RaySceneQueryListener* listener)
01997     {
01998         // Note that becuase we have no scene partitioning, we actually
01999         // perform a complete scene search even if restricted results are
02000         // requested; smarter scene manager queries can utilise the paritioning 
02001         // of the scene in order to reduce the number of intersection tests 
02002         // required to fulfil the query
02003 
02004         // TODO: BillboardSets? Will need per-billboard collision most likely
02005         // Entities only for now
02006         SceneManager::EntityList::const_iterator i, iEnd;
02007         iEnd = mParentSceneMgr->mEntities.end();
02008         for (i = mParentSceneMgr->mEntities.begin(); i != iEnd; ++i)
02009         {
02010             // Do ray / box test
02011             std::pair<bool, Real> result = 
02012                 mRay.intersects(i->second->getWorldBoundingBox());
02013 
02014             if (result.first)
02015             {
02016                 listener->queryResult(i->second, result.second);
02017             }
02018         }
02019 
02020     }
02021     //---------------------------------------------------------------------
02022     DefaultSphereSceneQuery::
02023     DefaultSphereSceneQuery(SceneManager* creator) : SphereSceneQuery(creator)
02024     {
02025         // No world geometry results supported
02026         mSupportedWorldFragments.insert(SceneQuery::WFT_NONE);
02027     }
02028     //---------------------------------------------------------------------
02029     DefaultSphereSceneQuery::~DefaultSphereSceneQuery()
02030     {
02031     }
02032     //---------------------------------------------------------------------
02033     void DefaultSphereSceneQuery::execute(SceneQueryListener* listener)
02034     {
02035         // TODO: BillboardSets? Will need per-billboard collision most likely
02036         // Entities only for now
02037         SceneManager::EntityList::const_iterator i, iEnd;
02038         iEnd = mParentSceneMgr->mEntities.end();
02039         Sphere testSphere;
02040         for (i = mParentSceneMgr->mEntities.begin(); i != iEnd; ++i)
02041         {
02042             // Do sphere / sphere test
02043             testSphere.setCenter(i->second->getParentNode()->_getDerivedPosition());
02044             testSphere.setRadius(i->second->getBoundingRadius());
02045             if (mSphere.intersects(testSphere))
02046             {
02047                 listener->queryResult(i->second);
02048             }
02049         }
02050     }
02051 
02052 
02053 }

Copyright © 2002-2003 by The OGRE Team
Last modified Wed Jan 21 00:10:26 2004