2 -----------------------------------------------------------------------------
3 This source file is part of OGRE
4 (Object-oriented Graphics Rendering Engine)
5 For the latest info, see http://www.ogre3d.org
7 Copyright (c) 2000-2006 Torus Knot Software Ltd
8 Also see acknowledgements in Readme.html
10 This program is free software; you can redistribute it and/or modify it under
11 the terms of the GNU Lesser General Public License as published by the Free Software
12 Foundation; either version 2 of the License, or (at your option) any later
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License along with
20 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22 http://www.gnu.org/copyleft/lesser.txt.
24 You may alternatively use this source under the terms of a specific version of
25 the OGRE Unrestricted License provided you have obtained such a license from
26 Torus Knot Software Ltd.
27 -----------------------------------------------------------------------------
29 #include "OgreStableHeaders.h"
30 #include "OgreEntity.h"
32 #include "OgreMeshManager.h"
33 #include "OgreSubMesh.h"
34 #include "OgreSubEntity.h"
35 #include "OgreException.h"
36 #include "OgreSceneManager.h"
37 #include "OgreLogManager.h"
38 #include "OgreSkeleton.h"
40 #include "OgreCamera.h"
41 #include "OgreTagPoint.h"
42 #include "OgreAxisAlignedBox.h"
43 #include "OgreHardwareBufferManager.h"
44 #include "OgreVector4.h"
46 #include "OgreTechnique.h"
48 #include "OgreSkeletonInstance.h"
49 #include "OgreEdgeListBuilder.h"
50 #include "OgreStringConverter.h"
51 #include "OgreAnimation.h"
52 #include "OgreOptimisedUtil.h"
53 #include "OgreSceneNode.h"
54 #include "OgreLodStrategy.h"
55 #include "OgreLodListener.h"
58 //-----------------------------------------------------------------------
60 : mAnimationState(NULL
),
61 mSkelAnimVertexData(0),
62 mSoftwareVertexAnimVertexData(0),
63 mHardwareVertexAnimVertexData(0),
64 mPreparedForShadowVolumes(false),
65 mBoneWorldMatrices(NULL
),
68 mFrameAnimationLastUpdated(std::numeric_limits
<unsigned long>::max()),
69 mFrameBonesLastUpdated(NULL
),
70 mSharedSkeletonEntities(NULL
),
71 mDisplaySkeleton(false),
72 mHardwareAnimation(false),
73 mHardwarePoseCount(0),
74 mVertexProgramInUse(false),
75 mSoftwareAnimationRequests(0),
76 mSoftwareAnimationNormalsRequests(0),
78 mMeshLodFactorTransformed(1.0f
),
80 mMaxMeshLodIndex(0), // Backwards, remember low value = high detail
81 mMaterialLodFactor(1.0f
),
82 mMaterialLodFactorTransformed(1.0f
),
83 mMinMaterialLodIndex(99),
84 mMaxMaterialLodIndex(0), // Backwards, remember low value = high detail
87 mLastParentXform(Matrix4::ZERO
),
92 //-----------------------------------------------------------------------
93 Entity::Entity( const String
& name
, const MeshPtr
& mesh
) :
96 mAnimationState(NULL
),
97 mSkelAnimVertexData(0),
98 mSoftwareVertexAnimVertexData(0),
99 mHardwareVertexAnimVertexData(0),
100 mPreparedForShadowVolumes(false),
101 mBoneWorldMatrices(NULL
),
104 mFrameAnimationLastUpdated(std::numeric_limits
<unsigned long>::max()),
105 mFrameBonesLastUpdated(NULL
),
106 mSharedSkeletonEntities(NULL
),
107 mDisplaySkeleton(false),
108 mHardwareAnimation(false),
109 mVertexProgramInUse(false),
110 mSoftwareAnimationRequests(0),
111 mSoftwareAnimationNormalsRequests(0),
113 mMeshLodFactorTransformed(1.0f
),
114 mMinMeshLodIndex(99),
115 mMaxMeshLodIndex(0), // Backwards, remember low value = high detail
116 mMaterialLodFactor(1.0f
),
117 mMaterialLodFactorTransformed(1.0f
),
118 mMinMaterialLodIndex(99),
119 mMaxMaterialLodIndex(0), // Backwards, remember low value = high detail
120 mSkeletonInstance(0),
122 mLastParentXform(Matrix4::ZERO
),
128 //-----------------------------------------------------------------------
129 void Entity::backgroundLoadingComplete(Resource
* res
)
131 if (res
== mMesh
.get())
133 // mesh loading has finished, we can construct ourselves now
137 //-----------------------------------------------------------------------
138 void Entity::_initialise(bool forceReinitialise
)
140 if (forceReinitialise
)
146 if (mMesh
->isBackgroundLoaded() && !mMesh
->isLoaded())
148 // register for a callback when mesh is finished loading
149 // do this before asking for load to happen to avoid race
150 mMesh
->addListener(this);
155 // If loading failed, or deferred loading isn't done yet, defer
156 // Will get a callback in the case of deferred loading
157 // Skeletons are cascade-loaded so no issues there
158 if (!mMesh
->isLoaded())
161 // Is mesh skeletally animated?
162 if (mMesh
->hasSkeleton() && !mMesh
->getSkeleton().isNull())
164 mSkeletonInstance
= OGRE_NEW
SkeletonInstance(mMesh
->getSkeleton());
165 mSkeletonInstance
->load();
168 // Build main subentity list
169 buildSubEntityList(mMesh
, &mSubEntityList
);
171 // Check if mesh is using manual LOD
172 if (mMesh
->isLodManual())
175 numLod
= mMesh
->getNumLodLevels();
176 // NB skip LOD 0 which is the original
177 for (i
= 1; i
< numLod
; ++i
)
179 const MeshLodUsage
& usage
= mMesh
->getLodLevel(i
);
180 // Manually create entity
181 Entity
* lodEnt
= OGRE_NEW
Entity(mName
+ "Lod" + StringConverter::toString(i
),
183 mLodEntityList
.push_back(lodEnt
);
188 // Initialise the AnimationState, if Mesh has animation
191 mFrameBonesLastUpdated
= OGRE_NEW_T(unsigned long, MEMCATEGORY_ANIMATION
)(std::numeric_limits
<unsigned long>::max());
192 mNumBoneMatrices
= mSkeletonInstance
->getNumBones();
193 mBoneMatrices
= static_cast<Matrix4
*>(OGRE_MALLOC_SIMD(sizeof(Matrix4
) * mNumBoneMatrices
, MEMCATEGORY_ANIMATION
));
195 if (hasSkeleton() || hasVertexAnimation())
197 mAnimationState
= OGRE_NEW
AnimationStateSet();
198 mMesh
->_initAnimationState(mAnimationState
);
199 prepareTempBlendBuffers();
202 reevaluateVertexProcessing();
204 // Update of bounds of the parent SceneNode, if Entity already attached
205 // this can happen if Mesh is loaded in background or after reinitialisation
208 getParentSceneNode()->needUpdate();
212 mMeshStateCount
= mMesh
->getStateCount();
215 //-----------------------------------------------------------------------
216 void Entity::_deinitialise(void)
222 SubEntityList::iterator i
, iend
;
223 iend
= mSubEntityList
.end();
224 for (i
= mSubEntityList
.begin(); i
!= iend
; ++i
)
229 mSubEntityList
.clear();
231 // Delete LOD entities
232 LODEntityList::iterator li
, liend
;
233 liend
= mLodEntityList
.end();
234 for (li
= mLodEntityList
.begin(); li
!= liend
; ++li
)
239 mLodEntityList
.clear();
241 // Delete shadow renderables
242 ShadowRenderableList::iterator si
, siend
;
243 siend
= mShadowRenderables
.end();
244 for (si
= mShadowRenderables
.begin(); si
!= siend
; ++si
)
248 mShadowRenderables
.clear();
250 // Detach all child objects, do this manually to avoid needUpdate() call
251 // which can fail because of deleted items
252 detachAllObjectsImpl();
254 if (mSkeletonInstance
) {
255 OGRE_FREE_SIMD(mBoneWorldMatrices
, MEMCATEGORY_ANIMATION
);
257 if (mSharedSkeletonEntities
) {
258 mSharedSkeletonEntities
->erase(this);
259 if (mSharedSkeletonEntities
->size() == 1)
261 (*mSharedSkeletonEntities
->begin())->stopSharingSkeletonInstance();
263 // Should never occuring, just in case
264 else if (mSharedSkeletonEntities
->empty())
266 OGRE_DELETE_T(mSharedSkeletonEntities
, EntitySet
, MEMCATEGORY_ANIMATION
);
267 // using OGRE_FREE since unsigned long is not a destructor
268 OGRE_FREE(mFrameBonesLastUpdated
, MEMCATEGORY_ANIMATION
);
269 OGRE_DELETE mSkeletonInstance
;
270 OGRE_FREE_SIMD(mBoneMatrices
, MEMCATEGORY_ANIMATION
);
271 OGRE_DELETE mAnimationState
;
274 // using OGRE_FREE since unsigned long is not a destructor
275 OGRE_FREE(mFrameBonesLastUpdated
, MEMCATEGORY_ANIMATION
);
276 OGRE_DELETE mSkeletonInstance
;
277 OGRE_FREE_SIMD(mBoneMatrices
, MEMCATEGORY_ANIMATION
);
278 OGRE_DELETE mAnimationState
;
281 else if (hasVertexAnimation())
283 OGRE_DELETE mAnimationState
;
286 OGRE_DELETE mSkelAnimVertexData
;
287 OGRE_DELETE mSoftwareVertexAnimVertexData
;
288 OGRE_DELETE mHardwareVertexAnimVertexData
;
290 mInitialised
= false;
292 //-----------------------------------------------------------------------
296 // Unregister our listener
297 mMesh
->removeListener(this);
299 //-----------------------------------------------------------------------
300 bool Entity::hasVertexAnimation(void) const
302 return mMesh
->hasVertexAnimation();
304 //-----------------------------------------------------------------------
305 const MeshPtr
& Entity::getMesh(void) const
309 //-----------------------------------------------------------------------
310 SubEntity
* Entity::getSubEntity(unsigned int index
) const
312 if (index
>= mSubEntityList
.size())
313 OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS
,
314 "Index out of bounds.",
315 "Entity::getSubEntity");
316 return mSubEntityList
[index
];
318 //-----------------------------------------------------------------------
319 SubEntity
* Entity::getSubEntity(const String
& name
) const
321 ushort index
= mMesh
->_getSubMeshIndex(name
);
322 return getSubEntity(index
);
324 //-----------------------------------------------------------------------
325 unsigned int Entity::getNumSubEntities(void) const
327 return static_cast< unsigned int >( mSubEntityList
.size() );
329 //-----------------------------------------------------------------------
330 Entity
* Entity::clone( const String
& newName
) const
334 OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND
,
335 "Cannot clone an Entity that wasn't created through a "
336 "SceneManager", "Entity::clone");
338 Entity
* newEnt
= mManager
->createEntity(newName
, getMesh()->getName() );
342 // Copy material settings
343 SubEntityList::const_iterator i
;
345 for (i
= mSubEntityList
.begin(); i
!= mSubEntityList
.end(); ++i
, ++n
)
347 newEnt
->getSubEntity(n
)->setMaterialName((*i
)->getMaterialName());
351 OGRE_DELETE newEnt
->mAnimationState
;
352 newEnt
->mAnimationState
= OGRE_NEW
AnimationStateSet(*mAnimationState
);
358 //-----------------------------------------------------------------------
359 void Entity::setMaterialName( const String
& name
, const String
& groupName
/* = ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME */)
361 // Set for all subentities
362 SubEntityList::iterator i
;
363 for (i
= mSubEntityList
.begin(); i
!= mSubEntityList
.end(); ++i
)
365 (*i
)->setMaterialName(name
);
371 void Entity::setMaterial( const MaterialPtr
& material
)
373 // Set for all subentities
374 SubEntityList::iterator i
;
375 for (i
= mSubEntityList
.begin(); i
!= mSubEntityList
.end(); ++i
)
377 (*i
)->setMaterial(material
);
381 //-----------------------------------------------------------------------
382 void Entity::_notifyCurrentCamera(Camera
* cam
)
384 MovableObject::_notifyCurrentCamera(cam
);
389 // Get mesh lod strategy
390 const LodStrategy
*meshStrategy
= mMesh
->getLodStrategy();
391 // Get the appropriate lod value
392 Real lodValue
= meshStrategy
->getValue(this, cam
);
393 // Bias the lod value
394 Real biasedMeshLodValue
= lodValue
* mMeshLodFactorTransformed
;
397 // Get the index at this biased depth
398 ushort newMeshLodIndex
= mMesh
->getLodIndex(biasedMeshLodValue
);
399 // Apply maximum detail restriction (remember lower = higher detail)
400 newMeshLodIndex
= std::max(mMaxMeshLodIndex
, newMeshLodIndex
);
401 // Apply minimum detail restriction (remember higher = lower detail)
402 newMeshLodIndex
= std::min(mMinMeshLodIndex
, newMeshLodIndex
);
404 // Construct event object
405 EntityMeshLodChangedEvent evt
;
408 evt
.lodValue
= biasedMeshLodValue
;
409 evt
.previousLodIndex
= mMeshLodIndex
;
410 evt
.newLodIndex
= newMeshLodIndex
;
412 // Notify lod event listeners
413 cam
->getSceneManager()->_notifyEntityMeshLodChanged(evt
);
416 mMeshLodIndex
= evt
.newLodIndex
;
418 // Now do material LOD
419 lodValue
*= mMaterialLodFactorTransformed
;
423 SubEntityList::iterator i
, iend
;
424 iend
= mSubEntityList
.end();
425 for (i
= mSubEntityList
.begin(); i
!= iend
; ++i
)
427 // Get sub-entity material
428 MaterialPtr material
= (*i
)->mpMaterial
;
430 // Get material lod strategy
431 const LodStrategy
*materialStrategy
= material
->getLodStrategy();
433 // Recalculate lod value if strategies do not match
434 Real biasedMaterialLodValue
;
435 if (meshStrategy
== materialStrategy
)
436 biasedMaterialLodValue
= lodValue
;
438 biasedMaterialLodValue
= materialStrategy
->getValue(this, cam
) * materialStrategy
->transformBias(mMaterialLodFactor
);
440 // Get the index at this biased depth
441 unsigned short idx
= material
->getLodIndex(biasedMaterialLodValue
);
442 // Apply maximum detail restriction (remember lower = higher detail)
443 idx
= std::max(mMaxMaterialLodIndex
, idx
);
444 // Apply minimum detail restriction (remember higher = lower detail)
445 idx
= std::min(mMinMaterialLodIndex
, idx
);
447 // Construct event object
448 EntityMaterialLodChangedEvent evt
;
449 evt
.subEntity
= (*i
);
451 evt
.lodValue
= biasedMaterialLodValue
;
452 evt
.previousLodIndex
= (*i
)->mMaterialLodIndex
;
453 evt
.newLodIndex
= idx
;
455 // Notify lod event listeners
456 cam
->getSceneManager()->_notifyEntityMaterialLodChanged(evt
);
459 (*i
)->mMaterialLodIndex
= evt
.newLodIndex
;
461 // Also invalidate any camera distance cache
462 (*i
)->_invalidateCameraCache ();
467 // Notify any child objects
468 ChildObjectList::iterator child_itr
= mChildObjectList
.begin();
469 ChildObjectList::iterator child_itr_end
= mChildObjectList
.end();
470 for( ; child_itr
!= child_itr_end
; child_itr
++)
472 (*child_itr
).second
->_notifyCurrentCamera(cam
);
475 //-----------------------------------------------------------------------
476 const AxisAlignedBox
& Entity::getBoundingBox(void) const
479 mFullBoundingBox
= mMesh
->getBounds();
480 mFullBoundingBox
.merge(getChildObjectsBoundingBox());
482 // Don't scale here, this is taken into account when world BBox calculation is done
484 return mFullBoundingBox
;
486 //-----------------------------------------------------------------------
487 AxisAlignedBox
Entity::getChildObjectsBoundingBox(void) const
489 AxisAlignedBox aa_box
;
490 AxisAlignedBox full_aa_box
;
491 full_aa_box
.setNull();
493 ChildObjectList::const_iterator child_itr
= mChildObjectList
.begin();
494 ChildObjectList::const_iterator child_itr_end
= mChildObjectList
.end();
495 for( ; child_itr
!= child_itr_end
; child_itr
++)
497 aa_box
= child_itr
->second
->getBoundingBox();
498 TagPoint
* tp
= (TagPoint
*)child_itr
->second
->getParentNode();
499 // Use transform local to skeleton since world xform comes later
500 aa_box
.transformAffine(tp
->_getFullLocalTransform());
502 full_aa_box
.merge(aa_box
);
507 //-----------------------------------------------------------------------
508 const AxisAlignedBox
& Entity::getWorldBoundingBox(bool derive
) const
512 // derive child bounding boxes
513 ChildObjectList::const_iterator child_itr
= mChildObjectList
.begin();
514 ChildObjectList::const_iterator child_itr_end
= mChildObjectList
.end();
515 for( ; child_itr
!= child_itr_end
; child_itr
++)
517 child_itr
->second
->getWorldBoundingBox(true);
520 return MovableObject::getWorldBoundingBox(derive
);
522 //-----------------------------------------------------------------------
523 const Sphere
& Entity::getWorldBoundingSphere(bool derive
) const
527 // derive child bounding boxes
528 ChildObjectList::const_iterator child_itr
= mChildObjectList
.begin();
529 ChildObjectList::const_iterator child_itr_end
= mChildObjectList
.end();
530 for( ; child_itr
!= child_itr_end
; child_itr
++)
532 child_itr
->second
->getWorldBoundingSphere(true);
535 return MovableObject::getWorldBoundingSphere(derive
);
538 //-----------------------------------------------------------------------
539 void Entity::_updateRenderQueue(RenderQueue
* queue
)
541 // Do nothing if not initialised yet
545 // Check mesh state count, will be incremented if reloaded
546 if (mMesh
->getStateCount() != mMeshStateCount
)
548 // force reinitialise
552 Entity
* displayEntity
= this;
553 // Check we're not using a manual LOD
554 if (mMeshLodIndex
> 0 && mMesh
->isLodManual())
556 // Use alternate entity
557 assert( static_cast< size_t >( mMeshLodIndex
- 1 ) < mLodEntityList
.size() &&
558 "No LOD EntityList - did you build the manual LODs after creating the entity?");
559 // index - 1 as we skip index 0 (original lod)
560 if (hasSkeleton() && mLodEntityList
[mMeshLodIndex
- 1]->hasSkeleton())
562 // Copy the animation state set to lod entity, we assume the lod
563 // entity only has a subset animation states
564 mAnimationState
->copyMatchingState(
565 mLodEntityList
[mMeshLodIndex
- 1]->mAnimationState
);
567 displayEntity
= mLodEntityList
[mMeshLodIndex
- 1];
570 // Add each visible SubEntity to the queue
571 SubEntityList::iterator i
, iend
;
572 iend
= displayEntity
->mSubEntityList
.end();
573 for (i
= displayEntity
->mSubEntityList
.begin(); i
!= iend
; ++i
)
575 if((*i
)->isVisible())
577 if(mRenderQueueIDSet
)
579 queue
->addRenderable(*i
, mRenderQueueID
);
583 queue
->addRenderable(*i
);
588 // Since we know we're going to be rendered, take this opportunity to
589 // update the animation
590 if (displayEntity
->hasSkeleton() || displayEntity
->hasVertexAnimation())
592 displayEntity
->updateAnimation();
594 //--- pass this point, we are sure that the transformation matrix of each bone and tagPoint have been updated
595 ChildObjectList::iterator child_itr
= mChildObjectList
.begin();
596 ChildObjectList::iterator child_itr_end
= mChildObjectList
.end();
597 for( ; child_itr
!= child_itr_end
; child_itr
++)
599 MovableObject
* child
= child_itr
->second
;
600 bool isVisible
= child
->isVisible();
601 if (isVisible
&& (displayEntity
!= this))
603 //Check if the bone exists in the current LOD
605 //The child is connected to a tagpoint which is connected to a bone
606 Bone
* bone
= static_cast<Bone
*>(child
->getParentNode()->getParent());
607 if (!displayEntity
->getSkeleton()->hasBone(bone
->getName()))
609 //Current LOD entity does not have the bone that the
610 //child is connected to. Do not display.
616 child
->_updateRenderQueue(queue
);
621 // HACK to display bones
622 // This won't work if the entity is not centered at the origin
623 // TODO work out a way to allow bones to be rendered when Entity not centered
624 if (mDisplaySkeleton
&& hasSkeleton())
626 int numBones
= mSkeletonInstance
->getNumBones();
627 for (int b
= 0; b
< numBones
; ++b
)
629 Bone
* bone
= mSkeletonInstance
->getBone(b
);
630 if(mRenderQueueIDSet
)
632 queue
->addRenderable(bone
->getDebugRenderable(1), mRenderQueueID
);
634 queue
->addRenderable(bone
->getDebugRenderable(1));
643 //-----------------------------------------------------------------------
644 AnimationState
* Entity::getAnimationState(const String
& name
) const
646 if (!mAnimationState
)
648 OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND
, "Entity is not animated",
649 "Entity::getAnimationState");
652 return mAnimationState
->getAnimationState(name
);
654 //-----------------------------------------------------------------------
655 AnimationStateSet
* Entity::getAllAnimationStates(void) const
657 return mAnimationState
;
659 //-----------------------------------------------------------------------
660 const String
& Entity::getMovableType(void) const
662 return EntityFactory::FACTORY_TYPE_NAME
;
664 //-----------------------------------------------------------------------
665 bool Entity::tempVertexAnimBuffersBound(void) const
667 // Do we still have temp buffers for software vertex animation bound?
669 if (mMesh
->sharedVertexData
&& mMesh
->getSharedVertexDataAnimationType() != VAT_NONE
)
671 ret
= ret
&& mTempVertexAnimInfo
.buffersCheckedOut(true, false);
673 for (SubEntityList::const_iterator i
= mSubEntityList
.begin();
674 i
!= mSubEntityList
.end(); ++i
)
677 if (!sub
->getSubMesh()->useSharedVertices
678 && sub
->getSubMesh()->getVertexAnimationType() != VAT_NONE
)
680 ret
= ret
&& sub
->_getVertexAnimTempBufferInfo()->buffersCheckedOut(true, false);
685 //-----------------------------------------------------------------------
686 bool Entity::tempSkelAnimBuffersBound(bool requestNormals
) const
688 // Do we still have temp buffers for software skeleton animation bound?
689 if (mSkelAnimVertexData
)
691 if (!mTempSkelAnimInfo
.buffersCheckedOut(true, requestNormals
))
694 for (SubEntityList::const_iterator i
= mSubEntityList
.begin();
695 i
!= mSubEntityList
.end(); ++i
)
698 if (sub
->isVisible() && sub
->mSkelAnimVertexData
)
700 if (!sub
->mTempSkelAnimInfo
.buffersCheckedOut(true, requestNormals
))
706 //-----------------------------------------------------------------------
707 void Entity::updateAnimation(void)
709 // Do nothing if not initialised yet
713 Root
& root
= Root::getSingleton();
714 bool hwAnimation
= isHardwareAnimationEnabled();
715 bool forcedSwAnimation
= getSoftwareAnimationRequests()>0;
716 bool forcedNormals
= getSoftwareAnimationNormalsRequests()>0;
717 bool stencilShadows
= false;
718 if (getCastShadows() && hasEdgeList() && root
._getCurrentSceneManager())
719 stencilShadows
= root
._getCurrentSceneManager()->isShadowTechniqueStencilBased();
720 bool softwareAnimation
= !hwAnimation
|| stencilShadows
|| forcedSwAnimation
;
721 // Blend normals in s/w only if we're not using h/w animation,
722 // since shadows only require positions
723 bool blendNormals
= !hwAnimation
|| forcedNormals
;
724 // Animation dirty if animation state modified or manual bones modified
725 bool animationDirty
=
726 (mFrameAnimationLastUpdated
!= mAnimationState
->getDirtyFrameNumber()) ||
727 (hasSkeleton() && getSkeleton()->getManualBonesDirty());
729 // We only do these tasks if animation is dirty
730 // Or, if we're using a skeleton and manual bones have been moved
731 // Or, if we're using software animation and temp buffers are unbound
732 if (animationDirty
||
733 (softwareAnimation
&& hasVertexAnimation() && !tempVertexAnimBuffersBound()) ||
734 (softwareAnimation
&& hasSkeleton() && !tempSkelAnimBuffersBound(blendNormals
)))
736 if (hasVertexAnimation())
738 if (softwareAnimation
)
740 // grab & bind temporary buffer for positions
741 if (mSoftwareVertexAnimVertexData
742 && mMesh
->getSharedVertexDataAnimationType() != VAT_NONE
)
744 mTempVertexAnimInfo
.checkoutTempCopies(true, false);
745 // NB we suppress hardware upload while doing blend if we're
746 // hardware animation, because the only reason for doing this
747 // is for shadow, which need only be uploaded then
748 mTempVertexAnimInfo
.bindTempCopies(mSoftwareVertexAnimVertexData
,
751 SubEntityList::iterator i
, iend
;
752 iend
= mSubEntityList
.end();
753 for (i
= mSubEntityList
.begin(); i
!= iend
; ++i
)
755 // Blend dedicated geometry
757 if (se
->isVisible() && se
->mSoftwareVertexAnimVertexData
758 && se
->getSubMesh()->getVertexAnimationType() != VAT_NONE
)
760 se
->mTempVertexAnimInfo
.checkoutTempCopies(true, false);
761 se
->mTempVertexAnimInfo
.bindTempCopies(se
->mSoftwareVertexAnimVertexData
,
767 applyVertexAnimation(hwAnimation
, stencilShadows
);
775 if (softwareAnimation
)
777 const Matrix4
* blendMatrices
[256];
779 // Ok, we need to do a software blend
780 // Firstly, check out working vertex buffers
781 if (mSkelAnimVertexData
)
783 // Blend shared geometry
784 // NB we suppress hardware upload while doing blend if we're
785 // hardware animation, because the only reason for doing this
786 // is for shadow, which need only be uploaded then
787 mTempSkelAnimInfo
.checkoutTempCopies(true, blendNormals
);
788 mTempSkelAnimInfo
.bindTempCopies(mSkelAnimVertexData
,
790 // Prepare blend matrices, TODO: Move out of here
791 Mesh::prepareMatricesForVertexBlend(blendMatrices
,
792 mBoneMatrices
, mMesh
->sharedBlendIndexToBoneIndexMap
);
793 // Blend, taking source from either mesh data or morph data
794 Mesh::softwareVertexBlend(
795 (mMesh
->getSharedVertexDataAnimationType() != VAT_NONE
) ?
796 mSoftwareVertexAnimVertexData
: mMesh
->sharedVertexData
,
798 blendMatrices
, mMesh
->sharedBlendIndexToBoneIndexMap
.size(),
801 SubEntityList::iterator i
, iend
;
802 iend
= mSubEntityList
.end();
803 for (i
= mSubEntityList
.begin(); i
!= iend
; ++i
)
805 // Blend dedicated geometry
807 if (se
->isVisible() && se
->mSkelAnimVertexData
)
809 se
->mTempSkelAnimInfo
.checkoutTempCopies(true, blendNormals
);
810 se
->mTempSkelAnimInfo
.bindTempCopies(se
->mSkelAnimVertexData
,
812 // Prepare blend matrices, TODO: Move out of here
813 Mesh::prepareMatricesForVertexBlend(blendMatrices
,
814 mBoneMatrices
, se
->mSubMesh
->blendIndexToBoneIndexMap
);
815 // Blend, taking source from either mesh data or morph data
816 Mesh::softwareVertexBlend(
817 (se
->getSubMesh()->getVertexAnimationType() != VAT_NONE
)?
818 se
->mSoftwareVertexAnimVertexData
: se
->mSubMesh
->vertexData
,
819 se
->mSkelAnimVertexData
,
820 blendMatrices
, se
->mSubMesh
->blendIndexToBoneIndexMap
.size(),
829 // Trigger update of bounding box if necessary
830 if (!mChildObjectList
.empty())
831 mParentNode
->needUpdate();
833 mFrameAnimationLastUpdated
= mAnimationState
->getDirtyFrameNumber();
836 // Need to update the child object's transforms when animation dirty
837 // or parent node transform has altered.
839 (animationDirty
|| mLastParentXform
!= _getParentNodeFullTransform()))
841 // Cache last parent transform for next frame use too.
842 mLastParentXform
= _getParentNodeFullTransform();
844 //--- Update the child object's transforms
845 ChildObjectList::iterator child_itr
= mChildObjectList
.begin();
846 ChildObjectList::iterator child_itr_end
= mChildObjectList
.end();
847 for( ; child_itr
!= child_itr_end
; child_itr
++)
849 (*child_itr
).second
->getParentNode()->_update(true, true);
852 // Also calculate bone world matrices, since are used as replacement world matrices,
853 // but only if it's used (when using hardware animation and skeleton animated).
854 if (hwAnimation
&& _isSkeletonAnimated())
856 // Allocate bone world matrices on demand, for better memory footprint
857 // when using software animation.
858 if (!mBoneWorldMatrices
)
861 static_cast<Matrix4
*>(OGRE_MALLOC_SIMD(sizeof(Matrix4
) * mNumBoneMatrices
, MEMCATEGORY_ANIMATION
));
864 OptimisedUtil::getImplementation()->concatenateAffineMatrices(
872 //-----------------------------------------------------------------------
873 void Entity::initHardwareAnimationElements(VertexData
* vdata
,
874 ushort numberOfElements
)
876 if (vdata
->hwAnimationDataList
.size() < numberOfElements
)
878 vdata
->allocateHardwareAnimationElements(numberOfElements
);
880 // Initialise parametrics incase we don't use all of them
881 for (size_t i
= 0; i
< vdata
->hwAnimationDataList
.size(); ++i
)
883 vdata
->hwAnimationDataList
[i
].parametric
= 0.0f
;
886 vdata
->hwAnimDataItemsUsed
= 0;
889 //-----------------------------------------------------------------------
890 void Entity::applyVertexAnimation(bool hardwareAnimation
, bool stencilShadows
)
892 const MeshPtr
& msh
= getMesh();
893 bool swAnim
= !hardwareAnimation
|| stencilShadows
|| (mSoftwareAnimationRequests
>0);
895 // make sure we have enough hardware animation elements to play with
896 if (hardwareAnimation
)
898 if (mHardwareVertexAnimVertexData
899 && msh
->getSharedVertexDataAnimationType() != VAT_NONE
)
901 initHardwareAnimationElements(mHardwareVertexAnimVertexData
,
902 (msh
->getSharedVertexDataAnimationType() == VAT_POSE
)
903 ? mHardwarePoseCount
: 1);
905 for (SubEntityList::iterator si
= mSubEntityList
.begin();
906 si
!= mSubEntityList
.end(); ++si
)
908 SubEntity
* sub
= *si
;
909 if (sub
->getSubMesh()->getVertexAnimationType() != VAT_NONE
&&
910 !sub
->getSubMesh()->useSharedVertices
)
912 initHardwareAnimationElements(
913 sub
->_getHardwareVertexAnimVertexData(),
914 (sub
->getSubMesh()->getVertexAnimationType() == VAT_POSE
)
915 ? sub
->mHardwarePoseCount
: 1);
922 // May be blending multiple poses in software
923 // Suppress hardware upload of buffers
924 if (mSoftwareVertexAnimVertexData
&&
925 mMesh
->getSharedVertexDataAnimationType() == VAT_POSE
)
927 const VertexElement
* elem
= mSoftwareVertexAnimVertexData
928 ->vertexDeclaration
->findElementBySemantic(VES_POSITION
);
929 HardwareVertexBufferSharedPtr buf
= mSoftwareVertexAnimVertexData
930 ->vertexBufferBinding
->getBuffer(elem
->getSource());
931 buf
->suppressHardwareUpdate(true);
933 for (SubEntityList::iterator si
= mSubEntityList
.begin();
934 si
!= mSubEntityList
.end(); ++si
)
936 SubEntity
* sub
= *si
;
937 if (!sub
->getSubMesh()->useSharedVertices
&&
938 sub
->getSubMesh()->getVertexAnimationType() == VAT_POSE
)
940 VertexData
* data
= sub
->_getSoftwareVertexAnimVertexData();
941 const VertexElement
* elem
= data
->vertexDeclaration
942 ->findElementBySemantic(VES_POSITION
);
943 HardwareVertexBufferSharedPtr buf
= data
944 ->vertexBufferBinding
->getBuffer(elem
->getSource());
945 buf
->suppressHardwareUpdate(true);
951 // Now apply the animation(s)
952 // Note - you should only apply one morph animation to each set of vertex data
953 // at once; if you do more, only the last one will actually apply
954 markBuffersUnusedForAnimation();
955 ConstEnabledAnimationStateIterator animIt
= mAnimationState
->getEnabledAnimationStateIterator();
956 while(animIt
.hasMoreElements())
958 const AnimationState
* state
= animIt
.getNext();
959 Animation
* anim
= msh
->_getAnimationImpl(state
->getAnimationName());
962 anim
->apply(this, state
->getTimePosition(), state
->getWeight(),
963 swAnim
, hardwareAnimation
);
966 // Deal with cases where no animation applied
967 restoreBuffersForUnusedAnimation(hardwareAnimation
);
969 // Unsuppress hardware upload if we suppressed it
970 if (!hardwareAnimation
)
972 if (mSoftwareVertexAnimVertexData
&&
973 msh
->getSharedVertexDataAnimationType() == VAT_POSE
)
975 const VertexElement
* elem
= mSoftwareVertexAnimVertexData
976 ->vertexDeclaration
->findElementBySemantic(VES_POSITION
);
977 HardwareVertexBufferSharedPtr buf
= mSoftwareVertexAnimVertexData
978 ->vertexBufferBinding
->getBuffer(elem
->getSource());
979 buf
->suppressHardwareUpdate(false);
981 for (SubEntityList::iterator si
= mSubEntityList
.begin();
982 si
!= mSubEntityList
.end(); ++si
)
984 SubEntity
* sub
= *si
;
985 if (!sub
->getSubMesh()->useSharedVertices
&&
986 sub
->getSubMesh()->getVertexAnimationType() == VAT_POSE
)
988 VertexData
* data
= sub
->_getSoftwareVertexAnimVertexData();
989 const VertexElement
* elem
= data
->vertexDeclaration
990 ->findElementBySemantic(VES_POSITION
);
991 HardwareVertexBufferSharedPtr buf
= data
992 ->vertexBufferBinding
->getBuffer(elem
->getSource());
993 buf
->suppressHardwareUpdate(false);
999 //-----------------------------------------------------------------------------
1000 void Entity::markBuffersUnusedForAnimation(void)
1002 mVertexAnimationAppliedThisFrame
= false;
1003 for (SubEntityList::iterator i
= mSubEntityList
.begin();
1004 i
!= mSubEntityList
.end(); ++i
)
1006 (*i
)->_markBuffersUnusedForAnimation();
1009 //-----------------------------------------------------------------------------
1010 void Entity::_markBuffersUsedForAnimation(void)
1012 mVertexAnimationAppliedThisFrame
= true;
1015 //-----------------------------------------------------------------------------
1016 void Entity::restoreBuffersForUnusedAnimation(bool hardwareAnimation
)
1018 // Rebind original positions if:
1019 // We didn't apply any animation and
1020 // We're morph animated (hardware binds keyframe, software is missing)
1021 // or we're pose animated and software (hardware is fine, still bound)
1022 if (mMesh
->sharedVertexData
&&
1023 !mVertexAnimationAppliedThisFrame
&&
1024 (!hardwareAnimation
|| mMesh
->getSharedVertexDataAnimationType() == VAT_MORPH
))
1026 const VertexElement
* srcPosElem
=
1027 mMesh
->sharedVertexData
->vertexDeclaration
->findElementBySemantic(VES_POSITION
);
1028 HardwareVertexBufferSharedPtr srcBuf
=
1029 mMesh
->sharedVertexData
->vertexBufferBinding
->getBuffer(
1030 srcPosElem
->getSource());
1033 const VertexElement
* destPosElem
=
1034 mSoftwareVertexAnimVertexData
->vertexDeclaration
->findElementBySemantic(VES_POSITION
);
1035 mSoftwareVertexAnimVertexData
->vertexBufferBinding
->setBinding(
1036 destPosElem
->getSource(), srcBuf
);
1040 // rebind any missing hardware pose buffers
1041 // Caused by not having any animations enabled, or keyframes which reference
1043 if (mMesh
->sharedVertexData
&& hardwareAnimation
1044 && mMesh
->getSharedVertexDataAnimationType() == VAT_POSE
)
1046 bindMissingHardwarePoseBuffers(mMesh
->sharedVertexData
, mHardwareVertexAnimVertexData
);
1050 for (SubEntityList::iterator i
= mSubEntityList
.begin();
1051 i
!= mSubEntityList
.end(); ++i
)
1053 (*i
)->_restoreBuffersForUnusedAnimation(hardwareAnimation
);
1057 //---------------------------------------------------------------------
1058 void Entity::bindMissingHardwarePoseBuffers(const VertexData
* srcData
,
1059 VertexData
* destData
)
1061 // For hardware pose animation, also make sure we've bound buffers to all the elements
1062 // required - if there are missing bindings for elements in use,
1063 // some rendersystems can complain because elements refer
1064 // to an unbound source.
1065 // Get the original position source, we'll use this to fill gaps
1066 const VertexElement
* srcPosElem
=
1067 srcData
->vertexDeclaration
->findElementBySemantic(VES_POSITION
);
1068 HardwareVertexBufferSharedPtr srcBuf
=
1069 srcData
->vertexBufferBinding
->getBuffer(
1070 srcPosElem
->getSource());
1072 for (VertexData::HardwareAnimationDataList::const_iterator i
= destData
->hwAnimationDataList
.begin();
1073 i
!= destData
->hwAnimationDataList
.end(); ++i
)
1075 const VertexData::HardwareAnimationData
& animData
= *i
;
1076 if (!destData
->vertexBufferBinding
->isBufferBound(
1077 animData
.targetVertexElement
->getSource()))
1079 // Bind to a safe default
1080 destData
->vertexBufferBinding
->setBinding(
1081 animData
.targetVertexElement
->getSource(), srcBuf
);
1086 //-----------------------------------------------------------------------
1087 void Entity::_updateAnimation(void)
1089 // Externally visible method
1090 if (hasSkeleton() || hasVertexAnimation())
1095 //-----------------------------------------------------------------------
1096 bool Entity::_isAnimated(void) const
1098 return (mAnimationState
&& mAnimationState
->hasEnabledAnimationState()) ||
1099 (getSkeleton() && getSkeleton()->hasManualBones());
1101 //-----------------------------------------------------------------------
1102 bool Entity::_isSkeletonAnimated(void) const
1104 return getSkeleton() &&
1105 (mAnimationState
->hasEnabledAnimationState() || getSkeleton()->hasManualBones());
1107 //-----------------------------------------------------------------------
1108 VertexData
* Entity::_getSkelAnimVertexData(void) const
1110 assert (mSkelAnimVertexData
&& "Not software skinned or has no shared vertex data!");
1111 return mSkelAnimVertexData
;
1113 //-----------------------------------------------------------------------
1114 VertexData
* Entity::_getSoftwareVertexAnimVertexData(void) const
1116 assert (mSoftwareVertexAnimVertexData
&& "Not vertex animated or has no shared vertex data!");
1117 return mSoftwareVertexAnimVertexData
;
1119 //-----------------------------------------------------------------------
1120 VertexData
* Entity::_getHardwareVertexAnimVertexData(void) const
1122 assert (mHardwareVertexAnimVertexData
&& "Not vertex animated or has no shared vertex data!");
1123 return mHardwareVertexAnimVertexData
;
1125 //-----------------------------------------------------------------------
1126 TempBlendedBufferInfo
* Entity::_getSkelAnimTempBufferInfo(void)
1128 return &mTempSkelAnimInfo
;
1130 //-----------------------------------------------------------------------
1131 TempBlendedBufferInfo
* Entity::_getVertexAnimTempBufferInfo(void)
1133 return &mTempVertexAnimInfo
;
1135 //-----------------------------------------------------------------------
1136 void Entity::cacheBoneMatrices(void)
1138 Root
& root
= Root::getSingleton();
1139 unsigned long currentFrameNumber
= root
.getNextFrameNumber();
1140 if (*mFrameBonesLastUpdated
!= currentFrameNumber
) {
1142 mSkeletonInstance
->setAnimationState(*mAnimationState
);
1143 mSkeletonInstance
->_getBoneMatrices(mBoneMatrices
);
1144 *mFrameBonesLastUpdated
= currentFrameNumber
;
1147 //-----------------------------------------------------------------------
1148 void Entity::setDisplaySkeleton(bool display
)
1150 mDisplaySkeleton
= display
;
1152 //-----------------------------------------------------------------------
1153 bool Entity::getDisplaySkeleton(void) const
1155 return mDisplaySkeleton
;
1157 //-----------------------------------------------------------------------
1158 Entity
* Entity::getManualLodLevel(size_t index
) const
1160 assert(index
< mLodEntityList
.size());
1162 return mLodEntityList
[index
];
1164 //-----------------------------------------------------------------------
1165 size_t Entity::getNumManualLodLevels(void) const
1167 return mLodEntityList
.size();
1169 //-----------------------------------------------------------------------
1170 void Entity::setMeshLodBias(Real factor
, ushort maxDetailIndex
, ushort minDetailIndex
)
1172 mMeshLodFactorTransformed
= mMesh
->getLodStrategy()->transformBias(factor
);
1173 mMaxMeshLodIndex
= maxDetailIndex
;
1174 mMinMeshLodIndex
= minDetailIndex
;
1177 //-----------------------------------------------------------------------
1178 void Entity::setMaterialLodBias(Real factor
, ushort maxDetailIndex
, ushort minDetailIndex
)
1180 mMaterialLodFactor
= factor
;
1181 mMaterialLodFactorTransformed
= mMesh
->getLodStrategy()->transformBias(factor
);
1182 mMaxMaterialLodIndex
= maxDetailIndex
;
1183 mMinMaterialLodIndex
= minDetailIndex
;
1186 //-----------------------------------------------------------------------
1187 void Entity::buildSubEntityList(MeshPtr
& mesh
, SubEntityList
* sublist
)
1189 // Create SubEntities
1190 unsigned short i
, numSubMeshes
;
1194 numSubMeshes
= mesh
->getNumSubMeshes();
1195 for (i
= 0; i
< numSubMeshes
; ++i
)
1197 subMesh
= mesh
->getSubMesh(i
);
1198 subEnt
= OGRE_NEW
SubEntity(this, subMesh
);
1199 if (subMesh
->isMatInitialised())
1200 subEnt
->setMaterialName(subMesh
->getMaterialName(), mesh
->getGroup());
1201 sublist
->push_back(subEnt
);
1204 //-----------------------------------------------------------------------
1205 void Entity::setPolygonModeOverrideable(bool overrideable
)
1207 SubEntityList::iterator i
, iend
;
1208 iend
= mSubEntityList
.end();
1210 for( i
= mSubEntityList
.begin(); i
!= iend
; ++i
)
1212 (*i
)->setPolygonModeOverrideable(overrideable
);
1216 //-----------------------------------------------------------------------
1217 TagPoint
* Entity::attachObjectToBone(const String
&boneName
, MovableObject
*pMovable
, const Quaternion
&offsetOrientation
, const Vector3
&offsetPosition
)
1219 if (mChildObjectList
.find(pMovable
->getName()) != mChildObjectList
.end())
1221 OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM
,
1222 "An object with the name " + pMovable
->getName() + " already attached",
1223 "Entity::attachObjectToBone");
1225 if(pMovable
->isAttached())
1227 OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS
, "Object already attached to a sceneNode or a Bone",
1228 "Entity::attachObjectToBone");
1232 OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS
, "This entity's mesh has no skeleton to attach object to.",
1233 "Entity::attachObjectToBone");
1235 Bone
* bone
= mSkeletonInstance
->getBone(boneName
);
1238 OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS
, "Cannot locate bone named " + boneName
,
1239 "Entity::attachObjectToBone");
1242 TagPoint
*tp
= mSkeletonInstance
->createTagPointOnBone(
1243 bone
, offsetOrientation
, offsetPosition
);
1244 tp
->setParentEntity(this);
1245 tp
->setChildObject(pMovable
);
1247 attachObjectImpl(pMovable
, tp
);
1249 // Trigger update of bounding box if necessary
1251 mParentNode
->needUpdate();
1256 //-----------------------------------------------------------------------
1257 void Entity::attachObjectImpl(MovableObject
*pObject
, TagPoint
*pAttachingPoint
)
1259 assert(mChildObjectList
.find(pObject
->getName()) == mChildObjectList
.end());
1260 mChildObjectList
[pObject
->getName()] = pObject
;
1261 pObject
->_notifyAttached(pAttachingPoint
, true);
1264 //-----------------------------------------------------------------------
1265 MovableObject
* Entity::detachObjectFromBone(const String
&name
)
1267 ChildObjectList::iterator i
= mChildObjectList
.find(name
);
1269 if (i
== mChildObjectList
.end())
1271 OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND
, "No child object entry found named " + name
,
1272 "Entity::detachObjectFromBone");
1274 MovableObject
*obj
= i
->second
;
1275 detachObjectImpl(obj
);
1276 mChildObjectList
.erase(i
);
1278 // Trigger update of bounding box if necessary
1280 mParentNode
->needUpdate();
1284 //-----------------------------------------------------------------------
1285 void Entity::detachObjectFromBone(MovableObject
* obj
)
1287 ChildObjectList::iterator i
, iend
;
1288 iend
= mChildObjectList
.end();
1289 for (i
= mChildObjectList
.begin(); i
!= iend
; ++i
)
1291 if (i
->second
== obj
)
1293 detachObjectImpl(obj
);
1294 mChildObjectList
.erase(i
);
1296 // Trigger update of bounding box if necessary
1298 mParentNode
->needUpdate();
1303 //-----------------------------------------------------------------------
1304 void Entity::detachAllObjectsFromBone(void)
1306 detachAllObjectsImpl();
1308 // Trigger update of bounding box if necessary
1310 mParentNode
->needUpdate();
1312 //-----------------------------------------------------------------------
1313 void Entity::detachObjectImpl(MovableObject
* pObject
)
1315 TagPoint
* tp
= static_cast<TagPoint
*>(pObject
->getParentNode());
1317 // free the TagPoint so we can reuse it later
1318 mSkeletonInstance
->freeTagPoint(tp
);
1320 pObject
->_notifyAttached((TagPoint
*)0);
1322 //-----------------------------------------------------------------------
1323 void Entity::detachAllObjectsImpl(void)
1325 ChildObjectList::const_iterator i
, iend
;
1326 iend
= mChildObjectList
.end();
1327 for (i
= mChildObjectList
.begin(); i
!= iend
; ++i
)
1329 detachObjectImpl(i
->second
);
1331 mChildObjectList
.clear();
1334 //-----------------------------------------------------------------------
1335 Entity::ChildObjectListIterator
Entity::getAttachedObjectIterator()
1337 return ChildObjectListIterator(mChildObjectList
.begin(), mChildObjectList
.end());
1339 //-----------------------------------------------------------------------
1340 Real
Entity::getBoundingRadius(void) const
1342 Real rad
= mMesh
->getBoundingSphereRadius();
1343 // Scale by largest scale factor
1346 const Vector3
& s
= mParentNode
->_getDerivedScale();
1347 rad
*= std::max(s
.x
, std::max(s
.y
, s
.z
));
1351 //-----------------------------------------------------------------------
1352 void Entity::prepareTempBlendBuffers(void)
1354 if (mSkelAnimVertexData
)
1356 OGRE_DELETE mSkelAnimVertexData
;
1357 mSkelAnimVertexData
= 0;
1359 if (mSoftwareVertexAnimVertexData
)
1361 OGRE_DELETE mSoftwareVertexAnimVertexData
;
1362 mSoftwareVertexAnimVertexData
= 0;
1364 if (mHardwareVertexAnimVertexData
)
1366 OGRE_DELETE mHardwareVertexAnimVertexData
;
1367 mHardwareVertexAnimVertexData
= 0;
1370 if (hasVertexAnimation())
1373 if (mMesh
->sharedVertexData
1374 && mMesh
->getSharedVertexDataAnimationType() != VAT_NONE
)
1376 // Create temporary vertex blend info
1377 // Prepare temp vertex data if needed
1378 // Clone without copying data, don't remove any blending info
1379 // (since if we skeletally animate too, we need it)
1380 mSoftwareVertexAnimVertexData
= mMesh
->sharedVertexData
->clone(false);
1381 extractTempBufferInfo(mSoftwareVertexAnimVertexData
, &mTempVertexAnimInfo
);
1383 // Also clone for hardware usage, don't remove blend info since we'll
1384 // need it if we also hardware skeletally animate
1385 mHardwareVertexAnimVertexData
= mMesh
->sharedVertexData
->clone(false);
1392 if (mMesh
->sharedVertexData
)
1394 // Create temporary vertex blend info
1395 // Prepare temp vertex data if needed
1396 // Clone without copying data, remove blending info
1397 // (since blend is performed in software)
1398 mSkelAnimVertexData
=
1399 cloneVertexDataRemoveBlendInfo(mMesh
->sharedVertexData
);
1400 extractTempBufferInfo(mSkelAnimVertexData
, &mTempSkelAnimInfo
);
1406 SubEntityList::iterator i
, iend
;
1407 iend
= mSubEntityList
.end();
1408 for (i
= mSubEntityList
.begin(); i
!= iend
; ++i
)
1411 s
->prepareTempBlendBuffers();
1414 // It's prepared for shadow volumes only if mesh has been prepared for shadow volumes.
1415 mPreparedForShadowVolumes
= mMesh
->isPreparedForShadowVolumes();
1417 //-----------------------------------------------------------------------
1418 void Entity::extractTempBufferInfo(VertexData
* sourceData
, TempBlendedBufferInfo
* info
)
1420 info
->extractFrom(sourceData
);
1422 //-----------------------------------------------------------------------
1423 VertexData
* Entity::cloneVertexDataRemoveBlendInfo(const VertexData
* source
)
1425 // Clone without copying data
1426 VertexData
* ret
= source
->clone(false);
1427 const VertexElement
* blendIndexElem
=
1428 source
->vertexDeclaration
->findElementBySemantic(VES_BLEND_INDICES
);
1429 const VertexElement
* blendWeightElem
=
1430 source
->vertexDeclaration
->findElementBySemantic(VES_BLEND_WEIGHTS
);
1431 // Remove blend index
1434 // Remove buffer reference
1435 ret
->vertexBufferBinding
->unsetBinding(blendIndexElem
->getSource());
1438 if (blendWeightElem
&&
1439 blendWeightElem
->getSource() != blendIndexElem
->getSource())
1441 // Remove buffer reference
1442 ret
->vertexBufferBinding
->unsetBinding(blendWeightElem
->getSource());
1444 // remove elements from declaration
1445 ret
->vertexDeclaration
->removeElement(VES_BLEND_INDICES
);
1446 ret
->vertexDeclaration
->removeElement(VES_BLEND_WEIGHTS
);
1448 // Close gaps in bindings for effective and safely
1449 ret
->closeGapsInBindings();
1453 //-----------------------------------------------------------------------
1454 EdgeData
* Entity::getEdgeList(void)
1457 return mMesh
->getEdgeList(mMeshLodIndex
);
1459 //-----------------------------------------------------------------------
1460 bool Entity::hasEdgeList(void)
1462 // check if mesh has an edge list attached
1463 // give mesh a chance to built it if scheduled
1464 return (mMesh
->getEdgeList(mMeshLodIndex
) != NULL
);
1466 //-----------------------------------------------------------------------
1467 void Entity::reevaluateVertexProcessing(void)
1470 mHardwareAnimation
= false;
1471 mVertexProgramInUse
= false; // assume false because we just assign this
1472 bool firstPass
= true;
1474 SubEntityList::iterator i
, iend
;
1475 iend
= mSubEntityList
.end();
1476 for (i
= mSubEntityList
.begin(); i
!= iend
; ++i
)
1478 SubEntity
* sub
= *i
;
1479 const MaterialPtr
& m
= sub
->getMaterial();
1480 // Make sure it's loaded
1482 Technique
* t
= m
->getBestTechnique(0, sub
);
1485 // No supported techniques
1488 if (t
->getNumPasses() == 0)
1490 // No passes, invalid
1493 Pass
* p
= t
->getPass(0);
1494 if (p
->hasVertexProgram())
1496 // If one material uses a vertex program, set this flag
1497 // Causes some special processing like forcing a separate light cap
1498 mVertexProgramInUse
= true;
1502 // All materials must support skinning for us to consider using
1503 // hardware animation - if one fails we use software
1506 mHardwareAnimation
= p
->getVertexProgram()->isSkeletalAnimationIncluded();
1511 mHardwareAnimation
= mHardwareAnimation
&&
1512 p
->getVertexProgram()->isSkeletalAnimationIncluded();
1516 VertexAnimationType animType
= VAT_NONE
;
1517 if (sub
->getSubMesh()->useSharedVertices
)
1519 animType
= mMesh
->getSharedVertexDataAnimationType();
1523 animType
= sub
->getSubMesh()->getVertexAnimationType();
1525 if (animType
== VAT_MORPH
)
1527 // All materials must support morph animation for us to consider using
1528 // hardware animation - if one fails we use software
1531 mHardwareAnimation
= p
->getVertexProgram()->isMorphAnimationIncluded();
1536 mHardwareAnimation
= mHardwareAnimation
&&
1537 p
->getVertexProgram()->isMorphAnimationIncluded();
1540 else if (animType
== VAT_POSE
)
1542 // All materials must support pose animation for us to consider using
1543 // hardware animation - if one fails we use software
1546 mHardwareAnimation
= p
->getVertexProgram()->isPoseAnimationIncluded();
1547 if (sub
->getSubMesh()->useSharedVertices
)
1548 mHardwarePoseCount
= p
->getVertexProgram()->getNumberOfPosesIncluded();
1550 sub
->mHardwarePoseCount
= p
->getVertexProgram()->getNumberOfPosesIncluded();
1555 mHardwareAnimation
= mHardwareAnimation
&&
1556 p
->getVertexProgram()->isPoseAnimationIncluded();
1557 if (sub
->getSubMesh()->useSharedVertices
)
1558 mHardwarePoseCount
= std::max(mHardwarePoseCount
,
1559 p
->getVertexProgram()->getNumberOfPosesIncluded());
1561 sub
->mHardwarePoseCount
= std::max(sub
->mHardwarePoseCount
,
1562 p
->getVertexProgram()->getNumberOfPosesIncluded());
1569 // Should be force update of animation if they exists, due reevaluate
1570 // vertex processing might switchs between hardware/software animation,
1571 // and then we'll end with NULL or incorrect mBoneWorldMatrices, or
1572 // incorrect blended software animation buffers.
1573 if (mAnimationState
)
1575 mFrameAnimationLastUpdated
= mAnimationState
->getDirtyFrameNumber() - 1;
1578 //-----------------------------------------------------------------------
1579 Real
Entity::_getMeshLodFactorTransformed() const
1581 return mMeshLodFactorTransformed
;
1583 //-----------------------------------------------------------------------
1584 ShadowCaster::ShadowRenderableListIterator
1585 Entity::getShadowVolumeRenderableIterator(
1586 ShadowTechnique shadowTechnique
, const Light
* light
,
1587 HardwareIndexBufferSharedPtr
* indexBuffer
,
1588 bool extrude
, Real extrusionDistance
, unsigned long flags
)
1590 assert(indexBuffer
&& "Only external index buffers are supported right now");
1591 assert((*indexBuffer
)->getType() == HardwareIndexBuffer::IT_16BIT
&&
1592 "Only 16-bit indexes supported for now");
1594 // Potentially delegate to LOD entity
1595 if (mMesh
->isLodManual() && mMeshLodIndex
> 0)
1597 // Use alternate entity
1598 assert( static_cast< size_t >( mMeshLodIndex
- 1 ) < mLodEntityList
.size() &&
1599 "No LOD EntityList - did you build the manual LODs after creating the entity?");
1600 // delegate, we're using manual LOD and not the top lod index
1601 if (hasSkeleton() && mLodEntityList
[mMeshLodIndex
- 1]->hasSkeleton())
1603 // Copy the animation state set to lod entity, we assume the lod
1604 // entity only has a subset animation states
1605 mAnimationState
->copyMatchingState(
1606 mLodEntityList
[mMeshLodIndex
- 1]->mAnimationState
);
1608 return mLodEntityList
[mMeshLodIndex
-1]->getShadowVolumeRenderableIterator(
1609 shadowTechnique
, light
, indexBuffer
, extrude
,
1610 extrusionDistance
, flags
);
1614 // Prepare temp buffers if required
1615 if (!mPreparedForShadowVolumes
)
1617 mMesh
->prepareForShadowVolume();
1618 // reset frame last updated to force update of animations if they exist
1619 if (mAnimationState
)
1620 mFrameAnimationLastUpdated
= mAnimationState
->getDirtyFrameNumber() - 1;
1621 // re-prepare buffers
1622 prepareTempBlendBuffers();
1626 bool hasAnimation
= (hasSkeleton() || hasVertexAnimation());
1628 // Update any animation
1634 // Calculate the object space light details
1635 Vector4 lightPos
= light
->getAs4DVector();
1636 Matrix4 world2Obj
= mParentNode
->_getFullTransform().inverseAffine();
1637 lightPos
= world2Obj
.transformAffine(lightPos
);
1639 // We need to search the edge list for silhouette edges
1640 EdgeData
* edgeList
= getEdgeList();
1644 // we can't get an edge list for some reason, return blank
1645 // really we shouldn't be able to get here, but this is a safeguard
1646 return ShadowRenderableListIterator(mShadowRenderables
.begin(), mShadowRenderables
.end());
1649 // Init shadow renderable list if required
1650 bool init
= mShadowRenderables
.empty();
1652 EdgeData::EdgeGroupList::iterator egi
;
1653 ShadowRenderableList::iterator si
, siend
;
1654 EntityShadowRenderable
* esr
= 0;
1656 mShadowRenderables
.resize(edgeList
->edgeGroups
.size());
1658 bool isAnimated
= hasAnimation
;
1659 bool updatedSharedGeomNormals
= false;
1660 siend
= mShadowRenderables
.end();
1661 egi
= edgeList
->edgeGroups
.begin();
1662 for (si
= mShadowRenderables
.begin(); si
!= siend
; ++si
, ++egi
)
1664 const VertexData
*pVertData
;
1668 pVertData
= findBlendedVertexData(egi
->vertexData
);
1672 pVertData
= egi
->vertexData
;
1676 // Try to find corresponding SubEntity; this allows the
1677 // linkage of visibility between ShadowRenderable and SubEntity
1678 SubEntity
* subent
= findSubEntityForVertexData(egi
->vertexData
);
1679 // Create a new renderable, create a separate light cap if
1680 // we're using a vertex program (either for this model, or
1681 // for extruding the shadow volume) since otherwise we can
1682 // get depth-fighting on the light cap
1684 *si
= OGRE_NEW
EntityShadowRenderable(this, indexBuffer
, pVertData
,
1685 mVertexProgramInUse
|| !extrude
, subent
);
1689 // If we have animation, we have no guarantee that the position
1690 // buffer we used last frame is the same one we used last frame
1691 // since a temporary buffer is requested each frame
1692 // therefore, we need to update the EntityShadowRenderable
1693 // with the current position buffer
1694 static_cast<EntityShadowRenderable
*>(*si
)->rebindPositionBuffer(pVertData
, hasAnimation
);
1697 // Get shadow renderable
1698 esr
= static_cast<EntityShadowRenderable
*>(*si
);
1699 HardwareVertexBufferSharedPtr esrPositionBuffer
= esr
->getPositionBuffer();
1700 // For animated entities we need to recalculate the face normals
1703 if (egi
->vertexData
!= mMesh
->sharedVertexData
|| !updatedSharedGeomNormals
)
1705 // recalculate face normals
1706 edgeList
->updateFaceNormals(egi
->vertexSet
, esrPositionBuffer
);
1707 // If we're not extruding in software we still need to update
1708 // the latter part of the buffer (the hardware extruded part)
1709 // with the latest animated positions
1712 // Lock, we'll be locking the (suppressed hardware update) shadow buffer
1713 float* pSrc
= static_cast<float*>(
1714 esrPositionBuffer
->lock(HardwareBuffer::HBL_NORMAL
));
1715 float* pDest
= pSrc
+ (egi
->vertexData
->vertexCount
* 3);
1716 memcpy(pDest
, pSrc
, sizeof(float) * 3 * egi
->vertexData
->vertexCount
);
1717 esrPositionBuffer
->unlock();
1719 if (egi
->vertexData
== mMesh
->sharedVertexData
)
1721 updatedSharedGeomNormals
= true;
1725 // Extrude vertices in software if required
1728 extrudeVertices(esrPositionBuffer
,
1729 egi
->vertexData
->vertexCount
,
1730 lightPos
, extrusionDistance
);
1733 // Stop suppressing hardware update now, if we were
1734 esrPositionBuffer
->suppressHardwareUpdate(false);
1737 // Calc triangle light facing
1738 updateEdgeListLightFacing(edgeList
, lightPos
);
1740 // Generate indexes and update renderables
1741 generateShadowVolume(edgeList
, *indexBuffer
, light
,
1742 mShadowRenderables
, flags
);
1745 return ShadowRenderableListIterator(mShadowRenderables
.begin(), mShadowRenderables
.end());
1747 //-----------------------------------------------------------------------
1748 const VertexData
* Entity::findBlendedVertexData(const VertexData
* orig
)
1750 bool skel
= hasSkeleton();
1752 if (orig
== mMesh
->sharedVertexData
)
1754 return skel
? mSkelAnimVertexData
: mSoftwareVertexAnimVertexData
;
1756 SubEntityList::iterator i
, iend
;
1757 iend
= mSubEntityList
.end();
1758 for (i
= mSubEntityList
.begin(); i
!= iend
; ++i
)
1761 if (orig
== se
->getSubMesh()->vertexData
)
1763 return skel
? se
->_getSkelAnimVertexData() : se
->_getSoftwareVertexAnimVertexData();
1767 OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND
,
1768 "Cannot find blended version of the vertex data specified.",
1769 "Entity::findBlendedVertexData");
1771 //-----------------------------------------------------------------------
1772 SubEntity
* Entity::findSubEntityForVertexData(const VertexData
* orig
)
1774 if (orig
== mMesh
->sharedVertexData
)
1779 SubEntityList::iterator i
, iend
;
1780 iend
= mSubEntityList
.end();
1781 for (i
= mSubEntityList
.begin(); i
!= iend
; ++i
)
1784 if (orig
== se
->getSubMesh()->vertexData
)
1793 //-----------------------------------------------------------------------
1794 void Entity::addSoftwareAnimationRequest(bool normalsAlso
)
1796 mSoftwareAnimationRequests
++;
1798 mSoftwareAnimationNormalsRequests
++;
1801 //-----------------------------------------------------------------------
1802 void Entity::removeSoftwareAnimationRequest(bool normalsAlso
)
1804 if (mSoftwareAnimationRequests
== 0 ||
1805 (normalsAlso
&& mSoftwareAnimationNormalsRequests
== 0))
1807 OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS
,
1808 "Attempt to remove nonexistant request.",
1809 "Entity::removeSoftwareAnimationRequest");
1811 mSoftwareAnimationRequests
--;
1813 mSoftwareAnimationNormalsRequests
--;
1816 //-----------------------------------------------------------------------
1817 void Entity::_notifyAttached(Node
* parent
, bool isTagPoint
)
1819 MovableObject::_notifyAttached(parent
, isTagPoint
);
1820 // Also notify LOD entities
1821 LODEntityList::iterator i
, iend
;
1822 iend
= mLodEntityList
.end();
1823 for (i
= mLodEntityList
.begin(); i
!= iend
; ++i
)
1825 (*i
)->_notifyAttached(parent
, isTagPoint
);
1829 //-----------------------------------------------------------------------
1830 //-----------------------------------------------------------------------
1831 Entity::EntityShadowRenderable::EntityShadowRenderable(Entity
* parent
,
1832 HardwareIndexBufferSharedPtr
* indexBuffer
, const VertexData
* vertexData
,
1833 bool createSeparateLightCap
, SubEntity
* subent
, bool isLightCap
)
1834 : mParent(parent
), mSubEntity(subent
)
1836 // Save link to vertex data
1837 mCurrentVertexData
= vertexData
;
1839 // Initialise render op
1840 mRenderOp
.indexData
= OGRE_NEW
IndexData();
1841 mRenderOp
.indexData
->indexBuffer
= *indexBuffer
;
1842 mRenderOp
.indexData
->indexStart
= 0;
1843 // index start and count are sorted out later
1845 // Create vertex data which just references position component (and 2 component)
1846 mRenderOp
.vertexData
= OGRE_NEW
VertexData();
1847 // Map in position data
1848 mRenderOp
.vertexData
->vertexDeclaration
->addElement(0,0,VET_FLOAT3
, VES_POSITION
);
1849 mOriginalPosBufferBinding
=
1850 vertexData
->vertexDeclaration
->findElementBySemantic(VES_POSITION
)->getSource();
1851 mPositionBuffer
= vertexData
->vertexBufferBinding
->getBuffer(mOriginalPosBufferBinding
);
1852 mRenderOp
.vertexData
->vertexBufferBinding
->setBinding(0, mPositionBuffer
);
1853 // Map in w-coord buffer (if present)
1854 if(!vertexData
->hardwareShadowVolWBuffer
.isNull())
1856 mRenderOp
.vertexData
->vertexDeclaration
->addElement(1,0,VET_FLOAT1
, VES_TEXTURE_COORDINATES
, 0);
1857 mWBuffer
= vertexData
->hardwareShadowVolWBuffer
;
1858 mRenderOp
.vertexData
->vertexBufferBinding
->setBinding(1, mWBuffer
);
1860 // Use same vertex start as input
1861 mRenderOp
.vertexData
->vertexStart
= vertexData
->vertexStart
;
1865 // Use original vertex count, no extrusion
1866 mRenderOp
.vertexData
->vertexCount
= vertexData
->vertexCount
;
1870 // Vertex count must take into account the doubling of the buffer,
1871 // because second half of the buffer is the extruded copy
1872 mRenderOp
.vertexData
->vertexCount
=
1873 vertexData
->vertexCount
* 2;
1874 if (createSeparateLightCap
)
1876 // Create child light cap
1877 mLightCap
= OGRE_NEW
EntityShadowRenderable(parent
,
1878 indexBuffer
, vertexData
, false, subent
, true);
1883 //-----------------------------------------------------------------------
1884 Entity::EntityShadowRenderable::~EntityShadowRenderable()
1886 OGRE_DELETE mRenderOp
.indexData
;
1887 OGRE_DELETE mRenderOp
.vertexData
;
1889 //-----------------------------------------------------------------------
1890 void Entity::EntityShadowRenderable::getWorldTransforms(Matrix4
* xform
) const
1892 *xform
= mParent
->_getParentNodeFullTransform();
1894 //-----------------------------------------------------------------------
1895 void Entity::EntityShadowRenderable::rebindPositionBuffer(const VertexData
* vertexData
, bool force
)
1897 if (force
|| mCurrentVertexData
!= vertexData
)
1899 mCurrentVertexData
= vertexData
;
1900 mPositionBuffer
= mCurrentVertexData
->vertexBufferBinding
->getBuffer(
1901 mOriginalPosBufferBinding
);
1902 mRenderOp
.vertexData
->vertexBufferBinding
->setBinding(0, mPositionBuffer
);
1905 static_cast<EntityShadowRenderable
*>(mLightCap
)->rebindPositionBuffer(vertexData
, force
);
1909 //-----------------------------------------------------------------------
1910 bool Entity::EntityShadowRenderable::isVisible(void) const
1914 return mSubEntity
->isVisible();
1918 return ShadowRenderable::isVisible();
1921 //-----------------------------------------------------------------------
1922 void Entity::setRenderQueueGroup(uint8 queueID
)
1924 MovableObject::setRenderQueueGroup(queueID
);
1926 // Set render queue for all manual LOD entities
1927 if (mMesh
->isLodManual())
1929 LODEntityList::iterator li
, liend
;
1930 liend
= mLodEntityList
.end();
1931 for (li
= mLodEntityList
.begin(); li
!= liend
; ++li
)
1933 (*li
)->setRenderQueueGroup(queueID
);
1937 //-----------------------------------------------------------------------
1938 void Entity::shareSkeletonInstanceWith(Entity
* entity
)
1940 if (entity
->getMesh()->getSkeleton() != getMesh()->getSkeleton())
1942 OGRE_EXCEPT(Exception::ERR_RT_ASSERTION_FAILED
,
1943 "The supplied entity has a different skeleton.",
1944 "Entity::shareSkeletonWith");
1946 if (!mSkeletonInstance
)
1948 OGRE_EXCEPT(Exception::ERR_RT_ASSERTION_FAILED
,
1949 "This entity has no skeleton.",
1950 "Entity::shareSkeletonWith");
1952 if (mSharedSkeletonEntities
!= NULL
&& entity
->mSharedSkeletonEntities
!= NULL
)
1954 OGRE_EXCEPT(Exception::ERR_RT_ASSERTION_FAILED
,
1955 "Both entities already shares their SkeletonInstances! At least "
1956 "one of the instances must not share it's instance.",
1957 "Entity::shareSkeletonWith");
1960 //check if we already share our skeletoninstance, we don't want to delete it if so
1961 if (mSharedSkeletonEntities
!= NULL
)
1963 entity
->shareSkeletonInstanceWith(this);
1967 OGRE_DELETE mSkeletonInstance
;
1968 OGRE_FREE_SIMD(mBoneMatrices
, MEMCATEGORY_ANIMATION
);
1969 OGRE_DELETE mAnimationState
;
1970 // using OGRE_FREE since unsigned long is not a destructor
1971 OGRE_FREE(mFrameBonesLastUpdated
, MEMCATEGORY_ANIMATION
);
1972 mSkeletonInstance
= entity
->mSkeletonInstance
;
1973 mNumBoneMatrices
= entity
->mNumBoneMatrices
;
1974 mBoneMatrices
= entity
->mBoneMatrices
;
1975 mAnimationState
= entity
->mAnimationState
;
1976 mFrameBonesLastUpdated
= entity
->mFrameBonesLastUpdated
;
1977 if (entity
->mSharedSkeletonEntities
== NULL
)
1979 entity
->mSharedSkeletonEntities
= OGRE_NEW_T(EntitySet
, MEMCATEGORY_ANIMATION
)();
1980 entity
->mSharedSkeletonEntities
->insert(entity
);
1982 mSharedSkeletonEntities
= entity
->mSharedSkeletonEntities
;
1983 mSharedSkeletonEntities
->insert(this);
1986 //-----------------------------------------------------------------------
1987 void Entity::stopSharingSkeletonInstance()
1989 if (mSharedSkeletonEntities
== NULL
)
1991 OGRE_EXCEPT(Exception::ERR_RT_ASSERTION_FAILED
,
1992 "This entity is not sharing it's skeletoninstance.",
1993 "Entity::shareSkeletonWith");
1995 //check if there's no other than us sharing the skeleton instance
1996 if (mSharedSkeletonEntities
->size() == 1)
1999 OGRE_DELETE_T(mSharedSkeletonEntities
, EntitySet
, MEMCATEGORY_ANIMATION
);
2000 mSharedSkeletonEntities
= 0;
2004 mSkeletonInstance
= OGRE_NEW
SkeletonInstance(mMesh
->getSkeleton());
2005 mSkeletonInstance
->load();
2006 mAnimationState
= OGRE_NEW
AnimationStateSet();
2007 mMesh
->_initAnimationState(mAnimationState
);
2008 mFrameBonesLastUpdated
= OGRE_NEW_T(unsigned long, MEMCATEGORY_ANIMATION
)(std::numeric_limits
<unsigned long>::max());
2009 mNumBoneMatrices
= mSkeletonInstance
->getNumBones();
2010 mBoneMatrices
= static_cast<Matrix4
*>(OGRE_MALLOC_SIMD(sizeof(Matrix4
) * mNumBoneMatrices
, MEMCATEGORY_ANIMATION
));
2012 mSharedSkeletonEntities
->erase(this);
2013 if (mSharedSkeletonEntities
->size() == 1)
2015 (*mSharedSkeletonEntities
->begin())->stopSharingSkeletonInstance();
2017 mSharedSkeletonEntities
= 0;
2020 //-----------------------------------------------------------------------
2021 void Entity::refreshAvailableAnimationState(void)
2023 mMesh
->_refreshAnimationState(mAnimationState
);
2025 //-----------------------------------------------------------------------
2026 uint32
Entity::getTypeFlags(void) const
2028 return SceneManager::ENTITY_TYPE_MASK
;
2030 //-----------------------------------------------------------------------
2031 VertexData
* Entity::getVertexDataForBinding(void)
2033 Entity::VertexDataBindChoice c
=
2034 chooseVertexDataForBinding(mMesh
->getSharedVertexDataAnimationType() != VAT_NONE
);
2038 return mMesh
->sharedVertexData
;
2039 case BIND_HARDWARE_MORPH
:
2040 return mHardwareVertexAnimVertexData
;
2041 case BIND_SOFTWARE_MORPH
:
2042 return mSoftwareVertexAnimVertexData
;
2043 case BIND_SOFTWARE_SKELETAL
:
2044 return mSkelAnimVertexData
;
2046 // keep compiler happy
2047 return mMesh
->sharedVertexData
;
2049 //-----------------------------------------------------------------------
2050 Entity::VertexDataBindChoice
Entity::chooseVertexDataForBinding(bool vertexAnim
) const
2054 if (!mHardwareAnimation
)
2056 // all software skeletal binds same vertex data
2057 // may be a 2-stage s/w transform including morph earlier though
2058 return BIND_SOFTWARE_SKELETAL
;
2060 else if (vertexAnim
)
2062 // hardware morph animation
2063 return BIND_HARDWARE_MORPH
;
2067 // hardware skeletal, no morphing
2068 return BIND_ORIGINAL
;
2071 else if (vertexAnim
)
2073 // morph only, no skeletal
2074 if (mHardwareAnimation
)
2076 return BIND_HARDWARE_MORPH
;
2080 return BIND_SOFTWARE_MORPH
;
2086 return BIND_ORIGINAL
;
2090 //---------------------------------------------------------------------
2091 void Entity::visitRenderables(Renderable::Visitor
* visitor
,
2092 bool debugRenderables
)
2094 // Visit each SubEntity
2095 for (SubEntityList::iterator i
= mSubEntityList
.begin(); i
!= mSubEntityList
.end(); ++i
)
2097 visitor
->visit(*i
, 0, false);
2099 // if manual LOD is in use, visit those too
2101 for (LODEntityList::iterator e
= mLodEntityList
.begin();
2102 e
!= mLodEntityList
.end(); ++e
, ++lodi
)
2105 uint nsub
= (*e
)->getNumSubEntities();
2106 for (uint s
= 0; s
< nsub
; ++s
)
2108 visitor
->visit((*e
)->getSubEntity(s
), lodi
, false);
2113 //-----------------------------------------------------------------------
2114 //-----------------------------------------------------------------------
2115 String
EntityFactory::FACTORY_TYPE_NAME
= "Entity";
2116 //-----------------------------------------------------------------------
2117 const String
& EntityFactory::getType(void) const
2119 return FACTORY_TYPE_NAME
;
2121 //-----------------------------------------------------------------------
2122 MovableObject
* EntityFactory::createInstanceImpl( const String
& name
,
2123 const NameValuePairList
* params
)
2125 // must have mesh parameter
2129 String groupName
= ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME
;
2131 NameValuePairList::const_iterator ni
;
2133 ni
= params
->find("resourceGroup");
2134 if (ni
!= params
->end())
2136 groupName
= ni
->second
;
2139 ni
= params
->find("mesh");
2140 if (ni
!= params
->end())
2142 // Get mesh (load if required)
2143 pMesh
= MeshManager::getSingleton().load(
2145 // autodetect group location
2152 OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS
,
2153 "'mesh' parameter required when constructing an Entity.",
2154 "EntityFactory::createInstance");
2157 return OGRE_NEW
Entity(name
, pMesh
);
2160 //-----------------------------------------------------------------------
2161 void EntityFactory::destroyInstance( MovableObject
* obj
)