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