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

OgreNode.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 "OgreNode.h"
00027 
00028 #include "OgreException.h"
00029 #include "OgreMath.h"
00030 
00031 // Dependencies on render-related types due to ability to render node
00032 #include "OgreMaterialManager.h"
00033 #include "OgreMeshManager.h"
00034 #include "OgreMesh.h"
00035 #include "OgreSubMesh.h"
00036 #include "OgreCamera.h"
00037 
00038 namespace Ogre {
00039     
00040     unsigned long Node::msNextGeneratedNameExt = 1;
00041     //-----------------------------------------------------------------------
00042     Node::Node()
00043     {
00044         mParent = 0;
00045         mOrientation = mInitialOrientation = mDerivedOrientation = Quaternion::IDENTITY;
00046         mPosition = mInitialPosition = mDerivedPosition = Vector3::ZERO;
00047         mScale = mInitialScale = mDerivedScale = Vector3::UNIT_SCALE;
00048         mInheritScale = true;
00049         mParentNotified = false ;
00050 
00051         // Generate a name
00052         static char temp[64];
00053         sprintf(temp, "Unnamed_%lu", msNextGeneratedNameExt++);
00054         mName = temp;
00055         mAccumAnimWeight = 0.0f;
00056 
00057         needUpdate();
00058 
00059     }
00060     //-----------------------------------------------------------------------
00061     Node::Node(const String& name)
00062     {
00063         mName = name;
00064         mParent = 0;
00065         mOrientation = mInitialOrientation = mDerivedOrientation = Quaternion::IDENTITY;
00066         mPosition = mInitialPosition = mDerivedPosition = Vector3::ZERO;
00067         mScale = mInitialScale = mDerivedScale = Vector3::UNIT_SCALE;
00068         mInheritScale = true;
00069         mAccumAnimWeight = 0.0f;
00070         mParentNotified = false ;
00071 
00072         needUpdate();
00073 
00074     }
00075 
00076     //-----------------------------------------------------------------------
00077     Node::~Node()
00078     {
00079     }    
00080 
00081     //-----------------------------------------------------------------------
00082     Node* Node::getParent(void) const
00083     {
00084         return mParent;
00085     }
00086 
00087     //-----------------------------------------------------------------------
00088     void Node::setParent(Node* parent)
00089     {
00090         mParent = parent;
00091         // Request update from parent
00092         mParentNotified = false ;
00093         needUpdate();
00094     }
00095 
00096     //-----------------------------------------------------------------------
00097     Matrix4 Node::_getFullTransform(void) const
00098     {
00099         if (mCachedTransformOutOfDate)
00100         {
00101             // Use derived values 
00102             makeTransform( 
00103                 _getDerivedPosition(), _getDerivedScale(), 
00104                 _getDerivedOrientation(), mCachedTransform);
00105             mCachedTransformOutOfDate = false;
00106         }
00107         return mCachedTransform;
00108     }
00109     //-----------------------------------------------------------------------
00110     void Node::_update(bool updateChildren, bool parentHasChanged)
00111     {
00112         // always clear information about parent notification
00113         mParentNotified = false ;
00114         
00115         // Short circuit the off case
00116         if (!updateChildren && !mNeedParentUpdate && !mNeedChildUpdate && !parentHasChanged )
00117         {
00118             return;
00119         }
00120 
00121 
00122         // See if we should process everyone
00123         if (mNeedParentUpdate || parentHasChanged)
00124         {
00125             // Update transforms from parent
00126             _updateFromParent();
00127             mNeedParentUpdate = false;
00128         }
00129 
00130         if (mNeedChildUpdate || parentHasChanged)
00131         {
00132 
00133             ChildNodeMap::iterator it, itend;
00134             itend = mChildren.end();
00135             for (it = mChildren.begin(); it != itend; ++it)
00136             {
00137                 Node* child = it->second;
00138                 child->_update(true, true);
00139             }
00140             mChildrenToUpdate.clear();
00141         }
00142         else
00143         {
00144             // Just update selected children
00145 
00146             ChildUpdateSet::iterator it, itend;
00147             itend = mChildrenToUpdate.end();
00148             for(it = mChildrenToUpdate.begin(); it != itend; ++it)
00149             {
00150                 Node* child = *it;
00151                 child->_update(true, false);
00152             }
00153 
00154             mChildrenToUpdate.clear();
00155         }
00156 
00157         mNeedChildUpdate = false;
00158 
00159     }
00160 
00161     //-----------------------------------------------------------------------
00162     void Node::_updateFromParent(void) const
00163     {
00164         if (mParent)
00165         {
00166             // Combine orientation with that of parent
00167             Quaternion mParentQ = mParent->_getDerivedOrientation();
00168             mDerivedOrientation = mParentQ * mOrientation;
00169 
00170             // Change position vector based on parent's orientation & scale
00171             mDerivedPosition = mParentQ * (mPosition * mParent->_getDerivedScale());
00172 
00173             // Update scale
00174             if (mInheritScale)
00175             {
00176                 // Scale own position by parent scale
00177                 Vector3 parentScale = mParent->_getDerivedScale();
00178                 // Set own scale, NB just combine as equivalent axes, no shearing
00179                 mDerivedScale = mScale * parentScale;
00180 
00181             }
00182             else
00183             {
00184                 // No inheritence
00185                 mDerivedScale = mScale;
00186             }
00187 
00188             // Add altered position vector to parents
00189             mDerivedPosition += mParent->_getDerivedPosition();
00190         }
00191         else
00192         {
00193             // Root node, no parent
00194             mDerivedOrientation = mOrientation;
00195             mDerivedPosition = mPosition;
00196             mDerivedScale = mScale;
00197         }
00198 
00199         mCachedTransformOutOfDate = true;
00200         
00201 
00202     }
00203     //-----------------------------------------------------------------------
00204     Node* Node::createChild(const Vector3& translate, const Quaternion& rotate)
00205     {
00206         Node* newNode = createChildImpl();
00207         newNode->translate(translate);
00208         newNode->rotate(rotate);
00209         this->addChild(newNode);
00210 
00211         return newNode;
00212     }
00213     //-----------------------------------------------------------------------
00214     Node* Node::createChild(const String& name, const Vector3& translate, const Quaternion& rotate)
00215     {
00216         Node* newNode = createChildImpl(name);
00217         newNode->translate(translate);
00218         newNode->rotate(rotate);
00219         this->addChild(newNode);
00220 
00221         return newNode;
00222     }
00223     //-----------------------------------------------------------------------
00224     void Node::addChild(Node* child)
00225     {
00226         mChildren.insert(ChildNodeMap::value_type(child->getName(), child));
00227         child->setParent(this);
00228 
00229     }
00230     //-----------------------------------------------------------------------
00231     unsigned short Node::numChildren(void) const
00232     {
00233         return static_cast< unsigned short >( mChildren.size() );
00234     }
00235     //-----------------------------------------------------------------------
00236     Node* Node::getChild(unsigned short index) const
00237     {
00238         if( index < mChildren.size() )
00239         {
00240             ChildNodeMap::const_iterator i = mChildren.begin();
00241             while (index--) ++i;
00242             return i->second;
00243         }
00244         else
00245             return NULL;
00246     }
00247     //-----------------------------------------------------------------------
00248     Node* Node::removeChild(unsigned short index)
00249     {
00250         Node* ret;
00251         if (index < mChildren.size())
00252         {
00253             ChildNodeMap::iterator i = mChildren.begin();
00254             while (index--) ++i;
00255             ret = i->second;
00256             // cancel any pending update
00257             cancelUpdate(ret);
00258 
00259             mChildren.erase(i);
00260             ret->setParent(NULL);
00261             return ret;            
00262         }
00263         else
00264         {
00265             Except(
00266                 Exception::ERR_INVALIDPARAMS, 
00267                 "Child index out of bounds.", 
00268                 "Node::getChild" );
00269         }
00270         needUpdate();
00271         return 0;
00272     }
00273     //-----------------------------------------------------------------------
00274     const Quaternion& Node::getOrientation() const
00275     {
00276         return mOrientation;
00277     }
00278 
00279     //-----------------------------------------------------------------------
00280     void Node::setOrientation( const Quaternion & q )
00281     {
00282         mOrientation = q;
00283         needUpdate();
00284     }
00285     //-----------------------------------------------------------------------
00286     void Node::setOrientation( Real w, Real x, Real y, Real z)
00287     {
00288         mOrientation.w = w;
00289         mOrientation.x = x;
00290         mOrientation.y = y;
00291         mOrientation.z = z;
00292         needUpdate();
00293     }
00294     //-----------------------------------------------------------------------
00295     void Node::resetOrientation(void)
00296     {
00297         mOrientation = Quaternion::IDENTITY;
00298         needUpdate();
00299     }
00300 
00301     //-----------------------------------------------------------------------
00302     void Node::setPosition(const Vector3& pos)
00303     {
00304         mPosition = pos;
00305         needUpdate();
00306     }
00307 
00308 
00309     //-----------------------------------------------------------------------
00310     void Node::setPosition(Real x, Real y, Real z)
00311     {
00312         Vector3 v(x,y,z);
00313         setPosition(v);
00314     }
00315 
00316     //-----------------------------------------------------------------------
00317     const Vector3 & Node::getPosition(void) const
00318     {
00319         return mPosition;
00320     }
00321     //-----------------------------------------------------------------------
00322     Matrix3 Node::getLocalAxes(void) const
00323     {
00324         Vector3 axisX = Vector3::UNIT_X;
00325         Vector3 axisY = Vector3::UNIT_Y;
00326         Vector3 axisZ = Vector3::UNIT_Z;
00327 
00328         axisX = mOrientation * axisX;
00329         axisY = mOrientation * axisY;
00330         axisZ = mOrientation * axisZ;
00331 
00332         return Matrix3(axisX.x, axisY.x, axisZ.x,
00333                        axisX.y, axisY.y, axisZ.y,
00334                        axisX.z, axisY.z, axisZ.z);
00335     }
00336 
00337     //-----------------------------------------------------------------------
00338     void Node::translate(const Vector3& d)
00339     {
00340         mPosition += d;
00341         needUpdate();
00342 
00343     }
00344     //-----------------------------------------------------------------------
00345     void Node::translate(Real x, Real y, Real z)
00346     {
00347         Vector3 v(x,y,z);
00348         translate(v);
00349     }
00350     //-----------------------------------------------------------------------
00351     void Node::translate(const Matrix3& axes, const Vector3& move)
00352     {
00353         Vector3 derived = axes * move;
00354         translate(derived);
00355     }
00356     //-----------------------------------------------------------------------
00357     void Node::translate(const Matrix3& axes, Real x, Real y, Real z)
00358     {
00359         Vector3 d(x,y,z);
00360         translate(axes,d);
00361     }
00362     //-----------------------------------------------------------------------
00363     void Node::roll(Real angleunits)
00364     {
00365         rotate(Vector3::UNIT_Z, angleunits);
00366     }
00367     //-----------------------------------------------------------------------
00368     void Node::pitch(Real angleunits)
00369     {
00370         rotate(Vector3::UNIT_X, angleunits);
00371     }
00372     //-----------------------------------------------------------------------
00373     void Node::yaw(Real angleunits)
00374     {
00375         rotate(Vector3::UNIT_Y, angleunits);
00376 
00377     }
00378     //-----------------------------------------------------------------------
00379     void Node::rotate(const Vector3& axis, Real angleunits)
00380     {
00381         Quaternion q;
00382         q.FromAngleAxis(Math::AngleUnitsToRadians(angleunits),axis);
00383         rotate(q);
00384     }
00385 
00386     //-----------------------------------------------------------------------
00387     void Node::rotate(const Quaternion& q)
00388     {
00389         // Note the order of the mult, i.e. q comes after
00390         mOrientation = mOrientation * q;
00391         needUpdate();
00392     }
00393     //-----------------------------------------------------------------------
00394     const Quaternion & Node::_getDerivedOrientation(void) const
00395     {
00396         if (mNeedParentUpdate)
00397         {
00398             _updateFromParent();
00399             mNeedParentUpdate = false;
00400         }
00401         return mDerivedOrientation;
00402     }
00403     //-----------------------------------------------------------------------
00404     const Vector3 & Node::_getDerivedPosition(void) const
00405     {
00406         if (mNeedParentUpdate)
00407         {
00408             _updateFromParent();
00409             mNeedParentUpdate = false;
00410         }
00411         return mDerivedPosition;
00412     }
00413     //-----------------------------------------------------------------------
00414     const Vector3 & Node::_getDerivedScale(void) const
00415     {
00416         return mDerivedScale;
00417     }
00418     //-----------------------------------------------------------------------
00419     void Node::removeAllChildren(void)
00420     {
00421         mChildren.clear();
00422     }
00423     //-----------------------------------------------------------------------
00424     void Node::setScale(const Vector3& scale)
00425     {
00426         mScale = scale;
00427         needUpdate();
00428     }
00429     //-----------------------------------------------------------------------
00430     void Node::setScale(Real x, Real y, Real z)
00431     {
00432         mScale.x = x;
00433         mScale.y = y;
00434         mScale.z = z;
00435         needUpdate();
00436     }
00437     //-----------------------------------------------------------------------
00438     const Vector3 & Node::getScale(void) const
00439     {
00440         return mScale;
00441     }
00442     //-----------------------------------------------------------------------
00443     void Node::setInheritScale(bool inherit)
00444     {
00445         mInheritScale = inherit;
00446         needUpdate();
00447     }
00448     //-----------------------------------------------------------------------
00449     bool Node::getInheritScale(void) const
00450     {
00451         return mInheritScale;
00452     }
00453     //-----------------------------------------------------------------------
00454     void Node::scale(const Vector3& scale)
00455     {
00456         mScale = mScale * scale;
00457         needUpdate();
00458 
00459     }
00460     //-----------------------------------------------------------------------
00461     void Node::scale(Real x, Real y, Real z)
00462     {
00463         mScale.x *= x;
00464         mScale.y *= y;
00465         mScale.z *= z;
00466         needUpdate();
00467 
00468     }
00469     //-----------------------------------------------------------------------
00470     void Node::makeTransform(const Vector3& position, const Vector3& scale, const Quaternion& orientation, 
00471         Matrix4& destMatrix) const
00472     {
00473         destMatrix = Matrix4::IDENTITY;
00474         // Ordering:
00475         //    1. Scale
00476         //    2. Rotate
00477         //    3. Translate
00478 
00479         // Parent scaling is already applied to derived position
00480         // Own scale is applied before rotation
00481         Matrix3 rot3x3, scale3x3;
00482         orientation.ToRotationMatrix(rot3x3);
00483         scale3x3 = Matrix3::ZERO;
00484         scale3x3[0][0] = scale.x;
00485         scale3x3[1][1] = scale.y;
00486         scale3x3[2][2] = scale.z;
00487 
00488         destMatrix = rot3x3 * scale3x3;
00489         destMatrix.setTrans(position);
00490     }
00491     //-----------------------------------------------------------------------
00492     void Node::makeInverseTransform(const Vector3& position, const Vector3& scale, const Quaternion& orientation, 
00493         Matrix4& destMatrix)
00494     {
00495         destMatrix = Matrix4::IDENTITY;
00496 
00497         // Invert the parameters
00498         Vector3 invTranslate = -position;
00499         Vector3 invScale;
00500         invScale.x = 1 / scale.x;
00501         invScale.y = 1 / scale.y;
00502         invScale.z = 1 / scale.z;
00503 
00504         Quaternion invRot = orientation.Inverse();
00505         
00506         // Because we're inverting, order is translation, rotation, scale
00507         // So make translation relative to scale & rotation
00508         invTranslate.x *= invScale.x; // scale
00509         invTranslate.y *= invScale.y; // scale
00510         invTranslate.z *= invScale.z; // scale
00511         invTranslate = invRot * invTranslate; // rotate
00512 
00513         // Next, make a 3x3 rotation matrix and apply inverse scale
00514         Matrix3 rot3x3, scale3x3;
00515         invRot.ToRotationMatrix(rot3x3);
00516         scale3x3 = Matrix3::ZERO;
00517         scale3x3[0][0] = invScale.x;
00518         scale3x3[1][1] = invScale.y;
00519         scale3x3[2][2] = invScale.z;
00520 
00521         // Set up final matrix with scale & rotation
00522         destMatrix = scale3x3 * rot3x3;
00523 
00524         destMatrix.setTrans(invTranslate);
00525     }
00526     //-----------------------------------------------------------------------
00527     const String& Node::getName(void) const
00528     {
00529         return mName;
00530     }
00531     //-----------------------------------------------------------------------
00532     Material* Node::getMaterial(void) const
00533     {
00534         static Material* pMaterial = 0;
00535 
00536         if (!pMaterial)
00537         {
00538             pMaterial = (Material*)MaterialManager::getSingleton().getByName("Core/NodeMaterial");
00539             if (!pMaterial)
00540                 Except( Exception::ERR_ITEM_NOT_FOUND, "Could not find material Core/NodeMaterial",
00541                     "Node::getMaterial" );
00542             pMaterial->load();
00543         }
00544         return pMaterial;
00545 
00546     }
00547     //-----------------------------------------------------------------------
00548     void Node::getRenderOperation(RenderOperation& op)
00549     {
00550         static SubMesh* pSubMesh = 0;
00551         if (!pSubMesh)
00552         {
00553             Mesh *pMesh = MeshManager::getSingleton().load("axes.mesh");
00554             pSubMesh = pMesh->getSubMesh(0);
00555         }
00556         pSubMesh->_getRenderOperation(op);
00557     }
00558     //-----------------------------------------------------------------------
00559     void Node::getWorldTransforms(Matrix4* xform) const
00560     {
00561         // Assumes up to date
00562         *xform = this->_getFullTransform();
00563     }
00564     //-----------------------------------------------------------------------
00565     const Quaternion& Node::getWorldOrientation(void) const
00566     {
00567         return _getDerivedOrientation();
00568     }
00569     //-----------------------------------------------------------------------
00570     const Vector3& Node::getWorldPosition(void) const
00571     {
00572         return _getDerivedPosition();
00573     }
00574     //-----------------------------------------------------------------------
00575     void Node::setInitialState(void)
00576     {
00577         mInitialPosition = mPosition;
00578         mInitialOrientation = mOrientation;
00579         mInitialScale = mScale;
00580     }
00581     //-----------------------------------------------------------------------
00582     void Node::resetToInitialState(void)
00583     {
00584         mPosition = mInitialPosition;
00585         mOrientation = mInitialOrientation;
00586         mScale = mInitialScale;
00587 
00588         // Reset weights
00589         mAccumAnimWeight = 0.0f;
00590         mTransFromInitial = Vector3::ZERO;
00591         mRotFromInitial = Quaternion::IDENTITY;
00592         mScaleFromInitial = Vector3::UNIT_SCALE;
00593 
00594         needUpdate();
00595     }
00596     //-----------------------------------------------------------------------
00597     const Vector3& Node::getInitialPosition(void) const
00598     {
00599         return mInitialPosition;
00600     }
00601     //-----------------------------------------------------------------------
00602     const Quaternion& Node::getInitialOrientation(void) const
00603     {
00604         return mInitialOrientation;
00605 
00606     }
00607     //-----------------------------------------------------------------------
00608     const Vector3& Node::getInitialScale(void) const
00609     {
00610         return mInitialScale;
00611     }
00612     //-----------------------------------------------------------------------
00613     Node* Node::getChild(const String& name) const
00614     {
00615         ChildNodeMap::const_iterator i = mChildren.find(name);
00616 
00617         if (i == mChildren.end())
00618         {
00619             Except(Exception::ERR_ITEM_NOT_FOUND, "Child node named " + name +
00620                 " does not exist.", "Node::getChild");
00621         }
00622         return i->second;
00623 
00624     }
00625     //-----------------------------------------------------------------------
00626     Node* Node::removeChild(const String& name)
00627     {
00628         ChildNodeMap::iterator i = mChildren.find(name);
00629 
00630         if (i == mChildren.end())
00631         {
00632             Except(Exception::ERR_ITEM_NOT_FOUND, "Child node named " + name +
00633                 " does not exist.", "Node::removeChild");
00634         }
00635 
00636         Node* ret = i->second;
00637         // Cancel any pending update
00638         cancelUpdate(ret);
00639 
00640         mChildren.erase(i);
00641         ret->setParent(NULL);
00642 
00643         return ret;
00644 
00645 
00646     }
00647     //-----------------------------------------------------------------------
00648     Node::ChildNodeIterator Node::getChildIterator(void)
00649     {
00650         return ChildNodeIterator(mChildren.begin(), mChildren.end());
00651     }
00652     //-----------------------------------------------------------------------
00653     void Node::_weightedTransform(Real weight, const Vector3& translate, 
00654        const Quaternion& rotate, const Vector3& scale)
00655     {
00656         // If no previous transforms, we can just apply
00657         if (mAccumAnimWeight == 0.0f)
00658         {
00659             mRotFromInitial = rotate;
00660             mTransFromInitial = translate;
00661             mScaleFromInitial = scale;
00662             mAccumAnimWeight = weight;
00663         }
00664         else
00665         {
00666             // Blend with existing
00667             Real factor = weight / (mAccumAnimWeight + weight);
00668             mTransFromInitial += (translate - mTransFromInitial) * factor;
00669             mRotFromInitial = 
00670                 Quaternion::Slerp(factor, mRotFromInitial, rotate);
00671             // For scale, find delta from 1.0, factor then add back before applying
00672             Vector3 scaleDiff = (scale - Vector3::UNIT_SCALE) * factor;
00673             mScaleFromInitial = mScaleFromInitial * 
00674                 (scaleDiff + Vector3::UNIT_SCALE);
00675             mAccumAnimWeight += weight;
00676 
00677         }
00678 
00679         // Update final based on bind position + offsets
00680         mOrientation = mInitialOrientation * mRotFromInitial;
00681         mPosition = mInitialPosition + mTransFromInitial;
00682         mScale = mInitialScale * mScaleFromInitial;
00683         needUpdate();
00684 
00685     }
00686     //-----------------------------------------------------------------------
00687     Real Node::getSquaredViewDepth(const Camera* cam) const
00688     {
00689         Vector3 diff = _getDerivedPosition() - cam->getDerivedPosition();
00690 
00691         // NB use squared length rather than real depth to avoid square root
00692         return diff.squaredLength();
00693     }
00694     //-----------------------------------------------------------------------
00695     void Node::needUpdate()
00696     {
00697         // If we're already going to update everything this doesn't matter
00698         /* FIX: removed because this causes newly created nodes
00699                 which already have mNeedUpdate == true not to notify parent when 
00700                 added!
00701         if (mNeedUpdate)
00702         {
00703             return;
00704         }
00705         */
00706 
00707         mNeedParentUpdate = true;
00708         mNeedChildUpdate = true;
00709         mCachedTransformOutOfDate = true;
00710 
00711         // Make sure we're not root and parent hasn't been notified before
00712         if (mParent && !mParentNotified)
00713         {
00714             mParent->requestUpdate(this);
00715             mParentNotified = true ;
00716         }
00717 
00718         // all children will be updated
00719         mChildrenToUpdate.clear();
00720     }
00721     //-----------------------------------------------------------------------
00722     void Node::requestUpdate(Node* child)
00723     {
00724         // If we're already going to update everything this doesn't matter
00725         if (mNeedChildUpdate)
00726         {
00727             return;
00728         }
00729             
00730         mChildrenToUpdate.insert(child);
00731         // Request selective update of me, if we didn't do it before
00732         if (mParent && !mParentNotified) {
00733             mParent->requestUpdate(this);
00734             mParentNotified = true ;
00735         }
00736 
00737     }
00738     //-----------------------------------------------------------------------
00739     void Node::cancelUpdate(Node* child)
00740     {
00741         mChildrenToUpdate.erase(child);
00742 
00743         // Propogate this up if we're done
00744         if (mChildrenToUpdate.empty() && mParent && !mNeedChildUpdate)
00745         {
00746             mParent->cancelUpdate(this);
00747             mParentNotified = false ;
00748         }
00749     }
00750 }
00751 

Copyright © 2002-2003 by The OGRE Team
Last modified Wed Jan 21 00:10:19 2004