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), 
00041     mCreator(creator), mYawFixed(false), mAutoTrackTarget(0)
00042     {
00043         needUpdate();
00044     }
00045     //-----------------------------------------------------------------------
00046     SceneNode::SceneNode(SceneManager* creator, const String& name) 
00047     : Node(name), mLightListDirty(true), mWireBoundingBox(0), mShowBoundingBox(false), 
00048     mCreator(creator), mYawFixed(false), mAutoTrackTarget(0)
00049     {
00050         needUpdate();
00051     }
00052     //-----------------------------------------------------------------------
00053     SceneNode::~SceneNode()
00054     {
00055         // Detach all objects, do this manually to avoid needUpdate() call 
00056         // which can fail because of deleted items
00057         ObjectMap::iterator itr;
00058         MovableObject* ret;
00059         for ( itr = mObjectsByName.begin(); itr != mObjectsByName.end(); itr++ )
00060         {
00061           ret = itr->second;
00062           ret->_notifyAttached((SceneNode*)0);
00063         }
00064         mObjectsByName.clear();
00065 
00066         if (mWireBoundingBox) {
00067             delete mWireBoundingBox;
00068         }
00069     }
00070     //-----------------------------------------------------------------------
00071     void SceneNode::_update(bool updateChildren, bool parentHasChanged)
00072     {
00073         Node::_update(updateChildren, parentHasChanged);
00074         _updateBounds();
00075         mLightListDirty = true;
00076 
00077     }
00078 
00079     //-----------------------------------------------------------------------
00080     void SceneNode::attachObject(MovableObject* obj)
00081     {
00082         obj->_notifyAttached(this);
00083 
00084         // Also add to name index
00085         std::pair<ObjectMap::iterator, bool> insresult = 
00086             mObjectsByName.insert(ObjectMap::value_type(obj->getName(), obj));
00087         assert(insresult.second && "Object was not attached because an object of the "
00088             "same name was already attached to this node.");
00089 
00090         // Make sure bounds get updated (must go right to the top)
00091         needUpdate();
00092     }
00093     //-----------------------------------------------------------------------
00094     unsigned short SceneNode::numAttachedObjects(void) const
00095     {
00096         return static_cast< unsigned short >( mObjectsByName.size() );
00097     }
00098     //-----------------------------------------------------------------------
00099     MovableObject* SceneNode::getAttachedObject(unsigned short index)
00100     {
00101         if (index < mObjectsByName.size())
00102         {
00103             ObjectMap::iterator i = mObjectsByName.begin();
00104             // Increment (must do this one at a time)            
00105             while (index--)++i;
00106 
00107             return i->second;
00108         }
00109         else
00110         {
00111             Except(Exception::ERR_INVALIDPARAMS, "Object index out of bounds.", "SceneNode::getAttachedObject");
00112         }
00113         return 0;
00114     }
00115     //-----------------------------------------------------------------------
00116     MovableObject* SceneNode::getAttachedObject(const String& name)
00117     {
00118         // Look up 
00119         ObjectMap::iterator i = mObjectsByName.find(name);
00120 
00121         if (i == mObjectsByName.end())
00122         {
00123             Except(Exception::ERR_ITEM_NOT_FOUND, "Attached object " + 
00124                 name + " not found.", "SceneNode::getAttachedObject");
00125         }
00126 
00127         return i->second;
00128 
00129     }
00130     //-----------------------------------------------------------------------
00131     MovableObject* SceneNode::detachObject(unsigned short index)
00132     {
00133         MovableObject* ret;
00134         if (index < mObjectsByName.size())
00135         {
00136 
00137             ObjectMap::iterator i = mObjectsByName.begin();
00138             // Increment (must do this one at a time)            
00139             while (index--)++i;
00140 
00141             ret = i->second;
00142             mObjectsByName.erase(i);
00143             ret->_notifyAttached((SceneNode*)0);
00144 
00145             // Make sure bounds get updated (must go right to the top)
00146             needUpdate();
00147 
00148             return ret;
00149 
00150         }
00151         else
00152         {
00153             Except(Exception::ERR_INVALIDPARAMS, "Object index out of bounds.", "SceneNode::getAttchedEntity");
00154         }
00155         return 0;
00156 
00157     }
00158     //-----------------------------------------------------------------------
00159     MovableObject* SceneNode::detachObject(const String& name)
00160     {
00161         ObjectMap::iterator it = mObjectsByName.find(name);
00162         if (it == mObjectsByName.end())
00163         {
00164             Except(Exception::ERR_ITEM_NOT_FOUND, "Object " + name + " is not attached "
00165                 "to this node.", "SceneNode::detachObject");
00166         }
00167         MovableObject* ret = it->second;
00168         mObjectsByName.erase(it);
00169         ret->_notifyAttached((SceneNode*)0);
00170         // Make sure bounds get updated (must go right to the top)
00171         needUpdate();
00172         
00173         return ret;
00174 
00175     }
00176     //-----------------------------------------------------------------------
00177     void SceneNode::detachObject(MovableObject* obj)
00178     {
00179         ObjectMap::iterator i, iend;
00180         iend = mObjectsByName.end();
00181         for (i = mObjectsByName.begin(); i != iend; ++i)
00182         {
00183             if (i->second == obj)
00184             {
00185                 mObjectsByName.erase(i);
00186                 break;
00187             }
00188         }
00189         obj->_notifyAttached((SceneNode*)0);
00190 
00191         // Make sure bounds get updated (must go right to the top)
00192         needUpdate();
00193 
00194     }
00195     //-----------------------------------------------------------------------
00196     void SceneNode::attachCamera(Camera* cam)
00197     {
00198         attachObject(cam);
00199     }
00200     //-----------------------------------------------------------------------
00201     void SceneNode::attachLight(Light* lgt)
00202     {
00203         attachObject(lgt);
00204     }
00205     //-----------------------------------------------------------------------
00206     void SceneNode::detachAllObjects(void)
00207     {
00208         ObjectMap::iterator itr;
00209         MovableObject* ret;
00210         for ( itr = mObjectsByName.begin(); itr != mObjectsByName.end(); itr++ )
00211         {
00212           ret = itr->second;
00213           ret->_notifyAttached((SceneNode*)0);
00214         }
00215         mObjectsByName.clear();
00216         // Make sure bounds get updated (must go right to the top)
00217         needUpdate();
00218     }
00219     //-----------------------------------------------------------------------
00220     void SceneNode::_updateBounds(void)
00221     {
00222         // Reset bounds first
00223         mWorldAABB.setNull();
00224 
00225         // Update bounds from own attached objects
00226         ObjectMap::iterator i;
00227         AxisAlignedBox bx;
00228         for (i = mObjectsByName.begin(); i != mObjectsByName.end(); ++i)
00229         {
00230             // Merge world bounds of each object
00231             mWorldAABB.merge(i->second->getWorldBoundingBox(true));
00232         }
00233 
00234         // Merge with children
00235         ChildNodeMap::iterator child;
00236         for (child = mChildren.begin(); child != mChildren.end(); ++child)
00237         {
00238             SceneNode* sceneChild = static_cast<SceneNode*>(child->second);
00239             mWorldAABB.merge(sceneChild->mWorldAABB);
00240         }
00241 
00242     }
00243     //-----------------------------------------------------------------------
00244     void SceneNode::_findVisibleObjects(Camera* cam, RenderQueue* queue, 
00245         bool includeChildren, bool displayNodes, bool onlyShadowCasters)
00246     {
00247         // Check self visible
00248         if (!cam->isVisible(mWorldAABB))
00249             return;
00250 
00251         // Add all entities
00252         ObjectMap::iterator iobj;
00253         ObjectMap::iterator iobjend = mObjectsByName.end();
00254         for (iobj = mObjectsByName.begin(); iobj != iobjend; ++iobj)
00255         {
00256             // Tell attached objects about camera position (incase any extra processing they want to do)
00257             iobj->second->_notifyCurrentCamera(cam);
00258             if (iobj->second->isVisible() && 
00259                 (!onlyShadowCasters || iobj->second->getCastShadows()))
00260             {
00261                 iobj->second->_updateRenderQueue(queue);
00262             }
00263         }
00264 
00265         if (includeChildren)
00266         {
00267             ChildNodeMap::iterator child, childend;
00268             childend = mChildren.end();
00269             for (child = mChildren.begin(); child != childend; ++child)
00270             {
00271                 SceneNode* sceneChild = static_cast<SceneNode*>(child->second);
00272                 sceneChild->_findVisibleObjects(cam, queue, includeChildren, displayNodes);
00273             }
00274         }
00275 
00276         if (displayNodes)
00277         {
00278             // Include self in the render queue
00279             queue->addRenderable(this);
00280         }
00281 
00282         // Check if the bounding box should be shown.
00283         // See if our flag is set or if the scene manager flag is set.
00284         if (mShowBoundingBox || (mCreator && mCreator->getShowBoundingBoxes())) 
00285         { 
00286             _addBoundingBoxToQueue(queue);
00287         }
00288 
00289 
00290     }
00291 
00292 
00293     void SceneNode::_addBoundingBoxToQueue(RenderQueue* queue) {
00294         // Create a WireBoundingBox if needed.
00295         if (mWireBoundingBox == NULL) {
00296             mWireBoundingBox = new WireBoundingBox();
00297         }
00298         mWireBoundingBox->setupBoundingBox(mWorldAABB);
00299         queue->addRenderable(mWireBoundingBox);
00300     }
00301 
00302     void SceneNode::showBoundingBox(bool bShow) {
00303         mShowBoundingBox = bShow;
00304     }
00305 
00306     bool SceneNode::getShowBoundingBox() const {
00307         return mShowBoundingBox;
00308     }
00309 
00310 
00311     //-----------------------------------------------------------------------
00312     Node* SceneNode::createChildImpl(void)
00313     {
00314         // Support detached scene nodes
00315         if (mCreator)
00316         {
00317             return mCreator->createSceneNode();
00318         }
00319         else
00320         {
00321             return new SceneNode(NULL);
00322         }
00323     }
00324     //-----------------------------------------------------------------------
00325     Node* SceneNode::createChildImpl(const String& name)
00326     {
00327         // Support detached scene nodes
00328         if (mCreator)
00329         {
00330             return mCreator->createSceneNode(name);
00331         }
00332         else
00333         {
00334             return new SceneNode(NULL, name);
00335         }
00336     }
00337     //-----------------------------------------------------------------------
00338     AxisAlignedBox SceneNode::_getWorldAABB(void) const
00339     {
00340         return mWorldAABB;
00341     }
00342     //-----------------------------------------------------------------------
00343     SceneNode::ObjectIterator SceneNode::getAttachedObjectIterator(void)
00344     {
00345         return ObjectIterator(mObjectsByName.begin(), mObjectsByName.end());
00346     }
00347     //-----------------------------------------------------------------------
00348     SceneManager* SceneNode::getCreator(void) const
00349     {
00350         return mCreator;
00351     }
00352     //-----------------------------------------------------------------------
00353     void SceneNode::removeAndDestroyChild(const String& name)
00354     {
00355         SceneNode* pChild = static_cast<SceneNode*>(getChild(name));
00356         pChild->removeAndDestroyAllChildren();
00357 
00358         removeChild(name);
00359         pChild->getCreator()->destroySceneNode(name);
00360 
00361     }
00362     //-----------------------------------------------------------------------
00363     void SceneNode::removeAndDestroyChild(unsigned short index)
00364     {
00365         SceneNode* pChild = static_cast<SceneNode*>(getChild(index));
00366         pChild->removeAndDestroyAllChildren();
00367 
00368         removeChild(index);
00369         pChild->getCreator()->destroySceneNode(pChild->getName());
00370     }
00371     //-----------------------------------------------------------------------
00372     void SceneNode::removeAndDestroyAllChildren(void)
00373     {
00374         ChildNodeMap::iterator i, iend;
00375         iend = mChildren.end();
00376         for (i = mChildren.begin(); i != iend; ++i)
00377         {
00378             SceneNode* sn = static_cast<SceneNode*>(i->second);
00379             sn->removeAndDestroyAllChildren();
00380             sn->getCreator()->destroySceneNode(sn->getName());
00381         }
00382         mChildren.clear();
00383         needUpdate();
00384     }
00385     //-----------------------------------------------------------------------
00386     SceneNode* SceneNode::createChildSceneNode(const Vector3& translate, 
00387         const Quaternion& rotate)
00388     {
00389         return static_cast<SceneNode*>(this->createChild(translate, rotate));
00390     }
00391     //-----------------------------------------------------------------------
00392     SceneNode* SceneNode::createChildSceneNode(const String& name, const Vector3& translate, 
00393         const Quaternion& rotate)
00394     {
00395         return static_cast<SceneNode*>(this->createChild(name, translate, rotate));
00396     }
00397     //-----------------------------------------------------------------------
00398     const LightList& SceneNode::getLights(void) const
00399     {
00400         // TEMP FIX
00401         // If a scene node is static and lights have moved, light list won't change
00402         // can't use a simple global boolean flag since this is only called for
00403         // visible nodes, so temporarily visible nodes will not be updated
00404         // Since this is only called for visible nodes, skip the check for now
00405         //if (mLightListDirty)
00406         if (mCreator)
00407         {
00408             // Use SceneManager to calculate
00409             mCreator->_populateLightList(this->_getDerivedPosition(), mLightList);
00410             mLightListDirty = false;
00411         }
00412         return mLightList;
00413 
00414     }
00415     //-----------------------------------------------------------------------
00416     void SceneNode::setAutoTracking(bool enabled, SceneNode* target, 
00417         const Vector3& localDirectionVector,
00418         const Vector3& offset)
00419     {
00420         if (enabled)
00421         {
00422             mAutoTrackTarget = target;
00423             mAutoTrackOffset = offset;
00424             mAutoTrackLocalDirection = localDirectionVector;
00425         }
00426         else
00427         {
00428             mAutoTrackTarget = 0;
00429         }
00430         if (mCreator)
00431             mCreator->_notifyAutotrackingSceneNode(this, enabled);
00432     }
00433     //-----------------------------------------------------------------------
00434     void SceneNode::setFixedYawAxis(bool useFixed, const Vector3& fixedAxis)
00435     {
00436         mYawFixed = useFixed;
00437         mYawFixedAxis = fixedAxis;
00438     }
00439 
00440     //-----------------------------------------------------------------------
00441     void SceneNode::setDirection(Real x, Real y, Real z, TransformSpace relativeTo, 
00442         const Vector3& localDirectionVector)
00443     {
00444         setDirection(Vector3(x,y,z), relativeTo, localDirectionVector);
00445     }
00446 
00447     //-----------------------------------------------------------------------
00448     void SceneNode::setDirection(const Vector3& vec, TransformSpace relativeTo, 
00449         const Vector3& localDirectionVector)
00450     {
00451         // Do nothing if given a zero vector
00452         if (vec == Vector3::ZERO) return;
00453 
00454         // Adjust vector so that it is relative to local Z
00455         Vector3 zAdjustVec;
00456         if (localDirectionVector == Vector3::NEGATIVE_UNIT_Z)
00457         {
00458             zAdjustVec = -vec;
00459         }
00460         else
00461         {
00462             Quaternion localToUnitZ = localDirectionVector.getRotationTo(Vector3::UNIT_Z);
00463             zAdjustVec = localToUnitZ * vec;
00464         }
00465         zAdjustVec.normalise();
00466 
00467         Quaternion targetOrientation;
00468         if( mYawFixed )
00469         {
00470             Vector3 xVec = mYawFixedAxis.crossProduct( zAdjustVec );
00471             xVec.normalise();
00472 
00473             Vector3 yVec = zAdjustVec.crossProduct( xVec );
00474             yVec.normalise();
00475             
00476             targetOrientation.FromAxes( xVec, yVec, zAdjustVec );
00477         }
00478         else
00479         {
00480 
00481             // Get axes from current quaternion
00482             Vector3 axes[3];
00483             _getDerivedOrientation().ToAxes(axes);
00484             Quaternion rotQuat;
00485             if (-zAdjustVec == axes[2])
00486             {
00487                 // Oops, a 180 degree turn (infinite possible rotation axes)
00488                 // Default to yaw i.e. use current UP
00489                 rotQuat.FromAngleAxis(Math::PI, axes[1]);
00490             }
00491             else
00492             {
00493                 // Derive shortest arc to new direction
00494                 rotQuat = axes[2].getRotationTo(zAdjustVec);
00495 
00496             }
00497             targetOrientation = rotQuat * mOrientation;
00498         }
00499 
00500         if (relativeTo == TS_LOCAL || !mParent)
00501         {
00502             mOrientation = targetOrientation;
00503         }
00504         else
00505         {
00506             if (relativeTo == TS_PARENT)
00507             {
00508                 mOrientation = targetOrientation * mParent->getOrientation().Inverse();
00509             }
00510             else if (relativeTo == TS_WORLD)
00511             {
00512                 mOrientation = targetOrientation * mParent->_getDerivedOrientation().Inverse();
00513             }
00514         }
00515 
00516 
00517     }
00518     //-----------------------------------------------------------------------
00519     void SceneNode::lookAt( const Vector3& targetPoint, TransformSpace relativeTo, 
00520         const Vector3& localDirectionVector)
00521     {
00522         this->setDirection(targetPoint - _getDerivedPosition(), relativeTo, 
00523             localDirectionVector);
00524     }
00525     //-----------------------------------------------------------------------
00526     void SceneNode::_autoTrack(void)
00527     {
00528         // NB assumes that all scene nodes have been updated
00529         if (mAutoTrackTarget)
00530         {
00531             lookAt(mAutoTrackTarget->_getDerivedPosition() + mAutoTrackOffset, 
00532                 TS_WORLD, mAutoTrackLocalDirection);
00533             // update self & children
00534             _update(true, true);
00535         }
00536     }
00537 
00538 
00539 }

Copyright © 2002-2003 by The OGRE Team
Last modified Fri May 14 23:22:44 2004