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::detachAllObjects(void)
00197     {
00198         ObjectMap::iterator itr;
00199         MovableObject* ret;
00200         for ( itr = mObjectsByName.begin(); itr != mObjectsByName.end(); itr++ )
00201         {
00202           ret = itr->second;
00203           ret->_notifyAttached((SceneNode*)0);
00204         }
00205         mObjectsByName.clear();
00206         // Make sure bounds get updated (must go right to the top)
00207         needUpdate();
00208     }
00209     //-----------------------------------------------------------------------
00210     void SceneNode::_updateBounds(void)
00211     {
00212         // Reset bounds first
00213         mWorldAABB.setNull();
00214 
00215         // Update bounds from own attached objects
00216         ObjectMap::iterator i;
00217         for (i = mObjectsByName.begin(); i != mObjectsByName.end(); ++i)
00218         {
00219             // Merge world bounds of each object
00220             mWorldAABB.merge(i->second->getWorldBoundingBox(true));
00221         }
00222 
00223         // Merge with children
00224         ChildNodeMap::iterator child;
00225         for (child = mChildren.begin(); child != mChildren.end(); ++child)
00226         {
00227             SceneNode* sceneChild = static_cast<SceneNode*>(child->second);
00228             mWorldAABB.merge(sceneChild->mWorldAABB);
00229         }
00230 
00231     }
00232     //-----------------------------------------------------------------------
00233     void SceneNode::_findVisibleObjects(Camera* cam, RenderQueue* queue, 
00234         bool includeChildren, bool displayNodes, bool onlyShadowCasters)
00235     {
00236         // Check self visible
00237         if (!cam->isVisible(mWorldAABB))
00238             return;
00239 
00240         // Add all entities
00241         ObjectMap::iterator iobj;
00242         ObjectMap::iterator iobjend = mObjectsByName.end();
00243         for (iobj = mObjectsByName.begin(); iobj != iobjend; ++iobj)
00244         {
00245             // Tell attached objects about camera position (incase any extra processing they want to do)
00246             iobj->second->_notifyCurrentCamera(cam);
00247             if (iobj->second->isVisible() && 
00248                 (!onlyShadowCasters || iobj->second->getCastShadows()))
00249             {
00250                 iobj->second->_updateRenderQueue(queue);
00251             }
00252         }
00253 
00254         if (includeChildren)
00255         {
00256             ChildNodeMap::iterator child, childend;
00257             childend = mChildren.end();
00258             for (child = mChildren.begin(); child != childend; ++child)
00259             {
00260                 SceneNode* sceneChild = static_cast<SceneNode*>(child->second);
00261                 sceneChild->_findVisibleObjects(cam, queue, includeChildren, displayNodes);
00262             }
00263         }
00264 
00265         if (displayNodes)
00266         {
00267             // Include self in the render queue
00268             queue->addRenderable(this);
00269         }
00270 
00271         // Check if the bounding box should be shown.
00272         // See if our flag is set or if the scene manager flag is set.
00273         if (mShowBoundingBox || (mCreator && mCreator->getShowBoundingBoxes())) 
00274         { 
00275             _addBoundingBoxToQueue(queue);
00276         }
00277 
00278 
00279     }
00280 
00281 
00282     void SceneNode::_addBoundingBoxToQueue(RenderQueue* queue) {
00283         // Create a WireBoundingBox if needed.
00284         if (mWireBoundingBox == NULL) {
00285             mWireBoundingBox = new WireBoundingBox();
00286         }
00287         mWireBoundingBox->setupBoundingBox(mWorldAABB);
00288         queue->addRenderable(mWireBoundingBox);
00289     }
00290 
00291     void SceneNode::showBoundingBox(bool bShow) {
00292         mShowBoundingBox = bShow;
00293     }
00294 
00295     bool SceneNode::getShowBoundingBox() const {
00296         return mShowBoundingBox;
00297     }
00298 
00299 
00300     //-----------------------------------------------------------------------
00301     Node* SceneNode::createChildImpl(void)
00302     {
00303         assert(mCreator);
00304         return mCreator->createSceneNode();
00305     }
00306     //-----------------------------------------------------------------------
00307     Node* SceneNode::createChildImpl(const String& name)
00308     {
00309         assert(mCreator);
00310         return mCreator->createSceneNode(name);
00311     }
00312     //-----------------------------------------------------------------------
00313     AxisAlignedBox SceneNode::_getWorldAABB(void) const
00314     {
00315         return mWorldAABB;
00316     }
00317     //-----------------------------------------------------------------------
00318     SceneNode::ObjectIterator SceneNode::getAttachedObjectIterator(void)
00319     {
00320         return ObjectIterator(mObjectsByName.begin(), mObjectsByName.end());
00321     }
00322     //-----------------------------------------------------------------------
00323     SceneManager* SceneNode::getCreator(void) const
00324     {
00325         return mCreator;
00326     }
00327     //-----------------------------------------------------------------------
00328     void SceneNode::removeAndDestroyChild(const String& name)
00329     {
00330         SceneNode* pChild = static_cast<SceneNode*>(getChild(name));
00331         pChild->removeAndDestroyAllChildren();
00332 
00333         removeChild(name);
00334         pChild->getCreator()->destroySceneNode(name);
00335 
00336     }
00337     //-----------------------------------------------------------------------
00338     void SceneNode::removeAndDestroyChild(unsigned short index)
00339     {
00340         SceneNode* pChild = static_cast<SceneNode*>(getChild(index));
00341         pChild->removeAndDestroyAllChildren();
00342 
00343         removeChild(index);
00344         pChild->getCreator()->destroySceneNode(pChild->getName());
00345     }
00346     //-----------------------------------------------------------------------
00347     void SceneNode::removeAndDestroyAllChildren(void)
00348     {
00349         ChildNodeMap::iterator i, iend;
00350         iend = mChildren.end();
00351         for (i = mChildren.begin(); i != iend; ++i)
00352         {
00353             SceneNode* sn = static_cast<SceneNode*>(i->second);
00354             sn->removeAndDestroyAllChildren();
00355             sn->getCreator()->destroySceneNode(sn->getName());
00356         }
00357         mChildren.clear();
00358         needUpdate();
00359     }
00360     //-----------------------------------------------------------------------
00361     SceneNode* SceneNode::createChildSceneNode(const Vector3& translate, 
00362         const Quaternion& rotate)
00363     {
00364         return static_cast<SceneNode*>(this->createChild(translate, rotate));
00365     }
00366     //-----------------------------------------------------------------------
00367     SceneNode* SceneNode::createChildSceneNode(const String& name, const Vector3& translate, 
00368         const Quaternion& rotate)
00369     {
00370         return static_cast<SceneNode*>(this->createChild(name, translate, rotate));
00371     }
00372     //-----------------------------------------------------------------------
00373     const LightList& SceneNode::findLights(Real radius) const
00374     {
00375         // TEMP FIX
00376         // If a scene node is static and lights have moved, light list won't change
00377         // can't use a simple global boolean flag since this is only called for
00378         // visible nodes, so temporarily visible nodes will not be updated
00379         // Since this is only called for visible nodes, skip the check for now
00380         //if (mLightListDirty)
00381         if (mCreator)
00382         {
00383             // Use SceneManager to calculate
00384             mCreator->_populateLightList(this->_getDerivedPosition(), radius, mLightList);
00385             mLightListDirty = false;
00386         }
00387         return mLightList;
00388 
00389     }
00390     //-----------------------------------------------------------------------
00391     void SceneNode::setAutoTracking(bool enabled, SceneNode* target, 
00392         const Vector3& localDirectionVector,
00393         const Vector3& offset)
00394     {
00395         if (enabled)
00396         {
00397             mAutoTrackTarget = target;
00398             mAutoTrackOffset = offset;
00399             mAutoTrackLocalDirection = localDirectionVector;
00400         }
00401         else
00402         {
00403             mAutoTrackTarget = 0;
00404         }
00405         if (mCreator)
00406             mCreator->_notifyAutotrackingSceneNode(this, enabled);
00407     }
00408     //-----------------------------------------------------------------------
00409     void SceneNode::setFixedYawAxis(bool useFixed, const Vector3& fixedAxis)
00410     {
00411         mYawFixed = useFixed;
00412         mYawFixedAxis = fixedAxis;
00413     }
00414 
00415     //-----------------------------------------------------------------------
00416     void SceneNode::yaw(const Radian& angle, TransformSpace relativeTo)
00417     {
00418         if (mYawFixed)
00419         {
00420             rotate(mYawFixedAxis, angle, relativeTo);
00421         }
00422         else
00423         {
00424             rotate(Vector3::UNIT_Y, angle, relativeTo);
00425         }
00426 
00427     }
00428     //-----------------------------------------------------------------------
00429     void SceneNode::setDirection(Real x, Real y, Real z, TransformSpace relativeTo, 
00430         const Vector3& localDirectionVector)
00431     {
00432         setDirection(Vector3(x,y,z), relativeTo, localDirectionVector);
00433     }
00434 
00435     //-----------------------------------------------------------------------
00436     void SceneNode::setDirection(const Vector3& vec, TransformSpace relativeTo, 
00437         const Vector3& localDirectionVector)
00438     {
00439         // Do nothing if given a zero vector
00440         if (vec == Vector3::ZERO) return;
00441 
00442         // Adjust vector so that it is relative to local Z
00443         Vector3 zAdjustVec;
00444         if (localDirectionVector == Vector3::NEGATIVE_UNIT_Z)
00445         {
00446             zAdjustVec = -vec;
00447         }
00448         else
00449         {
00450             Quaternion localToUnitZ = localDirectionVector.getRotationTo(Vector3::UNIT_Z);
00451             zAdjustVec = localToUnitZ * vec;
00452         }
00453         zAdjustVec.normalise();
00454 
00455         Quaternion targetOrientation;
00456         if( mYawFixed )
00457         {
00458             Vector3 xVec = mYawFixedAxis.crossProduct( zAdjustVec );
00459             xVec.normalise();
00460 
00461             Vector3 yVec = zAdjustVec.crossProduct( xVec );
00462             yVec.normalise();
00463             
00464             targetOrientation.FromAxes( xVec, yVec, zAdjustVec );
00465         }
00466         else
00467         {
00468 
00469             // Get axes from current quaternion
00470             Vector3 axes[3];
00471             _getDerivedOrientation().ToAxes(axes);
00472             Quaternion rotQuat;
00473             if (-zAdjustVec == axes[2])
00474             {
00475                 // Oops, a 180 degree turn (infinite possible rotation axes)
00476                 // Default to yaw i.e. use current UP
00477                 rotQuat.FromAngleAxis(Radian(Math::PI), axes[1]);
00478             }
00479             else
00480             {
00481                 // Derive shortest arc to new direction
00482                 rotQuat = axes[2].getRotationTo(zAdjustVec);
00483 
00484             }
00485             targetOrientation = rotQuat * mOrientation;
00486         }
00487 
00488         if (relativeTo == TS_LOCAL || !mParent)
00489         {
00490             mOrientation = targetOrientation;
00491         }
00492         else
00493         {
00494             if (relativeTo == TS_PARENT)
00495             {
00496                 mOrientation = targetOrientation * mParent->getOrientation().Inverse();
00497             }
00498             else if (relativeTo == TS_WORLD)
00499             {
00500                 mOrientation = targetOrientation * mParent->_getDerivedOrientation().Inverse();
00501             }
00502         }
00503 
00504 
00505     }
00506     //-----------------------------------------------------------------------
00507     void SceneNode::lookAt( const Vector3& targetPoint, TransformSpace relativeTo, 
00508         const Vector3& localDirectionVector)
00509     {
00510         this->setDirection(targetPoint - _getDerivedPosition(), relativeTo, 
00511             localDirectionVector);
00512     }
00513     //-----------------------------------------------------------------------
00514     void SceneNode::_autoTrack(void)
00515     {
00516         // NB assumes that all scene nodes have been updated
00517         if (mAutoTrackTarget)
00518         {
00519             lookAt(mAutoTrackTarget->_getDerivedPosition() + mAutoTrackOffset, 
00520                 TS_WORLD, mAutoTrackLocalDirection);
00521             // update self & children
00522             _update(true, true);
00523         }
00524     }
00525     //-----------------------------------------------------------------------
00526     SceneNode* SceneNode::getParentSceneNode(void) const
00527     {
00528         return static_cast<SceneNode*>(getParent());
00529     }
00530     //-----------------------------------------------------------------------
00531     void SceneNode::setVisible(bool visible, bool cascade)
00532     {
00533         ObjectMap::iterator oi, oiend;
00534         oiend = mObjectsByName.end();
00535         for (oi = mObjectsByName.begin(); oi != oiend; ++oi)
00536         {
00537             oi->second->setVisible(visible);
00538         }
00539 
00540         if (cascade)
00541         {
00542             ChildNodeMap::iterator i, iend;
00543             iend = mChildren.end();
00544             for (i = mChildren.begin(); i != iend; ++i)
00545             {
00546                 static_cast<SceneNode*>(i->second)->setVisible(visible, cascade);
00547             }
00548         }
00549     }
00550     //-----------------------------------------------------------------------
00551     void SceneNode::flipVisibility(bool cascade)
00552     {
00553         ObjectMap::iterator oi, oiend;
00554         oiend = mObjectsByName.end();
00555         for (oi = mObjectsByName.begin(); oi != oiend; ++oi)
00556         {
00557             oi->second->setVisible(!oi->second->isVisible());
00558         }
00559 
00560         if (cascade)
00561         {
00562             ChildNodeMap::iterator i, iend;
00563             iend = mChildren.end();
00564             for (i = mChildren.begin(); i != iend; ++i)
00565             {
00566                 static_cast<SceneNode*>(i->second)->flipVisibility(cascade);
00567             }
00568         }
00569     }
00570 
00571 
00572 
00573 }

Copyright © 2002-2003 by The OGRE Team
Last modified Sun Nov 28 19:48:45 2004