00001 /* 00002 ----------------------------------------------------------------------------- 00003 This source file is part of OGRE 00004 (Object-oriented Graphics Rendering Engine) 00005 For the latest info, see http://www.ogre3d.org/ 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 #include "OgreSceneNode.h" 00027 00028 #include "OgreException.h" 00029 #include "OgreEntity.h" 00030 #include "OgreCamera.h" 00031 #include "OgreLight.h" 00032 #include "OgreMath.h" 00033 #include "OgreSceneManager.h" 00034 #include "OgreMovableObject.h" 00035 #include "OgreWireBoundingBox.h" 00036 00037 namespace Ogre { 00038 //----------------------------------------------------------------------- 00039 SceneNode::SceneNode(SceneManager* creator) 00040 : Node(), mLightListDirty(true), mWireBoundingBox(0), mShowBoundingBox(false), mCreator(creator) 00041 { 00042 needUpdate(); 00043 } 00044 //----------------------------------------------------------------------- 00045 SceneNode::SceneNode(SceneManager* creator, const String& name) 00046 : Node(name), mLightListDirty(true), mWireBoundingBox(0), mShowBoundingBox(false), mCreator(creator) 00047 { 00048 needUpdate(); 00049 } 00050 //----------------------------------------------------------------------- 00051 SceneNode::~SceneNode() 00052 { 00053 // Detach all objects, do this manually to avoid needUpdate() call 00054 // which can fail because of deleted items 00055 ObjectMap::iterator itr; 00056 MovableObject* ret; 00057 for ( itr = mObjectsByName.begin(); itr != mObjectsByName.end(); itr++ ) 00058 { 00059 ret = itr->second; 00060 ret->_notifyAttached((SceneNode*)0); 00061 } 00062 mObjectsByName.clear(); 00063 00064 if (mWireBoundingBox) { 00065 delete mWireBoundingBox; 00066 } 00067 } 00068 //----------------------------------------------------------------------- 00069 void SceneNode::_update(bool updateChildren, bool parentHasChanged) 00070 { 00071 Node::_update(updateChildren, parentHasChanged); 00072 _updateBounds(); 00073 mLightListDirty = true; 00074 00075 } 00076 00077 //----------------------------------------------------------------------- 00078 void SceneNode::attachObject(MovableObject* obj) 00079 { 00080 obj->_notifyAttached(this); 00081 00082 // Also add to name index 00083 std::pair<ObjectMap::iterator, bool> insresult = 00084 mObjectsByName.insert(ObjectMap::value_type(obj->getName(), obj)); 00085 assert(insresult.second && "Object was not attached because an object of the " 00086 "same name was already attached to this node."); 00087 00088 // Make sure bounds get updated (must go right to the top) 00089 needUpdate(); 00090 } 00091 //----------------------------------------------------------------------- 00092 unsigned short SceneNode::numAttachedObjects(void) const 00093 { 00094 return static_cast< unsigned short >( mObjectsByName.size() ); 00095 } 00096 //----------------------------------------------------------------------- 00097 MovableObject* SceneNode::getAttachedObject(unsigned short index) 00098 { 00099 if (index < mObjectsByName.size()) 00100 { 00101 ObjectMap::iterator i = mObjectsByName.begin(); 00102 // Increment (must do this one at a time) 00103 while (index--)++i; 00104 00105 return i->second; 00106 } 00107 else 00108 { 00109 Except(Exception::ERR_INVALIDPARAMS, "Object index out of bounds.", "SceneNode::getAttachedObject"); 00110 } 00111 return 0; 00112 } 00113 //----------------------------------------------------------------------- 00114 MovableObject* SceneNode::getAttachedObject(const String& name) 00115 { 00116 // Look up 00117 ObjectMap::iterator i = mObjectsByName.find(name); 00118 00119 if (i == mObjectsByName.end()) 00120 { 00121 Except(Exception::ERR_ITEM_NOT_FOUND, "Attached object " + 00122 name + " not found.", "SceneNode::getAttachedObject"); 00123 } 00124 00125 return i->second; 00126 00127 } 00128 //----------------------------------------------------------------------- 00129 MovableObject* SceneNode::detachObject(unsigned short index) 00130 { 00131 MovableObject* ret; 00132 if (index < mObjectsByName.size()) 00133 { 00134 00135 ObjectMap::iterator i = mObjectsByName.begin(); 00136 // Increment (must do this one at a time) 00137 while (index--)++i; 00138 00139 ret = i->second; 00140 mObjectsByName.erase(i); 00141 ret->_notifyAttached((SceneNode*)0); 00142 00143 // Make sure bounds get updated (must go right to the top) 00144 needUpdate(); 00145 00146 return ret; 00147 00148 } 00149 else 00150 { 00151 Except(Exception::ERR_INVALIDPARAMS, "Object index out of bounds.", "SceneNode::getAttchedEntity"); 00152 } 00153 return 0; 00154 00155 } 00156 //----------------------------------------------------------------------- 00157 MovableObject* SceneNode::detachObject(const String& name) 00158 { 00159 ObjectMap::iterator it = mObjectsByName.find(name); 00160 if (it == mObjectsByName.end()) 00161 { 00162 Except(Exception::ERR_ITEM_NOT_FOUND, "Object " + name + " is not attached " 00163 "to this node.", "SceneNode::detachObject"); 00164 } 00165 MovableObject* ret = it->second; 00166 mObjectsByName.erase(it); 00167 ret->_notifyAttached((SceneNode*)0); 00168 // Make sure bounds get updated (must go right to the top) 00169 needUpdate(); 00170 00171 return ret; 00172 00173 } 00174 //----------------------------------------------------------------------- 00175 void SceneNode::detachObject(MovableObject* obj) 00176 { 00177 ObjectMap::iterator i, iend; 00178 iend = mObjectsByName.end(); 00179 for (i = mObjectsByName.begin(); i != iend; ++i) 00180 { 00181 if (i->second == obj) 00182 { 00183 mObjectsByName.erase(i); 00184 break; 00185 } 00186 } 00187 obj->_notifyAttached((SceneNode*)0); 00188 00189 // Make sure bounds get updated (must go right to the top) 00190 needUpdate(); 00191 00192 } 00193 //----------------------------------------------------------------------- 00194 void SceneNode::attachCamera(Camera* cam) 00195 { 00196 attachObject(cam); 00197 } 00198 //----------------------------------------------------------------------- 00199 void SceneNode::attachLight(Light* lgt) 00200 { 00201 attachObject(lgt); 00202 } 00203 //----------------------------------------------------------------------- 00204 void SceneNode::detachAllObjects(void) 00205 { 00206 ObjectMap::iterator itr; 00207 MovableObject* ret; 00208 for ( itr = mObjectsByName.begin(); itr != mObjectsByName.end(); itr++ ) 00209 { 00210 ret = itr->second; 00211 ret->_notifyAttached((SceneNode*)0); 00212 } 00213 mObjectsByName.clear(); 00214 // Make sure bounds get updated (must go right to the top) 00215 needUpdate(); 00216 } 00217 //----------------------------------------------------------------------- 00218 void SceneNode::_updateBounds(void) 00219 { 00220 // Reset bounds first 00221 mWorldAABB.setNull(); 00222 00223 // Update bounds from own attached objects 00224 ObjectMap::iterator i; 00225 AxisAlignedBox bx; 00226 for (i = mObjectsByName.begin(); i != mObjectsByName.end(); ++i) 00227 { 00228 // Merge world bounds of each object 00229 mWorldAABB.merge(i->second->getWorldBoundingBox(true)); 00230 } 00231 00232 // Merge with children 00233 ChildNodeMap::iterator child; 00234 for (child = mChildren.begin(); child != mChildren.end(); ++child) 00235 { 00236 SceneNode* sceneChild = static_cast<SceneNode*>(child->second); 00237 mWorldAABB.merge(sceneChild->mWorldAABB); 00238 } 00239 00240 } 00241 //----------------------------------------------------------------------- 00242 void SceneNode::_findVisibleObjects(Camera* cam, RenderQueue* queue, bool includeChildren, bool displayNodes) 00243 { 00244 // Check self visible 00245 if (!cam->isVisible(mWorldAABB)) 00246 return; 00247 00248 // Add all entities 00249 ObjectMap::iterator iobj; 00250 ObjectMap::iterator iobjend = mObjectsByName.end(); 00251 for (iobj = mObjectsByName.begin(); iobj != iobjend; ++iobj) 00252 { 00253 // Tell attached objects about camera position (incase any extra processing they want to do) 00254 iobj->second->_notifyCurrentCamera(cam); 00255 if (iobj->second->isVisible()) 00256 { 00257 iobj->second->_updateRenderQueue(queue); 00258 } 00259 } 00260 00261 if (includeChildren) 00262 { 00263 ChildNodeMap::iterator child, childend; 00264 childend = mChildren.end(); 00265 for (child = mChildren.begin(); child != childend; ++child) 00266 { 00267 SceneNode* sceneChild = static_cast<SceneNode*>(child->second); 00268 sceneChild->_findVisibleObjects(cam, queue, includeChildren, displayNodes); 00269 } 00270 } 00271 00272 if (displayNodes) 00273 { 00274 // Include self in the render queue 00275 queue->addRenderable(this); 00276 } 00277 00278 // Check if the bounding box should be shown. 00279 // See if our flag is set or if the scene manager flag is set. 00280 if (mShowBoundingBox || mCreator->getShowBoundingBoxes()) 00281 { 00282 _addBoundingBoxToQueue(queue); 00283 } 00284 00285 00286 } 00287 00288 00289 void SceneNode::_addBoundingBoxToQueue(RenderQueue* queue) { 00290 // Create a WireBoundingBox if needed. 00291 if (mWireBoundingBox == NULL) { 00292 mWireBoundingBox = new WireBoundingBox(); 00293 } 00294 mWireBoundingBox->setupBoundingBox(mWorldAABB); 00295 queue->addRenderable(mWireBoundingBox); 00296 } 00297 00298 void SceneNode::showBoundingBox(bool bShow) { 00299 mShowBoundingBox = bShow; 00300 } 00301 00302 bool SceneNode::getShowBoundingBox() const { 00303 return mShowBoundingBox; 00304 } 00305 00306 00307 //----------------------------------------------------------------------- 00308 Node* SceneNode::createChildImpl(void) 00309 { 00310 return mCreator->createSceneNode(); 00311 } 00312 //----------------------------------------------------------------------- 00313 Node* SceneNode::createChildImpl(const String& name) 00314 { 00315 return mCreator->createSceneNode(name); 00316 } 00317 //----------------------------------------------------------------------- 00318 AxisAlignedBox SceneNode::_getWorldAABB(void) const 00319 { 00320 return mWorldAABB; 00321 } 00322 //----------------------------------------------------------------------- 00323 SceneNode::ObjectIterator SceneNode::getAttachedObjectIterator(void) 00324 { 00325 return ObjectIterator(mObjectsByName.begin(), mObjectsByName.end()); 00326 } 00327 //----------------------------------------------------------------------- 00328 SceneManager* SceneNode::getCreator(void) const 00329 { 00330 return mCreator; 00331 } 00332 //----------------------------------------------------------------------- 00333 void SceneNode::removeAndDestroyChild(const String& name) 00334 { 00335 SceneNode* pChild = static_cast<SceneNode*>(getChild(name)); 00336 pChild->removeAndDestroyAllChildren(); 00337 00338 removeChild(name); 00339 pChild->getCreator()->destroySceneNode(name); 00340 00341 } 00342 //----------------------------------------------------------------------- 00343 void SceneNode::removeAndDestroyChild(unsigned short index) 00344 { 00345 SceneNode* pChild = static_cast<SceneNode*>(getChild(index)); 00346 pChild->removeAndDestroyAllChildren(); 00347 00348 removeChild(index); 00349 pChild->getCreator()->destroySceneNode(pChild->getName()); 00350 } 00351 //----------------------------------------------------------------------- 00352 void SceneNode::removeAndDestroyAllChildren(void) 00353 { 00354 ChildNodeMap::iterator i, iend; 00355 iend = mChildren.end(); 00356 for (i = mChildren.begin(); i != iend; ++i) 00357 { 00358 SceneNode* sn = static_cast<SceneNode*>(i->second); 00359 sn->removeAndDestroyAllChildren(); 00360 sn->getCreator()->destroySceneNode(sn->getName()); 00361 } 00362 mChildren.clear(); 00363 needUpdate(); 00364 } 00365 //----------------------------------------------------------------------- 00366 SceneNode* SceneNode::createChildSceneNode(const Vector3& translate, 00367 const Quaternion& rotate) 00368 { 00369 return static_cast<SceneNode*>(this->createChild(translate, rotate)); 00370 } 00371 //----------------------------------------------------------------------- 00372 SceneNode* SceneNode::createChildSceneNode(const String& name, const Vector3& translate, 00373 const Quaternion& rotate) 00374 { 00375 return static_cast<SceneNode*>(this->createChild(name, translate, rotate)); 00376 } 00377 //----------------------------------------------------------------------- 00378 const LightList& SceneNode::getLights(void) const 00379 { 00380 // TEMP FIX 00381 // If a scene node is static and lights have moved, light list won't change 00382 // can't use a simple global boolean flag since this is only called for 00383 // visible nodes, so temporarily visible nodes will not be updated 00384 // Since this is only called for visible nodes, skip the check for now 00385 //if (mLightListDirty) 00386 { 00387 // Use SceneManager to calculate 00388 mCreator->_populateLightList(this->_getDerivedPosition(), mLightList); 00389 mLightListDirty = false; 00390 } 00391 return mLightList; 00392 00393 } 00394 00395 00396 }
Copyright © 2002-2003 by The OGRE Team
Last modified Wed Jan 21 00:10:26 2004