1 /*
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
6 
7 Copyright (c) 2000-2013 Torus Knot Software Ltd
8 
9 Permission is hereby granted, free of charge, to any person obtaining a copy
10 of this software and associated documentation files (the "Software"), to deal
11 in the Software without restriction, including without limitation the rights
12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom the Software is
14 furnished to do so, subject to the following conditions:
15 
16 The above copyright notice and this permission notice shall be included in
17 all copies or substantial portions of the Software.
18 
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 THE SOFTWARE.
26 -----------------------------------------------------------------------------
27 */
28 #include "OgreStableHeaders.h"
29 #include "OgreEntity.h"
30 
31 #include "OgreMeshManager.h"
32 #include "OgreSubMesh.h"
33 #include "OgreSubEntity.h"
34 #include "OgreException.h"
35 #include "OgreSceneManager.h"
36 #include "OgreLogManager.h"
37 #include "OgreSkeleton.h"
38 #include "OgreBone.h"
39 #include "OgreCamera.h"
40 #include "OgreTagPoint.h"
41 #include "OgreAxisAlignedBox.h"
42 #include "OgreHardwareBufferManager.h"
43 #include "OgreVector4.h"
44 #include "OgreRoot.h"
45 #include "OgreTechnique.h"
46 #include "OgrePass.h"
47 #include "OgreSkeletonInstance.h"
48 #include "OgreEdgeListBuilder.h"
49 #include "OgreStringConverter.h"
50 #include "OgreAnimation.h"
51 #include "OgreOptimisedUtil.h"
52 #include "OgreSceneNode.h"
53 #include "OgreLodStrategy.h"
54 #include "OgreLodListener.h"
55 #include "OgreMaterialManager.h"
56 
57 namespace Ogre {
58     //-----------------------------------------------------------------------
Entity()59     Entity::Entity ()
60 		: mAnimationState(NULL),
61           mSkelAnimVertexData(0),
62 		  mSoftwareVertexAnimVertexData(0),
63 		  mHardwareVertexAnimVertexData(0),
64           mVertexAnimationAppliedThisFrame(false),
65           mPreparedForShadowVolumes(false),
66           mBoneWorldMatrices(NULL),
67           mBoneMatrices(NULL),
68           mNumBoneMatrices(0),
69 		  mFrameAnimationLastUpdated(std::numeric_limits<unsigned long>::max()),
70           mFrameBonesLastUpdated(NULL),
71 		  mSharedSkeletonEntities(NULL),
72 		  mDisplaySkeleton(false),
73 		  mCurrentHWAnimationState(false),
74 	      mHardwarePoseCount(0),
75 		  mVertexProgramInUse(false),
76 		  mSoftwareAnimationRequests(0),
77 		  mSoftwareAnimationNormalsRequests(0),
78           mSkipAnimStateUpdates(false),
79 		  mAlwaysUpdateMainSkeleton(false),
80 		  mMeshLodIndex(0),
81 		  mMeshLodFactorTransformed(1.0f),
82 		  mMinMeshLodIndex(99),
83 		  mMaxMeshLodIndex(0),		// Backwards, remember low value = high detail
84           mMaterialLodFactor(1.0f),
85           mMaterialLodFactorTransformed(1.0f),
86 		  mMinMaterialLodIndex(99),
87 		  mMaxMaterialLodIndex(0), 		// Backwards, remember low value = high detail
88           mSkeletonInstance(0),
89 		  mInitialised(false),
90 		  mLastParentXform(Matrix4::ZERO),
91 		  mMeshStateCount(0),
92           mFullBoundingBox()
93     {
94     }
95     //-----------------------------------------------------------------------
Entity(const String & name,const MeshPtr & mesh)96     Entity::Entity( const String& name, const MeshPtr& mesh) :
97 		MovableObject(name),
98         mMesh(mesh),
99         mAnimationState(NULL),
100 		mSkelAnimVertexData(0),
101 		mSoftwareVertexAnimVertexData(0),
102 		mHardwareVertexAnimVertexData(0),
103         mVertexAnimationAppliedThisFrame(false),
104         mPreparedForShadowVolumes(false),
105         mBoneWorldMatrices(NULL),
106         mBoneMatrices(NULL),
107         mNumBoneMatrices(0),
108 		mFrameAnimationLastUpdated(std::numeric_limits<unsigned long>::max()),
109         mFrameBonesLastUpdated(NULL),
110         mSharedSkeletonEntities(NULL),
111 		mDisplaySkeleton(false),
112 		mCurrentHWAnimationState(false),
113 		mVertexProgramInUse(false),
114 		mSoftwareAnimationRequests(0),
115 		mSoftwareAnimationNormalsRequests(0),
116         mSkipAnimStateUpdates(false),
117 		mAlwaysUpdateMainSkeleton(false),
118 		mMeshLodIndex(0),
119 		mMeshLodFactorTransformed(1.0f),
120 		mMinMeshLodIndex(99),
121 		mMaxMeshLodIndex(0),		// Backwards, remember low value = high detail
122         mMaterialLodFactor(1.0f),
123         mMaterialLodFactorTransformed(1.0f),
124 		mMinMaterialLodIndex(99),
125 		mMaxMaterialLodIndex(0), 		// Backwards, remember low value = high detail
126 		mSkeletonInstance(0),
127 		mInitialised(false),
128 		mLastParentXform(Matrix4::ZERO),
129 		mMeshStateCount(0),
130         mFullBoundingBox()
131 	{
132 		_initialise();
133     }
134 	//-----------------------------------------------------------------------
backgroundLoadingComplete(Resource * res)135 	void Entity::backgroundLoadingComplete(Resource* res)
136 	{
137 		if (res == mMesh.get())
138 		{
139 			// mesh loading has finished, we can construct ourselves now
140 			_initialise();
141 		}
142 	}
143 	//-----------------------------------------------------------------------
_initialise(bool forceReinitialise)144 	void Entity::_initialise(bool forceReinitialise)
145 	{
146 		if (forceReinitialise)
147 			_deinitialise();
148 
149 		if (mInitialised)
150 			return;
151 
152 		if (mMesh->isBackgroundLoaded() && !mMesh->isLoaded())
153 		{
154 			// register for a callback when mesh is finished loading
155 			// do this before asking for load to happen to avoid race
156 			mMesh->addListener(this);
157 		}
158 
159 		// On-demand load
160 		mMesh->load();
161 		// If loading failed, or deferred loading isn't done yet, defer
162 		// Will get a callback in the case of deferred loading
163 		// Skeletons are cascade-loaded so no issues there
164 		if (!mMesh->isLoaded())
165 			return;
166 
167 		// Is mesh skeletally animated?
168 		if (mMesh->hasSkeleton() && !mMesh->getSkeleton().isNull())
169 		{
170 			mSkeletonInstance = OGRE_NEW SkeletonInstance(mMesh->getSkeleton());
171 			mSkeletonInstance->load();
172 		}
173 
174 		// Build main subentity list
175 		buildSubEntityList(mMesh, &mSubEntityList);
176 
177 		// Check if mesh is using manual LOD
178 		if (mMesh->isLodManual())
179 		{
180 			ushort i, numLod;
181 			numLod = mMesh->getNumLodLevels();
182 			// NB skip LOD 0 which is the original
183 			for (i = 1; i < numLod; ++i)
184 			{
185 				const MeshLodUsage& usage = mMesh->getLodLevel(i);
186 				// Manually create entity
187 				Entity* lodEnt = OGRE_NEW Entity(mName + "Lod" + StringConverter::toString(i),
188 					usage.manualMesh);
189 				mLodEntityList.push_back(lodEnt);
190 			}
191 		}
192 
193 
194 		// Initialise the AnimationState, if Mesh has animation
195 		if (hasSkeleton())
196 		{
197 			mFrameBonesLastUpdated = OGRE_NEW_T(unsigned long, MEMCATEGORY_ANIMATION)(std::numeric_limits<unsigned long>::max());
198 			mNumBoneMatrices = mSkeletonInstance->getNumBones();
199 			mBoneMatrices = static_cast<Matrix4*>(OGRE_MALLOC_SIMD(sizeof(Matrix4) * mNumBoneMatrices, MEMCATEGORY_ANIMATION));
200 		}
201 		if (hasSkeleton() || hasVertexAnimation())
202 		{
203 			mAnimationState = OGRE_NEW AnimationStateSet();
204 			mMesh->_initAnimationState(mAnimationState);
205 			prepareTempBlendBuffers();
206 		}
207 
208 		reevaluateVertexProcessing();
209 
210 		// Update of bounds of the parent SceneNode, if Entity already attached
211 		// this can happen if Mesh is loaded in background or after reinitialisation
212 		if( mParentNode )
213 		{
214 			getParentSceneNode()->needUpdate();
215 		}
216 
217 		mInitialised = true;
218 		mMeshStateCount = mMesh->getStateCount();
219 
220 	}
221 	//-----------------------------------------------------------------------
_deinitialise(void)222 	void Entity::_deinitialise(void)
223 	{
224 		if (!mInitialised)
225 			return;
226 
227 		// Delete submeshes
228 		SubEntityList::iterator i, iend;
229 		iend = mSubEntityList.end();
230 		for (i = mSubEntityList.begin(); i != iend; ++i)
231 		{
232 			// Delete SubEntity
233 			OGRE_DELETE *i;
234             *i = 0;
235 		}
236 		mSubEntityList.clear();
237 
238 		// Delete LOD entities
239 		LODEntityList::iterator li, liend;
240 		liend = mLodEntityList.end();
241 		for (li = mLodEntityList.begin(); li != liend; ++li)
242 		{
243 			// Delete
244 			OGRE_DELETE *li;
245             *li = 0;
246 		}
247         mLodEntityList.clear();
248 
249 		// Delete shadow renderables
250 		ShadowRenderableList::iterator si, siend;
251 		siend = mShadowRenderables.end();
252 		for (si = mShadowRenderables.begin(); si != siend; ++si)
253 		{
254 			OGRE_DELETE *si;
255             *si = 0;
256 		}
257         mShadowRenderables.clear();
258 
259 		// Detach all child objects, do this manually to avoid needUpdate() call
260 		// which can fail because of deleted items
261 		detachAllObjectsImpl();
262 
263 		if (mSkeletonInstance) {
264 			OGRE_FREE_SIMD(mBoneWorldMatrices, MEMCATEGORY_ANIMATION);
265             mBoneWorldMatrices = 0;
266 
267             if (mSharedSkeletonEntities) {
268                 mSharedSkeletonEntities->erase(this);
269                 if (mSharedSkeletonEntities->size() == 1)
270                 {
271                     (*mSharedSkeletonEntities->begin())->stopSharingSkeletonInstance();
272                 }
273                 // Should never occur, just in case
274                 else if (mSharedSkeletonEntities->empty())
275                 {
276                     OGRE_DELETE_T(mSharedSkeletonEntities, EntitySet, MEMCATEGORY_ANIMATION); mSharedSkeletonEntities = 0;
277 					// using OGRE_FREE since unsigned long is not a destructor
278                     OGRE_FREE(mFrameBonesLastUpdated, MEMCATEGORY_ANIMATION); mFrameBonesLastUpdated = 0;
279                     OGRE_DELETE mSkeletonInstance; mSkeletonInstance = 0;
280                     OGRE_FREE_SIMD(mBoneMatrices, MEMCATEGORY_ANIMATION); mBoneMatrices = 0;
281                     OGRE_DELETE mAnimationState; mAnimationState = 0;
282                 }
283             } else {
284 				// using OGRE_FREE since unsigned long is not a destructor
285 				OGRE_FREE(mFrameBonesLastUpdated, MEMCATEGORY_ANIMATION); mFrameBonesLastUpdated = 0;
286                 OGRE_DELETE mSkeletonInstance; mSkeletonInstance = 0;
287                 OGRE_FREE_SIMD(mBoneMatrices, MEMCATEGORY_ANIMATION); mBoneMatrices = 0;
288                 OGRE_DELETE mAnimationState; mAnimationState = 0;
289             }
290         }
291 		else if (hasVertexAnimation())
292 		{
293 			OGRE_DELETE mAnimationState;
294             mAnimationState = 0;
295 		}
296 
297 		OGRE_DELETE mSkelAnimVertexData; mSkelAnimVertexData = 0;
298 		OGRE_DELETE mSoftwareVertexAnimVertexData; mSoftwareVertexAnimVertexData = 0;
299 		OGRE_DELETE mHardwareVertexAnimVertexData; mHardwareVertexAnimVertexData = 0;
300 
301 		mInitialised = false;
302 	}
303     //-----------------------------------------------------------------------
~Entity()304     Entity::~Entity()
305     {
306 		_deinitialise();
307 		// Unregister our listener
308 		mMesh->removeListener(this);
309     }
310 	//-----------------------------------------------------------------------
hasVertexAnimation(void) const311 	bool Entity::hasVertexAnimation(void) const
312 	{
313 		return mMesh->hasVertexAnimation();
314 	}
315     //-----------------------------------------------------------------------
getMesh(void) const316     const MeshPtr& Entity::getMesh(void) const
317     {
318         return mMesh;
319     }
320     //-----------------------------------------------------------------------
getSubEntity(unsigned int index) const321     SubEntity* Entity::getSubEntity(unsigned int index) const
322     {
323         if (index >= mSubEntityList.size())
324             OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
325             "Index out of bounds.",
326             "Entity::getSubEntity");
327         return mSubEntityList[index];
328     }
329     //-----------------------------------------------------------------------
getSubEntity(const String & name) const330     SubEntity* Entity::getSubEntity(const String& name) const
331     {
332         ushort index = mMesh->_getSubMeshIndex(name);
333         return getSubEntity(index);
334     }
335     //-----------------------------------------------------------------------
getNumSubEntities(void) const336     unsigned int Entity::getNumSubEntities(void) const
337     {
338         return static_cast< unsigned int >( mSubEntityList.size() );
339     }
340     //-----------------------------------------------------------------------
clone(const String & newName) const341     Entity* Entity::clone( const String& newName) const
342     {
343    		if (!mManager)
344 		{
345 			OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
346 				"Cannot clone an Entity that wasn't created through a "
347 				"SceneManager", "Entity::clone");
348 		}
349 	    Entity* newEnt = mManager->createEntity(newName, getMesh()->getName() );
350 
351 		if (mInitialised)
352 		{
353 			// Copy material settings
354 			SubEntityList::const_iterator i;
355 			unsigned int n = 0;
356 			for (i = mSubEntityList.begin(); i != mSubEntityList.end(); ++i, ++n)
357 			{
358 				newEnt->getSubEntity(n)->setMaterialName((*i)->getMaterialName());
359 			}
360 			if (mAnimationState)
361 			{
362 				OGRE_DELETE newEnt->mAnimationState;
363 				newEnt->mAnimationState = OGRE_NEW AnimationStateSet(*mAnimationState);
364 			}
365 		}
366 
367         return newEnt;
368     }
369     //-----------------------------------------------------------------------
setMaterialName(const String & name,const String & groupName)370     void Entity::setMaterialName( const String& name, const String& groupName /* = ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME */)
371     {
372         // Set for all subentities
373         SubEntityList::iterator i;
374         for (i = mSubEntityList.begin(); i != mSubEntityList.end(); ++i)
375         {
376             (*i)->setMaterialName(name, groupName);
377         }
378 
379     }
380 
381 
setMaterial(const MaterialPtr & material)382 	void Entity::setMaterial( const MaterialPtr& material )
383 	{
384 		// Set for all subentities
385 		SubEntityList::iterator i;
386 		for (i = mSubEntityList.begin(); i != mSubEntityList.end(); ++i)
387 		{
388 			(*i)->setMaterial(material);
389 		}
390 	}
391 
392     //-----------------------------------------------------------------------
_notifyCurrentCamera(Camera * cam)393     void Entity::_notifyCurrentCamera(Camera* cam)
394     {
395 		MovableObject::_notifyCurrentCamera(cam);
396 
397         // Calculate the LOD
398         if (mParentNode)
399         {
400             // Get mesh LOD strategy
401             const LodStrategy *meshStrategy = mMesh->getLodStrategy();
402             // Get the appropriate LOD value
403             Real lodValue = meshStrategy->getValue(this, cam);
404             // Bias the LOD value
405             Real biasedMeshLodValue = lodValue * mMeshLodFactorTransformed;
406 
407 
408             // Get the index at this biased depth
409             ushort newMeshLodIndex = mMesh->getLodIndex(biasedMeshLodValue);
410             // Apply maximum detail restriction (remember lower = higher detail)
411             newMeshLodIndex = std::max(mMaxMeshLodIndex, newMeshLodIndex);
412             // Apply minimum detail restriction (remember higher = lower detail)
413             newMeshLodIndex = std::min(mMinMeshLodIndex, newMeshLodIndex);
414 
415             // Construct event object
416             EntityMeshLodChangedEvent evt;
417             evt.entity = this;
418             evt.camera = cam;
419             evt.lodValue = biasedMeshLodValue;
420             evt.previousLodIndex = mMeshLodIndex;
421             evt.newLodIndex = newMeshLodIndex;
422 
423             // Notify LOD event listeners
424             cam->getSceneManager()->_notifyEntityMeshLodChanged(evt);
425 
426             // Change LOD index
427             mMeshLodIndex = evt.newLodIndex;
428 
429             // Now do material LOD
430             lodValue *= mMaterialLodFactorTransformed;
431 
432 
433 
434             SubEntityList::iterator i, iend;
435             iend = mSubEntityList.end();
436             for (i = mSubEntityList.begin(); i != iend; ++i)
437             {
438                 // Get sub-entity material
439                 const MaterialPtr& material = (*i)->getMaterial();
440 
441                 // Get material LOD strategy
442                 const LodStrategy *materialStrategy = material->getLodStrategy();
443 
444                 // Recalculate LOD value if strategies do not match
445                 Real biasedMaterialLodValue;
446                 if (meshStrategy == materialStrategy)
447                     biasedMaterialLodValue = lodValue;
448                 else
449                     biasedMaterialLodValue = materialStrategy->getValue(this, cam) * materialStrategy->transformBias(mMaterialLodFactor);
450 
451                 // Get the index at this biased depth
452                 unsigned short idx = material->getLodIndex(biasedMaterialLodValue);
453                 // Apply maximum detail restriction (remember lower = higher detail)
454                 idx = std::max(mMaxMaterialLodIndex, idx);
455                 // Apply minimum detail restriction (remember higher = lower detail)
456                 idx = std::min(mMinMaterialLodIndex, idx);
457 
458                 // Construct event object
459                 EntityMaterialLodChangedEvent subEntEvt;
460                 subEntEvt.subEntity = (*i);
461                 subEntEvt.camera = cam;
462                 subEntEvt.lodValue = biasedMaterialLodValue;
463                 subEntEvt.previousLodIndex = (*i)->mMaterialLodIndex;
464                 subEntEvt.newLodIndex = idx;
465 
466                 // Notify LOD event listeners
467                 cam->getSceneManager()->_notifyEntityMaterialLodChanged(subEntEvt);
468 
469                 // Change LOD index
470                 (*i)->mMaterialLodIndex = subEntEvt.newLodIndex;
471 
472 				// Also invalidate any camera distance cache
473 				(*i)->_invalidateCameraCache ();
474             }
475 
476 
477         }
478         // Notify any child objects
479         ChildObjectList::iterator child_itr = mChildObjectList.begin();
480         ChildObjectList::iterator child_itr_end = mChildObjectList.end();
481         for( ; child_itr != child_itr_end; ++child_itr)
482         {
483             (*child_itr).second->_notifyCurrentCamera(cam);
484         }
485     }
486     //-----------------------------------------------------------------------
getBoundingBox(void) const487     const AxisAlignedBox& Entity::getBoundingBox(void) const
488     {
489 		// Get from Mesh
490 		if (mMesh->isLoaded())
491 		{
492 			mFullBoundingBox = mMesh->getBounds();
493 			mFullBoundingBox.merge(getChildObjectsBoundingBox());
494 
495 			// Don't scale here, this is taken into account when world BBox calculation is done
496 		}
497 		else
498 			mFullBoundingBox.setNull();
499 
500         return mFullBoundingBox;
501     }
502     //-----------------------------------------------------------------------
getChildObjectsBoundingBox(void) const503     AxisAlignedBox Entity::getChildObjectsBoundingBox(void) const
504     {
505         AxisAlignedBox aa_box;
506         AxisAlignedBox full_aa_box;
507         full_aa_box.setNull();
508 
509         ChildObjectList::const_iterator child_itr = mChildObjectList.begin();
510         ChildObjectList::const_iterator child_itr_end = mChildObjectList.end();
511         for( ; child_itr != child_itr_end; ++child_itr)
512         {
513             aa_box = child_itr->second->getBoundingBox();
514             TagPoint* tp = static_cast<TagPoint*>(child_itr->second->getParentNode());
515             // Use transform local to skeleton since world xform comes later
516             aa_box.transformAffine(tp->_getFullLocalTransform());
517 
518             full_aa_box.merge(aa_box);
519         }
520 
521         return full_aa_box;
522     }
523 	//-----------------------------------------------------------------------
getWorldBoundingBox(bool derive) const524 	const AxisAlignedBox& Entity::getWorldBoundingBox(bool derive) const
525 	{
526 		if (derive)
527 		{
528 			// derive child bounding boxes
529 			ChildObjectList::const_iterator child_itr = mChildObjectList.begin();
530 			ChildObjectList::const_iterator child_itr_end = mChildObjectList.end();
531 			for( ; child_itr != child_itr_end; ++child_itr)
532 			{
533 				child_itr->second->getWorldBoundingBox(true);
534 			}
535 		}
536 		return MovableObject::getWorldBoundingBox(derive);
537 	}
538 	//-----------------------------------------------------------------------
getWorldBoundingSphere(bool derive) const539 	const Sphere& Entity::getWorldBoundingSphere(bool derive) const
540 	{
541 		if (derive)
542 		{
543 			// derive child bounding boxes
544 			ChildObjectList::const_iterator child_itr = mChildObjectList.begin();
545 			ChildObjectList::const_iterator child_itr_end = mChildObjectList.end();
546 			for( ; child_itr != child_itr_end; ++child_itr)
547 			{
548 				child_itr->second->getWorldBoundingSphere(true);
549 			}
550 		}
551 		return MovableObject::getWorldBoundingSphere(derive);
552 
553 	}
554     //-----------------------------------------------------------------------
_updateRenderQueue(RenderQueue * queue)555     void Entity::_updateRenderQueue(RenderQueue* queue)
556     {
557 		// Do nothing if not initialised yet
558 		if (!mInitialised)
559 			return;
560 
561 		// Check mesh state count, will be incremented if reloaded
562 		if (mMesh->getStateCount() != mMeshStateCount)
563 		{
564 			// force reinitialise
565 			_initialise(true);
566 		}
567 
568         Entity* displayEntity = this;
569 		// Check we're not using a manual LOD
570         if (mMeshLodIndex > 0 && mMesh->isLodManual())
571         {
572             // Use alternate entity
573             assert( static_cast< size_t >( mMeshLodIndex - 1 ) < mLodEntityList.size() &&
574                 "No LOD EntityList - did you build the manual LODs after creating the entity?");
575             // index - 1 as we skip index 0 (original LOD)
576             if (hasSkeleton() && mLodEntityList[mMeshLodIndex - 1]->hasSkeleton())
577             {
578                 // Copy the animation state set to LOD entity, we assume the LOD
579                 // entity only has a subset animation states
580                 AnimationStateSet* targetState = mLodEntityList[mMeshLodIndex - 1]->mAnimationState;
581 				if (mAnimationState != targetState) // only copy if LODs use different skeleton instances
582 				{
583 					if (mAnimationState->getDirtyFrameNumber() != targetState->getDirtyFrameNumber()) // only copy if animation was updated
584 						mAnimationState->copyMatchingState(targetState);
585 				}
586             }
587             displayEntity = mLodEntityList[mMeshLodIndex - 1];
588         }
589 
590         // Add each visible SubEntity to the queue
591         SubEntityList::iterator i, iend;
592         iend = displayEntity->mSubEntityList.end();
593         for (i = displayEntity->mSubEntityList.begin(); i != iend; ++i)
594         {
595             if((*i)->isVisible())
596             {
597                 // Order: first use subentity queue settings, if available
598                 //        if not then use entity queue settings, if available
599                 //        finally fall back on default queue settings
600                 if((*i)->isRenderQueuePrioritySet())
601                 {
602 					assert((*i)->isRenderQueueGroupSet() == true);
603                     queue->addRenderable(*i, (*i)->getRenderQueueGroup(), (*i)->getRenderQueuePriority());
604                 }
605                 else if((*i)->isRenderQueueGroupSet())
606                 {
607                     queue->addRenderable(*i, (*i)->getRenderQueueGroup());
608                 }
609 				else if (mRenderQueuePrioritySet)
610 				{
611 					assert(mRenderQueueIDSet == true);
612 					queue->addRenderable(*i, mRenderQueueID, mRenderQueuePriority);
613 				}
614                 else if(mRenderQueueIDSet)
615                 {
616                     queue->addRenderable(*i, mRenderQueueID);
617 				}
618                 else
619                 {
620                     queue->addRenderable(*i);
621                 }
622             }
623         }
624 
625 		if (getAlwaysUpdateMainSkeleton() && hasSkeleton() && (mMeshLodIndex > 0))
626 		{
627 			//check if an update was made
628 			if (cacheBoneMatrices())
629 			{
630 				getSkeleton()->_updateTransforms();
631 				//We will mark the skeleton as dirty. Otherwise, if in the same frame the entity will
632 				//be rendered first with a low LOD and then with a high LOD the system wont know that
633 				//the bone matrices has changed and there for will not update the vertex buffers
634 				getSkeleton()->_notifyManualBonesDirty();
635 			}
636 		}
637 
638         // Since we know we're going to be rendered, take this opportunity to
639         // update the animation
640         if (displayEntity->hasSkeleton() || displayEntity->hasVertexAnimation())
641         {
642             displayEntity->updateAnimation();
643 
644             //--- pass this point,  we are sure that the transformation matrix of each bone and tagPoint have been updated
645             ChildObjectList::iterator child_itr = mChildObjectList.begin();
646             ChildObjectList::iterator child_itr_end = mChildObjectList.end();
647             for( ; child_itr != child_itr_end; ++child_itr)
648             {
649                 MovableObject* child = child_itr->second;
650                 bool visible = child->isVisible();
651                 if (visible && (displayEntity != this))
652                 {
653                     //Check if the bone exists in the current LOD
654 
655                     //The child is connected to a tagpoint which is connected to a bone
656                     Bone* bone = static_cast<Bone*>(child->getParentNode()->getParent());
657                     if (!displayEntity->getSkeleton()->hasBone(bone->getName()))
658                     {
659                         //Current LOD entity does not have the bone that the
660                         //child is connected to. Do not display.
661                         visible = false;
662                     }
663                 }
664                 if (visible)
665                 {
666                     child->_updateRenderQueue(queue);
667                 }
668             }
669         }
670 
671         // HACK to display bones
672         // This won't work if the entity is not centered at the origin
673         // TODO work out a way to allow bones to be rendered when Entity not centered
674         if (mDisplaySkeleton && hasSkeleton())
675         {
676             int numBones = mSkeletonInstance->getNumBones();
677             for (unsigned short b = 0; b < numBones; ++b)
678             {
679                 Bone* bone = mSkeletonInstance->getBone(b);
680 				if (mRenderQueuePrioritySet)
681 				{
682 					assert(mRenderQueueIDSet == true);
683 					queue->addRenderable(bone->getDebugRenderable(1), mRenderQueueID, mRenderQueuePriority);
684 				}
685 				else if(mRenderQueueIDSet)
686                 {
687                      queue->addRenderable(bone->getDebugRenderable(1), mRenderQueueID);
688                 }
689 				else
690 				{
691                      queue->addRenderable(bone->getDebugRenderable(1));
692                 }
693             }
694         }
695     }
696     //-----------------------------------------------------------------------
getAnimationState(const String & name) const697     AnimationState* Entity::getAnimationState(const String& name) const
698     {
699         if (!mAnimationState)
700         {
701             OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Entity is not animated",
702                 "Entity::getAnimationState");
703         }
704 
705 		return mAnimationState->getAnimationState(name);
706     }
707     //-----------------------------------------------------------------------
hasAnimationState(const String & name) const708     bool Entity::hasAnimationState(const String& name) const
709     {
710         return mAnimationState && mAnimationState->hasAnimationState(name);
711     }
712     //-----------------------------------------------------------------------
getAllAnimationStates(void) const713     AnimationStateSet* Entity::getAllAnimationStates(void) const
714     {
715         return mAnimationState;
716     }
717     //-----------------------------------------------------------------------
getMovableType(void) const718     const String& Entity::getMovableType(void) const
719     {
720 		return EntityFactory::FACTORY_TYPE_NAME;
721     }
722 	//-----------------------------------------------------------------------
tempVertexAnimBuffersBound(void) const723 	bool Entity::tempVertexAnimBuffersBound(void) const
724 	{
725 		// Do we still have temp buffers for software vertex animation bound?
726 		bool ret = true;
727 		if (mMesh->sharedVertexData && mMesh->getSharedVertexDataAnimationType() != VAT_NONE)
728 		{
729 			ret = ret && mTempVertexAnimInfo.buffersCheckedOut(true, mMesh->getSharedVertexDataAnimationIncludesNormals());
730 		}
731 		for (SubEntityList::const_iterator i = mSubEntityList.begin();
732 			i != mSubEntityList.end(); ++i)
733 		{
734 			SubEntity* sub = *i;
735 			if (!sub->getSubMesh()->useSharedVertices
736 				&& sub->getSubMesh()->getVertexAnimationType() != VAT_NONE)
737 			{
738 				ret = ret && sub->_getVertexAnimTempBufferInfo()->buffersCheckedOut(
739 					true, sub->getSubMesh()->getVertexAnimationIncludesNormals());
740 			}
741 		}
742 		return ret;
743 	}
744     //-----------------------------------------------------------------------
tempSkelAnimBuffersBound(bool requestNormals) const745     bool Entity::tempSkelAnimBuffersBound(bool requestNormals) const
746     {
747         // Do we still have temp buffers for software skeleton animation bound?
748         if (mSkelAnimVertexData)
749         {
750             if (!mTempSkelAnimInfo.buffersCheckedOut(true, requestNormals))
751                 return false;
752         }
753         for (SubEntityList::const_iterator i = mSubEntityList.begin();
754             i != mSubEntityList.end(); ++i)
755         {
756             SubEntity* sub = *i;
757             if (sub->isVisible() && sub->mSkelAnimVertexData)
758             {
759                 if (!sub->mTempSkelAnimInfo.buffersCheckedOut(true, requestNormals))
760                     return false;
761             }
762         }
763         return true;
764     }
765     //-----------------------------------------------------------------------
updateAnimation(void)766     void Entity::updateAnimation(void)
767     {
768 		// Do nothing if not initialised yet
769 		if (!mInitialised)
770 			return;
771 
772 		Root& root = Root::getSingleton();
773 		bool hwAnimation = isHardwareAnimationEnabled();
774 		bool isNeedUpdateHardwareAnim = hwAnimation && !mCurrentHWAnimationState;
775 		bool forcedSwAnimation = getSoftwareAnimationRequests()>0;
776 		bool forcedNormals = getSoftwareAnimationNormalsRequests()>0;
777 		bool stencilShadows = false;
778 		if (getCastShadows() && hasEdgeList() && root._getCurrentSceneManager())
779 			stencilShadows =  root._getCurrentSceneManager()->isShadowTechniqueStencilBased();
780 		bool softwareAnimation = !hwAnimation || stencilShadows || forcedSwAnimation;
781 		// Blend normals in s/w only if we're not using h/w animation,
782 		// since shadows only require positions
783 		bool blendNormals = !hwAnimation || forcedNormals;
784         // Animation dirty if animation state modified or manual bones modified
785         bool animationDirty =
786             (mFrameAnimationLastUpdated != mAnimationState->getDirtyFrameNumber()) ||
787             (hasSkeleton() && getSkeleton()->getManualBonesDirty());
788 
789 		//update the current hardware animation state
790 		mCurrentHWAnimationState = hwAnimation;
791 
792 		// We only do these tasks if animation is dirty
793 		// Or, if we're using a skeleton and manual bones have been moved
794 		// Or, if we're using software animation and temp buffers are unbound
795         if (animationDirty ||
796 			(softwareAnimation && hasVertexAnimation() && !tempVertexAnimBuffersBound()) ||
797 			(softwareAnimation && hasSkeleton() && !tempSkelAnimBuffersBound(blendNormals)))
798         {
799 			if (hasVertexAnimation())
800 			{
801 				if (softwareAnimation)
802 				{
803 					// grab & bind temporary buffer for positions (& normals if they are included)
804 					if (mSoftwareVertexAnimVertexData
805 						&& mMesh->getSharedVertexDataAnimationType() != VAT_NONE)
806 					{
807 						bool useNormals = mMesh->getSharedVertexDataAnimationIncludesNormals();
808 						mTempVertexAnimInfo.checkoutTempCopies(true, useNormals);
809 						// NB we suppress hardware upload while doing blend if we're
810 						// hardware animation, because the only reason for doing this
811 						// is for shadow, which need only be uploaded then
812 						mTempVertexAnimInfo.bindTempCopies(mSoftwareVertexAnimVertexData,
813 							hwAnimation);
814 					}
815 					SubEntityList::iterator i, iend;
816 					iend = mSubEntityList.end();
817 					for (i = mSubEntityList.begin(); i != iend; ++i)
818 					{
819 						// Blend dedicated geometry
820 						SubEntity* se = *i;
821 						if (se->isVisible() && se->mSoftwareVertexAnimVertexData
822 							&& se->getSubMesh()->getVertexAnimationType() != VAT_NONE)
823 						{
824 							bool useNormals = se->getSubMesh()->getVertexAnimationIncludesNormals();
825 							se->mTempVertexAnimInfo.checkoutTempCopies(true, useNormals);
826 							se->mTempVertexAnimInfo.bindTempCopies(se->mSoftwareVertexAnimVertexData,
827 								hwAnimation);
828 						}
829 
830 					}
831 				}
832 				applyVertexAnimation(hwAnimation, stencilShadows);
833 			}
834 
835 			if (hasSkeleton())
836 			{
837 				cacheBoneMatrices();
838 
839 				// Software blend?
840 				if (softwareAnimation)
841 				{
842                     const Matrix4* blendMatrices[256];
843 
844 					// Ok, we need to do a software blend
845 					// Firstly, check out working vertex buffers
846 					if (mSkelAnimVertexData)
847 					{
848 						// Blend shared geometry
849 						// NB we suppress hardware upload while doing blend if we're
850 						// hardware animation, because the only reason for doing this
851 						// is for shadow, which need only be uploaded then
852 						mTempSkelAnimInfo.checkoutTempCopies(true, blendNormals);
853 						mTempSkelAnimInfo.bindTempCopies(mSkelAnimVertexData,
854 							hwAnimation);
855                         // Prepare blend matrices, TODO: Move out of here
856                         Mesh::prepareMatricesForVertexBlend(blendMatrices,
857                             mBoneMatrices, mMesh->sharedBlendIndexToBoneIndexMap);
858 						// Blend, taking source from either mesh data or morph data
859 						Mesh::softwareVertexBlend(
860 							(mMesh->getSharedVertexDataAnimationType() != VAT_NONE) ?
861 								mSoftwareVertexAnimVertexData :	mMesh->sharedVertexData,
862 							mSkelAnimVertexData,
863 							blendMatrices, mMesh->sharedBlendIndexToBoneIndexMap.size(),
864 							blendNormals);
865 					}
866 					SubEntityList::iterator i, iend;
867 					iend = mSubEntityList.end();
868 					for (i = mSubEntityList.begin(); i != iend; ++i)
869 					{
870 						// Blend dedicated geometry
871 						SubEntity* se = *i;
872 						if (se->isVisible() && se->mSkelAnimVertexData)
873 						{
874 							se->mTempSkelAnimInfo.checkoutTempCopies(true, blendNormals);
875 							se->mTempSkelAnimInfo.bindTempCopies(se->mSkelAnimVertexData,
876 								hwAnimation);
877                             // Prepare blend matrices, TODO: Move out of here
878                             Mesh::prepareMatricesForVertexBlend(blendMatrices,
879                                 mBoneMatrices, se->mSubMesh->blendIndexToBoneIndexMap);
880 							// Blend, taking source from either mesh data or morph data
881 							Mesh::softwareVertexBlend(
882 								(se->getSubMesh()->getVertexAnimationType() != VAT_NONE)?
883 									se->mSoftwareVertexAnimVertexData : se->mSubMesh->vertexData,
884 								se->mSkelAnimVertexData,
885 								blendMatrices, se->mSubMesh->blendIndexToBoneIndexMap.size(),
886 								blendNormals);
887 						}
888 
889 					}
890 
891 				}
892 			}
893 
894             // Trigger update of bounding box if necessary
895             if (!mChildObjectList.empty())
896                 mParentNode->needUpdate();
897 
898 			mFrameAnimationLastUpdated = mAnimationState->getDirtyFrameNumber();
899         }
900 
901         // Need to update the child object's transforms when animation dirty
902         // or parent node transform has altered.
903 		if (hasSkeleton() &&
904             (isNeedUpdateHardwareAnim ||
905 			animationDirty || mLastParentXform != _getParentNodeFullTransform()))
906         {
907             // Cache last parent transform for next frame use too.
908             mLastParentXform = _getParentNodeFullTransform();
909 
910             //--- Update the child object's transforms
911             ChildObjectList::iterator child_itr = mChildObjectList.begin();
912             ChildObjectList::iterator child_itr_end = mChildObjectList.end();
913             for( ; child_itr != child_itr_end; ++child_itr)
914             {
915                 (*child_itr).second->getParentNode()->_update(true, true);
916             }
917 
918             // Also calculate bone world matrices, since are used as replacement world matrices,
919             // but only if it's used (when using hardware animation and skeleton animated).
920             if (hwAnimation && _isSkeletonAnimated())
921             {
922                 // Allocate bone world matrices on demand, for better memory footprint
923                 // when using software animation.
924                 if (!mBoneWorldMatrices)
925                 {
926                     mBoneWorldMatrices =
927                         static_cast<Matrix4*>(OGRE_MALLOC_SIMD(sizeof(Matrix4) * mNumBoneMatrices, MEMCATEGORY_ANIMATION));
928                 }
929 
930                 OptimisedUtil::getImplementation()->concatenateAffineMatrices(
931                     mLastParentXform,
932                     mBoneMatrices,
933                     mBoneWorldMatrices,
934                     mNumBoneMatrices);
935             }
936         }
937     }
938 	//-----------------------------------------------------------------------
initHardwareAnimationElements(VertexData * vdata,ushort numberOfElements,bool animateNormals)939 	ushort Entity::initHardwareAnimationElements(VertexData* vdata,
940 		ushort numberOfElements, bool animateNormals)
941 	{
942 		ushort elemsSupported = numberOfElements;
943 		if (vdata->hwAnimationDataList.size() < numberOfElements)
944 		{
945 			elemsSupported =
946 				vdata->allocateHardwareAnimationElements(numberOfElements, animateNormals);
947 		}
948 		// Initialise parametrics incase we don't use all of them
949 		for (size_t i = 0; i < vdata->hwAnimationDataList.size(); ++i)
950 		{
951 			vdata->hwAnimationDataList[i].parametric = 0.0f;
952 		}
953 		// reset used count
954 		vdata->hwAnimDataItemsUsed = 0;
955 
956 		return elemsSupported;
957 
958 	}
959 	//-----------------------------------------------------------------------
applyVertexAnimation(bool hardwareAnimation,bool stencilShadows)960 	void Entity::applyVertexAnimation(bool hardwareAnimation, bool stencilShadows)
961 	{
962 		const MeshPtr& msh = getMesh();
963 		bool swAnim = !hardwareAnimation || stencilShadows || (mSoftwareAnimationRequests>0);
964 
965 		// make sure we have enough hardware animation elements to play with
966 		if (hardwareAnimation)
967 		{
968 			if (mHardwareVertexAnimVertexData
969 				&& msh->getSharedVertexDataAnimationType() != VAT_NONE)
970 			{
971 				ushort supportedCount =
972 				  initHardwareAnimationElements(mHardwareVertexAnimVertexData,
973 					(msh->getSharedVertexDataAnimationType() == VAT_POSE)
974 					? mHardwarePoseCount : 1,
975 					msh->getSharedVertexDataAnimationIncludesNormals());
976 
977 				if (msh->getSharedVertexDataAnimationType() == VAT_POSE &&
978 					supportedCount < mHardwarePoseCount)
979 				{
980 					LogManager::getSingleton().stream() <<
981 					  "Vertex program assigned to Entity '" << mName <<
982 					  "' claimed to support " << mHardwarePoseCount <<
983 					  " morph/pose vertex sets, but in fact only " << supportedCount <<
984 					  " were able to be supported in the shared mesh data.";
985 					mHardwarePoseCount = supportedCount;
986 				}
987 
988 			}
989 			for (SubEntityList::iterator si = mSubEntityList.begin();
990 				si != mSubEntityList.end(); ++si)
991 			{
992 				SubEntity* sub = *si;
993 				if (sub->getSubMesh()->getVertexAnimationType() != VAT_NONE &&
994 					!sub->getSubMesh()->useSharedVertices)
995 				{
996 					ushort supportedCount = initHardwareAnimationElements(
997 						sub->_getHardwareVertexAnimVertexData(),
998 						(sub->getSubMesh()->getVertexAnimationType() == VAT_POSE)
999 						? sub->mHardwarePoseCount : 1,
1000 						sub->getSubMesh()->getVertexAnimationIncludesNormals());
1001 
1002 					if (sub->getSubMesh()->getVertexAnimationType() == VAT_POSE &&
1003 						supportedCount < sub->mHardwarePoseCount)
1004 					{
1005 						LogManager::getSingleton().stream() <<
1006 						"Vertex program assigned to SubEntity of '" << mName <<
1007 						"' claimed to support " << sub->mHardwarePoseCount <<
1008 						" morph/pose vertex sets, but in fact only " << supportedCount <<
1009 						" were able to be supported in the mesh data.";
1010 						sub->mHardwarePoseCount = supportedCount;
1011 					}
1012 
1013 				}
1014 			}
1015 
1016 		}
1017 		else
1018 		{
1019 			// May be blending multiple poses in software
1020 			// Suppress hardware upload of buffers
1021 			// Note, we query position buffer here but it may also include normals
1022 			if (mSoftwareVertexAnimVertexData &&
1023 				mMesh->getSharedVertexDataAnimationType() == VAT_POSE)
1024 			{
1025 				const VertexElement* elem = mSoftwareVertexAnimVertexData
1026 					->vertexDeclaration->findElementBySemantic(VES_POSITION);
1027 				HardwareVertexBufferSharedPtr buf = mSoftwareVertexAnimVertexData
1028 					->vertexBufferBinding->getBuffer(elem->getSource());
1029 				buf->suppressHardwareUpdate(true);
1030 
1031 				initialisePoseVertexData(mMesh->sharedVertexData, mSoftwareVertexAnimVertexData,
1032 					mMesh->getSharedVertexDataAnimationIncludesNormals());
1033 			}
1034 			for (SubEntityList::iterator si = mSubEntityList.begin();
1035 				si != mSubEntityList.end(); ++si)
1036 			{
1037 				SubEntity* sub = *si;
1038 				if (!sub->getSubMesh()->useSharedVertices &&
1039 					sub->getSubMesh()->getVertexAnimationType() == VAT_POSE)
1040 				{
1041 					VertexData* data = sub->_getSoftwareVertexAnimVertexData();
1042 					const VertexElement* elem = data->vertexDeclaration
1043 						->findElementBySemantic(VES_POSITION);
1044 					HardwareVertexBufferSharedPtr buf = data
1045 						->vertexBufferBinding->getBuffer(elem->getSource());
1046 					buf->suppressHardwareUpdate(true);
1047 					// if we're animating normals, we need to start with zeros
1048 					initialisePoseVertexData(sub->getSubMesh()->vertexData, data,
1049 						sub->getSubMesh()->getVertexAnimationIncludesNormals());
1050 				}
1051 			}
1052 		}
1053 
1054 
1055 		// Now apply the animation(s)
1056 		// Note - you should only apply one morph animation to each set of vertex data
1057 		// at once; if you do more, only the last one will actually apply
1058 		markBuffersUnusedForAnimation();
1059 		ConstEnabledAnimationStateIterator animIt = mAnimationState->getEnabledAnimationStateIterator();
1060 		while(animIt.hasMoreElements())
1061 		{
1062             const AnimationState* state = animIt.getNext();
1063             Animation* anim = msh->_getAnimationImpl(state->getAnimationName());
1064             if (anim)
1065             {
1066                 anim->apply(this, state->getTimePosition(), state->getWeight(),
1067                     swAnim, hardwareAnimation);
1068             }
1069 		}
1070 		// Deal with cases where no animation applied
1071 		restoreBuffersForUnusedAnimation(hardwareAnimation);
1072 
1073 		// Unsuppress hardware upload if we suppressed it
1074 		if (!hardwareAnimation)
1075 		{
1076 			if (mSoftwareVertexAnimVertexData &&
1077 				msh->getSharedVertexDataAnimationType() == VAT_POSE)
1078 			{
1079 				// if we're animating normals, if pose influence < 1 need to use the base mesh
1080 				if (mMesh->getSharedVertexDataAnimationIncludesNormals())
1081 					finalisePoseNormals(mMesh->sharedVertexData, mSoftwareVertexAnimVertexData);
1082 
1083 				const VertexElement* elem = mSoftwareVertexAnimVertexData
1084 					->vertexDeclaration->findElementBySemantic(VES_POSITION);
1085 				HardwareVertexBufferSharedPtr buf = mSoftwareVertexAnimVertexData
1086 					->vertexBufferBinding->getBuffer(elem->getSource());
1087 				buf->suppressHardwareUpdate(false);
1088 			}
1089 			for (SubEntityList::iterator si = mSubEntityList.begin();
1090 				si != mSubEntityList.end(); ++si)
1091 			{
1092 				SubEntity* sub = *si;
1093 				if (!sub->getSubMesh()->useSharedVertices &&
1094 					sub->getSubMesh()->getVertexAnimationType() == VAT_POSE)
1095 				{
1096 					VertexData* data = sub->_getSoftwareVertexAnimVertexData();
1097 					// if we're animating normals, if pose influence < 1 need to use the base mesh
1098 					if (sub->getSubMesh()->getVertexAnimationIncludesNormals())
1099 						finalisePoseNormals(sub->getSubMesh()->vertexData, data);
1100 
1101 					const VertexElement* elem = data->vertexDeclaration
1102 						->findElementBySemantic(VES_POSITION);
1103 					HardwareVertexBufferSharedPtr buf = data
1104 						->vertexBufferBinding->getBuffer(elem->getSource());
1105 					buf->suppressHardwareUpdate(false);
1106 				}
1107 			}
1108 		}
1109 
1110 	}
1111 	//-----------------------------------------------------------------------------
markBuffersUnusedForAnimation(void)1112 	void Entity::markBuffersUnusedForAnimation(void)
1113 	{
1114 		mVertexAnimationAppliedThisFrame = false;
1115 		for (SubEntityList::iterator i = mSubEntityList.begin();
1116 			i != mSubEntityList.end(); ++i)
1117 		{
1118 			(*i)->_markBuffersUnusedForAnimation();
1119 		}
1120 	}
1121 	//-----------------------------------------------------------------------------
_markBuffersUsedForAnimation(void)1122 	void Entity::_markBuffersUsedForAnimation(void)
1123 	{
1124 		mVertexAnimationAppliedThisFrame = true;
1125 		// no cascade
1126 	}
1127 	//-----------------------------------------------------------------------------
restoreBuffersForUnusedAnimation(bool hardwareAnimation)1128 	void Entity::restoreBuffersForUnusedAnimation(bool hardwareAnimation)
1129 	{
1130 		// Rebind original positions if:
1131 		//  We didn't apply any animation and
1132 		//    We're morph animated (hardware binds keyframe, software is missing)
1133 		//    or we're pose animated and software (hardware is fine, still bound)
1134 		if (mMesh->sharedVertexData &&
1135 			!mVertexAnimationAppliedThisFrame &&
1136 			(!hardwareAnimation || mMesh->getSharedVertexDataAnimationType() == VAT_MORPH))
1137 		{
1138 			// Note, VES_POSITION is specified here but if normals are included in animation
1139 			// then these will be re-bound too (buffers must be shared)
1140 			const VertexElement* srcPosElem =
1141 				mMesh->sharedVertexData->vertexDeclaration->findElementBySemantic(VES_POSITION);
1142 			HardwareVertexBufferSharedPtr srcBuf =
1143 				mMesh->sharedVertexData->vertexBufferBinding->getBuffer(
1144 					srcPosElem->getSource());
1145 
1146 			// Bind to software
1147 			const VertexElement* destPosElem =
1148 				mSoftwareVertexAnimVertexData->vertexDeclaration->findElementBySemantic(VES_POSITION);
1149 			mSoftwareVertexAnimVertexData->vertexBufferBinding->setBinding(
1150 				destPosElem->getSource(), srcBuf);
1151 
1152 		}
1153 
1154 		// rebind any missing hardware pose buffers
1155 		// Caused by not having any animations enabled, or keyframes which reference
1156 		// no poses
1157 		if (mMesh->sharedVertexData && hardwareAnimation
1158 			&& mMesh->getSharedVertexDataAnimationType() == VAT_POSE)
1159 		{
1160 			bindMissingHardwarePoseBuffers(mMesh->sharedVertexData, mHardwareVertexAnimVertexData);
1161 		}
1162 
1163 
1164 		for (SubEntityList::iterator i = mSubEntityList.begin();
1165 			i != mSubEntityList.end(); ++i)
1166 		{
1167 			(*i)->_restoreBuffersForUnusedAnimation(hardwareAnimation);
1168 		}
1169 
1170 	}
1171 	//---------------------------------------------------------------------
bindMissingHardwarePoseBuffers(const VertexData * srcData,VertexData * destData)1172 	void Entity::bindMissingHardwarePoseBuffers(const VertexData* srcData,
1173 		VertexData* destData)
1174 	{
1175 		// For hardware pose animation, also make sure we've bound buffers to all the elements
1176 		// required - if there are missing bindings for elements in use,
1177 		// some rendersystems can complain because elements refer
1178 		// to an unbound source.
1179 		// Get the original position source, we'll use this to fill gaps
1180 		const VertexElement* srcPosElem =
1181 			srcData->vertexDeclaration->findElementBySemantic(VES_POSITION);
1182 		HardwareVertexBufferSharedPtr srcBuf =
1183 			srcData->vertexBufferBinding->getBuffer(
1184 				srcPosElem->getSource());
1185 
1186 		for (VertexData::HardwareAnimationDataList::const_iterator i = destData->hwAnimationDataList.begin();
1187 			i != destData->hwAnimationDataList.end(); ++i)
1188 		{
1189 			const VertexData::HardwareAnimationData& animData = *i;
1190 			if (!destData->vertexBufferBinding->isBufferBound(
1191 				animData.targetBufferIndex))
1192 			{
1193 				// Bind to a safe default
1194 				destData->vertexBufferBinding->setBinding(
1195 					animData.targetBufferIndex, srcBuf);
1196 			}
1197 		}
1198 
1199 	}
1200 	//-----------------------------------------------------------------------
initialisePoseVertexData(const VertexData * srcData,VertexData * destData,bool animateNormals)1201 	void Entity::initialisePoseVertexData(const VertexData* srcData,
1202 		VertexData* destData, bool animateNormals)
1203 	{
1204 
1205 		// First time through for a piece of pose animated vertex data
1206 		// We need to copy the original position values to the temp accumulator
1207 		const VertexElement* origelem =
1208 			srcData->vertexDeclaration->findElementBySemantic(VES_POSITION);
1209 		const VertexElement* destelem =
1210 			destData->vertexDeclaration->findElementBySemantic(VES_POSITION);
1211 		HardwareVertexBufferSharedPtr origBuffer =
1212 			srcData->vertexBufferBinding->getBuffer(origelem->getSource());
1213 		HardwareVertexBufferSharedPtr destBuffer =
1214 			destData->vertexBufferBinding->getBuffer(destelem->getSource());
1215 		destBuffer->copyData(*origBuffer.get(), 0, 0, destBuffer->getSizeInBytes(), true);
1216 
1217 		// If normals are included in animation, we want to reset the normals to zero
1218 		if (animateNormals)
1219 		{
1220 			const VertexElement* normElem =
1221 				destData->vertexDeclaration->findElementBySemantic(VES_NORMAL);
1222 
1223 			if (normElem)
1224 			{
1225 				HardwareVertexBufferSharedPtr buf =
1226 					destData->vertexBufferBinding->getBuffer(normElem->getSource());
1227 				char* pBase = static_cast<char*>(buf->lock(HardwareBuffer::HBL_NORMAL));
1228 				pBase += destData->vertexStart * buf->getVertexSize();
1229 
1230 				for (size_t v = 0; v < destData->vertexCount; ++v)
1231 				{
1232 					float* pNorm;
1233 					normElem->baseVertexPointerToElement(pBase, &pNorm);
1234 					*pNorm++ = 0.0f;
1235 					*pNorm++ = 0.0f;
1236 					*pNorm++ = 0.0f;
1237 
1238 					pBase += buf->getVertexSize();
1239 				}
1240 				buf->unlock();
1241 			}
1242 		}
1243 	}
1244 	//-----------------------------------------------------------------------
finalisePoseNormals(const VertexData * srcData,VertexData * destData)1245 	void Entity::finalisePoseNormals(const VertexData* srcData, VertexData* destData)
1246 	{
1247 		const VertexElement* destNormElem =
1248 			destData->vertexDeclaration->findElementBySemantic(VES_NORMAL);
1249 		const VertexElement* srcNormElem =
1250 			srcData->vertexDeclaration->findElementBySemantic(VES_NORMAL);
1251 
1252 		if (destNormElem && srcNormElem)
1253 		{
1254 			HardwareVertexBufferSharedPtr srcbuf =
1255 				srcData->vertexBufferBinding->getBuffer(srcNormElem->getSource());
1256 			HardwareVertexBufferSharedPtr dstbuf =
1257 				destData->vertexBufferBinding->getBuffer(destNormElem->getSource());
1258 			char* pSrcBase = static_cast<char*>(srcbuf->lock(HardwareBuffer::HBL_READ_ONLY));
1259 			char* pDstBase = static_cast<char*>(dstbuf->lock(HardwareBuffer::HBL_NORMAL));
1260 			pSrcBase += srcData->vertexStart * srcbuf->getVertexSize();
1261 			pDstBase += destData->vertexStart * dstbuf->getVertexSize();
1262 
1263 			// The goal here is to detect the length of the vertices, and to apply
1264 			// the base mesh vertex normal at one minus that length; this deals with
1265 			// any individual vertices which were either not affected by any pose, or
1266 			// were not affected to a complete extent
1267 			// We also normalise every normal to deal with over-weighting
1268 			for (size_t v = 0; v < destData->vertexCount; ++v)
1269 			{
1270 				float* pDstNorm;
1271 				destNormElem->baseVertexPointerToElement(pDstBase, &pDstNorm);
1272 				Vector3 norm(pDstNorm[0], pDstNorm[1], pDstNorm[2]);
1273 				Real len = norm.length();
1274 				if (len + 1e-4f < 1.0f)
1275 				{
1276 					// Poses did not completely fill in this normal
1277 					// Apply base mesh
1278 					float baseWeight = 1.0f - (float)len;
1279 					float* pSrcNorm;
1280 					srcNormElem->baseVertexPointerToElement(pSrcBase, &pSrcNorm);
1281 					norm.x += *pSrcNorm++ * baseWeight;
1282 					norm.y += *pSrcNorm++ * baseWeight;
1283 					norm.z += *pSrcNorm++ * baseWeight;
1284 				}
1285 				norm.normalise();
1286 
1287 				*pDstNorm++ = (float)norm.x;
1288 				*pDstNorm++ = (float)norm.y;
1289 				*pDstNorm++ = (float)norm.z;
1290 
1291 				pDstBase += dstbuf->getVertexSize();
1292 				pSrcBase += dstbuf->getVertexSize();
1293 			}
1294 			srcbuf->unlock();
1295 			dstbuf->unlock();
1296 		}
1297 	}
1298 	//-----------------------------------------------------------------------
_updateAnimation(void)1299 	void Entity::_updateAnimation(void)
1300 	{
1301 		// Externally visible method
1302 		if (hasSkeleton() || hasVertexAnimation())
1303 		{
1304 			updateAnimation();
1305 		}
1306 	}
1307 	//-----------------------------------------------------------------------
_isAnimated(void) const1308     bool Entity::_isAnimated(void) const
1309     {
1310         return (mAnimationState && mAnimationState->hasEnabledAnimationState()) ||
1311                (getSkeleton() && getSkeleton()->hasManualBones());
1312     }
1313 	//-----------------------------------------------------------------------
_isSkeletonAnimated(void) const1314     bool Entity::_isSkeletonAnimated(void) const
1315     {
1316         return getSkeleton() &&
1317             (mAnimationState->hasEnabledAnimationState() || getSkeleton()->hasManualBones());
1318     }
1319 	//-----------------------------------------------------------------------
_getSkelAnimVertexData(void) const1320 	VertexData* Entity::_getSkelAnimVertexData(void) const
1321 	{
1322 		assert (mSkelAnimVertexData && "Not software skinned or has no shared vertex data!");
1323         return mSkelAnimVertexData;
1324 	}
1325 	//-----------------------------------------------------------------------
_getSoftwareVertexAnimVertexData(void) const1326 	VertexData* Entity::_getSoftwareVertexAnimVertexData(void) const
1327 	{
1328 		assert (mSoftwareVertexAnimVertexData && "Not vertex animated or has no shared vertex data!");
1329 		return mSoftwareVertexAnimVertexData;
1330 	}
1331 	//-----------------------------------------------------------------------
_getHardwareVertexAnimVertexData(void) const1332 	VertexData* Entity::_getHardwareVertexAnimVertexData(void) const
1333 	{
1334 		assert (mHardwareVertexAnimVertexData && "Not vertex animated or has no shared vertex data!");
1335 		return mHardwareVertexAnimVertexData;
1336 	}
1337 	//-----------------------------------------------------------------------
_getSkelAnimTempBufferInfo(void)1338 	TempBlendedBufferInfo* Entity::_getSkelAnimTempBufferInfo(void)
1339 	{
1340 		return &mTempSkelAnimInfo;
1341 	}
1342 	//-----------------------------------------------------------------------
_getVertexAnimTempBufferInfo(void)1343 	TempBlendedBufferInfo* Entity::_getVertexAnimTempBufferInfo(void)
1344 	{
1345 		return &mTempVertexAnimInfo;
1346 	}
1347     //-----------------------------------------------------------------------
cacheBoneMatrices(void)1348     bool Entity::cacheBoneMatrices(void)
1349     {
1350         Root& root = Root::getSingleton();
1351         unsigned long currentFrameNumber = root.getNextFrameNumber();
1352         if ((*mFrameBonesLastUpdated != currentFrameNumber) ||
1353 			(hasSkeleton() && getSkeleton()->getManualBonesDirty()))
1354 		{
1355 			if ((!mSkipAnimStateUpdates) && (*mFrameBonesLastUpdated != currentFrameNumber))
1356 	            mSkeletonInstance->setAnimationState(*mAnimationState);
1357             mSkeletonInstance->_getBoneMatrices(mBoneMatrices);
1358             *mFrameBonesLastUpdated  = currentFrameNumber;
1359 
1360 			return true;
1361         }
1362 		return false;
1363     }
1364     //-----------------------------------------------------------------------
setDisplaySkeleton(bool display)1365     void Entity::setDisplaySkeleton(bool display)
1366     {
1367         mDisplaySkeleton = display;
1368     }
1369     //-----------------------------------------------------------------------
getDisplaySkeleton(void) const1370     bool Entity::getDisplaySkeleton(void) const
1371     {
1372         return mDisplaySkeleton;
1373     }
1374     //-----------------------------------------------------------------------
getManualLodLevel(size_t index) const1375     Entity* Entity::getManualLodLevel(size_t index) const
1376     {
1377         assert(index < mLodEntityList.size());
1378 
1379         return mLodEntityList[index];
1380     }
1381     //-----------------------------------------------------------------------
getNumManualLodLevels(void) const1382     size_t Entity::getNumManualLodLevels(void) const
1383     {
1384         return mLodEntityList.size();
1385     }
1386     //-----------------------------------------------------------------------
setMeshLodBias(Real factor,ushort maxDetailIndex,ushort minDetailIndex)1387     void Entity::setMeshLodBias(Real factor, ushort maxDetailIndex, ushort minDetailIndex)
1388     {
1389         mMeshLodFactorTransformed = mMesh->getLodStrategy()->transformBias(factor);
1390         mMaxMeshLodIndex = maxDetailIndex;
1391         mMinMeshLodIndex = minDetailIndex;
1392 
1393     }
1394     //-----------------------------------------------------------------------
setMaterialLodBias(Real factor,ushort maxDetailIndex,ushort minDetailIndex)1395     void Entity::setMaterialLodBias(Real factor, ushort maxDetailIndex, ushort minDetailIndex)
1396     {
1397         mMaterialLodFactor = factor;
1398         mMaterialLodFactorTransformed = mMesh->getLodStrategy()->transformBias(factor);
1399         mMaxMaterialLodIndex = maxDetailIndex;
1400         mMinMaterialLodIndex = minDetailIndex;
1401 
1402     }
1403     //-----------------------------------------------------------------------
buildSubEntityList(MeshPtr & mesh,SubEntityList * sublist)1404     void Entity::buildSubEntityList(MeshPtr& mesh, SubEntityList* sublist)
1405     {
1406         // Create SubEntities
1407         unsigned short i, numSubMeshes;
1408 
1409         numSubMeshes = mesh->getNumSubMeshes();
1410         for (i = 0; i < numSubMeshes; ++i)
1411         {
1412             SubMesh* subMesh = mesh->getSubMesh(i);
1413             SubEntity* subEnt = OGRE_NEW SubEntity(this, subMesh);
1414             if (subMesh->isMatInitialised())
1415                 subEnt->setMaterialName(subMesh->getMaterialName(), mesh->getGroup());
1416             sublist->push_back(subEnt);
1417         }
1418     }
1419     //-----------------------------------------------------------------------
setPolygonModeOverrideable(bool overrideable)1420     void Entity::setPolygonModeOverrideable(bool overrideable)
1421     {
1422         SubEntityList::iterator i, iend;
1423         iend = mSubEntityList.end();
1424 
1425         for( i = mSubEntityList.begin(); i != iend; ++i )
1426         {
1427             (*i)->setPolygonModeOverrideable(overrideable);
1428         }
1429     }
1430 
1431     //-----------------------------------------------------------------------
attachObjectToBone(const String & boneName,MovableObject * pMovable,const Quaternion & offsetOrientation,const Vector3 & offsetPosition)1432     TagPoint* Entity::attachObjectToBone(const String &boneName, MovableObject *pMovable, const Quaternion &offsetOrientation, const Vector3 &offsetPosition)
1433     {
1434         if (mChildObjectList.find(pMovable->getName()) != mChildObjectList.end())
1435         {
1436             OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM,
1437                 "An object with the name " + pMovable->getName() + " already attached",
1438                 "Entity::attachObjectToBone");
1439         }
1440         if(pMovable->isAttached())
1441         {
1442             OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Object already attached to a sceneNode or a Bone",
1443                 "Entity::attachObjectToBone");
1444         }
1445         if (!hasSkeleton())
1446         {
1447             OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "This entity's mesh has no skeleton to attach object to.",
1448                 "Entity::attachObjectToBone");
1449         }
1450         Bone* bone = mSkeletonInstance->getBone(boneName);
1451         if (!bone)
1452         {
1453             OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Cannot locate bone named " + boneName,
1454                 "Entity::attachObjectToBone");
1455         }
1456 
1457         TagPoint *tp = mSkeletonInstance->createTagPointOnBone(
1458             bone, offsetOrientation, offsetPosition);
1459         tp->setParentEntity(this);
1460         tp->setChildObject(pMovable);
1461 
1462         attachObjectImpl(pMovable, tp);
1463 
1464         // Trigger update of bounding box if necessary
1465         if (mParentNode)
1466             mParentNode->needUpdate();
1467 
1468 		return tp;
1469     }
1470 
1471     //-----------------------------------------------------------------------
attachObjectImpl(MovableObject * pObject,TagPoint * pAttachingPoint)1472     void Entity::attachObjectImpl(MovableObject *pObject, TagPoint *pAttachingPoint)
1473     {
1474         assert(mChildObjectList.find(pObject->getName()) == mChildObjectList.end());
1475         mChildObjectList[pObject->getName()] = pObject;
1476         pObject->_notifyAttached(pAttachingPoint, true);
1477     }
1478 
1479     //-----------------------------------------------------------------------
detachObjectFromBone(const String & name)1480     MovableObject* Entity::detachObjectFromBone(const String &name)
1481     {
1482         ChildObjectList::iterator i = mChildObjectList.find(name);
1483 
1484         if (i == mChildObjectList.end())
1485         {
1486             OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "No child object entry found named " + name,
1487                 "Entity::detachObjectFromBone");
1488         }
1489         MovableObject *obj = i->second;
1490         detachObjectImpl(obj);
1491         mChildObjectList.erase(i);
1492 
1493         // Trigger update of bounding box if necessary
1494         if (mParentNode)
1495             mParentNode->needUpdate();
1496 
1497         return obj;
1498     }
1499     //-----------------------------------------------------------------------
detachObjectFromBone(MovableObject * obj)1500     void Entity::detachObjectFromBone(MovableObject* obj)
1501     {
1502         ChildObjectList::iterator i, iend;
1503         iend = mChildObjectList.end();
1504         for (i = mChildObjectList.begin(); i != iend; ++i)
1505         {
1506             if (i->second == obj)
1507             {
1508                 detachObjectImpl(obj);
1509                 mChildObjectList.erase(i);
1510 
1511                 // Trigger update of bounding box if necessary
1512                 if (mParentNode)
1513                     mParentNode->needUpdate();
1514                 break;
1515             }
1516         }
1517     }
1518     //-----------------------------------------------------------------------
detachAllObjectsFromBone(void)1519     void Entity::detachAllObjectsFromBone(void)
1520     {
1521         detachAllObjectsImpl();
1522 
1523         // Trigger update of bounding box if necessary
1524         if (mParentNode)
1525             mParentNode->needUpdate();
1526     }
1527     //-----------------------------------------------------------------------
detachObjectImpl(MovableObject * pObject)1528     void Entity::detachObjectImpl(MovableObject* pObject)
1529     {
1530         TagPoint* tp = static_cast<TagPoint*>(pObject->getParentNode());
1531 
1532         // free the TagPoint so we can reuse it later
1533         mSkeletonInstance->freeTagPoint(tp);
1534 
1535         pObject->_notifyAttached((TagPoint*)0);
1536     }
1537     //-----------------------------------------------------------------------
detachAllObjectsImpl(void)1538     void Entity::detachAllObjectsImpl(void)
1539     {
1540         ChildObjectList::const_iterator i, iend;
1541         iend = mChildObjectList.end();
1542         for (i = mChildObjectList.begin(); i != iend; ++i)
1543         {
1544             detachObjectImpl(i->second);
1545         }
1546         mChildObjectList.clear();
1547     }
1548 
1549     //-----------------------------------------------------------------------
getAttachedObjectIterator()1550     Entity::ChildObjectListIterator Entity::getAttachedObjectIterator()
1551     {
1552         return ChildObjectListIterator(mChildObjectList.begin(), mChildObjectList.end());
1553     }
1554     //-----------------------------------------------------------------------
getBoundingRadius(void) const1555     Real Entity::getBoundingRadius(void) const
1556     {
1557         return mMesh->getBoundingSphereRadius();
1558     }
1559     //-----------------------------------------------------------------------
prepareTempBlendBuffers(void)1560     void Entity::prepareTempBlendBuffers(void)
1561     {
1562         if (mSkelAnimVertexData)
1563         {
1564             OGRE_DELETE mSkelAnimVertexData;
1565             mSkelAnimVertexData = 0;
1566         }
1567 		if (mSoftwareVertexAnimVertexData)
1568 		{
1569 			OGRE_DELETE mSoftwareVertexAnimVertexData;
1570 			mSoftwareVertexAnimVertexData = 0;
1571 		}
1572 		if (mHardwareVertexAnimVertexData)
1573 		{
1574 			OGRE_DELETE mHardwareVertexAnimVertexData;
1575 			mHardwareVertexAnimVertexData = 0;
1576 		}
1577 
1578 		if (hasVertexAnimation())
1579 		{
1580 			// Shared data
1581 			if (mMesh->sharedVertexData
1582 				&& mMesh->getSharedVertexDataAnimationType() != VAT_NONE)
1583 			{
1584 				// Create temporary vertex blend info
1585 				// Prepare temp vertex data if needed
1586 				// Clone without copying data, don't remove any blending info
1587 				// (since if we skeletally animate too, we need it)
1588 				mSoftwareVertexAnimVertexData = mMesh->sharedVertexData->clone(false);
1589 				extractTempBufferInfo(mSoftwareVertexAnimVertexData, &mTempVertexAnimInfo);
1590 
1591 				// Also clone for hardware usage, don't remove blend info since we'll
1592 				// need it if we also hardware skeletally animate
1593 				mHardwareVertexAnimVertexData = mMesh->sharedVertexData->clone(false);
1594 			}
1595 		}
1596 
1597         if (hasSkeleton())
1598         {
1599             // Shared data
1600             if (mMesh->sharedVertexData)
1601             {
1602                 // Create temporary vertex blend info
1603                 // Prepare temp vertex data if needed
1604                 // Clone without copying data, remove blending info
1605                 // (since blend is performed in software)
1606                 mSkelAnimVertexData =
1607                     cloneVertexDataRemoveBlendInfo(mMesh->sharedVertexData);
1608                 extractTempBufferInfo(mSkelAnimVertexData, &mTempSkelAnimInfo);
1609             }
1610 
1611         }
1612 
1613 		// Do SubEntities
1614 		SubEntityList::iterator i, iend;
1615 		iend = mSubEntityList.end();
1616 		for (i = mSubEntityList.begin(); i != iend; ++i)
1617 		{
1618 			SubEntity* s = *i;
1619 			s->prepareTempBlendBuffers();
1620 		}
1621 
1622         // It's prepared for shadow volumes only if mesh has been prepared for shadow volumes.
1623         mPreparedForShadowVolumes = mMesh->isPreparedForShadowVolumes();
1624     }
1625     //-----------------------------------------------------------------------
extractTempBufferInfo(VertexData * sourceData,TempBlendedBufferInfo * info)1626     void Entity::extractTempBufferInfo(VertexData* sourceData, TempBlendedBufferInfo* info)
1627     {
1628         info->extractFrom(sourceData);
1629     }
1630     //-----------------------------------------------------------------------
cloneVertexDataRemoveBlendInfo(const VertexData * source)1631     VertexData* Entity::cloneVertexDataRemoveBlendInfo(const VertexData* source)
1632     {
1633         // Clone without copying data
1634         VertexData* ret = source->clone(false);
1635 		bool removeIndices = Ogre::Root::getSingleton().isBlendIndicesGpuRedundant();
1636 		bool removeWeights = Ogre::Root::getSingleton().isBlendWeightsGpuRedundant();
1637 
1638 		unsigned short safeSource = 0xFFFF;
1639 		const VertexElement* blendIndexElem =
1640 			source->vertexDeclaration->findElementBySemantic(VES_BLEND_INDICES);
1641 		if (blendIndexElem)
1642 		{
1643 			//save the source in order to prevent the next stage from unbinding it.
1644 			safeSource = blendIndexElem->getSource();
1645 			if (removeIndices)
1646 			{
1647 				// Remove buffer reference
1648 				ret->vertexBufferBinding->unsetBinding(blendIndexElem->getSource());
1649 			}
1650 		}
1651 		if (removeWeights)
1652 		{
1653 			// Remove blend weights
1654 			const VertexElement* blendWeightElem =
1655 				source->vertexDeclaration->findElementBySemantic(VES_BLEND_WEIGHTS);
1656 			if (blendWeightElem &&
1657 				blendWeightElem->getSource() != safeSource)
1658 			{
1659 				// Remove buffer reference
1660 				ret->vertexBufferBinding->unsetBinding(blendWeightElem->getSource());
1661 			}
1662 		}
1663 
1664         // remove elements from declaration
1665         if (removeIndices)
1666 			ret->vertexDeclaration->removeElement(VES_BLEND_INDICES);
1667 		if (removeWeights)
1668 			ret->vertexDeclaration->removeElement(VES_BLEND_WEIGHTS);
1669 
1670         // Close gaps in bindings for effective and safely
1671 		if (removeWeights || removeIndices)
1672 			ret->closeGapsInBindings();
1673 
1674         return ret;
1675     }
1676     //-----------------------------------------------------------------------
getEdgeList(void)1677     EdgeData* Entity::getEdgeList(void)
1678     {
1679         // Get from Mesh
1680         return mMesh->getEdgeList(mMeshLodIndex);
1681     }
1682 	//-----------------------------------------------------------------------
hasEdgeList(void)1683     bool Entity::hasEdgeList(void)
1684     {
1685         // check if mesh has an edge list attached
1686         // give mesh a chance to built it if scheduled
1687         return (mMesh->getEdgeList(mMeshLodIndex) != NULL);
1688     }
1689     //-----------------------------------------------------------------------
isHardwareAnimationEnabled(void)1690 	bool Entity::isHardwareAnimationEnabled(void)
1691 	{
1692 		//find whether the entity has hardware animation for the current active sceme
1693 		unsigned short schemeIndex = MaterialManager::getSingleton()._getActiveSchemeIndex();
1694 		SchemeHardwareAnimMap::iterator it = mSchemeHardwareAnim.find(schemeIndex);
1695 		if (it == mSchemeHardwareAnim.end())
1696 		{
1697 			//evaluate the animation hardware value
1698 			it = mSchemeHardwareAnim.insert(
1699 				SchemeHardwareAnimMap::value_type(schemeIndex,
1700 					calcVertexProcessing())).first;
1701 		}
1702 		return it->second;
1703 	}
1704 
1705 	//-----------------------------------------------------------------------
reevaluateVertexProcessing(void)1706     void Entity::reevaluateVertexProcessing(void)
1707     {
1708 		//clear the cache so that the values will be reevaluated
1709 		mSchemeHardwareAnim.clear();
1710 	}
1711 	//-----------------------------------------------------------------------
calcVertexProcessing(void)1712     bool Entity::calcVertexProcessing(void)
1713 	{
1714         // init
1715 		bool hasHardwareAnimation = false;
1716         bool firstPass = true;
1717 
1718         SubEntityList::iterator i, iend;
1719         iend = mSubEntityList.end();
1720         for (i = mSubEntityList.begin(); i != iend; ++i)
1721         {
1722 			SubEntity* sub = *i;
1723             const MaterialPtr& m = sub->getMaterial();
1724             // Make sure it's loaded
1725             m->load();
1726             Technique* t = m->getBestTechnique(0, sub);
1727 			if (!t)
1728 			{
1729 				// No supported techniques
1730 				continue;
1731 			}
1732 			if (t->getNumPasses() == 0)
1733 			{
1734 				// No passes, invalid
1735 				continue;
1736 			}
1737             Pass* p = t->getPass(0);
1738             if (p->hasVertexProgram())
1739             {
1740                 if (mVertexProgramInUse == false)
1741 				{
1742 					// If one material uses a vertex program, set this flag
1743 					// Causes some special processing like forcing a separate light cap
1744 					mVertexProgramInUse = true;
1745 
1746 					// If shadow renderables already created create their light caps
1747 					ShadowRenderableList::iterator si = mShadowRenderables.begin();
1748 					ShadowRenderableList::iterator siend = mShadowRenderables.end();
1749 					for (si = mShadowRenderables.begin(); si != siend; ++si)
1750 					{
1751 						static_cast<EntityShadowRenderable*>(*si)->_createSeparateLightCap();
1752 					}
1753 				}
1754 
1755 				if (hasSkeleton())
1756 				{
1757 					// All materials must support skinning for us to consider using
1758 					// hardware animation - if one fails we use software
1759 					if (firstPass)
1760 					{
1761 						hasHardwareAnimation = p->getVertexProgram()->isSkeletalAnimationIncluded();
1762 						firstPass = false;
1763 					}
1764 					else
1765 					{
1766 						hasHardwareAnimation = hasHardwareAnimation &&
1767 							p->getVertexProgram()->isSkeletalAnimationIncluded();
1768 					}
1769 				}
1770 
1771 				VertexAnimationType animType = VAT_NONE;
1772 				if (sub->getSubMesh()->useSharedVertices)
1773 				{
1774 					animType = mMesh->getSharedVertexDataAnimationType();
1775 				}
1776 				else
1777 				{
1778 					animType = sub->getSubMesh()->getVertexAnimationType();
1779 				}
1780 				if (animType == VAT_MORPH)
1781 				{
1782 					// All materials must support morph animation for us to consider using
1783 					// hardware animation - if one fails we use software
1784 					if (firstPass)
1785 					{
1786 						hasHardwareAnimation = p->getVertexProgram()->isMorphAnimationIncluded();
1787 						firstPass = false;
1788 					}
1789 					else
1790 					{
1791 						hasHardwareAnimation = hasHardwareAnimation &&
1792 							p->getVertexProgram()->isMorphAnimationIncluded();
1793 					}
1794 				}
1795 				else if (animType == VAT_POSE)
1796 				{
1797 					// All materials must support pose animation for us to consider using
1798 					// hardware animation - if one fails we use software
1799 					if (firstPass)
1800 					{
1801 						hasHardwareAnimation = p->getVertexProgram()->isPoseAnimationIncluded();
1802 						if (sub->getSubMesh()->useSharedVertices)
1803 							mHardwarePoseCount = p->getVertexProgram()->getNumberOfPosesIncluded();
1804 						else
1805 							sub->mHardwarePoseCount = p->getVertexProgram()->getNumberOfPosesIncluded();
1806 						firstPass = false;
1807 					}
1808 					else
1809 					{
1810 						hasHardwareAnimation = hasHardwareAnimation &&
1811 							p->getVertexProgram()->isPoseAnimationIncluded();
1812 						if (sub->getSubMesh()->useSharedVertices)
1813 							mHardwarePoseCount = std::max(mHardwarePoseCount,
1814 								p->getVertexProgram()->getNumberOfPosesIncluded());
1815 						else
1816 							sub->mHardwarePoseCount = std::max(sub->mHardwarePoseCount,
1817 								p->getVertexProgram()->getNumberOfPosesIncluded());
1818 					}
1819 				}
1820 
1821             }
1822         }
1823 
1824         // Should be force update of animation if they exists, due reevaluate
1825         // vertex processing might switchs between hardware/software animation,
1826         // and then we'll end with NULL or incorrect mBoneWorldMatrices, or
1827         // incorrect blended software animation buffers.
1828         if (mAnimationState)
1829         {
1830             mFrameAnimationLastUpdated = mAnimationState->getDirtyFrameNumber() - 1;
1831         }
1832 
1833 		return hasHardwareAnimation;
1834     }
1835     //-----------------------------------------------------------------------
_getMeshLodFactorTransformed() const1836     Real Entity::_getMeshLodFactorTransformed() const
1837     {
1838         return mMeshLodFactorTransformed;
1839     }
1840     //-----------------------------------------------------------------------
1841     ShadowCaster::ShadowRenderableListIterator
getShadowVolumeRenderableIterator(ShadowTechnique shadowTechnique,const Light * light,HardwareIndexBufferSharedPtr * indexBuffer,size_t * indexBufferUsedSize,bool extrude,Real extrusionDistance,unsigned long flags)1842         Entity::getShadowVolumeRenderableIterator(
1843         ShadowTechnique shadowTechnique, const Light* light,
1844         HardwareIndexBufferSharedPtr* indexBuffer, size_t* indexBufferUsedSize,
1845         bool extrude, Real extrusionDistance, unsigned long flags)
1846     {
1847         assert(indexBuffer && "Only external index buffers are supported right now");
1848         assert((*indexBuffer)->getType() == HardwareIndexBuffer::IT_16BIT &&
1849             "Only 16-bit indexes supported for now");
1850 
1851         // Potentially delegate to LOD entity
1852         if (mMesh->isLodManual() && mMeshLodIndex > 0)
1853         {
1854             // Use alternate entity
1855             assert( static_cast< size_t >( mMeshLodIndex - 1 ) < mLodEntityList.size() &&
1856                 "No LOD EntityList - did you build the manual LODs after creating the entity?");
1857             // delegate, we're using manual LOD and not the top LOD index
1858             if (hasSkeleton() && mLodEntityList[mMeshLodIndex - 1]->hasSkeleton())
1859             {
1860                 // Copy the animation state set to LOD entity, we assume the lod
1861                 // entity only has a subset animation states
1862                 AnimationStateSet* targetState = mLodEntityList[mMeshLodIndex - 1]->mAnimationState;
1863 				if (mAnimationState != targetState) // only copy if lods have different skeleton instances
1864 				{
1865 					if (mAnimationState->getDirtyFrameNumber() != targetState->getDirtyFrameNumber()) // only copy if animation was updated
1866 						mAnimationState->copyMatchingState(targetState);
1867 				}
1868             }
1869             return mLodEntityList[mMeshLodIndex-1]->getShadowVolumeRenderableIterator(
1870                 shadowTechnique, light, indexBuffer, indexBufferUsedSize,
1871                 extrude, extrusionDistance, flags);
1872         }
1873 
1874 
1875         // Prepare temp buffers if required
1876         if (!mPreparedForShadowVolumes)
1877         {
1878             mMesh->prepareForShadowVolume();
1879             // reset frame last updated to force update of animations if they exist
1880             if (mAnimationState)
1881                 mFrameAnimationLastUpdated = mAnimationState->getDirtyFrameNumber() - 1;
1882             // re-prepare buffers
1883             prepareTempBlendBuffers();
1884         }
1885 
1886 
1887         bool hasAnimation = (hasSkeleton() || hasVertexAnimation());
1888 
1889         // Update any animation
1890         if (hasAnimation)
1891         {
1892             updateAnimation();
1893         }
1894 
1895         // Calculate the object space light details
1896         Vector4 lightPos = light->getAs4DVector();
1897         Matrix4 world2Obj = mParentNode->_getFullTransform().inverseAffine();
1898         lightPos = world2Obj.transformAffine(lightPos);
1899         Matrix3 world2Obj3x3;
1900         world2Obj.extract3x3Matrix(world2Obj3x3);
1901         extrusionDistance *= Math::Sqrt(std::min(std::min(world2Obj3x3.GetColumn(0).squaredLength(), world2Obj3x3.GetColumn(1).squaredLength()), world2Obj3x3.GetColumn(2).squaredLength()));
1902 
1903         // We need to search the edge list for silhouette edges
1904         EdgeData* edgeList = getEdgeList();
1905 
1906 		if (!edgeList)
1907 		{
1908 			// we can't get an edge list for some reason, return blank
1909 			// really we shouldn't be able to get here, but this is a safeguard
1910 			return ShadowRenderableListIterator(mShadowRenderables.begin(), mShadowRenderables.end());
1911 		}
1912 
1913         // Init shadow renderable list if required
1914         bool init = mShadowRenderables.empty();
1915 
1916         EdgeData::EdgeGroupList::iterator egi;
1917         ShadowRenderableList::iterator si, siend;
1918         EntityShadowRenderable* esr = 0;
1919         if (init)
1920             mShadowRenderables.resize(edgeList->edgeGroups.size());
1921 
1922         bool isAnimated = hasAnimation;
1923         bool updatedSharedGeomNormals = false;
1924         siend = mShadowRenderables.end();
1925         egi = edgeList->edgeGroups.begin();
1926         for (si = mShadowRenderables.begin(); si != siend; ++si, ++egi)
1927         {
1928             const VertexData *pVertData;
1929             if (isAnimated)
1930             {
1931                 // Use temp buffers
1932                 pVertData = findBlendedVertexData(egi->vertexData);
1933             }
1934             else
1935             {
1936                 pVertData = egi->vertexData;
1937             }
1938             if (init)
1939             {
1940                 // Try to find corresponding SubEntity; this allows the
1941                 // linkage of visibility between ShadowRenderable and SubEntity
1942                 SubEntity* subent = findSubEntityForVertexData(egi->vertexData);
1943                 // Create a new renderable, create a separate light cap if
1944                 // we're using a vertex program (either for this model, or
1945                 // for extruding the shadow volume) since otherwise we can
1946                 // get depth-fighting on the light cap
1947 
1948                 *si = OGRE_NEW EntityShadowRenderable(this, indexBuffer, pVertData,
1949                     mVertexProgramInUse || !extrude, subent);
1950             }
1951             else
1952             {
1953                 // If we have animation, we have no guarantee that the position
1954                 // buffer we used last frame is the same one we used last frame
1955                 // since a temporary buffer is requested each frame
1956                 // therefore, we need to update the EntityShadowRenderable
1957                 // with the current position buffer
1958                 static_cast<EntityShadowRenderable*>(*si)->rebindPositionBuffer(pVertData, hasAnimation);
1959 
1960             }
1961             // Get shadow renderable
1962             esr = static_cast<EntityShadowRenderable*>(*si);
1963             HardwareVertexBufferSharedPtr esrPositionBuffer = esr->getPositionBuffer();
1964             // For animated entities we need to recalculate the face normals
1965             if (hasAnimation)
1966             {
1967                 if (egi->vertexData != mMesh->sharedVertexData || !updatedSharedGeomNormals)
1968                 {
1969                     // recalculate face normals
1970                     edgeList->updateFaceNormals(egi->vertexSet, esrPositionBuffer);
1971                     // If we're not extruding in software we still need to update
1972                     // the latter part of the buffer (the hardware extruded part)
1973                     // with the latest animated positions
1974                     if (!extrude)
1975                     {
1976                         // Lock, we'll be locking the (suppressed hardware update) shadow buffer
1977                         float* pSrc = static_cast<float*>(
1978                             esrPositionBuffer->lock(HardwareBuffer::HBL_NORMAL));
1979                         float* pDest = pSrc + (egi->vertexData->vertexCount * 3);
1980                         memcpy(pDest, pSrc, sizeof(float) * 3 * egi->vertexData->vertexCount);
1981                         esrPositionBuffer->unlock();
1982                     }
1983                     if (egi->vertexData == mMesh->sharedVertexData)
1984                     {
1985                         updatedSharedGeomNormals = true;
1986                     }
1987                 }
1988             }
1989             // Extrude vertices in software if required
1990             if (extrude)
1991             {
1992                 extrudeVertices(esrPositionBuffer,
1993                     egi->vertexData->vertexCount,
1994                     lightPos, extrusionDistance);
1995 
1996             }
1997             // Stop suppressing hardware update now, if we were
1998             esrPositionBuffer->suppressHardwareUpdate(false);
1999 
2000         }
2001         // Calc triangle light facing
2002         updateEdgeListLightFacing(edgeList, lightPos);
2003 
2004         // Generate indexes and update renderables
2005         generateShadowVolume(edgeList, *indexBuffer, *indexBufferUsedSize,
2006             light, mShadowRenderables, flags);
2007 
2008 
2009         return ShadowRenderableListIterator(mShadowRenderables.begin(), mShadowRenderables.end());
2010     }
2011     //-----------------------------------------------------------------------
findBlendedVertexData(const VertexData * orig)2012     const VertexData* Entity::findBlendedVertexData(const VertexData* orig)
2013     {
2014 		bool skel = hasSkeleton();
2015 
2016         if (orig == mMesh->sharedVertexData)
2017         {
2018 			return skel? mSkelAnimVertexData : mSoftwareVertexAnimVertexData;
2019         }
2020         SubEntityList::iterator i, iend;
2021         iend = mSubEntityList.end();
2022         for (i = mSubEntityList.begin(); i != iend; ++i)
2023         {
2024             SubEntity* se = *i;
2025             if (orig == se->getSubMesh()->vertexData)
2026             {
2027 				return skel? se->_getSkelAnimVertexData() : se->_getSoftwareVertexAnimVertexData();
2028             }
2029         }
2030         // None found
2031         OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
2032             "Cannot find blended version of the vertex data specified.",
2033             "Entity::findBlendedVertexData");
2034     }
2035     //-----------------------------------------------------------------------
findSubEntityForVertexData(const VertexData * orig)2036     SubEntity* Entity::findSubEntityForVertexData(const VertexData* orig)
2037     {
2038         if (orig == mMesh->sharedVertexData)
2039         {
2040             return 0;
2041         }
2042 
2043         SubEntityList::iterator i, iend;
2044         iend = mSubEntityList.end();
2045         for (i = mSubEntityList.begin(); i != iend; ++i)
2046         {
2047             SubEntity* se = *i;
2048             if (orig == se->getSubMesh()->vertexData)
2049             {
2050                 return se;
2051             }
2052         }
2053 
2054         // None found
2055         return 0;
2056     }
2057     //-----------------------------------------------------------------------
addSoftwareAnimationRequest(bool normalsAlso)2058     void Entity::addSoftwareAnimationRequest(bool normalsAlso)
2059     {
2060         mSoftwareAnimationRequests++;
2061         if (normalsAlso) {
2062             mSoftwareAnimationNormalsRequests++;
2063         }
2064     }
2065     //-----------------------------------------------------------------------
removeSoftwareAnimationRequest(bool normalsAlso)2066     void Entity::removeSoftwareAnimationRequest(bool normalsAlso)
2067     {
2068         if (mSoftwareAnimationRequests == 0 ||
2069             (normalsAlso && mSoftwareAnimationNormalsRequests == 0))
2070         {
2071             OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
2072                         "Attempt to remove nonexistent request.",
2073                         "Entity::removeSoftwareAnimationRequest");
2074         }
2075         mSoftwareAnimationRequests--;
2076         if (normalsAlso) {
2077             mSoftwareAnimationNormalsRequests--;
2078         }
2079     }
2080     //-----------------------------------------------------------------------
_notifyAttached(Node * parent,bool isTagPoint)2081     void Entity::_notifyAttached(Node* parent, bool isTagPoint)
2082     {
2083         MovableObject::_notifyAttached(parent, isTagPoint);
2084         // Also notify LOD entities
2085         LODEntityList::iterator i, iend;
2086         iend = mLodEntityList.end();
2087         for (i = mLodEntityList.begin(); i != iend; ++i)
2088         {
2089             (*i)->_notifyAttached(parent, isTagPoint);
2090         }
2091 
2092     }
2093     //-----------------------------------------------------------------------
2094     //-----------------------------------------------------------------------
EntityShadowRenderable(Entity * parent,HardwareIndexBufferSharedPtr * indexBuffer,const VertexData * vertexData,bool createSeparateLightCap,SubEntity * subent,bool isLightCap)2095     Entity::EntityShadowRenderable::EntityShadowRenderable(Entity* parent,
2096         HardwareIndexBufferSharedPtr* indexBuffer, const VertexData* vertexData,
2097         bool createSeparateLightCap, SubEntity* subent, bool isLightCap)
2098         : mParent(parent), mSubEntity(subent)
2099     {
2100         // Save link to vertex data
2101         mCurrentVertexData = vertexData;
2102 
2103         // Initialise render op
2104         mRenderOp.indexData = OGRE_NEW IndexData();
2105         mRenderOp.indexData->indexBuffer = *indexBuffer;
2106         mRenderOp.indexData->indexStart = 0;
2107         // index start and count are sorted out later
2108 
2109         // Create vertex data which just references position component (and 2 component)
2110         mRenderOp.vertexData = OGRE_NEW VertexData();
2111         // Map in position data
2112         mRenderOp.vertexData->vertexDeclaration->addElement(0,0,VET_FLOAT3, VES_POSITION);
2113         mOriginalPosBufferBinding =
2114             vertexData->vertexDeclaration->findElementBySemantic(VES_POSITION)->getSource();
2115         mPositionBuffer = vertexData->vertexBufferBinding->getBuffer(mOriginalPosBufferBinding);
2116         mRenderOp.vertexData->vertexBufferBinding->setBinding(0, mPositionBuffer);
2117         // Map in w-coord buffer (if present)
2118         if(!vertexData->hardwareShadowVolWBuffer.isNull())
2119         {
2120             mRenderOp.vertexData->vertexDeclaration->addElement(1,0,VET_FLOAT1, VES_TEXTURE_COORDINATES, 0);
2121             mWBuffer = vertexData->hardwareShadowVolWBuffer;
2122             mRenderOp.vertexData->vertexBufferBinding->setBinding(1, mWBuffer);
2123         }
2124         // Use same vertex start as input
2125         mRenderOp.vertexData->vertexStart = vertexData->vertexStart;
2126 
2127         if (isLightCap)
2128         {
2129             // Use original vertex count, no extrusion
2130             mRenderOp.vertexData->vertexCount = vertexData->vertexCount;
2131         }
2132         else
2133         {
2134             // Vertex count must take into account the doubling of the buffer,
2135             // because second half of the buffer is the extruded copy
2136             mRenderOp.vertexData->vertexCount =
2137                 vertexData->vertexCount * 2;
2138             if (createSeparateLightCap)
2139             {
2140 				_createSeparateLightCap();
2141             }
2142         }
2143     }
2144 
2145 	//-----------------------------------------------------------------------
_createSeparateLightCap()2146     void Entity::EntityShadowRenderable::_createSeparateLightCap()
2147 	{
2148 		if (mLightCap == NULL)
2149 		{
2150 			// Create child light cap
2151 			mLightCap = OGRE_NEW EntityShadowRenderable(mParent,
2152 				&mRenderOp.indexData->indexBuffer, mCurrentVertexData, false, mSubEntity, true);
2153 		}
2154 	}
2155     //-----------------------------------------------------------------------
~EntityShadowRenderable()2156     Entity::EntityShadowRenderable::~EntityShadowRenderable()
2157     {
2158         OGRE_DELETE mRenderOp.indexData;
2159         OGRE_DELETE mRenderOp.vertexData;
2160     }
2161     //-----------------------------------------------------------------------
getWorldTransforms(Matrix4 * xform) const2162     void Entity::EntityShadowRenderable::getWorldTransforms(Matrix4* xform) const
2163     {
2164         *xform = mParent->_getParentNodeFullTransform();
2165     }
2166     //-----------------------------------------------------------------------
rebindPositionBuffer(const VertexData * vertexData,bool force)2167     void Entity::EntityShadowRenderable::rebindPositionBuffer(const VertexData* vertexData, bool force)
2168     {
2169         if (force || mCurrentVertexData != vertexData)
2170         {
2171             mCurrentVertexData = vertexData;
2172             mPositionBuffer = mCurrentVertexData->vertexBufferBinding->getBuffer(
2173                 mOriginalPosBufferBinding);
2174             mRenderOp.vertexData->vertexBufferBinding->setBinding(0, mPositionBuffer);
2175             if (mLightCap)
2176             {
2177                 static_cast<EntityShadowRenderable*>(mLightCap)->rebindPositionBuffer(vertexData, force);
2178             }
2179         }
2180     }
2181     //-----------------------------------------------------------------------
isVisible(void) const2182     bool Entity::EntityShadowRenderable::isVisible(void) const
2183     {
2184         if (mSubEntity)
2185         {
2186             return mSubEntity->isVisible();
2187         }
2188         else
2189         {
2190             return ShadowRenderable::isVisible();
2191         }
2192     }
2193 	//-----------------------------------------------------------------------
rebindIndexBuffer(const HardwareIndexBufferSharedPtr & indexBuffer)2194 	void Entity::EntityShadowRenderable::rebindIndexBuffer(const HardwareIndexBufferSharedPtr& indexBuffer)
2195 	{
2196 		mRenderOp.indexData->indexBuffer = indexBuffer;
2197 		if (mLightCap) mLightCap->rebindIndexBuffer(indexBuffer);
2198 	}
2199 
2200     //-----------------------------------------------------------------------
setRenderQueueGroup(uint8 queueID)2201     void Entity::setRenderQueueGroup(uint8 queueID)
2202     {
2203         MovableObject::setRenderQueueGroup(queueID);
2204 
2205         // Set render queue for all manual LOD entities
2206         if (mMesh->isLodManual())
2207         {
2208             LODEntityList::iterator li, liend;
2209             liend = mLodEntityList.end();
2210             for (li = mLodEntityList.begin(); li != liend; ++li)
2211             {
2212                 (*li)->setRenderQueueGroup(queueID);
2213             }
2214         }
2215     }
2216 	//-----------------------------------------------------------------------
setRenderQueueGroupAndPriority(uint8 queueID,ushort priority)2217 	void Entity::setRenderQueueGroupAndPriority(uint8 queueID, ushort priority)
2218 	{
2219 		MovableObject::setRenderQueueGroupAndPriority(queueID, priority);
2220 
2221 		// Set render queue for all manual LOD entities
2222 		if (mMesh->isLodManual())
2223 		{
2224 			LODEntityList::iterator li, liend;
2225 			liend = mLodEntityList.end();
2226 			for (li = mLodEntityList.begin(); li != liend; ++li)
2227 			{
2228 				(*li)->setRenderQueueGroupAndPriority(queueID, priority);
2229 			}
2230 		}
2231 	}
2232     //-----------------------------------------------------------------------
shareSkeletonInstanceWith(Entity * entity)2233     void Entity::shareSkeletonInstanceWith(Entity* entity)
2234     {
2235         if (entity->getMesh()->getSkeleton() != getMesh()->getSkeleton())
2236         {
2237             OGRE_EXCEPT(Exception::ERR_RT_ASSERTION_FAILED,
2238                 "The supplied entity has a different skeleton.",
2239                 "Entity::shareSkeletonWith");
2240         }
2241         if (!mSkeletonInstance)
2242         {
2243             OGRE_EXCEPT(Exception::ERR_RT_ASSERTION_FAILED,
2244                 "This entity has no skeleton.",
2245                 "Entity::shareSkeletonWith");
2246         }
2247         if (mSharedSkeletonEntities != NULL && entity->mSharedSkeletonEntities != NULL)
2248         {
2249             OGRE_EXCEPT(Exception::ERR_RT_ASSERTION_FAILED,
2250                 "Both entities already shares their SkeletonInstances! At least "
2251                 "one of the instances must not share it's instance.",
2252                 "Entity::shareSkeletonWith");
2253         }
2254 
2255         //check if we already share our skeletoninstance, we don't want to delete it if so
2256         if (mSharedSkeletonEntities != NULL)
2257         {
2258             entity->shareSkeletonInstanceWith(this);
2259         }
2260         else
2261         {
2262             OGRE_DELETE mSkeletonInstance;
2263             OGRE_FREE_SIMD(mBoneMatrices, MEMCATEGORY_ANIMATION);
2264             OGRE_DELETE mAnimationState;
2265 			// using OGRE_FREE since unsigned long is not a destructor
2266 			OGRE_FREE(mFrameBonesLastUpdated, MEMCATEGORY_ANIMATION);
2267             mSkeletonInstance = entity->mSkeletonInstance;
2268             mNumBoneMatrices = entity->mNumBoneMatrices;
2269             mBoneMatrices = entity->mBoneMatrices;
2270             mAnimationState = entity->mAnimationState;
2271             mFrameBonesLastUpdated = entity->mFrameBonesLastUpdated;
2272             if (entity->mSharedSkeletonEntities == NULL)
2273             {
2274                 entity->mSharedSkeletonEntities = OGRE_NEW_T(EntitySet, MEMCATEGORY_ANIMATION)();
2275                 entity->mSharedSkeletonEntities->insert(entity);
2276             }
2277             mSharedSkeletonEntities = entity->mSharedSkeletonEntities;
2278             mSharedSkeletonEntities->insert(this);
2279         }
2280     }
2281     //-----------------------------------------------------------------------
stopSharingSkeletonInstance()2282     void Entity::stopSharingSkeletonInstance()
2283     {
2284         if (mSharedSkeletonEntities == NULL)
2285         {
2286             OGRE_EXCEPT(Exception::ERR_RT_ASSERTION_FAILED,
2287                 "This entity is not sharing it's skeletoninstance.",
2288                 "Entity::shareSkeletonWith");
2289         }
2290         //check if there's no other than us sharing the skeleton instance
2291         if (mSharedSkeletonEntities->size() == 1)
2292         {
2293             //just reset
2294             OGRE_DELETE_T(mSharedSkeletonEntities, EntitySet, MEMCATEGORY_ANIMATION);
2295             mSharedSkeletonEntities = 0;
2296         }
2297         else
2298         {
2299             mSkeletonInstance = OGRE_NEW SkeletonInstance(mMesh->getSkeleton());
2300             mSkeletonInstance->load();
2301             mAnimationState = OGRE_NEW AnimationStateSet();
2302             mMesh->_initAnimationState(mAnimationState);
2303             mFrameBonesLastUpdated = OGRE_NEW_T(unsigned long, MEMCATEGORY_ANIMATION)(std::numeric_limits<unsigned long>::max());
2304             mNumBoneMatrices = mSkeletonInstance->getNumBones();
2305             mBoneMatrices = static_cast<Matrix4*>(OGRE_MALLOC_SIMD(sizeof(Matrix4) * mNumBoneMatrices, MEMCATEGORY_ANIMATION));
2306 
2307             mSharedSkeletonEntities->erase(this);
2308             if (mSharedSkeletonEntities->size() == 1)
2309             {
2310                 (*mSharedSkeletonEntities->begin())->stopSharingSkeletonInstance();
2311             }
2312             mSharedSkeletonEntities = 0;
2313         }
2314     }
2315     //-----------------------------------------------------------------------
refreshAvailableAnimationState(void)2316 	void Entity::refreshAvailableAnimationState(void)
2317 	{
2318 		mMesh->_refreshAnimationState(mAnimationState);
2319 	}
2320 	//-----------------------------------------------------------------------
getTypeFlags(void) const2321 	uint32 Entity::getTypeFlags(void) const
2322 	{
2323 		return SceneManager::ENTITY_TYPE_MASK;
2324 	}
2325 	//-----------------------------------------------------------------------
getVertexDataForBinding(void)2326 	VertexData* Entity::getVertexDataForBinding(void)
2327 	{
2328 		Entity::VertexDataBindChoice c =
2329 			chooseVertexDataForBinding(mMesh->getSharedVertexDataAnimationType() != VAT_NONE);
2330 		switch(c)
2331 		{
2332 		case BIND_ORIGINAL:
2333 			return mMesh->sharedVertexData;
2334 		case BIND_HARDWARE_MORPH:
2335 			return mHardwareVertexAnimVertexData;
2336 		case BIND_SOFTWARE_MORPH:
2337 			return mSoftwareVertexAnimVertexData;
2338 		case BIND_SOFTWARE_SKELETAL:
2339 			return mSkelAnimVertexData;
2340 		};
2341 		// keep compiler happy
2342 		return mMesh->sharedVertexData;
2343 	}
2344 	//-----------------------------------------------------------------------
chooseVertexDataForBinding(bool vertexAnim)2345 	Entity::VertexDataBindChoice Entity::chooseVertexDataForBinding(bool vertexAnim)
2346 	{
2347 		if (hasSkeleton())
2348 		{
2349 			if (!isHardwareAnimationEnabled())
2350 			{
2351 				// all software skeletal binds same vertex data
2352 				// may be a 2-stage s/w transform including morph earlier though
2353 				return BIND_SOFTWARE_SKELETAL;
2354 			}
2355 			else if (vertexAnim)
2356 			{
2357 				// hardware morph animation
2358 				return BIND_HARDWARE_MORPH;
2359 			}
2360 			else
2361 			{
2362 				// hardware skeletal, no morphing
2363 				return BIND_ORIGINAL;
2364 			}
2365 		}
2366 		else if (vertexAnim)
2367 		{
2368 			// morph only, no skeletal
2369 			if (isHardwareAnimationEnabled())
2370 			{
2371 				return BIND_HARDWARE_MORPH;
2372 			}
2373 			else
2374 			{
2375 				return BIND_SOFTWARE_MORPH;
2376 			}
2377 
2378 		}
2379 		else
2380 		{
2381 			return BIND_ORIGINAL;
2382 		}
2383 
2384 	}
2385 	//---------------------------------------------------------------------
visitRenderables(Renderable::Visitor * visitor,bool debugRenderables)2386 	void Entity::visitRenderables(Renderable::Visitor* visitor,
2387 		bool debugRenderables)
2388 	{
2389 		// Visit each SubEntity
2390 		for (SubEntityList::iterator i = mSubEntityList.begin(); i != mSubEntityList.end(); ++i)
2391 		{
2392 			visitor->visit(*i, 0, false);
2393 		}
2394 		// if manual LOD is in use, visit those too
2395 		ushort lodi = 1;
2396 		for (LODEntityList::iterator e = mLodEntityList.begin();
2397 			e != mLodEntityList.end(); ++e, ++lodi)
2398 		{
2399 
2400 			uint nsub = (*e)->getNumSubEntities();
2401 			for (uint s = 0; s < nsub; ++s)
2402 			{
2403 				visitor->visit((*e)->getSubEntity(s), lodi, false);
2404 			}
2405 		}
2406 
2407 	}
2408 	//-----------------------------------------------------------------------
2409 	//-----------------------------------------------------------------------
2410 	String EntityFactory::FACTORY_TYPE_NAME = "Entity";
2411 	//-----------------------------------------------------------------------
getType(void) const2412 	const String& EntityFactory::getType(void) const
2413 	{
2414 		return FACTORY_TYPE_NAME;
2415 	}
2416 	//-----------------------------------------------------------------------
createInstanceImpl(const String & name,const NameValuePairList * params)2417 	MovableObject* EntityFactory::createInstanceImpl( const String& name,
2418 		const NameValuePairList* params)
2419 	{
2420 		// must have mesh parameter
2421 		MeshPtr pMesh;
2422 		if (params != 0)
2423 		{
2424 			String groupName = ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME;
2425 
2426 			NameValuePairList::const_iterator ni;
2427 
2428 			ni = params->find("resourceGroup");
2429 			if (ni != params->end())
2430 			{
2431 				groupName = ni->second;
2432 			}
2433 
2434 			ni = params->find("mesh");
2435 			if (ni != params->end())
2436 			{
2437 				// Get mesh (load if required)
2438 				pMesh = MeshManager::getSingleton().load(
2439 					ni->second,
2440 					// autodetect group location
2441 					groupName );
2442 			}
2443 
2444 		}
2445 		if (pMesh.isNull())
2446 		{
2447 			OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
2448 				"'mesh' parameter required when constructing an Entity.",
2449 				"EntityFactory::createInstance");
2450 		}
2451 
2452 		return OGRE_NEW Entity(name, pMesh);
2453 
2454 	}
2455 	//-----------------------------------------------------------------------
destroyInstance(MovableObject * obj)2456 	void EntityFactory::destroyInstance( MovableObject* obj)
2457 	{
2458 		OGRE_DELETE obj;
2459 	}
2460 
2461 
2462 }
2463