source: trunk/VUT/work/ogre_changes/OgreMain/src/OgreSceneNode.cpp @ 61

Revision 61, 21.9 KB checked in by mattausch, 19 years ago (diff)
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2005 The OGRE Team
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23-----------------------------------------------------------------------------
24*/
25#include "OgreStableHeaders.h"
26#include "OgreSceneNode.h"
27
28#include "OgreException.h"
29#include "OgreEntity.h"
30#include "OgreCamera.h"
31#include "OgreLight.h"
32#include "OgreMath.h"
33#include "OgreSceneManager.h"
34#include "OgreMovableObject.h"
35#include "OgreWireBoundingBox.h"
36
37namespace Ogre {
38    //-----------------------------------------------------------------------
39    SceneNode::SceneNode(SceneManager* creator)
40    : Node(), mLightListDirty(true), mWireBoundingBox(0),
41        mShowBoundingBox(false), mCreator(creator),
42        mYawFixed(false), mAutoTrackTarget(0), mIsInSceneGraph(false)
43#ifdef GTP_VISIBILITY_MODIFIED_OGRE
44        , mLastVisited(0), mVisible(false), mLastRendered(-1)
45#endif //GTP_VISIBILITY_MODIFIED_OGRE
46    {
47        needUpdate();
48    }
49    //-----------------------------------------------------------------------
50    SceneNode::SceneNode(SceneManager* creator, const String& name)
51    : Node(name), mLightListDirty(true), mWireBoundingBox(0),
52        mShowBoundingBox(false), mCreator(creator), mYawFixed(false),
53        mAutoTrackTarget(0), mIsInSceneGraph(false)
54        #ifdef GTP_VISIBILITY_MODIFIED_OGRE
55        , mLastVisited(0), mVisible(false)
56        #endif //GTP_VISIBILITY_MODIFIED_OGRE
57    {
58        needUpdate();
59    }
60    //-----------------------------------------------------------------------
61    SceneNode::~SceneNode()
62    {
63        // Detach all objects, do this manually to avoid needUpdate() call
64        // which can fail because of deleted items
65                ObjectMap::iterator itr;
66                MovableObject* ret;
67                for ( itr = mObjectsByName.begin(); itr != mObjectsByName.end(); itr++ )
68                {
69                  ret = itr->second;
70                  ret->_notifyAttached((SceneNode*)0);
71                }
72        mObjectsByName.clear();
73
74        if (mWireBoundingBox) {
75                        delete mWireBoundingBox;
76                }
77    }
78    //-----------------------------------------------------------------------
79    void SceneNode::_update(bool updateChildren, bool parentHasChanged)
80    {
81        Node::_update(updateChildren, parentHasChanged);
82        _updateBounds();
83        mLightListDirty = true;
84
85    }
86    //-----------------------------------------------------------------------
87        void SceneNode::setParent(Node* parent)
88        {
89                Node::setParent(parent);
90
91                if (parent)
92                {
93                        SceneNode* sceneParent = static_cast<SceneNode*>(parent);
94                        setInSceneGraph(sceneParent->isInSceneGraph());
95                }
96                else
97                {
98                        setInSceneGraph(false);
99                }
100        }
101    //-----------------------------------------------------------------------
102        void SceneNode::setInSceneGraph(bool inGraph)
103        {
104                if (inGraph != mIsInSceneGraph)
105                {
106                        mIsInSceneGraph = inGraph;
107                        // Tell children
108                ChildNodeMap::iterator child;
109            for (child = mChildren.begin(); child != mChildren.end(); ++child)
110                {
111                SceneNode* sceneChild = static_cast<SceneNode*>(child->second);
112                                sceneChild->setInSceneGraph(inGraph);
113                        }
114                }
115        }
116    //-----------------------------------------------------------------------
117    void SceneNode::attachObject(MovableObject* obj)
118    {
119        obj->_notifyAttached(this);
120
121        // Also add to name index
122        std::pair<ObjectMap::iterator, bool> insresult =
123            mObjectsByName.insert(ObjectMap::value_type(obj->getName(), obj));
124        assert(insresult.second && "Object was not attached because an object of the "
125            "same name was already attached to this node.");
126
127        // Make sure bounds get updated (must go right to the top)
128        needUpdate();
129    }
130    //-----------------------------------------------------------------------
131    unsigned short SceneNode::numAttachedObjects(void) const
132    {
133        return static_cast< unsigned short >( mObjectsByName.size() );
134    }
135    //-----------------------------------------------------------------------
136    MovableObject* SceneNode::getAttachedObject(unsigned short index)
137    {
138        if (index < mObjectsByName.size())
139        {
140            ObjectMap::iterator i = mObjectsByName.begin();
141            // Increment (must do this one at a time)           
142            while (index--)++i;
143
144            return i->second;
145        }
146        else
147        {
148            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Object index out of bounds.", "SceneNode::getAttachedObject");
149        }
150        return 0;
151    }
152    //-----------------------------------------------------------------------
153    MovableObject* SceneNode::getAttachedObject(const String& name)
154    {
155        // Look up
156        ObjectMap::iterator i = mObjectsByName.find(name);
157
158        if (i == mObjectsByName.end())
159        {
160            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Attached object " +
161                name + " not found.", "SceneNode::getAttachedObject");
162        }
163
164        return i->second;
165
166    }
167    //-----------------------------------------------------------------------
168    MovableObject* SceneNode::detachObject(unsigned short index)
169    {
170        MovableObject* ret;
171        if (index < mObjectsByName.size())
172        {
173
174            ObjectMap::iterator i = mObjectsByName.begin();
175            // Increment (must do this one at a time)           
176            while (index--)++i;
177
178            ret = i->second;
179            mObjectsByName.erase(i);
180            ret->_notifyAttached((SceneNode*)0);
181
182            // Make sure bounds get updated (must go right to the top)
183            needUpdate();
184
185            return ret;
186
187        }
188        else
189        {
190            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Object index out of bounds.", "SceneNode::getAttchedEntity");
191        }
192        return 0;
193
194    }
195    //-----------------------------------------------------------------------
196    MovableObject* SceneNode::detachObject(const String& name)
197    {
198        ObjectMap::iterator it = mObjectsByName.find(name);
199        if (it == mObjectsByName.end())
200        {
201            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Object " + name + " is not attached "
202                "to this node.", "SceneNode::detachObject");
203        }
204        MovableObject* ret = it->second;
205        mObjectsByName.erase(it);
206        ret->_notifyAttached((SceneNode*)0);
207        // Make sure bounds get updated (must go right to the top)
208        needUpdate();
209       
210        return ret;
211
212    }
213    //-----------------------------------------------------------------------
214    void SceneNode::detachObject(MovableObject* obj)
215    {
216        ObjectMap::iterator i, iend;
217        iend = mObjectsByName.end();
218        for (i = mObjectsByName.begin(); i != iend; ++i)
219        {
220            if (i->second == obj)
221            {
222                mObjectsByName.erase(i);
223                break;
224            }
225        }
226        obj->_notifyAttached((SceneNode*)0);
227
228        // Make sure bounds get updated (must go right to the top)
229        needUpdate();
230
231    }
232    //-----------------------------------------------------------------------
233    void SceneNode::detachAllObjects(void)
234    {
235                ObjectMap::iterator itr;
236                MovableObject* ret;
237                for ( itr = mObjectsByName.begin(); itr != mObjectsByName.end(); itr++ )
238                {
239                  ret = itr->second;
240                  ret->_notifyAttached((SceneNode*)0);
241                }
242        mObjectsByName.clear();
243        // Make sure bounds get updated (must go right to the top)
244        needUpdate();
245    }
246    //-----------------------------------------------------------------------
247    void SceneNode::_updateBounds(void)
248    {
249        // Reset bounds first
250        mWorldAABB.setNull();
251
252        // Update bounds from own attached objects
253        ObjectMap::iterator i;
254        for (i = mObjectsByName.begin(); i != mObjectsByName.end(); ++i)
255        {
256            // Merge world bounds of each object
257            mWorldAABB.merge(i->second->getWorldBoundingBox(true));
258        }
259
260        // Merge with children
261        ChildNodeMap::iterator child;
262        for (child = mChildren.begin(); child != mChildren.end(); ++child)
263        {
264            SceneNode* sceneChild = static_cast<SceneNode*>(child->second);
265            mWorldAABB.merge(sceneChild->mWorldAABB);
266        }
267
268    }
269    //-----------------------------------------------------------------------
270    void SceneNode::_findVisibleObjects(Camera* cam, RenderQueue* queue,
271        bool includeChildren, bool displayNodes, bool onlyShadowCasters)
272    {
273        // Check self visible
274        if (!cam->isVisible(mWorldAABB))
275            return;
276
277        // Add all entities
278        ObjectMap::iterator iobj;
279        ObjectMap::iterator iobjend = mObjectsByName.end();
280        for (iobj = mObjectsByName.begin(); iobj != iobjend; ++iobj)
281        {
282            // Tell attached objects about camera position (incase any extra processing they want to do)
283            iobj->second->_notifyCurrentCamera(cam);
284            if (iobj->second->isVisible() &&
285                (!onlyShadowCasters || iobj->second->getCastShadows()))
286            {
287                iobj->second->_updateRenderQueue(queue);
288            }
289        }
290
291        if (includeChildren)
292        {
293            ChildNodeMap::iterator child, childend;
294            childend = mChildren.end();
295            for (child = mChildren.begin(); child != childend; ++child)
296            {
297                SceneNode* sceneChild = static_cast<SceneNode*>(child->second);
298                sceneChild->_findVisibleObjects(cam, queue, includeChildren, displayNodes);
299            }
300        }
301
302        if (displayNodes)
303        {
304            // Include self in the render queue
305            queue->addRenderable(this);
306        }
307
308                // Check if the bounding box should be shown.
309                // See if our flag is set or if the scene manager flag is set.
310                if (mShowBoundingBox || (mCreator && mCreator->getShowBoundingBoxes()))
311                {
312                        _addBoundingBoxToQueue(queue);
313                }
314
315
316    }
317
318
319        void SceneNode::_addBoundingBoxToQueue(RenderQueue* queue) {
320                // Create a WireBoundingBox if needed.
321                if (mWireBoundingBox == NULL) {
322                        mWireBoundingBox = new WireBoundingBox();
323                }
324                mWireBoundingBox->setupBoundingBox(mWorldAABB);
325                queue->addRenderable(mWireBoundingBox);
326        }
327
328        void SceneNode::showBoundingBox(bool bShow) {
329                mShowBoundingBox = bShow;
330        }
331
332        bool SceneNode::getShowBoundingBox() const {
333                return mShowBoundingBox;
334        }
335
336
337    //-----------------------------------------------------------------------
338    Node* SceneNode::createChildImpl(void)
339    {
340        assert(mCreator);
341        return mCreator->createSceneNode();
342    }
343    //-----------------------------------------------------------------------
344    Node* SceneNode::createChildImpl(const String& name)
345    {
346        assert(mCreator);
347        return mCreator->createSceneNode(name);
348    }
349    //-----------------------------------------------------------------------
350    AxisAlignedBox SceneNode::_getWorldAABB(void) const
351    {
352        return mWorldAABB;
353    }
354    //-----------------------------------------------------------------------
355    SceneNode::ObjectIterator SceneNode::getAttachedObjectIterator(void)
356    {
357        return ObjectIterator(mObjectsByName.begin(), mObjectsByName.end());
358    }
359        //-----------------------------------------------------------------------
360        SceneNode::ConstObjectIterator SceneNode::getAttachedObjectIterator(void) const
361        {
362                return ConstObjectIterator(mObjectsByName.begin(), mObjectsByName.end());
363        }
364    //-----------------------------------------------------------------------
365    SceneManager* SceneNode::getCreator(void) const
366    {
367        return mCreator;
368    }
369    //-----------------------------------------------------------------------
370    void SceneNode::removeAndDestroyChild(const String& name)
371    {
372        SceneNode* pChild = static_cast<SceneNode*>(getChild(name));
373        pChild->removeAndDestroyAllChildren();
374
375        removeChild(name);
376        pChild->getCreator()->destroySceneNode(name);
377
378    }
379    //-----------------------------------------------------------------------
380    void SceneNode::removeAndDestroyChild(unsigned short index)
381    {
382        SceneNode* pChild = static_cast<SceneNode*>(getChild(index));
383        pChild->removeAndDestroyAllChildren();
384
385        removeChild(index);
386        pChild->getCreator()->destroySceneNode(pChild->getName());
387    }
388    //-----------------------------------------------------------------------
389    void SceneNode::removeAndDestroyAllChildren(void)
390    {
391        ChildNodeMap::iterator i, iend;
392        iend = mChildren.end();
393        for (i = mChildren.begin(); i != iend; ++i)
394        {
395            SceneNode* sn = static_cast<SceneNode*>(i->second);
396            sn->removeAndDestroyAllChildren();
397            sn->getCreator()->destroySceneNode(sn->getName());
398        }
399            mChildren.clear();
400        needUpdate();
401    }
402    //-----------------------------------------------------------------------
403        SceneNode* SceneNode::createChildSceneNode(const Vector3& translate,
404        const Quaternion& rotate)
405        {
406                return static_cast<SceneNode*>(this->createChild(translate, rotate));
407        }
408    //-----------------------------------------------------------------------
409    SceneNode* SceneNode::createChildSceneNode(const String& name, const Vector3& translate,
410                const Quaternion& rotate)
411        {
412                return static_cast<SceneNode*>(this->createChild(name, translate, rotate));
413        }
414    //-----------------------------------------------------------------------
415    const LightList& SceneNode::findLights(Real radius) const
416    {
417        // TEMP FIX
418        // If a scene node is static and lights have moved, light list won't change
419        // can't use a simple global boolean flag since this is only called for
420        // visible nodes, so temporarily visible nodes will not be updated
421        // Since this is only called for visible nodes, skip the check for now
422        //if (mLightListDirty)
423        if (mCreator)
424        {
425            // Use SceneManager to calculate
426            mCreator->_populateLightList(this->_getDerivedPosition(), radius, mLightList);
427            mLightListDirty = false;
428        }
429        return mLightList;
430
431    }
432    //-----------------------------------------------------------------------
433    void SceneNode::setAutoTracking(bool enabled, SceneNode* target,
434        const Vector3& localDirectionVector,
435        const Vector3& offset)
436    {
437        if (enabled)
438        {
439            mAutoTrackTarget = target;
440            mAutoTrackOffset = offset;
441            mAutoTrackLocalDirection = localDirectionVector;
442        }
443        else
444        {
445            mAutoTrackTarget = 0;
446        }
447        if (mCreator)
448            mCreator->_notifyAutotrackingSceneNode(this, enabled);
449    }
450    //-----------------------------------------------------------------------
451    void SceneNode::setFixedYawAxis(bool useFixed, const Vector3& fixedAxis)
452    {
453        mYawFixed = useFixed;
454        mYawFixedAxis = fixedAxis;
455    }
456
457        //-----------------------------------------------------------------------
458        void SceneNode::yaw(const Radian& angle, TransformSpace relativeTo)
459        {
460                if (mYawFixed)
461                {
462                        rotate(mYawFixedAxis, angle, relativeTo);
463                }
464                else
465                {
466                        rotate(Vector3::UNIT_Y, angle, relativeTo);
467                }
468
469        }
470    //-----------------------------------------------------------------------
471    void SceneNode::setDirection(Real x, Real y, Real z, TransformSpace relativeTo,
472        const Vector3& localDirectionVector)
473    {
474        setDirection(Vector3(x,y,z), relativeTo, localDirectionVector);
475    }
476
477    //-----------------------------------------------------------------------
478    void SceneNode::setDirection(const Vector3& vec, TransformSpace relativeTo,
479        const Vector3& localDirectionVector)
480    {
481        // Do nothing if given a zero vector
482        if (vec == Vector3::ZERO) return;
483
484        // Adjust vector so that it is relative to local Z
485        Vector3 zAdjustVec;
486        if (localDirectionVector == Vector3::NEGATIVE_UNIT_Z)
487        {
488            zAdjustVec = -vec;
489        }
490        else
491        {
492            Quaternion localToUnitZ = localDirectionVector.getRotationTo(Vector3::UNIT_Z);
493            zAdjustVec = localToUnitZ * vec;
494        }
495        zAdjustVec.normalise();
496
497        Quaternion targetOrientation;
498        if( mYawFixed )
499        {
500            Vector3 xVec = mYawFixedAxis.crossProduct( zAdjustVec );
501            xVec.normalise();
502
503            Vector3 yVec = zAdjustVec.crossProduct( xVec );
504            yVec.normalise();
505           
506            targetOrientation.FromAxes( xVec, yVec, zAdjustVec );
507        }
508        else
509        {
510
511            // Get axes from current quaternion
512            Vector3 axes[3];
513            _getDerivedOrientation().ToAxes(axes);
514            Quaternion rotQuat;
515            if ( (axes[2]+zAdjustVec).squaredLength() <  0.00005f)
516            {
517                // Oops, a 180 degree turn (infinite possible rotation axes)
518                // Default to yaw i.e. use current UP
519                rotQuat.FromAngleAxis(Radian(Math::PI), axes[1]);
520            }
521            else
522            {
523                // Derive shortest arc to new direction
524                rotQuat = axes[2].getRotationTo(zAdjustVec);
525
526            }
527            targetOrientation = rotQuat * mOrientation;
528        }
529
530        if (relativeTo == TS_LOCAL || !mParent)
531        {
532            setOrientation(targetOrientation);
533        }
534        else
535        {
536            if (relativeTo == TS_PARENT)
537            {
538                setOrientation(targetOrientation * mParent->getOrientation().Inverse());
539            }
540            else if (relativeTo == TS_WORLD)
541            {
542                setOrientation(targetOrientation * mParent->_getDerivedOrientation().Inverse());
543            }
544        }
545
546
547    }
548    //-----------------------------------------------------------------------
549    void SceneNode::lookAt( const Vector3& targetPoint, TransformSpace relativeTo,
550        const Vector3& localDirectionVector)
551    {
552        this->setDirection(targetPoint - _getDerivedPosition(), relativeTo,
553            localDirectionVector);
554    }
555    //-----------------------------------------------------------------------
556    void SceneNode::_autoTrack(void)
557    {
558        // NB assumes that all scene nodes have been updated
559        if (mAutoTrackTarget)
560        {
561            lookAt(mAutoTrackTarget->_getDerivedPosition() + mAutoTrackOffset,
562                TS_WORLD, mAutoTrackLocalDirection);
563            // update self & children
564            _update(true, true);
565        }
566    }
567    //-----------------------------------------------------------------------
568    SceneNode* SceneNode::getParentSceneNode(void) const
569    {
570        return static_cast<SceneNode*>(getParent());
571    }
572    //-----------------------------------------------------------------------
573    void SceneNode::setVisible(bool visible, bool cascade)
574    {
575        ObjectMap::iterator oi, oiend;
576        oiend = mObjectsByName.end();
577        for (oi = mObjectsByName.begin(); oi != oiend; ++oi)
578        {
579            oi->second->setVisible(visible);
580        }
581
582        if (cascade)
583        {
584            ChildNodeMap::iterator i, iend;
585            iend = mChildren.end();
586            for (i = mChildren.begin(); i != iend; ++i)
587            {
588                static_cast<SceneNode*>(i->second)->setVisible(visible, cascade);
589            }
590        }
591    }
592    //-----------------------------------------------------------------------
593    void SceneNode::flipVisibility(bool cascade)
594    {
595        ObjectMap::iterator oi, oiend;
596        oiend = mObjectsByName.end();
597        for (oi = mObjectsByName.begin(); oi != oiend; ++oi)
598        {
599            oi->second->setVisible(!oi->second->isVisible());
600        }
601
602        if (cascade)
603        {
604            ChildNodeMap::iterator i, iend;
605            iend = mChildren.end();
606            for (i = mChildren.begin(); i != iend; ++i)
607            {
608                static_cast<SceneNode*>(i->second)->flipVisibility(cascade);
609            }
610        }
611    }
612        #ifdef GTP_VISIBILITY_MODIFIED_OGRE
613        //-----------------------------------------------------------------------       
614        int SceneNode::lastVisited(void)
615        {
616                return mLastVisited;
617        }
618        //-----------------------------------------------------------------------
619        void SceneNode::setLastVisited(int frameid)
620        {
621                mLastVisited = frameid;
622        }
623        //-----------------------------------------------------------------------       
624        void SceneNode::setNodeVisible(bool visible)
625        {
626                mVisible = visible;
627        }
628        //-----------------------------------------------------------------------       
629        bool SceneNode::isNodeVisible(void)
630        {
631                return mVisible;
632        }
633        //-----------------------------------------------------------------------       
634        int SceneNode::lastRendered(void)
635        {
636                return mLastRendered;
637        }
638        //-----------------------------------------------------------------------
639        void SceneNode::setLastRendered(int frameid)
640        {
641                mLastRendered = frameid;
642        }
643        #endif //GTP_VISIBILITY_MODIFIED_OGRE
644}
Note: See TracBrowser for help on using the repository browser.