source: OGRE/trunk/ogrenew/OgreMain/src/OgreEntity.cpp @ 692

Revision 692, 72.4 KB checked in by mattausch, 19 years ago (diff)

adding ogre 1.2 and dependencies

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