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

OgreSceneNode.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://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