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