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