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