Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/OgreMain/src/OgreEntity.cpp @ 3

Last change on this file since 3 was 3, checked in by anonymous, 17 years ago

=update

File size: 73.1 KB
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-2006 Torus Knot Software Ltd
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
24You may alternatively use this source under the terms of a specific version of
25the OGRE Unrestricted License provided you have obtained such a license from
26Torus Knot Software Ltd.
27-----------------------------------------------------------------------------
28*/
29#include "OgreStableHeaders.h"
30#include "OgreEntity.h"
31
32#include "OgreMeshManager.h"
33#include "OgreSubMesh.h"
34#include "OgreSubEntity.h"
35#include "OgreException.h"
36#include "OgreSceneManager.h"
37#include "OgreLogManager.h"
38#include "OgreSkeleton.h"
39#include "OgreBone.h"
40#include "OgreCamera.h"
41#include "OgreTagPoint.h"
42#include "OgreAxisAlignedBox.h"
43#include "OgreHardwareBufferManager.h"
44#include "OgreVector4.h"
45#include "OgreRoot.h"
46#include "OgreTechnique.h"
47#include "OgrePass.h"
48#include "OgreSkeletonInstance.h"
49#include "OgreEdgeListBuilder.h"
50#include "OgreStringConverter.h"
51#include "OgreAnimation.h"
52#include "OgreAlignedAllocator.h"
53#include "OgreOptimisedUtil.h"
54
55namespace Ogre {
56    //-----------------------------------------------------------------------
57    Entity::Entity ()
58                : mAnimationState(NULL),
59          mSkelAnimVertexData(0),
60                  mSoftwareVertexAnimVertexData(0),
61                  mHardwareVertexAnimVertexData(0),
62          mPreparedForShadowVolumes(false),
63          mBoneWorldMatrices(NULL),
64          mBoneMatrices(NULL),
65          mNumBoneMatrices(0),
66                  mFrameAnimationLastUpdated(std::numeric_limits<unsigned long>::max()),
67          mFrameBonesLastUpdated(NULL),
68                  mSharedSkeletonEntities(NULL),
69                  mDisplaySkeleton(false),
70              mHardwareAnimation(false),
71                  mVertexProgramInUse(false),
72                  mSoftwareAnimationRequests(0),
73                  mSoftwareAnimationNormalsRequests(0),
74                  mMeshLodIndex(0),
75                  mMeshLodFactorInv(1.0f),
76                  mMinMeshLodIndex(99),
77                  mMaxMeshLodIndex(0),          // Backwards, remember low value = high detail
78                  mMaterialLodFactorInv(1.0f),
79                  mMinMaterialLodIndex(99),
80                  mMaxMaterialLodIndex(0),              // Backwards, remember low value = high detail
81          mSkeletonInstance(0),
82                  mInitialised(false),
83                  mLastParentXform(Matrix4::ZERO),
84          mFullBoundingBox(),
85                  mNormaliseNormals(false)
86    {
87    }
88    //-----------------------------------------------------------------------
89    Entity::Entity( const String& name, MeshPtr& mesh) :
90                MovableObject(name),
91        mMesh(mesh),
92        mAnimationState(NULL),
93                mSkelAnimVertexData(0),
94                mSoftwareVertexAnimVertexData(0),
95                mHardwareVertexAnimVertexData(0),
96        mPreparedForShadowVolumes(false),
97        mBoneWorldMatrices(NULL),
98        mBoneMatrices(NULL),
99        mNumBoneMatrices(0),
100                mFrameAnimationLastUpdated(std::numeric_limits<unsigned long>::max()),
101        mFrameBonesLastUpdated(NULL),
102        mSharedSkeletonEntities(NULL),
103                mDisplaySkeleton(false),
104                mHardwareAnimation(false),
105                mVertexProgramInUse(false),
106                mSoftwareAnimationRequests(0),
107                mSoftwareAnimationNormalsRequests(0),
108                mMeshLodIndex(0),
109                mMeshLodFactorInv(1.0f),
110                mMinMeshLodIndex(99),
111                mMaxMeshLodIndex(0),            // Backwards, remember low value = high detail
112                mMaterialLodFactorInv(1.0f),
113                mMinMaterialLodIndex(99),
114                mMaxMaterialLodIndex(0),                // Backwards, remember low value = high detail
115                mSkeletonInstance(0),
116                mInitialised(false),
117                mLastParentXform(Matrix4::ZERO),
118        mFullBoundingBox(),
119                mNormaliseNormals(false)
120        {
121                _initialise();
122    }
123        //-----------------------------------------------------------------------
124        void Entity::backgroundLoadingComplete(Resource* res)
125        {
126                if (res == mMesh.get())
127                {
128                        // mesh loading has finished, we can construct ourselves now
129                        _initialise();
130                }
131        }
132        //-----------------------------------------------------------------------
133        void Entity::_initialise(bool forceReinitialise)
134        {
135                if (forceReinitialise)
136                        _deinitialise();
137
138                if (mInitialised)
139                        return;
140
141                if (mMesh->isBackgroundLoaded() && !mMesh->isLoaded())
142                {
143                        // register for a callback when mesh is finished loading
144                        // do this before asking for load to happen to avoid race
145                        mMesh->addListener(this);
146                }
147               
148                // On-demand load
149                mMesh->load();
150                // If loading failed, or deferred loading isn't done yet, defer
151                // Will get a callback in the case of deferred loading
152                // Skeletons are cascade-loaded so no issues there
153                if (!mMesh->isLoaded())
154                        return;
155
156                // Is mesh skeletally animated?
157                if (mMesh->hasSkeleton() && !mMesh->getSkeleton().isNull())
158                {
159                        mSkeletonInstance = new SkeletonInstance(mMesh->getSkeleton());
160                        mSkeletonInstance->load();
161                }
162
163                // Build main subentity list
164                buildSubEntityList(mMesh, &mSubEntityList);
165
166                // Check if mesh is using manual LOD
167                if (mMesh->isLodManual())
168                {
169                        ushort i, numLod;
170                        numLod = mMesh->getNumLodLevels();
171                        // NB skip LOD 0 which is the original
172                        for (i = 1; i < numLod; ++i)
173                        {
174                                const MeshLodUsage& usage = mMesh->getLodLevel(i);
175                                // Manually create entity
176                                Entity* lodEnt = new Entity(mName + "Lod" + StringConverter::toString(i),
177                                        usage.manualMesh);
178                                mLodEntityList.push_back(lodEnt);
179                        }
180                }
181
182
183                // Initialise the AnimationState, if Mesh has animation
184                if (hasSkeleton())
185                {
186                        mFrameBonesLastUpdated = new unsigned long(std::numeric_limits<unsigned long>::max());
187                        mNumBoneMatrices = mSkeletonInstance->getNumBones();
188                        mBoneMatrices = static_cast<Matrix4*>(AlignedMemory::allocate(sizeof(Matrix4) * mNumBoneMatrices));
189                }
190                if (hasSkeleton() || hasVertexAnimation())
191                {
192                        mAnimationState = new AnimationStateSet();
193                        mMesh->_initAnimationState(mAnimationState);
194                        prepareTempBlendBuffers();
195                }
196
197                reevaluateVertexProcessing();
198
199
200                mInitialised = true;
201
202        }
203        //-----------------------------------------------------------------------
204        void Entity::_deinitialise(void)
205        {
206                if (!mInitialised)
207                        return;
208
209                // Delete submeshes
210                SubEntityList::iterator i, iend;
211                iend = mSubEntityList.end();
212                for (i = mSubEntityList.begin(); i != iend; ++i)
213                {
214                        // Delete SubEntity
215                        delete *i;
216                }
217                mSubEntityList.clear();
218               
219                // Delete LOD entities
220                LODEntityList::iterator li, liend;
221                liend = mLodEntityList.end();
222                for (li = mLodEntityList.begin(); li != liend; ++li)
223                {
224                        // Delete
225                        delete (*li);
226                }
227        mLodEntityList.clear();
228       
229                // Delete shadow renderables
230                ShadowRenderableList::iterator si, siend;
231                siend = mShadowRenderables.end();
232                for (si = mShadowRenderables.begin(); si != siend; ++si)
233                {
234                        delete *si;
235                }
236        mShadowRenderables.clear();
237       
238                // Detach all child objects, do this manually to avoid needUpdate() call
239                // which can fail because of deleted items
240                detachAllObjectsImpl();
241
242                if (mSkeletonInstance) {
243                        AlignedMemory::deallocate(mBoneWorldMatrices);
244
245            if (mSharedSkeletonEntities) {
246                mSharedSkeletonEntities->erase(this);
247                if (mSharedSkeletonEntities->size() == 1)
248                {
249                    (*mSharedSkeletonEntities->begin())->stopSharingSkeletonInstance();
250                }
251                // Should never occuring, just in case
252                else if (mSharedSkeletonEntities->empty())
253                {
254                    delete mSharedSkeletonEntities;
255                    delete mFrameBonesLastUpdated;
256                    delete mSkeletonInstance;
257                    AlignedMemory::deallocate(mBoneMatrices);
258                    delete mAnimationState;
259                }
260            } else {
261                delete mFrameBonesLastUpdated;
262                delete mSkeletonInstance;
263                AlignedMemory::deallocate(mBoneMatrices);
264                delete mAnimationState;
265            }
266        }
267                else if (hasVertexAnimation())
268                {
269                        delete mAnimationState;
270                }
271
272                delete mSkelAnimVertexData;
273                delete mSoftwareVertexAnimVertexData;
274                delete mHardwareVertexAnimVertexData;
275
276                mInitialised = false;
277        }
278    //-----------------------------------------------------------------------
279    Entity::~Entity()
280    {
281                _deinitialise();
282    }
283        //-----------------------------------------------------------------------
284        bool Entity::hasVertexAnimation(void) const
285        {
286                return mMesh->hasVertexAnimation();
287        }
288    //-----------------------------------------------------------------------
289    const MeshPtr& Entity::getMesh(void) const
290    {
291        return mMesh;
292    }
293    //-----------------------------------------------------------------------
294    SubEntity* Entity::getSubEntity(unsigned int index) const
295    {
296        if (index >= mSubEntityList.size())
297            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
298            "Index out of bounds.",
299            "Entity::getSubEntity");
300        return mSubEntityList[index];
301    }
302    //-----------------------------------------------------------------------
303    SubEntity* Entity::getSubEntity(const String& name) const
304    {
305        ushort index = mMesh->_getSubMeshIndex(name);
306        return getSubEntity(index);
307    }
308    //-----------------------------------------------------------------------
309    unsigned int Entity::getNumSubEntities(void) const
310    {
311        return static_cast< unsigned int >( mSubEntityList.size() );
312    }
313    //-----------------------------------------------------------------------
314    Entity* Entity::clone( const String& newName) const
315    {
316                if (!mManager)
317                {
318                        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, 
319                                "Cannot clone an Entity that wasn't created through a "
320                                "SceneManager", "Entity::clone");
321                }
322            Entity* newEnt = mManager->createEntity(newName, getMesh()->getName() );
323
324                if (mInitialised)
325                {
326                        // Copy material settings
327                        SubEntityList::const_iterator i;
328                        unsigned int n = 0;
329                        for (i = mSubEntityList.begin(); i != mSubEntityList.end(); ++i, ++n)
330                        {
331                                newEnt->getSubEntity(n)->setMaterialName((*i)->getMaterialName());
332                        }
333                        if (mAnimationState)
334                        {
335                                delete newEnt->mAnimationState;
336                                newEnt->mAnimationState = new AnimationStateSet(*mAnimationState);
337                        }
338                }
339
340        return newEnt;
341    }
342    //-----------------------------------------------------------------------
343    void Entity::setMaterialName(const String& name)
344    {
345        // Set for all subentities
346        SubEntityList::iterator i;
347        for (i = mSubEntityList.begin(); i != mSubEntityList.end(); ++i)
348        {
349            (*i)->setMaterialName(name);
350        }
351
352    }
353    //-----------------------------------------------------------------------
354    void Entity::_notifyCurrentCamera(Camera* cam)
355    {
356                MovableObject::_notifyCurrentCamera(cam);
357
358        // Calculate the LOD
359        if (mParentNode)
360        {
361            Real squaredDepth = mParentNode->getSquaredViewDepth(cam);
362
363            // Do Mesh LOD
364            // Adjust this depth by the entity bias factor
365            Real tmp = squaredDepth * mMeshLodFactorInv;
366            // Now adjust it by the camera bias
367            tmp = tmp * cam->_getLodBiasInverse();
368            // Get the index at this biased depth
369            mMeshLodIndex = mMesh->getLodIndexSquaredDepth(tmp);
370            // Apply maximum detail restriction (remember lower = higher detail)
371            mMeshLodIndex = std::max(mMaxMeshLodIndex, mMeshLodIndex);
372            // Apply minimum detail restriction (remember higher = lower detail)
373            mMeshLodIndex = std::min(mMinMeshLodIndex, mMeshLodIndex);
374
375            // Now do material LOD
376            // Adjust this depth by the entity bias factor
377            tmp = squaredDepth * mMaterialLodFactorInv;
378            // Now adjust it by the camera bias
379            tmp = tmp * cam->_getLodBiasInverse();
380            SubEntityList::iterator i, iend;
381            iend = mSubEntityList.end();
382            for (i = mSubEntityList.begin(); i != iend; ++i)
383            {
384                // Get the index at this biased depth
385                unsigned short idx = (*i)->mpMaterial->getLodIndexSquaredDepth(tmp);
386                // Apply maximum detail restriction (remember lower = higher detail)
387                idx = std::max(mMaxMaterialLodIndex, idx);
388                // Apply minimum detail restriction (remember higher = lower detail)
389                (*i)->mMaterialLodIndex = std::min(mMinMaterialLodIndex, idx);
390
391                                // Also invalidate any camera distance cache
392                                (*i)->_invalidateCameraCache ();
393            }
394
395
396        }
397        // Notify any child objects
398        ChildObjectList::iterator child_itr = mChildObjectList.begin();
399        ChildObjectList::iterator child_itr_end = mChildObjectList.end();
400        for( ; child_itr != child_itr_end; child_itr++)
401        {
402            (*child_itr).second->_notifyCurrentCamera(cam);
403        }
404    }
405    //-----------------------------------------------------------------------
406    const AxisAlignedBox& Entity::getBoundingBox(void) const
407    {
408                // Get from Mesh
409        mFullBoundingBox = mMesh->getBounds();
410        mFullBoundingBox.merge(getChildObjectsBoundingBox());
411
412        // Don't scale here, this is taken into account when world BBox calculation is done
413
414        return mFullBoundingBox;
415    }
416    //-----------------------------------------------------------------------
417    AxisAlignedBox Entity::getChildObjectsBoundingBox(void) const
418    {
419        AxisAlignedBox aa_box;
420        AxisAlignedBox full_aa_box;
421        full_aa_box.setNull();
422
423        ChildObjectList::const_iterator child_itr = mChildObjectList.begin();
424        ChildObjectList::const_iterator child_itr_end = mChildObjectList.end();
425        for( ; child_itr != child_itr_end; child_itr++)
426        {
427            aa_box = child_itr->second->getBoundingBox();
428            TagPoint* tp = (TagPoint*)child_itr->second->getParentNode();
429            // Use transform local to skeleton since world xform comes later
430            aa_box.transformAffine(tp->_getFullLocalTransform());
431
432            full_aa_box.merge(aa_box);
433        }
434
435        return full_aa_box;
436    }
437        //-----------------------------------------------------------------------
438        const AxisAlignedBox& Entity::getWorldBoundingBox(bool derive) const
439        {
440                if (derive)
441                {
442                        // derive child bounding boxes
443                        ChildObjectList::const_iterator child_itr = mChildObjectList.begin();
444                        ChildObjectList::const_iterator child_itr_end = mChildObjectList.end();
445                        for( ; child_itr != child_itr_end; child_itr++)
446                        {
447                                child_itr->second->getWorldBoundingBox(true);
448                        }
449                }
450                return MovableObject::getWorldBoundingBox(derive);
451        }
452        //-----------------------------------------------------------------------
453        const Sphere& Entity::getWorldBoundingSphere(bool derive) const
454        {
455                if (derive)
456                {
457                        // derive child bounding boxes
458                        ChildObjectList::const_iterator child_itr = mChildObjectList.begin();
459                        ChildObjectList::const_iterator child_itr_end = mChildObjectList.end();
460                        for( ; child_itr != child_itr_end; child_itr++)
461                        {
462                                child_itr->second->getWorldBoundingSphere(true);
463                        }
464                }
465                return MovableObject::getWorldBoundingSphere(derive);
466
467        }
468    //-----------------------------------------------------------------------
469    void Entity::_updateRenderQueue(RenderQueue* queue)
470    {
471                // Do nothing if not initialised yet
472                if (!mInitialised)
473                        return;
474
475        // Check we're not using a manual LOD
476        if (mMeshLodIndex > 0 && mMesh->isLodManual())
477        {
478            // Use alternate entity
479            assert( static_cast< size_t >( mMeshLodIndex - 1 ) < mLodEntityList.size() &&
480                "No LOD EntityList - did you build the manual LODs after creating the entity?");
481            // index - 1 as we skip index 0 (original lod)
482            if (hasSkeleton() && mLodEntityList[mMeshLodIndex - 1]->hasSkeleton())
483            {
484                // Copy the animation state set to lod entity, we assume the lod
485                // entity only has a subset animation states
486                mAnimationState->copyMatchingState(
487                                        mLodEntityList[mMeshLodIndex - 1]->mAnimationState);
488            }
489            mLodEntityList[mMeshLodIndex - 1]->_updateRenderQueue(queue);
490            return;
491        }
492
493        // Add each visible SubEntity to the queue
494        SubEntityList::iterator i, iend;
495        iend = mSubEntityList.end();
496        for (i = mSubEntityList.begin(); i != iend; ++i)
497        {
498            if((*i)->isVisible())
499            {
500                if(mRenderQueueIDSet)
501                {
502                    queue->addRenderable(*i, mRenderQueueID);
503                }
504                else
505                {
506                    queue->addRenderable(*i);
507                }
508            }
509        }
510
511        // Since we know we're going to be rendered, take this opportunity to
512        // update the animation
513        if (hasSkeleton() || hasVertexAnimation())
514        {
515            updateAnimation();
516
517            //--- pass this point,  we are sure that the transformation matrix of each bone and tagPoint have been updated
518            ChildObjectList::iterator child_itr = mChildObjectList.begin();
519            ChildObjectList::iterator child_itr_end = mChildObjectList.end();
520            for( ; child_itr != child_itr_end; child_itr++)
521            {
522                if ((*child_itr).second->isVisible())
523                    (*child_itr).second->_updateRenderQueue(queue);
524            }
525        }
526
527        // HACK to display bones
528        // This won't work if the entity is not centered at the origin
529        // TODO work out a way to allow bones to be rendered when Entity not centered
530        if (mDisplaySkeleton && hasSkeleton())
531        {
532            int numBones = mSkeletonInstance->getNumBones();
533            for (int b = 0; b < numBones; ++b)
534            {
535                Bone* bone = mSkeletonInstance->getBone(b);
536                if(mRenderQueueIDSet)
537                {
538                     queue->addRenderable(bone, mRenderQueueID);
539                } else {
540                     queue->addRenderable(bone);
541                }
542            }
543        }
544
545
546
547
548    }
549    //-----------------------------------------------------------------------
550    AnimationState* Entity::getAnimationState(const String& name) const
551    {
552        if (!mAnimationState)
553        {
554            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Entity is not animated",
555                "Entity::getAnimationState");
556        }
557
558                return mAnimationState->getAnimationState(name);
559    }
560    //-----------------------------------------------------------------------
561    AnimationStateSet* Entity::getAllAnimationStates(void) const
562    {
563        return mAnimationState;
564    }
565    //-----------------------------------------------------------------------
566    const String& Entity::getMovableType(void) const
567    {
568                return EntityFactory::FACTORY_TYPE_NAME;
569    }
570        //-----------------------------------------------------------------------
571        bool Entity::tempVertexAnimBuffersBound(void) const
572        {
573                // Do we still have temp buffers for software vertex animation bound?
574                bool ret = true;
575                if (mMesh->sharedVertexData && mMesh->getSharedVertexDataAnimationType() != VAT_NONE)
576                {
577                        ret = ret && mTempVertexAnimInfo.buffersCheckedOut(true, false);
578                }
579                for (SubEntityList::const_iterator i = mSubEntityList.begin();
580                        i != mSubEntityList.end(); ++i)
581                {
582                        SubEntity* sub = *i;
583                        if (!sub->getSubMesh()->useSharedVertices
584                                && sub->getSubMesh()->getVertexAnimationType() != VAT_NONE)
585                        {
586                                ret = ret && sub->_getVertexAnimTempBufferInfo()->buffersCheckedOut(true, false);
587                        }
588                }
589                return ret;
590        }
591    //-----------------------------------------------------------------------
592    bool Entity::tempSkelAnimBuffersBound(bool requestNormals) const
593    {
594        // Do we still have temp buffers for software skeleton animation bound?
595        if (mSkelAnimVertexData)
596        {
597            if (!mTempSkelAnimInfo.buffersCheckedOut(true, requestNormals))
598                return false;
599        }
600        for (SubEntityList::const_iterator i = mSubEntityList.begin();
601            i != mSubEntityList.end(); ++i)
602        {
603            SubEntity* sub = *i;
604            if (sub->isVisible() && sub->mSkelAnimVertexData)
605            {
606                if (!sub->mTempSkelAnimInfo.buffersCheckedOut(true, requestNormals))
607                    return false;
608            }
609        }
610        return true;
611    }
612    //-----------------------------------------------------------------------
613    void Entity::updateAnimation(void)
614    {
615                // Do nothing if not initialised yet
616                if (!mInitialised)
617                        return;
618
619                Root& root = Root::getSingleton();
620                bool hwAnimation = isHardwareAnimationEnabled();
621                bool forcedSwAnimation = getSoftwareAnimationRequests()>0;
622                bool forcedNormals = getSoftwareAnimationNormalsRequests()>0;
623                bool stencilShadows = false;
624                if (getCastShadows() && hasEdgeList() && root._getCurrentSceneManager())
625                        stencilShadows =  root._getCurrentSceneManager()->isShadowTechniqueStencilBased();
626                bool softwareAnimation = !hwAnimation || stencilShadows || forcedSwAnimation;
627                // Blend normals in s/w only if we're not using h/w animation,
628                // since shadows only require positions
629                bool blendNormals = !hwAnimation || forcedNormals;
630        // Animation dirty if animation state modified or manual bones modified
631        bool animationDirty =
632            (mFrameAnimationLastUpdated != mAnimationState->getDirtyFrameNumber()) ||
633            (hasSkeleton() && getSkeleton()->getManualBonesDirty());
634
635                // We only do these tasks if animation is dirty
636                // Or, if we're using a skeleton and manual bones have been moved
637                // Or, if we're using software animation and temp buffers are unbound
638        if (animationDirty ||
639                        (softwareAnimation && hasVertexAnimation() && !tempVertexAnimBuffersBound()) ||
640                        (softwareAnimation && hasSkeleton() && !tempSkelAnimBuffersBound(blendNormals)))
641        {
642                        if (hasVertexAnimation())
643                        {
644                                if (softwareAnimation)
645                                {
646                                        // grab & bind temporary buffer for positions
647                                        if (mSoftwareVertexAnimVertexData
648                                                && mMesh->getSharedVertexDataAnimationType() != VAT_NONE)
649                                        {
650                                                mTempVertexAnimInfo.checkoutTempCopies(true, false);
651                                                // NB we suppress hardware upload while doing blend if we're
652                                                // hardware animation, because the only reason for doing this
653                                                // is for shadow, which need only be uploaded then
654                                                mTempVertexAnimInfo.bindTempCopies(mSoftwareVertexAnimVertexData,
655                                                        hwAnimation);
656                                        }
657                                        SubEntityList::iterator i, iend;
658                                        iend = mSubEntityList.end();
659                                        for (i = mSubEntityList.begin(); i != iend; ++i)
660                                        {
661                                                // Blend dedicated geometry
662                                                SubEntity* se = *i;
663                                                if (se->isVisible() && se->mSoftwareVertexAnimVertexData
664                                                        && se->getSubMesh()->getVertexAnimationType() != VAT_NONE)
665                                                {
666                                                        se->mTempVertexAnimInfo.checkoutTempCopies(true, false);
667                                                        se->mTempVertexAnimInfo.bindTempCopies(se->mSoftwareVertexAnimVertexData,
668                                                                hwAnimation);
669                                                }
670
671                                        }
672                                }
673                                applyVertexAnimation(hwAnimation, stencilShadows);
674                        }
675
676                        if (hasSkeleton())
677                        {
678                                cacheBoneMatrices();
679
680                                // Software blend?
681                                if (softwareAnimation)
682                                {
683                    const Matrix4* blendMatrices[256];
684
685                                        // Ok, we need to do a software blend
686                                        // Firstly, check out working vertex buffers
687                                        if (mSkelAnimVertexData)
688                                        {
689                                                // Blend shared geometry
690                                                // NB we suppress hardware upload while doing blend if we're
691                                                // hardware animation, because the only reason for doing this
692                                                // is for shadow, which need only be uploaded then
693                                                mTempSkelAnimInfo.checkoutTempCopies(true, blendNormals);
694                                                mTempSkelAnimInfo.bindTempCopies(mSkelAnimVertexData,
695                                                        hwAnimation);
696                        // Prepare blend matrices, TODO: Move out of here
697                        Mesh::prepareMatricesForVertexBlend(blendMatrices,
698                            mBoneMatrices, mMesh->sharedBlendIndexToBoneIndexMap);
699                                                // Blend, taking source from either mesh data or morph data
700                                                Mesh::softwareVertexBlend(
701                                                        (mMesh->getSharedVertexDataAnimationType() != VAT_NONE) ?
702                                                                mSoftwareVertexAnimVertexData : mMesh->sharedVertexData,
703                                                        mSkelAnimVertexData,
704                                                        blendMatrices, mMesh->sharedBlendIndexToBoneIndexMap.size(),
705                                                        blendNormals);
706                                        }
707                                        SubEntityList::iterator i, iend;
708                                        iend = mSubEntityList.end();
709                                        for (i = mSubEntityList.begin(); i != iend; ++i)
710                                        {
711                                                // Blend dedicated geometry
712                                                SubEntity* se = *i;
713                                                if (se->isVisible() && se->mSkelAnimVertexData)
714                                                {
715                                                        se->mTempSkelAnimInfo.checkoutTempCopies(true, blendNormals);
716                                                        se->mTempSkelAnimInfo.bindTempCopies(se->mSkelAnimVertexData,
717                                                                hwAnimation);
718                            // Prepare blend matrices, TODO: Move out of here
719                            Mesh::prepareMatricesForVertexBlend(blendMatrices,
720                                mBoneMatrices, se->mSubMesh->blendIndexToBoneIndexMap);
721                                                        // Blend, taking source from either mesh data or morph data
722                                                        Mesh::softwareVertexBlend(
723                                                                (se->getSubMesh()->getVertexAnimationType() != VAT_NONE)?
724                                                                        se->mSoftwareVertexAnimVertexData : se->mSubMesh->vertexData,
725                                                                se->mSkelAnimVertexData,
726                                                                blendMatrices, se->mSubMesh->blendIndexToBoneIndexMap.size(),
727                                                                blendNormals);
728                                                }
729
730                                        }
731
732                                }
733                        }
734
735            // Trigger update of bounding box if necessary
736            if (!mChildObjectList.empty())
737                mParentNode->needUpdate();
738
739                        mFrameAnimationLastUpdated = mAnimationState->getDirtyFrameNumber();
740        }
741
742        // Need to update the child object's transforms when animation dirty
743        // or parent node transform has altered.
744        if (hasSkeleton() &&
745            (animationDirty || mLastParentXform != _getParentNodeFullTransform()))
746        {
747            // Cache last parent transform for next frame use too.
748            mLastParentXform = _getParentNodeFullTransform();
749
750            //--- Update the child object's transforms
751            ChildObjectList::iterator child_itr = mChildObjectList.begin();
752            ChildObjectList::iterator child_itr_end = mChildObjectList.end();
753            for( ; child_itr != child_itr_end; child_itr++)
754            {
755                (*child_itr).second->getParentNode()->_update(true, true);
756            }
757
758            // Also calculate bone world matrices, since are used as replacement world matrices,
759            // but only if it's used (when using hardware animation and skeleton animated).
760            if (hwAnimation && _isSkeletonAnimated())
761            {
762                // Allocate bone world matrices on demand, for better memory footprint
763                // when using software animation.
764                if (!mBoneWorldMatrices)
765                {
766                    mBoneWorldMatrices =
767                        static_cast<Matrix4*>(AlignedMemory::allocate(sizeof(Matrix4) * mNumBoneMatrices));
768                }
769
770                OptimisedUtil::getImplementation()->concatenateAffineMatrices(
771                    mLastParentXform,
772                    mBoneMatrices,
773                    mBoneWorldMatrices,
774                    mNumBoneMatrices);
775            }
776        }
777    }
778        //-----------------------------------------------------------------------
779        void Entity::initHardwareAnimationElements(VertexData* vdata,
780                ushort numberOfElements)
781        {
782                if (vdata->hwAnimationDataList.size() < numberOfElements)
783                {
784                        vdata->allocateHardwareAnimationElements(numberOfElements);
785                }
786                // Initialise parametrics incase we don't use all of them
787                for (size_t i = 0; i < vdata->hwAnimationDataList.size(); ++i)
788                {
789                        vdata->hwAnimationDataList[i].parametric = 0.0f;
790                }
791                // reset used count
792                vdata->hwAnimDataItemsUsed = 0;
793
794        }
795        //-----------------------------------------------------------------------
796        void Entity::applyVertexAnimation(bool hardwareAnimation, bool stencilShadows)
797        {
798                const MeshPtr& msh = getMesh();
799                bool swAnim = !hardwareAnimation || stencilShadows || (mSoftwareAnimationRequests>0);
800
801                // make sure we have enough hardware animation elements to play with
802                if (hardwareAnimation)
803                {
804                        if (mHardwareVertexAnimVertexData
805                                && msh->getSharedVertexDataAnimationType() != VAT_NONE)
806                        {
807                                initHardwareAnimationElements(mHardwareVertexAnimVertexData,
808                                        (msh->getSharedVertexDataAnimationType() == VAT_POSE)
809                                        ? mHardwarePoseCount : 1);
810                        }
811                        for (SubEntityList::iterator si = mSubEntityList.begin();
812                                si != mSubEntityList.end(); ++si)
813                        {
814                                SubEntity* sub = *si;
815                                if (sub->getSubMesh()->getVertexAnimationType() != VAT_NONE &&
816                                        !sub->getSubMesh()->useSharedVertices)
817                                {
818                                        initHardwareAnimationElements(
819                                                sub->_getHardwareVertexAnimVertexData(),
820                                                (sub->getSubMesh()->getVertexAnimationType() == VAT_POSE)
821                                                ? sub->mHardwarePoseCount : 1);
822                                }
823                        }
824
825                }
826                else
827                {
828                        // May be blending multiple poses in software
829                        // Suppress hardware upload of buffers
830                        if (mSoftwareVertexAnimVertexData &&
831                                mMesh->getSharedVertexDataAnimationType() == VAT_POSE)
832                        {
833                                const VertexElement* elem = mSoftwareVertexAnimVertexData
834                                        ->vertexDeclaration->findElementBySemantic(VES_POSITION);
835                                HardwareVertexBufferSharedPtr buf = mSoftwareVertexAnimVertexData
836                                        ->vertexBufferBinding->getBuffer(elem->getSource());
837                                buf->suppressHardwareUpdate(true);
838                        }
839                        for (SubEntityList::iterator si = mSubEntityList.begin();
840                                si != mSubEntityList.end(); ++si)
841                        {
842                                SubEntity* sub = *si;
843                                if (!sub->getSubMesh()->useSharedVertices &&
844                                        sub->getSubMesh()->getVertexAnimationType() == VAT_POSE)
845                                {
846                                        VertexData* data = sub->_getSoftwareVertexAnimVertexData();
847                                        const VertexElement* elem = data->vertexDeclaration
848                                                ->findElementBySemantic(VES_POSITION);
849                                        HardwareVertexBufferSharedPtr buf = data
850                                                ->vertexBufferBinding->getBuffer(elem->getSource());
851                                        buf->suppressHardwareUpdate(true);
852                                }
853                        }
854                }
855
856
857                // Now apply the animation(s)
858                // Note - you should only apply one morph animation to each set of vertex data
859                // at once; if you do more, only the last one will actually apply
860                markBuffersUnusedForAnimation();
861                ConstEnabledAnimationStateIterator animIt = mAnimationState->getEnabledAnimationStateIterator();
862                while(animIt.hasMoreElements())
863                {
864            const AnimationState* state = animIt.getNext();
865            Animation* anim = msh->_getAnimationImpl(state->getAnimationName());
866            if (anim)
867            {
868                anim->apply(this, state->getTimePosition(), state->getWeight(),
869                    swAnim, hardwareAnimation);
870            }
871                }
872                // Deal with cases where no animation applied
873                restoreBuffersForUnusedAnimation(hardwareAnimation);
874
875                // Unsuppress hardware upload if we suppressed it
876                if (!hardwareAnimation)
877                {
878                        if (mSoftwareVertexAnimVertexData &&
879                                msh->getSharedVertexDataAnimationType() == VAT_POSE)
880                        {
881                                const VertexElement* elem = mSoftwareVertexAnimVertexData
882                                        ->vertexDeclaration->findElementBySemantic(VES_POSITION);
883                                HardwareVertexBufferSharedPtr buf = mSoftwareVertexAnimVertexData
884                                        ->vertexBufferBinding->getBuffer(elem->getSource());
885                                buf->suppressHardwareUpdate(false);
886                        }
887                        for (SubEntityList::iterator si = mSubEntityList.begin();
888                                si != mSubEntityList.end(); ++si)
889                        {
890                                SubEntity* sub = *si;
891                                if (!sub->getSubMesh()->useSharedVertices &&
892                                        sub->getSubMesh()->getVertexAnimationType() == VAT_POSE)
893                                {
894                                        VertexData* data = sub->_getSoftwareVertexAnimVertexData();
895                                        const VertexElement* elem = data->vertexDeclaration
896                                                ->findElementBySemantic(VES_POSITION);
897                                        HardwareVertexBufferSharedPtr buf = data
898                                                ->vertexBufferBinding->getBuffer(elem->getSource());
899                                        buf->suppressHardwareUpdate(false);
900                                }
901                        }
902                }
903
904        }
905        //-----------------------------------------------------------------------------
906        void Entity::markBuffersUnusedForAnimation(void)
907        {
908                mVertexAnimationAppliedThisFrame = false;
909                for (SubEntityList::iterator i = mSubEntityList.begin();
910                        i != mSubEntityList.end(); ++i)
911                {
912                        (*i)->_markBuffersUnusedForAnimation();
913                }
914        }
915        //-----------------------------------------------------------------------------
916        void Entity::_markBuffersUsedForAnimation(void)
917        {
918                mVertexAnimationAppliedThisFrame = true;
919                // no cascade
920        }
921        //-----------------------------------------------------------------------------
922        void Entity::restoreBuffersForUnusedAnimation(bool hardwareAnimation)
923        {
924                // Rebind original positions if:
925                //  We didn't apply any animation and
926                //    We're morph animated (hardware binds keyframe, software is missing)
927                //    or we're pose animated and software (hardware is fine, still bound)
928                if (mMesh->sharedVertexData &&
929                        !mVertexAnimationAppliedThisFrame &&
930                        (!hardwareAnimation || mMesh->getSharedVertexDataAnimationType() == VAT_MORPH))
931                {
932                        const VertexElement* srcPosElem =
933                                mMesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_POSITION);
934                        HardwareVertexBufferSharedPtr srcBuf =
935                                mMesh->sharedVertexData->vertexBufferBinding->getBuffer(
936                                        srcPosElem->getSource());
937
938                        // Bind to software
939                        const VertexElement* destPosElem =
940                                mSoftwareVertexAnimVertexData->vertexDeclaration->findElementBySemantic(VES_POSITION);
941                        mSoftwareVertexAnimVertexData->vertexBufferBinding->setBinding(
942                                destPosElem->getSource(), srcBuf);
943
944                }
945
946                // rebind any missing hardware pose buffers
947                // Caused by not having any animations enabled, or keyframes which reference
948                // no poses
949                if (mMesh->sharedVertexData && hardwareAnimation
950                        && mMesh->getSharedVertexDataAnimationType() == VAT_POSE)
951                {
952                        bindMissingHardwarePoseBuffers(mMesh->sharedVertexData, mHardwareVertexAnimVertexData);
953                }
954
955
956                for (SubEntityList::iterator i = mSubEntityList.begin();
957                        i != mSubEntityList.end(); ++i)
958                {
959                        (*i)->_restoreBuffersForUnusedAnimation(hardwareAnimation);
960                }
961
962        }
963        //---------------------------------------------------------------------
964        void Entity::bindMissingHardwarePoseBuffers(const VertexData* srcData, 
965                VertexData* destData)
966        {
967                // For hardware pose animation, also make sure we've bound buffers to all the elements
968                // required - if there are missing bindings for elements in use,
969                // some rendersystems can complain because elements refer
970                // to an unbound source.
971                // Get the original position source, we'll use this to fill gaps
972                const VertexElement* srcPosElem =
973                        srcData->vertexDeclaration->findElementBySemantic(VES_POSITION);
974                HardwareVertexBufferSharedPtr srcBuf =
975                        srcData->vertexBufferBinding->getBuffer(
976                                srcPosElem->getSource());
977
978                for (VertexData::HardwareAnimationDataList::const_iterator i = destData->hwAnimationDataList.begin();
979                        i != destData->hwAnimationDataList.end(); ++i)
980                {
981                        const VertexData::HardwareAnimationData& animData = *i;
982                        if (!destData->vertexBufferBinding->isBufferBound(
983                                animData.targetVertexElement->getSource()))
984                        {
985                                // Bind to a safe default
986                                destData->vertexBufferBinding->setBinding(
987                                        animData.targetVertexElement->getSource(), srcBuf);
988                        }
989                }
990
991        }
992        //-----------------------------------------------------------------------
993        void Entity::_updateAnimation(void)
994        {
995                // Externally visible method
996                if (hasSkeleton() || hasVertexAnimation())
997                {
998                        updateAnimation();
999                }
1000        }
1001        //-----------------------------------------------------------------------
1002    bool Entity::_isAnimated(void) const
1003    {
1004        return (mAnimationState && mAnimationState->hasEnabledAnimationState()) ||
1005               (getSkeleton() && getSkeleton()->hasManualBones());
1006    }
1007        //-----------------------------------------------------------------------
1008    bool Entity::_isSkeletonAnimated(void) const
1009    {
1010        return getSkeleton() &&
1011            (mAnimationState->hasEnabledAnimationState() || getSkeleton()->hasManualBones());
1012    }
1013        //-----------------------------------------------------------------------
1014        VertexData* Entity::_getSkelAnimVertexData(void) const
1015        {
1016                assert (mSkelAnimVertexData && "Not software skinned or has no shared vertex data!");
1017        return mSkelAnimVertexData;
1018        }
1019        //-----------------------------------------------------------------------
1020        VertexData* Entity::_getSoftwareVertexAnimVertexData(void) const
1021        {
1022                assert (mSoftwareVertexAnimVertexData && "Not vertex animated or has no shared vertex data!");
1023                return mSoftwareVertexAnimVertexData;
1024        }
1025        //-----------------------------------------------------------------------
1026        VertexData* Entity::_getHardwareVertexAnimVertexData(void) const
1027        {
1028                assert (mHardwareVertexAnimVertexData && "Not vertex animated or has no shared vertex data!");
1029                return mHardwareVertexAnimVertexData;
1030        }
1031        //-----------------------------------------------------------------------
1032        TempBlendedBufferInfo* Entity::_getSkelAnimTempBufferInfo(void)
1033        {
1034                return &mTempSkelAnimInfo;
1035        }
1036        //-----------------------------------------------------------------------
1037        TempBlendedBufferInfo* Entity::_getVertexAnimTempBufferInfo(void)
1038        {
1039                return &mTempVertexAnimInfo;
1040        }
1041    //-----------------------------------------------------------------------
1042    void Entity::cacheBoneMatrices(void)
1043    {
1044        Root& root = Root::getSingleton();
1045        unsigned long currentFrameNumber = root.getCurrentFrameNumber();
1046        if (*mFrameBonesLastUpdated  != currentFrameNumber) {
1047
1048            mSkeletonInstance->setAnimationState(*mAnimationState);
1049            mSkeletonInstance->_getBoneMatrices(mBoneMatrices);
1050            *mFrameBonesLastUpdated  = currentFrameNumber;
1051        }
1052    }
1053    //-----------------------------------------------------------------------
1054    void Entity::setDisplaySkeleton(bool display)
1055    {
1056        mDisplaySkeleton = display;
1057    }
1058    //-----------------------------------------------------------------------
1059    bool Entity::getDisplaySkeleton(void) const
1060    {
1061        return mDisplaySkeleton;
1062    }
1063    //-----------------------------------------------------------------------
1064    Entity* Entity::getManualLodLevel(size_t index) const
1065    {
1066        assert(index < mLodEntityList.size());
1067
1068        return mLodEntityList[index];
1069    }
1070    //-----------------------------------------------------------------------
1071    size_t Entity::getNumManualLodLevels(void) const
1072    {
1073        return mLodEntityList.size();
1074    }
1075    //-----------------------------------------------------------------------
1076    void Entity::setMeshLodBias(Real factor, ushort maxDetailIndex, ushort minDetailIndex)
1077    {
1078        assert(factor > 0.0f && "Bias factor must be > 0!");
1079        mMeshLodFactorInv = 1.0f / factor;
1080        mMaxMeshLodIndex = maxDetailIndex;
1081        mMinMeshLodIndex = minDetailIndex;
1082
1083    }
1084    //-----------------------------------------------------------------------
1085    void Entity::setMaterialLodBias(Real factor, ushort maxDetailIndex, ushort minDetailIndex)
1086    {
1087        assert(factor > 0.0f && "Bias factor must be > 0!");
1088        mMaterialLodFactorInv = 1.0f / factor;
1089        mMaxMaterialLodIndex = maxDetailIndex;
1090        mMinMaterialLodIndex = minDetailIndex;
1091
1092    }
1093    //-----------------------------------------------------------------------
1094    void Entity::buildSubEntityList(MeshPtr& mesh, SubEntityList* sublist)
1095    {
1096        // Create SubEntities
1097        unsigned short i, numSubMeshes;
1098        SubMesh* subMesh;
1099        SubEntity* subEnt;
1100
1101        numSubMeshes = mesh->getNumSubMeshes();
1102        for (i = 0; i < numSubMeshes; ++i)
1103        {
1104            subMesh = mesh->getSubMesh(i);
1105            subEnt = new SubEntity(this, subMesh);
1106            if (subMesh->isMatInitialised())
1107                subEnt->setMaterialName(subMesh->getMaterialName());
1108            sublist->push_back(subEnt);
1109        }
1110    }
1111    //-----------------------------------------------------------------------
1112    void Entity::setPolygonModeOverrideable(bool overrideable)
1113    {
1114        SubEntityList::iterator i, iend;
1115        iend = mSubEntityList.end();
1116
1117        for( i = mSubEntityList.begin(); i != iend; ++i )
1118        {
1119            (*i)->setPolygonModeOverrideable(overrideable);
1120        }
1121    }
1122
1123    //-----------------------------------------------------------------------
1124    TagPoint* Entity::attachObjectToBone(const String &boneName, MovableObject *pMovable, const Quaternion &offsetOrientation, const Vector3 &offsetPosition)
1125    {
1126        if (mChildObjectList.find(pMovable->getName()) != mChildObjectList.end())
1127        {
1128            OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM,
1129                "An object with the name " + pMovable->getName() + " already attached",
1130                "Entity::attachObjectToBone");
1131        }
1132        if(pMovable->isAttached())
1133        {
1134            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Object already attached to a sceneNode or a Bone",
1135                "Entity::attachObjectToBone");
1136        }
1137        if (!hasSkeleton())
1138        {
1139            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "This entity's mesh has no skeleton to attach object to.",
1140                "Entity::attachObjectToBone");
1141        }
1142        Bone* bone = mSkeletonInstance->getBone(boneName);
1143        if (!bone)
1144        {
1145            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Cannot locate bone named " + boneName,
1146                "Entity::attachObjectToBone");
1147        }
1148
1149        TagPoint *tp = mSkeletonInstance->createTagPointOnBone(
1150            bone, offsetOrientation, offsetPosition);
1151        tp->setParentEntity(this);
1152        tp->setChildObject(pMovable);
1153
1154        attachObjectImpl(pMovable, tp);
1155
1156        // Trigger update of bounding box if necessary
1157        if (mParentNode)
1158            mParentNode->needUpdate();
1159
1160                return tp;
1161    }
1162
1163    //-----------------------------------------------------------------------
1164    void Entity::attachObjectImpl(MovableObject *pObject, TagPoint *pAttachingPoint)
1165    {
1166        assert(mChildObjectList.find(pObject->getName()) == mChildObjectList.end());
1167        mChildObjectList[pObject->getName()] = pObject;
1168        pObject->_notifyAttached(pAttachingPoint, true);
1169    }
1170
1171    //-----------------------------------------------------------------------
1172    MovableObject* Entity::detachObjectFromBone(const String &name)
1173    {
1174        ChildObjectList::iterator i = mChildObjectList.find(name);
1175
1176        if (i == mChildObjectList.end())
1177        {
1178            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "No child object entry found named " + name,
1179                "Entity::detachObjectFromBone");
1180        }
1181        MovableObject *obj = i->second;
1182        detachObjectImpl(obj);
1183        mChildObjectList.erase(i);
1184
1185        // Trigger update of bounding box if necessary
1186        if (mParentNode)
1187            mParentNode->needUpdate();
1188
1189        return obj;
1190    }
1191    //-----------------------------------------------------------------------
1192    void Entity::detachObjectFromBone(MovableObject* obj)
1193    {
1194        ChildObjectList::iterator i, iend;
1195        iend = mChildObjectList.end();
1196        for (i = mChildObjectList.begin(); i != iend; ++i)
1197        {
1198            if (i->second == obj)
1199            {
1200                detachObjectImpl(obj);
1201                mChildObjectList.erase(i);
1202
1203                // Trigger update of bounding box if necessary
1204                if (mParentNode)
1205                    mParentNode->needUpdate();
1206                break;
1207            }
1208        }
1209    }
1210    //-----------------------------------------------------------------------
1211    void Entity::detachAllObjectsFromBone(void)
1212    {
1213        detachAllObjectsImpl();
1214
1215        // Trigger update of bounding box if necessary
1216        if (mParentNode)
1217            mParentNode->needUpdate();
1218    }
1219    //-----------------------------------------------------------------------
1220    void Entity::detachObjectImpl(MovableObject* pObject)
1221    {
1222        TagPoint* tp = static_cast<TagPoint*>(pObject->getParentNode());
1223
1224        // free the TagPoint so we can reuse it later
1225        mSkeletonInstance->freeTagPoint(tp);
1226
1227        pObject->_notifyAttached((TagPoint*)0);
1228    }
1229    //-----------------------------------------------------------------------
1230    void Entity::detachAllObjectsImpl(void)
1231    {
1232        ChildObjectList::const_iterator i, iend;
1233        iend = mChildObjectList.end();
1234        for (i = mChildObjectList.begin(); i != iend; ++i)
1235        {
1236            detachObjectImpl(i->second);
1237        }
1238        mChildObjectList.clear();
1239    }
1240
1241    //-----------------------------------------------------------------------
1242    Entity::ChildObjectListIterator Entity::getAttachedObjectIterator()
1243    {
1244        return ChildObjectListIterator(mChildObjectList.begin(), mChildObjectList.end());
1245    }
1246    //-----------------------------------------------------------------------
1247    Real Entity::getBoundingRadius(void) const
1248    {
1249        Real rad = mMesh->getBoundingSphereRadius();
1250        // Scale by largest scale factor
1251        if (mParentNode)
1252        {
1253            const Vector3& s = mParentNode->_getDerivedScale();
1254            rad *= std::max(s.x, std::max(s.y, s.z));
1255        }
1256        return rad;
1257    }
1258    //-----------------------------------------------------------------------
1259    void Entity::prepareTempBlendBuffers(void)
1260    {
1261        if (mSkelAnimVertexData)
1262        {
1263            delete mSkelAnimVertexData;
1264            mSkelAnimVertexData = 0;
1265        }
1266                if (mSoftwareVertexAnimVertexData)
1267                {
1268                        delete mSoftwareVertexAnimVertexData;
1269                        mSoftwareVertexAnimVertexData = 0;
1270                }
1271                if (mHardwareVertexAnimVertexData)
1272                {
1273                        delete mHardwareVertexAnimVertexData;
1274                        mHardwareVertexAnimVertexData = 0;
1275                }
1276
1277                if (hasVertexAnimation())
1278                {
1279                        // Shared data
1280                        if (mMesh->sharedVertexData
1281                                && mMesh->getSharedVertexDataAnimationType() != VAT_NONE)
1282                        {
1283                                // Create temporary vertex blend info
1284                                // Prepare temp vertex data if needed
1285                                // Clone without copying data, don't remove any blending info
1286                                // (since if we skeletally animate too, we need it)
1287                                mSoftwareVertexAnimVertexData = mMesh->sharedVertexData->clone(false);
1288                                extractTempBufferInfo(mSoftwareVertexAnimVertexData, &mTempVertexAnimInfo);
1289
1290                                // Also clone for hardware usage, don't remove blend info since we'll
1291                                // need it if we also hardware skeletally animate
1292                                mHardwareVertexAnimVertexData = mMesh->sharedVertexData->clone(false);
1293                        }
1294                }
1295
1296        if (hasSkeleton())
1297        {
1298            // Shared data
1299            if (mMesh->sharedVertexData)
1300            {
1301                // Create temporary vertex blend info
1302                // Prepare temp vertex data if needed
1303                // Clone without copying data, remove blending info
1304                // (since blend is performed in software)
1305                mSkelAnimVertexData =
1306                    cloneVertexDataRemoveBlendInfo(mMesh->sharedVertexData);
1307                extractTempBufferInfo(mSkelAnimVertexData, &mTempSkelAnimInfo);
1308            }
1309
1310        }
1311
1312                // Do SubEntities
1313                SubEntityList::iterator i, iend;
1314                iend = mSubEntityList.end();
1315                for (i = mSubEntityList.begin(); i != iend; ++i)
1316                {
1317                        SubEntity* s = *i;
1318                        s->prepareTempBlendBuffers();
1319                }
1320
1321        // It's prepared for shadow volumes only if mesh has been prepared for shadow volumes.
1322        mPreparedForShadowVolumes = mMesh->isPreparedForShadowVolumes();
1323    }
1324    //-----------------------------------------------------------------------
1325    void Entity::extractTempBufferInfo(VertexData* sourceData, TempBlendedBufferInfo* info)
1326    {
1327        info->extractFrom(sourceData);
1328    }
1329    //-----------------------------------------------------------------------
1330    VertexData* Entity::cloneVertexDataRemoveBlendInfo(const VertexData* source)
1331    {
1332        // Clone without copying data
1333        VertexData* ret = source->clone(false);
1334        const VertexElement* blendIndexElem =
1335            source->vertexDeclaration->findElementBySemantic(VES_BLEND_INDICES);
1336        const VertexElement* blendWeightElem =
1337            source->vertexDeclaration->findElementBySemantic(VES_BLEND_WEIGHTS);
1338        // Remove blend index
1339        if (blendIndexElem)
1340        {
1341            // Remove buffer reference
1342            ret->vertexBufferBinding->unsetBinding(blendIndexElem->getSource());
1343
1344        }
1345        if (blendWeightElem &&
1346            blendWeightElem->getSource() != blendIndexElem->getSource())
1347        {
1348            // Remove buffer reference
1349            ret->vertexBufferBinding->unsetBinding(blendWeightElem->getSource());
1350        }
1351        // remove elements from declaration
1352        ret->vertexDeclaration->removeElement(VES_BLEND_INDICES);
1353        ret->vertexDeclaration->removeElement(VES_BLEND_WEIGHTS);
1354
1355        // Close gaps in bindings for effective and safely
1356        ret->closeGapsInBindings();
1357
1358        return ret;
1359    }
1360    //-----------------------------------------------------------------------
1361    EdgeData* Entity::getEdgeList(void)
1362    {
1363        // Get from Mesh
1364        return mMesh->getEdgeList(mMeshLodIndex);
1365    }
1366        //-----------------------------------------------------------------------
1367    bool Entity::hasEdgeList(void)
1368    {
1369        // check if mesh has an edge list attached
1370        // give mesh a chance to built it if scheduled
1371        return (mMesh->getEdgeList(mMeshLodIndex) != NULL);
1372    }
1373    //-----------------------------------------------------------------------
1374    void Entity::reevaluateVertexProcessing(void)
1375    {
1376        // init
1377        mHardwareAnimation = false;
1378        mVertexProgramInUse = false; // assume false because we just assign this
1379        bool firstPass = true;
1380
1381        SubEntityList::iterator i, iend;
1382        iend = mSubEntityList.end();
1383        for (i = mSubEntityList.begin(); i != iend; ++i)
1384        {
1385                        SubEntity* sub = *i;
1386            const MaterialPtr& m = sub->getMaterial();
1387            // Make sure it's loaded
1388            m->load();
1389            Technique* t = m->getBestTechnique();
1390            if (!t)
1391            {
1392                // No supported techniques
1393                continue;
1394            }
1395            Pass* p = t->getPass(0);
1396            if (!p)
1397            {
1398                // No passes, invalid
1399                continue;
1400            }
1401            if (p->hasVertexProgram())
1402            {
1403                // If one material uses a vertex program, set this flag
1404                // Causes some special processing like forcing a separate light cap
1405                mVertexProgramInUse = true;
1406
1407                if (hasSkeleton())
1408                                {
1409                                        // All materials must support skinning for us to consider using
1410                                        // hardware animation - if one fails we use software
1411                                        if (firstPass)
1412                                        {
1413                                                mHardwareAnimation = p->getVertexProgram()->isSkeletalAnimationIncluded();
1414                                                firstPass = false;
1415                                        }
1416                                        else
1417                                        {
1418                                                mHardwareAnimation = mHardwareAnimation &&
1419                                                        p->getVertexProgram()->isSkeletalAnimationIncluded();
1420                                        }
1421                                }
1422
1423                                VertexAnimationType animType = VAT_NONE;
1424                                if (sub->getSubMesh()->useSharedVertices)
1425                                {
1426                                        animType = mMesh->getSharedVertexDataAnimationType();
1427                                }
1428                                else
1429                                {
1430                                        animType = sub->getSubMesh()->getVertexAnimationType();
1431                                }
1432                                if (animType == VAT_MORPH)
1433                                {
1434                                        // All materials must support morph animation for us to consider using
1435                                        // hardware animation - if one fails we use software
1436                                        if (firstPass)
1437                                        {
1438                                                mHardwareAnimation = p->getVertexProgram()->isMorphAnimationIncluded();
1439                                                firstPass = false;
1440                                        }
1441                                        else
1442                                        {
1443                                                mHardwareAnimation = mHardwareAnimation &&
1444                                                        p->getVertexProgram()->isMorphAnimationIncluded();
1445                                        }
1446                                }
1447                                else if (animType == VAT_POSE)
1448                                {
1449                                        // All materials must support pose animation for us to consider using
1450                                        // hardware animation - if one fails we use software
1451                                        if (firstPass)
1452                                        {
1453                                                mHardwareAnimation = p->getVertexProgram()->isPoseAnimationIncluded();
1454                                                if (sub->getSubMesh()->useSharedVertices)
1455                                                        mHardwarePoseCount = p->getVertexProgram()->getNumberOfPosesIncluded();
1456                                                else
1457                                                        sub->mHardwarePoseCount = p->getVertexProgram()->getNumberOfPosesIncluded();
1458                                                firstPass = false;
1459                                        }
1460                                        else
1461                                        {
1462                                                mHardwareAnimation = mHardwareAnimation &&
1463                                                        p->getVertexProgram()->isPoseAnimationIncluded();
1464                                                if (sub->getSubMesh()->useSharedVertices)
1465                                                        mHardwarePoseCount = std::max(mHardwarePoseCount,
1466                                                                p->getVertexProgram()->getNumberOfPosesIncluded());
1467                                                else
1468                                                        sub->mHardwarePoseCount = std::max(sub->mHardwarePoseCount,
1469                                                                p->getVertexProgram()->getNumberOfPosesIncluded());
1470                                        }
1471                                }
1472
1473            }
1474        }
1475
1476        // Should be force update of animation if they exists, due reevaluate
1477        // vertex processing might switchs between hardware/software animation,
1478        // and then we'll end with NULL or incorrect mBoneWorldMatrices, or
1479        // incorrect blended software animation buffers.
1480        if (mAnimationState)
1481        {
1482            mFrameAnimationLastUpdated = mAnimationState->getDirtyFrameNumber() - 1;
1483        }
1484    }
1485    //-----------------------------------------------------------------------
1486    ShadowCaster::ShadowRenderableListIterator
1487        Entity::getShadowVolumeRenderableIterator(
1488        ShadowTechnique shadowTechnique, const Light* light,
1489        HardwareIndexBufferSharedPtr* indexBuffer,
1490        bool extrude, Real extrusionDistance, unsigned long flags)
1491    {
1492        assert(indexBuffer && "Only external index buffers are supported right now");
1493        assert((*indexBuffer)->getType() == HardwareIndexBuffer::IT_16BIT &&
1494            "Only 16-bit indexes supported for now");
1495
1496        // Potentially delegate to LOD entity
1497        if (mMesh->isLodManual() && mMeshLodIndex > 0)
1498        {
1499            // Use alternate entity
1500            assert( static_cast< size_t >( mMeshLodIndex - 1 ) < mLodEntityList.size() &&
1501                "No LOD EntityList - did you build the manual LODs after creating the entity?");
1502            // delegate, we're using manual LOD and not the top lod index
1503            if (hasSkeleton() && mLodEntityList[mMeshLodIndex - 1]->hasSkeleton())
1504            {
1505                // Copy the animation state set to lod entity, we assume the lod
1506                // entity only has a subset animation states
1507                mAnimationState->copyMatchingState(
1508                                        mLodEntityList[mMeshLodIndex - 1]->mAnimationState);
1509            }
1510            return mLodEntityList[mMeshLodIndex-1]->getShadowVolumeRenderableIterator(
1511                shadowTechnique, light, indexBuffer, extrude,
1512                extrusionDistance, flags);
1513        }
1514
1515
1516        // Prepare temp buffers if required
1517        if (!mPreparedForShadowVolumes)
1518        {
1519            mMesh->prepareForShadowVolume();
1520            // reset frame last updated to force update of animations if they exist
1521            if (mAnimationState)
1522                mFrameAnimationLastUpdated = mAnimationState->getDirtyFrameNumber() - 1;
1523            // re-prepare buffers
1524            prepareTempBlendBuffers();
1525        }
1526
1527
1528        bool hasAnimation = (hasSkeleton() || hasVertexAnimation());
1529
1530        // Update any animation
1531        if (hasAnimation)
1532        {
1533            updateAnimation();
1534        }
1535
1536        // Calculate the object space light details
1537        Vector4 lightPos = light->getAs4DVector();
1538        Matrix4 world2Obj = mParentNode->_getFullTransform().inverseAffine();
1539        lightPos = world2Obj.transformAffine(lightPos);
1540
1541        // We need to search the edge list for silhouette edges
1542        EdgeData* edgeList = getEdgeList();
1543
1544                if (!edgeList)
1545                {
1546                        // we can't get an edge list for some reason, return blank
1547                        // really we shouldn't be able to get here, but this is a safeguard
1548                        return ShadowRenderableListIterator(mShadowRenderables.begin(), mShadowRenderables.end());
1549                }
1550
1551        // Init shadow renderable list if required
1552        bool init = mShadowRenderables.empty();
1553
1554        EdgeData::EdgeGroupList::iterator egi;
1555        ShadowRenderableList::iterator si, siend;
1556        EntityShadowRenderable* esr = 0;
1557        if (init)
1558            mShadowRenderables.resize(edgeList->edgeGroups.size());
1559
1560        bool isAnimated = hasAnimation;
1561        bool updatedSharedGeomNormals = false;
1562        siend = mShadowRenderables.end();
1563        egi = edgeList->edgeGroups.begin();
1564        for (si = mShadowRenderables.begin(); si != siend; ++si, ++egi)
1565        {
1566            const VertexData *pVertData;
1567            if (isAnimated)
1568            {
1569                // Use temp buffers
1570                pVertData = findBlendedVertexData(egi->vertexData);
1571            }
1572            else
1573            {
1574                pVertData = egi->vertexData;
1575            }
1576            if (init)
1577            {
1578                // Try to find corresponding SubEntity; this allows the
1579                // linkage of visibility between ShadowRenderable and SubEntity
1580                SubEntity* subent = findSubEntityForVertexData(egi->vertexData);
1581                // Create a new renderable, create a separate light cap if
1582                // we're using a vertex program (either for this model, or
1583                // for extruding the shadow volume) since otherwise we can
1584                // get depth-fighting on the light cap
1585
1586                *si = new EntityShadowRenderable(this, indexBuffer, pVertData,
1587                    mVertexProgramInUse || !extrude, subent);
1588            }
1589            else
1590            {
1591                // If we have animation, we have no guarantee that the position
1592                // buffer we used last frame is the same one we used last frame
1593                // since a temporary buffer is requested each frame
1594                // therefore, we need to update the EntityShadowRenderable
1595                // with the current position buffer
1596                static_cast<EntityShadowRenderable*>(*si)->rebindPositionBuffer(pVertData, hasAnimation);
1597
1598            }
1599            // Get shadow renderable
1600            esr = static_cast<EntityShadowRenderable*>(*si);
1601            HardwareVertexBufferSharedPtr esrPositionBuffer = esr->getPositionBuffer();
1602            // For animated entities we need to recalculate the face normals
1603            if (hasAnimation)
1604            {
1605                if (egi->vertexData != mMesh->sharedVertexData || !updatedSharedGeomNormals)
1606                {
1607                    // recalculate face normals
1608                    edgeList->updateFaceNormals(egi->vertexSet, esrPositionBuffer);
1609                    // If we're not extruding in software we still need to update
1610                    // the latter part of the buffer (the hardware extruded part)
1611                    // with the latest animated positions
1612                    if (!extrude)
1613                    {
1614                        // Lock, we'll be locking the (suppressed hardware update) shadow buffer
1615                        float* pSrc = static_cast<float*>(
1616                            esrPositionBuffer->lock(HardwareBuffer::HBL_NORMAL));
1617                        float* pDest = pSrc + (egi->vertexData->vertexCount * 3);
1618                        memcpy(pDest, pSrc, sizeof(float) * 3 * egi->vertexData->vertexCount);
1619                        esrPositionBuffer->unlock();
1620                    }
1621                    if (egi->vertexData == mMesh->sharedVertexData)
1622                    {
1623                        updatedSharedGeomNormals = true;
1624                    }
1625                }
1626            }
1627            // Extrude vertices in software if required
1628            if (extrude)
1629            {
1630                extrudeVertices(esrPositionBuffer,
1631                    egi->vertexData->vertexCount,
1632                    lightPos, extrusionDistance);
1633
1634            }
1635            // Stop suppressing hardware update now, if we were
1636            esrPositionBuffer->suppressHardwareUpdate(false);
1637
1638        }
1639        // Calc triangle light facing
1640        updateEdgeListLightFacing(edgeList, lightPos);
1641
1642        // Generate indexes and update renderables
1643        generateShadowVolume(edgeList, *indexBuffer, light,
1644            mShadowRenderables, flags);
1645
1646
1647        return ShadowRenderableListIterator(mShadowRenderables.begin(), mShadowRenderables.end());
1648    }
1649    //-----------------------------------------------------------------------
1650    const VertexData* Entity::findBlendedVertexData(const VertexData* orig)
1651    {
1652                bool skel = hasSkeleton();
1653
1654        if (orig == mMesh->sharedVertexData)
1655        {
1656                        return skel? mSkelAnimVertexData : mSoftwareVertexAnimVertexData;
1657        }
1658        SubEntityList::iterator i, iend;
1659        iend = mSubEntityList.end();
1660        for (i = mSubEntityList.begin(); i != iend; ++i)
1661        {
1662            SubEntity* se = *i;
1663            if (orig == se->getSubMesh()->vertexData)
1664            {
1665                                return skel? se->_getSkelAnimVertexData() : se->_getSoftwareVertexAnimVertexData();
1666            }
1667        }
1668        // None found
1669        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
1670            "Cannot find blended version of the vertex data specified.",
1671            "Entity::findBlendedVertexData");
1672    }
1673    //-----------------------------------------------------------------------
1674    SubEntity* Entity::findSubEntityForVertexData(const VertexData* orig)
1675    {
1676        if (orig == mMesh->sharedVertexData)
1677        {
1678            return 0;
1679        }
1680
1681        SubEntityList::iterator i, iend;
1682        iend = mSubEntityList.end();
1683        for (i = mSubEntityList.begin(); i != iend; ++i)
1684        {
1685            SubEntity* se = *i;
1686            if (orig == se->getSubMesh()->vertexData)
1687            {
1688                return se;
1689            }
1690        }
1691
1692        // None found
1693        return 0;
1694    }
1695    //-----------------------------------------------------------------------
1696    void Entity::addSoftwareAnimationRequest(bool normalsAlso)
1697    {
1698        mSoftwareAnimationRequests++;
1699        if (normalsAlso) {
1700            mSoftwareAnimationNormalsRequests++;
1701        }
1702    }
1703    //-----------------------------------------------------------------------
1704    void Entity::removeSoftwareAnimationRequest(bool normalsAlso)
1705    {
1706        if (mSoftwareAnimationRequests == 0 ||
1707            (normalsAlso && mSoftwareAnimationNormalsRequests == 0))
1708        {
1709            OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
1710                        "Attempt to remove nonexistant request.",
1711                        "Entity::removeSoftwareAnimationRequest");
1712        }
1713        mSoftwareAnimationRequests--;
1714        if (normalsAlso) {
1715            mSoftwareAnimationNormalsRequests--;
1716        }
1717    }
1718    //-----------------------------------------------------------------------
1719    void Entity::_notifyAttached(Node* parent, bool isTagPoint)
1720    {
1721        MovableObject::_notifyAttached(parent, isTagPoint);
1722        // Also notify LOD entities
1723        LODEntityList::iterator i, iend;
1724        iend = mLodEntityList.end();
1725        for (i = mLodEntityList.begin(); i != iend; ++i)
1726        {
1727            (*i)->_notifyAttached(parent, isTagPoint);
1728        }
1729
1730    }
1731    //-----------------------------------------------------------------------
1732    //-----------------------------------------------------------------------
1733    Entity::EntityShadowRenderable::EntityShadowRenderable(Entity* parent,
1734        HardwareIndexBufferSharedPtr* indexBuffer, const VertexData* vertexData,
1735        bool createSeparateLightCap, SubEntity* subent, bool isLightCap)
1736        : mParent(parent), mSubEntity(subent)
1737    {
1738        // Save link to vertex data
1739        mCurrentVertexData = vertexData;
1740
1741        // Initialise render op
1742        mRenderOp.indexData = new IndexData();
1743        mRenderOp.indexData->indexBuffer = *indexBuffer;
1744        mRenderOp.indexData->indexStart = 0;
1745        // index start and count are sorted out later
1746
1747        // Create vertex data which just references position component (and 2 component)
1748        mRenderOp.vertexData = new VertexData();
1749        // Map in position data
1750        mRenderOp.vertexData->vertexDeclaration->addElement(0,0,VET_FLOAT3, VES_POSITION);
1751        mOriginalPosBufferBinding =
1752            vertexData->vertexDeclaration->findElementBySemantic(VES_POSITION)->getSource();
1753        mPositionBuffer = vertexData->vertexBufferBinding->getBuffer(mOriginalPosBufferBinding);
1754        mRenderOp.vertexData->vertexBufferBinding->setBinding(0, mPositionBuffer);
1755        // Map in w-coord buffer (if present)
1756        if(!vertexData->hardwareShadowVolWBuffer.isNull())
1757        {
1758            mRenderOp.vertexData->vertexDeclaration->addElement(1,0,VET_FLOAT1, VES_TEXTURE_COORDINATES, 0);
1759            mWBuffer = vertexData->hardwareShadowVolWBuffer;
1760            mRenderOp.vertexData->vertexBufferBinding->setBinding(1, mWBuffer);
1761        }
1762        // Use same vertex start as input
1763        mRenderOp.vertexData->vertexStart = vertexData->vertexStart;
1764
1765        if (isLightCap)
1766        {
1767            // Use original vertex count, no extrusion
1768            mRenderOp.vertexData->vertexCount = vertexData->vertexCount;
1769        }
1770        else
1771        {
1772            // Vertex count must take into account the doubling of the buffer,
1773            // because second half of the buffer is the extruded copy
1774            mRenderOp.vertexData->vertexCount =
1775                vertexData->vertexCount * 2;
1776            if (createSeparateLightCap)
1777            {
1778                // Create child light cap
1779                mLightCap = new EntityShadowRenderable(parent,
1780                    indexBuffer, vertexData, false, subent, true);
1781            }
1782        }
1783
1784    }
1785    //-----------------------------------------------------------------------
1786    Entity::EntityShadowRenderable::~EntityShadowRenderable()
1787    {
1788        delete mRenderOp.indexData;
1789        delete mRenderOp.vertexData;
1790    }
1791    //-----------------------------------------------------------------------
1792    void Entity::EntityShadowRenderable::getWorldTransforms(Matrix4* xform) const
1793    {
1794        *xform = mParent->_getParentNodeFullTransform();
1795    }
1796    //-----------------------------------------------------------------------
1797    const Quaternion& Entity::EntityShadowRenderable::getWorldOrientation(void) const
1798    {
1799        return mParent->getParentNode()->_getDerivedOrientation();
1800    }
1801    //-----------------------------------------------------------------------
1802    const Vector3& Entity::EntityShadowRenderable::getWorldPosition(void) const
1803    {
1804        return mParent->getParentNode()->_getDerivedPosition();
1805    }
1806    //-----------------------------------------------------------------------
1807    void Entity::EntityShadowRenderable::rebindPositionBuffer(const VertexData* vertexData, bool force)
1808    {
1809        if (force || mCurrentVertexData != vertexData)
1810        {
1811            mCurrentVertexData = vertexData;
1812            mPositionBuffer = mCurrentVertexData->vertexBufferBinding->getBuffer(
1813                mOriginalPosBufferBinding);
1814            mRenderOp.vertexData->vertexBufferBinding->setBinding(0, mPositionBuffer);
1815            if (mLightCap)
1816            {
1817                static_cast<EntityShadowRenderable*>(mLightCap)->rebindPositionBuffer(vertexData, force);
1818            }
1819        }
1820    }
1821    //-----------------------------------------------------------------------
1822    bool Entity::EntityShadowRenderable::isVisible(void) const
1823    {
1824        if (mSubEntity)
1825        {
1826            return mSubEntity->isVisible();
1827        }
1828        else
1829        {
1830            return ShadowRenderable::isVisible();
1831        }
1832    }
1833    //-----------------------------------------------------------------------
1834    void Entity::setRenderQueueGroup(uint8 queueID)
1835    {
1836        MovableObject::setRenderQueueGroup(queueID);
1837
1838        // Set render queue for all manual LOD entities
1839        if (mMesh->isLodManual())
1840        {
1841            LODEntityList::iterator li, liend;
1842            liend = mLodEntityList.end();
1843            for (li = mLodEntityList.begin(); li != liend; ++li)
1844            {
1845                (*li)->setRenderQueueGroup(queueID);
1846            }
1847        }
1848    }
1849    //-----------------------------------------------------------------------
1850    void Entity::shareSkeletonInstanceWith(Entity* entity)
1851    {
1852        if (entity->getMesh()->getSkeleton() != getMesh()->getSkeleton())
1853        {
1854            OGRE_EXCEPT(Exception::ERR_RT_ASSERTION_FAILED,
1855                "The supplied entity has a different skeleton.",
1856                "Entity::shareSkeletonWith");
1857        }
1858        if (!mSkeletonInstance)
1859        {
1860            OGRE_EXCEPT(Exception::ERR_RT_ASSERTION_FAILED,
1861                "This entity has no skeleton.",
1862                "Entity::shareSkeletonWith");
1863        }
1864        if (mSharedSkeletonEntities != NULL && entity->mSharedSkeletonEntities != NULL)
1865        {
1866            OGRE_EXCEPT(Exception::ERR_RT_ASSERTION_FAILED,
1867                "Both entities already shares their SkeletonInstances! At least "
1868                "one of the instances must not share it's instance.",
1869                "Entity::shareSkeletonWith");
1870        }
1871
1872        //check if we already share our skeletoninstance, we don't want to delete it if so
1873        if (mSharedSkeletonEntities != NULL)
1874        {
1875            entity->shareSkeletonInstanceWith(this);
1876        }
1877        else
1878        {
1879            delete mSkeletonInstance;
1880            AlignedMemory::deallocate(mBoneMatrices);
1881            delete mAnimationState;
1882            delete mFrameBonesLastUpdated;
1883            mSkeletonInstance = entity->mSkeletonInstance;
1884            mNumBoneMatrices = entity->mNumBoneMatrices;
1885            mBoneMatrices = entity->mBoneMatrices;
1886            mAnimationState = entity->mAnimationState;
1887            mFrameBonesLastUpdated = entity->mFrameBonesLastUpdated;
1888            if (entity->mSharedSkeletonEntities == NULL)
1889            {
1890                entity->mSharedSkeletonEntities = new EntitySet();
1891                entity->mSharedSkeletonEntities->insert(entity);
1892            }
1893            mSharedSkeletonEntities = entity->mSharedSkeletonEntities;
1894            mSharedSkeletonEntities->insert(this);
1895        }
1896    }
1897    //-----------------------------------------------------------------------
1898    void Entity::stopSharingSkeletonInstance()
1899    {
1900        if (mSharedSkeletonEntities == NULL)
1901        {
1902            OGRE_EXCEPT(Exception::ERR_RT_ASSERTION_FAILED,
1903                "This entity is not sharing it's skeletoninstance.",
1904                "Entity::shareSkeletonWith");
1905        }
1906        //check if there's no other than us sharing the skeleton instance
1907        if (mSharedSkeletonEntities->size() == 1)
1908        {
1909            //just reset
1910            delete mSharedSkeletonEntities;
1911            mSharedSkeletonEntities = 0;
1912        }
1913        else
1914        {
1915            mSkeletonInstance = new SkeletonInstance(mMesh->getSkeleton());
1916            mSkeletonInstance->load();
1917            mAnimationState = new AnimationStateSet();
1918            mMesh->_initAnimationState(mAnimationState);
1919            mFrameBonesLastUpdated = new unsigned long(std::numeric_limits<unsigned long>::max());
1920            mNumBoneMatrices = mSkeletonInstance->getNumBones();
1921            mBoneMatrices = static_cast<Matrix4*>(AlignedMemory::allocate(sizeof(Matrix4) * mNumBoneMatrices));
1922
1923            mSharedSkeletonEntities->erase(this);
1924            if (mSharedSkeletonEntities->size() == 1)
1925            {
1926                (*mSharedSkeletonEntities->begin())->stopSharingSkeletonInstance();
1927            }
1928            mSharedSkeletonEntities = 0;
1929        }
1930    }
1931    //-----------------------------------------------------------------------
1932        void Entity::refreshAvailableAnimationState(void)
1933        {
1934                mMesh->_refreshAnimationState(mAnimationState);
1935        }
1936        //-----------------------------------------------------------------------
1937        uint32 Entity::getTypeFlags(void) const
1938        {
1939                return SceneManager::ENTITY_TYPE_MASK;
1940        }
1941        //-----------------------------------------------------------------------
1942        VertexData* Entity::getVertexDataForBinding(void)
1943        {
1944                Entity::VertexDataBindChoice c =
1945                        chooseVertexDataForBinding(mMesh->getSharedVertexDataAnimationType() != VAT_NONE);
1946                switch(c)
1947                {
1948                case BIND_ORIGINAL:
1949                        return mMesh->sharedVertexData;
1950                case BIND_HARDWARE_MORPH:
1951                        return mHardwareVertexAnimVertexData;
1952                case BIND_SOFTWARE_MORPH:
1953                        return mSoftwareVertexAnimVertexData;
1954                case BIND_SOFTWARE_SKELETAL:
1955                        return mSkelAnimVertexData;
1956                };
1957                // keep compiler happy
1958                return mMesh->sharedVertexData;
1959        }
1960        //-----------------------------------------------------------------------
1961        Entity::VertexDataBindChoice Entity::chooseVertexDataForBinding(bool vertexAnim) const
1962        {
1963                if (hasSkeleton())
1964                {
1965                        if (!mHardwareAnimation)
1966                        {
1967                                // all software skeletal binds same vertex data
1968                                // may be a 2-stage s/w transform including morph earlier though
1969                                return BIND_SOFTWARE_SKELETAL;
1970                        }
1971                        else if (vertexAnim)
1972                        {
1973                                // hardware morph animation
1974                                return BIND_HARDWARE_MORPH;
1975                        }
1976                        else
1977                        {
1978                                // hardware skeletal, no morphing
1979                                return BIND_ORIGINAL;
1980                        }
1981                }
1982                else if (vertexAnim)
1983                {
1984                        // morph only, no skeletal
1985                        if (mHardwareAnimation)
1986                        {
1987                                return BIND_HARDWARE_MORPH;
1988                        }
1989                        else
1990                        {
1991                                return BIND_SOFTWARE_MORPH;
1992                        }
1993
1994                }
1995                else
1996                {
1997                        return BIND_ORIGINAL;
1998                }
1999
2000        }
2001        //-----------------------------------------------------------------------
2002        //-----------------------------------------------------------------------
2003        String EntityFactory::FACTORY_TYPE_NAME = "Entity";
2004        //-----------------------------------------------------------------------
2005        const String& EntityFactory::getType(void) const
2006        {
2007                return FACTORY_TYPE_NAME;
2008        }
2009        //-----------------------------------------------------------------------
2010        MovableObject* EntityFactory::createInstanceImpl( const String& name,
2011                const NameValuePairList* params)
2012        {
2013                // must have mesh parameter
2014                MeshPtr pMesh;
2015                if (params != 0)
2016                {
2017                        NameValuePairList::const_iterator ni = params->find("mesh");
2018                        if (ni != params->end())
2019                        {
2020                                // Get mesh (load if required)
2021                                pMesh = MeshManager::getSingleton().load(
2022                                        ni->second,
2023                                        // autodetect group location
2024                                        ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME );
2025                        }
2026
2027                }
2028                if (pMesh.isNull())
2029                {
2030                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
2031                                "'mesh' parameter required when constructing an Entity.",
2032                                "EntityFactory::createInstance");
2033                }
2034
2035                return new Entity(name, pMesh);
2036
2037        }
2038        //-----------------------------------------------------------------------
2039        void EntityFactory::destroyInstance( MovableObject* obj)
2040        {
2041                delete obj;
2042        }
2043
2044
2045}
Note: See TracBrowser for help on using the repository browser.