void gkSkeletonLoader::makeManual(gkEntity* ent) { Ogre::Entity* oent = ent->getEntity(); if (!oent || !oent->hasSkeleton()) return; Ogre::SkeletonInstance* inst = oent->getSkeleton(); gkBone::BoneList::Iterator it = m_skeleton->getBoneList().iterator(); while (it.hasMoreElements()) { gkBone* bone = it.getNext(); if (inst->hasBone(bone->getName())) { Ogre::Bone* obone = inst->getBone(bone->getName()); bone->_setOgreBone(obone); obone->setManuallyControlled(true); } } }
bool EC_Mesh::AttachMeshToBone(QObject* targetMesh, const QString& boneName) { if (!entity_) return false; // First make sure that the target mesh is valid, and the bone can be found EC_Mesh* targetMeshPtr = dynamic_cast<EC_Mesh*>(targetMesh); if (!targetMeshPtr) return false; Ogre::Entity* targetEntity = targetMeshPtr->GetEntity(); if (!targetEntity) return false; std::string boneNameStd = boneName.toStdString(); Ogre::SkeletonInstance* skeleton = targetEntity->getSkeleton(); if (!skeleton) return false; if (!skeleton->hasBone(boneNameStd)) return false; // We are ready to go. Detach the entity from its normal scene node first DetachMeshFromBone(); DetachEntity(); bone_tagpoint_ = targetEntity->attachObjectToBone(boneNameStd, entity_); bone_parent_mesh_ = targetMeshPtr; bone_parent_mesh_->bone_attached_mesh_ = this; attached_to_bone_ = true; // Force the adjustment for the tagpoint now OnAttributeUpdated(&nodeTransformation); return true; }
NifOgre::EntityList NpcAnimation::insertBoundedPart(const std::string &mesh, int group, const std::string &bonename) { NifOgre::EntityList entities = NifOgre::Loader::createEntities(mEntityList.mSkelBase, bonename, mInsert, mesh); std::vector<Ogre::Entity*> &parts = entities.mEntities; for(size_t i = 0;i < parts.size();i++) { parts[i]->getUserObjectBindings().setUserAny(Ogre::Any(group)); if (mVisibilityFlags != 0) parts[i]->setVisibilityFlags(mVisibilityFlags); for(unsigned int j=0; j < parts[i]->getNumSubEntities(); ++j) { Ogre::SubEntity* subEnt = parts[i]->getSubEntity(j); subEnt->setRenderQueueGroup(subEnt->getMaterial()->isTransparent() ? RQG_Alpha : RQG_Main); } } if(entities.mSkelBase) { Ogre::AnimationStateSet *aset = entities.mSkelBase->getAllAnimationStates(); Ogre::AnimationStateIterator asiter = aset->getAnimationStateIterator(); while(asiter.hasMoreElements()) { Ogre::AnimationState *state = asiter.getNext(); state->setEnabled(false); state->setLoop(false); } Ogre::SkeletonInstance *skelinst = entities.mSkelBase->getSkeleton(); Ogre::Skeleton::BoneIterator boneiter = skelinst->getBoneIterator(); while(boneiter.hasMoreElements()) boneiter.getNext()->setManuallyControlled(true); } return entities; }
int main(int argc, char **argv) { if(argc <= 1 || argc > 2) { std::cout << "Invalid argument, it sould be : ./ogre_show_animationstate /path/name.mesh !\n"; return -1; } std::string nameMesh(argv[1]); std::string pathMesh; int index = nameMesh.size(); while(nameMesh[index] != '/') { index--; if(index == 0) { pathMesh = "./"; break; } } if(index != 0) { pathMesh = nameMesh.substr(0, index); } // Init Ogre::Root* mRoot = new Ogre::Root(); new Ogre::DefaultHardwareBufferManager(); Ogre::ResourceGroupManager::getSingleton().addResourceLocation("./", "FileSystem", "General"); Ogre::ResourceGroupManager::getSingleton().addResourceLocation(pathMesh, "FileSystem", "General"); Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups(); // load mesh Ogre::MeshPtr mesh = Ogre::MeshManager::getSingleton().load(nameMesh, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); // create & load a SkeletonInstance Ogre::SkeletonInstance* skelInst = new Ogre::SkeletonInstance(mesh->getSkeleton()); skelInst->load(); // create & load an AnimationStateSet Ogre::AnimationStateSet* animStateSet = new Ogre::AnimationStateSet(); mesh->_initAnimationState(animStateSet); // show animation state std::cout << "Animation states : \n"; Ogre::AnimationStateIterator iter = animStateSet->getAnimationStateIterator(); while(iter.hasMoreElements()) { Ogre::AnimationState* animationState = iter.getNext(); std::cout << "\t- " << animationState->getAnimationName() << "\n"; } return 0; }
void CreatureWeaponAnimation::updatePart(NifOgre::ObjectScenePtr& scene, int slot) { MWWorld::InventoryStore& inv = mPtr.getClass().getInventoryStore(mPtr); MWWorld::ContainerStoreIterator it = inv.getSlot(slot); if (it == inv.end()) { scene.setNull(); return; } MWWorld::Ptr item = *it; std::string bonename; if (slot == MWWorld::InventoryStore::Slot_CarriedRight) bonename = "Weapon Bone"; else bonename = "Shield Bone"; scene = NifOgre::Loader::createObjects(mSkelBase, bonename, mInsert, item.getClass().getModel(item)); Ogre::Vector3 glowColor = getEnchantmentColor(item); setRenderProperties(scene, RV_Actors, RQG_Main, RQG_Alpha, 0, !item.getClass().getEnchantment(item).empty(), &glowColor); if(scene->mSkelBase) { Ogre::SkeletonInstance *skel = scene->mSkelBase->getSkeleton(); if(scene->mSkelBase->isParentTagPoint()) { Ogre::Node *root = scene->mSkelBase->getParentNode(); if(skel->hasBone("BoneOffset")) { Ogre::Bone *offset = skel->getBone("BoneOffset"); root->translate(offset->getPosition()); // It appears that the BoneOffset rotation is completely bogus, at least for light models. //root->rotate(offset->getOrientation()); root->pitch(Ogre::Degree(-90.0f)); root->scale(offset->getScale()); root->setInitialState(); } } updateSkeletonInstance(mSkelBase->getSkeleton(), skel); } // TODO: // type == ESM::PRT_Weapon should get an animation source based on the current offset // of the weapon attack animation (from its beginning, or start marker?) std::vector<Ogre::Controller<Ogre::Real> >::iterator ctrl(scene->mControllers.begin()); for(;ctrl != scene->mControllers.end();ctrl++) { if(ctrl->getSource().isNull()) ctrl->setSource(Ogre::SharedPtr<NullAnimationTime>(new NullAnimationTime())); } }
Ogre::Node *Animation::getNode(const std::string &name) { if(mSkelBase) { Ogre::SkeletonInstance *skel = mSkelBase->getSkeleton(); if(skel->hasBone(name)) return skel->getBone(name); } return NULL; }
Ogre::TagPoint *Animation::attachObjectToBone(const Ogre::String &bonename, Ogre::MovableObject *obj) { Ogre::TagPoint *tag = NULL; Ogre::SkeletonInstance *skel = (mSkelBase ? mSkelBase->getSkeleton() : NULL); if(skel && skel->hasBone(bonename)) { tag = mSkelBase->attachObjectToBone(bonename, obj); mAttachedObjects[obj] = bonename; } return tag; }
///Get the orientation of the wrist bone Ogre::Quaternion getWristOrientation() { Ogre::Entity* hand = this->Entity(); assert(hand); Ogre::SkeletonInstance* ske; Ogre::Bone* wrist; if(ske = hand->getSkeleton()) if(wrist = ske->getBone("Wrist")) return wrist->getOrientation(); return Ogre::Quaternion::IDENTITY; }
/** * Attaches an empty object to the owner. This has no effect if the owner is a node since * there's no notion of an "empty" object for nodes. For entities, an "empty" object corresponds * to a tag point that has no attachment */ void AttachEmpty(const Ogre::String& name = Ogre::StringUtil::BLANK) const { if (this->entity != 0 && !this->boneName.empty()) { Ogre::SkeletonInstance* skeleton = this->entity->getSkeleton(); Ogre::Bone* bone = skeleton->getBone(this->boneName); //TODO: Modify Ogre to accept name when creating TagPoint Ogre::TagPoint* tagPoint = skeleton->createTagPointOnBone(bone); tagPoint->setPosition(this->attachPosition); tagPoint->setScale(this->attachScale); tagPoint->setOrientation(this->attachRotation); } }
void BoneCollisionManager::checkMesh(Ogre::String outFileName, Ogre::SceneNode* node) { std::ofstream file(outFileName.c_str()); if (file) { Ogre::Entity* ent = (Ogre::Entity*)node->getAttachedObject(0); Ogre::SkeletonInstance* skeletonInst = ent->getSkeleton(); Ogre::Skeleton::BoneIterator boneI=skeletonInst->getBoneIterator(); //file<<"Creating bone length information from:\n"; file<<"Mesh name: "<<ent->getMesh()->getName()<<"\n"; file<<"Skeleton name: "<<skeletonInst->getName()<<"\n\n"; while(boneI.hasMoreElements()) { Ogre::Bone* bone=boneI.getNext(); Ogre::String bName=bone->getName(); if (bone->getChild(0)) { Ogre::Vector3 curr = bone->_getDerivedPosition(); Ogre::Vector3 next = bone->getChild(0)->_getDerivedPosition(); Ogre::Vector3 difference = next-curr; //length of bone Ogre::Real lenght = difference.length(); file<<bName<<":\nLength\t\t\t=\t"<<Ogre::StringConverter::toString(lenght,3)<<"\n"<< "Position"<<"\t\t=\t"<<Ogre::StringConverter::toString(curr.x,1)<<", "<< Ogre::StringConverter::toString(curr.y,1)<<", "<< Ogre::StringConverter::toString(curr.z,1)<<"\n"; if (!bone->getParent()) file<<bName<<" is a Root Bone!\n\n"; else file<<"\n\n"; } } } }
bool LIRenAttachmentEntity::create_skeleton () { Ogre::SkeletonInstance* skeleton = entity->getSkeleton (); if (skeleton == NULL) return false; /* Set the initial bone transformations. */ /* The mesh may not have set these correctly if it depended on bones in external skeletons. Because of external bones, we need to set the transformations using the pose skeleton of the object. */ LIRenModelData* model = get_model (); if (model != NULL && model->rest_pose_buffer != NULL) { for (int i = 0 ; i < model->rest_pose_buffer->bones.count ; i++) { const LIMdlPoseBufferBone* group = model->rest_pose_buffer->bones.array + i; if (!group->name) continue; LIMatTransform t; if (!object->get_node_transform (group->name, t)) continue; Ogre::Bone* bone = skeleton->getBone (i); bone->setPosition (t.position.x, t.position.y, t.position.z); bone->setOrientation (t.rotation.w, t.rotation.x, t.rotation.y, t.rotation.z); } } /* Make all bones manually controlled. */ for (int i = 0 ; i < skeleton->getNumBones () ; i++) { Ogre::Bone* bone = skeleton->getBone (i); bone->setManuallyControlled (true); } /* Set the binding pose. */ skeleton->setBindingPose (); return true; }
void TutorialApplication::createFrameListener(void) { BaseApplication::createFrameListener(); // create a params panel for displaying sample details Ogre::StringVector items; // items.push_back("Filtering"); // items.push_back("Poly Mode"); mStatusPanel = mTrayMgr->createParamsPanel(OgreBites::TL_BOTTOMRIGHT, "Params", 300, items); OgreBites::Slider* slider = NULL; mTrayMgr->createButton(OgreBites::TL_BOTTOMRIGHT, "Reset pose", "Reset pose"); mTrayMgr->createButton(OgreBites::TL_BOTTOMRIGHT, "Reload controller", "Reload controller"); mTrayMgr->createButton(OgreBites::TL_BOTTOMRIGHT, "Go to pose", "Go to pose"); // animations control slider = mTrayMgr->createLongSlider(OgreBites::TL_TOPLEFT, "Gravity X", "Gravity X", 400, 150, 50, -9.8, 9.8, 149 ); slider->setValue(0); slider = mTrayMgr->createLongSlider(OgreBites::TL_TOPLEFT, "Gravity Y", "Gravity Y", 400, 150, 50, -9.8, 9.8, 149 ); slider->setValue(0.0f); slider = mTrayMgr->createLongSlider(OgreBites::TL_TOPLEFT, "Gravity Z", "Gravity Z", 400, 150, 50, -9.8, 9.8, 149 ); slider->setValue(0.0f); slider = mTrayMgr->createLongSlider(OgreBites::TL_TOPLEFT, "Time multiplier", "Time multiplier", 400, 150, 50, 0, 1, 1000 ); slider->setValue(DEFAULT_TIME_MULTIPLIER); slider = mTrayMgr->createLongSlider(OgreBites::TL_TOPLEFT, "Animation speed", "Animation speed", 400, 150, 50, 0, 2, 1000 ); slider->setValue(DEFAULT_ANIMATION_SPEED); // animation selector int defaultAnimationIndex = 0; Ogre::SkeletonInstance* skel = mFigureEnt->getSkeleton(); Ogre::StringVector animationNames; animationNames.push_back("<none>"); if ( skel ) { std::cout << "got skeleton" << std::endl; for ( int i=0; i<skel->getNumAnimations(); i++ ) { std::string name = skel->getAnimation(i)->getName(); std::cout << " animation: " << name << std::endl; if ( /*i<5 || name == "WalkNew"*/true ) { animationNames.push_back(name); if ( name == DEFAULT_ANIMATION ) { defaultAnimationIndex = i; } } } //mFigureEnt->setDisplaySkeleton(true); } else { std::cout << "no skeleton" << std::endl; } mAnimationSelectMenu = mTrayMgr->createThickSelectMenu( OgreBites::TL_TOPLEFT, "Animation", "Animation", 400, animationNames.size()); if ( animationNames.size() ) { mAnimationSelectMenu->setItems(animationNames); mAnimationSelectMenu->selectItem(defaultAnimationIndex); } static const int debugDrawStyleCount = 8; OgreBites::SelectMenu* select = mTrayMgr->createThickSelectMenu( OgreBites::TL_BOTTOMRIGHT, "Debug draw", "Debug draw", 400, debugDrawStyleCount ); Ogre::StringVector debugDrawStates; const char* debugDrawStateNames[debugDrawStyleCount] = { "None", "Nodes", "Links", "Faces", "FaceAnchors", "Tetras", "TetraForces", "BadTetras" }; for ( int i=0; i<debugDrawStyleCount; i++ ) { debugDrawStates.push_back(debugDrawStateNames[i]); } select->setItems(debugDrawStates); select->selectItem(0); showControls(false); }
bool EC_Mesh::SetMeshWithSkeleton(const std::string& mesh_name, const std::string& skeleton_name, bool clone) { if (!ViewEnabled()) return false; OgreWorldPtr world = world_.lock(); Ogre::SkeletonPtr skel = Ogre::SkeletonManager::getSingleton().getByName(AssetAPI::SanitateAssetRef(skeleton_name)); if (skel.isNull()) { LogError("EC_Mesh::SetMeshWithSkeleton: Could not set skeleton " + skeleton_name + " to mesh " + mesh_name + ": not found"); return false; } RemoveMesh(); Ogre::SceneManager* sceneMgr = world->OgreSceneManager(); Ogre::Mesh* mesh = PrepareMesh(mesh_name, clone); if (!mesh) return false; try { mesh->_notifySkeleton(skel); // LogDebug("Set skeleton " + skeleton_name + " to mesh " + mesh_name); } catch(Ogre::Exception& e) { LogError("EC_Mesh::SetMeshWithSkeleton: Could not set skeleton " + skeleton_name + " to mesh " + mesh_name + ": " + std::string(e.what())); return false; } try { entity_ = sceneMgr->createEntity(world->GetUniqueObjectName("EC_Mesh_entwithskel"), mesh->getName()); if (!entity_) { LogError("EC_Mesh::SetMeshWithSkeleton: Could not set mesh " + mesh_name); return false; } entity_->setRenderingDistance(drawDistance.Get()); entity_->setCastShadows(castShadows.Get()); entity_->setUserAny(Ogre::Any(static_cast<IComponent *>(this))); // Set UserAny also on subentities for(uint i = 0; i < entity_->getNumSubEntities(); ++i) entity_->getSubEntity(i)->setUserAny(entity_->getUserAny()); if (entity_->hasSkeleton()) { Ogre::SkeletonInstance* skel = entity_->getSkeleton(); // Enable cumulative mode on skeletal animations if (skel) skel->setBlendMode(Ogre::ANIMBLEND_CUMULATIVE); } } catch(Ogre::Exception& e) { LogError("EC_Mesh::SetMeshWithSkeleton: Could not set mesh " + mesh_name + ": " + std::string(e.what())); return false; } AttachEntity(); emit MeshChanged(); return true; }
bool EC_Mesh::SetMesh(QString meshResourceName, bool clone) { if (!ViewEnabled()) return false; OgreWorldPtr world = world_.lock(); std::string mesh_name = meshResourceName.trimmed().toStdString(); RemoveMesh(); // If placeable is not set yet, set it manually by searching it from the parent entity if (!placeable_) { Entity* entity = ParentEntity(); if (entity) { ComponentPtr placeable = entity->GetComponent(EC_Placeable::TypeNameStatic()); if (placeable) placeable_ = placeable; } } Ogre::SceneManager* sceneMgr = world->OgreSceneManager(); Ogre::Mesh* mesh = PrepareMesh(mesh_name, clone); if (!mesh) return false; try { entity_ = sceneMgr->createEntity(world->GetUniqueObjectName("EC_Mesh_entity"), mesh->getName()); if (!entity_) { LogError("EC_Mesh::SetMesh: Could not set mesh " + mesh_name); return false; } entity_->setRenderingDistance(drawDistance.Get()); entity_->setCastShadows(castShadows.Get()); entity_->setUserAny(Ogre::Any(static_cast<IComponent *>(this))); // Set UserAny also on subentities for(uint i = 0; i < entity_->getNumSubEntities(); ++i) entity_->getSubEntity(i)->setUserAny(entity_->getUserAny()); if (entity_->hasSkeleton()) { Ogre::SkeletonInstance* skel = entity_->getSkeleton(); // Enable cumulative mode on skeletal animations if (skel) skel->setBlendMode(Ogre::ANIMBLEND_CUMULATIVE); } // Make sure adjustment node is uptodate Transform newTransform = nodeTransformation.Get(); adjustment_node_->setPosition(newTransform.pos); adjustment_node_->setOrientation(newTransform.Orientation()); // Prevent Ogre exception from zero scale adjustment_node_->setScale(Max(newTransform.scale, float3::FromScalar(0.0000001f))); // Force a re-apply of all materials to this new mesh. ApplyMaterial(); } catch(Ogre::Exception& e) { LogError("EC_Mesh::SetMesh: Could not set mesh " + mesh_name + ": " + std::string(e.what())); return false; } AttachEntity(); emit MeshChanged(); return true; }
void Animation::handleAnimationTransforms(){ Ogre::SkeletonInstance* skel = base->getSkeleton(); Ogre::Bone* b = skel->getRootBone(); b->setOrientation(Ogre::Real(.3),Ogre::Real(.3),Ogre::Real(.3), Ogre::Real(.3)); //This is a trick skel->_updateTransforms(); //skel->_notifyManualBonesDirty(); base->getAllAnimationStates()->_notifyDirty(); //base->_updateAnimation(); //base->_notifyMoved(); std::vector<Nif::NiKeyframeData>::iterator iter; int slot = 0; if(transformations){ for(iter = transformations->begin(); iter != transformations->end(); iter++){ if(time < iter->getStartTime() || time < startTime || time > iter->getStopTime()) { slot++; continue; } float x; float x2; const std::vector<Ogre::Quaternion> & quats = iter->getQuat(); const std::vector<float> & ttime = iter->gettTime(); const std::vector<float> & rtime = iter->getrTime(); int rindexJ = rindexI[slot]; timeIndex(time, rtime, rindexI[slot], rindexJ, x2); int tindexJ = tindexI[slot]; const std::vector<Ogre::Vector3> & translist1 = iter->getTranslist1(); timeIndex(time, ttime, tindexI[slot], tindexJ, x); Ogre::Vector3 t; Ogre::Quaternion r; bool bTrans = translist1.size() > 0; bool bQuats = quats.size() > 0; if(skel->hasBone(iter->getBonename())){ Ogre::Bone* bone = skel->getBone(iter->getBonename()); if(bTrans){ Ogre::Vector3 v1 = translist1[tindexI[slot]]; Ogre::Vector3 v2 = translist1[tindexJ]; t = (v1 + (v2 - v1) * x); bone->setPosition(t); } if(bQuats){ r = Ogre::Quaternion::Slerp(x2, quats[rindexI[slot]], quats[rindexJ], true); bone->setOrientation(r); } } slot++; } skel->_updateTransforms(); base->getAllAnimationStates()->_notifyDirty(); } }
void Animation::setObjectRoot(const std::string &model, bool baseonly) { OgreAssert(mAnimSources.empty(), "Setting object root while animation sources are set!"); mSkelBase = NULL; mObjectRoot.setNull(); if(model.empty()) return; std::string mdlname = Misc::StringUtils::lowerCase(model); std::string::size_type p = mdlname.rfind('\\'); if(p == std::string::npos) p = mdlname.rfind('/'); if(p != std::string::npos) mdlname.insert(mdlname.begin()+p+1, 'x'); else mdlname.insert(mdlname.begin(), 'x'); if(!Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(mdlname)) { mdlname = model; Misc::StringUtils::toLower(mdlname); } mObjectRoot = (!baseonly ? NifOgre::Loader::createObjects(mInsert, mdlname) : NifOgre::Loader::createObjectBase(mInsert, mdlname)); if(mObjectRoot->mSkelBase) { mSkelBase = mObjectRoot->mSkelBase; Ogre::AnimationStateSet *aset = mObjectRoot->mSkelBase->getAllAnimationStates(); Ogre::AnimationStateIterator asiter = aset->getAnimationStateIterator(); while(asiter.hasMoreElements()) { Ogre::AnimationState *state = asiter.getNext(); state->setEnabled(false); state->setLoop(false); } // Set the bones as manually controlled since we're applying the // transformations manually Ogre::SkeletonInstance *skelinst = mObjectRoot->mSkelBase->getSkeleton(); Ogre::Skeleton::BoneIterator boneiter = skelinst->getBoneIterator(); while(boneiter.hasMoreElements()) boneiter.getNext()->setManuallyControlled(true); // Reattach any objects that have been attached to this one ObjectAttachMap::iterator iter = mAttachedObjects.begin(); while(iter != mAttachedObjects.end()) { if(!skelinst->hasBone(iter->second)) mAttachedObjects.erase(iter++); else { mSkelBase->attachObjectToBone(iter->second, iter->first); ++iter; } } } else mAttachedObjects.clear(); for(size_t i = 0;i < mObjectRoot->mControllers.size();i++) { if(mObjectRoot->mControllers[i].getSource().isNull()) mObjectRoot->mControllers[i].setSource(mAnimationTimePtr[0]); } }
ManuallyControlledBone::ManuallyControlledBone(Ogre::String boneName,Ogre::Entity *dstEnty)//创建来自dstEnty实体的名为bonaName的骨骼手动控制的骨骼,在createScene里调用 { Ogre::SkeletonInstance *skel = dstEnty->getSkeleton();//得到实体骨架 ControlledBone = skel->getBone(boneName);//根据名字得到骨骼 }
void EC_OgreAnimationController::Update(f64 frametime) { Ogre::Entity* entity = GetEntity(); if (!entity) return; std::vector<std::string> erase_list; // Loop through all animations & update them as necessary for (AnimationMap::iterator i = animations_.begin(); i != animations_.end(); ++i) { Ogre::AnimationState* animstate = GetAnimationState(entity, i->first); if (!animstate) continue; switch(i->second.phase_) { case PHASE_FADEIN: // If period is infinitely fast, skip to full weight & PLAY status if (i->second.fade_period_ == 0.0f) { i->second.weight_ = 1.0f; i->second.phase_ = PHASE_PLAY; } else { i->second.weight_ += (1.0f / i->second.fade_period_) * frametime; if (i->second.weight_ >= 1.0f) { i->second.weight_ = 1.0f; i->second.phase_ = PHASE_PLAY; } } break; case PHASE_PLAY: if (i->second.auto_stop_ || i->second.num_repeats_ != 1) { if ((i->second.speed_factor_ >= 0.f && animstate->getTimePosition() >= animstate->getLength()) || (i->second.speed_factor_ < 0.f && animstate->getTimePosition() <= 0.f)) { if (i->second.num_repeats_ != 1) { if (i->second.num_repeats_ > 1) i->second.num_repeats_--; Ogre::Real rewindpos = i->second.speed_factor_ >= 0.f ? (animstate->getTimePosition() - animstate->getLength()) : animstate->getLength(); animstate->setTimePosition(rewindpos); } else { i->second.phase_ = PHASE_FADEOUT; } } } break; case PHASE_FADEOUT: // If period is infinitely fast, skip to disabled status immediately if (i->second.fade_period_ == 0.0f) { i->second.weight_ = 0.0f; i->second.phase_ = PHASE_STOP; } else { i->second.weight_ -= (1.0f / i->second.fade_period_) * frametime; if (i->second.weight_ <= 0.0f) { i->second.weight_ = 0.0f; i->second.phase_ = PHASE_STOP; } } break; } // Set weight & step the animation forward if (i->second.phase_ != PHASE_STOP) { Ogre::Real advance = i->second.speed_factor_ * frametime; Ogre::Real new_weight = i->second.weight_ * i->second.weight_factor_; if (new_weight != animstate->getWeight()) animstate->setWeight((Ogre::Real)i->second.weight_ * i->second.weight_factor_); if (advance != 0.0f) animstate->addTime((Ogre::Real)(i->second.speed_factor_ * frametime)); if (!animstate->getEnabled()) animstate->setEnabled(true); } else { // If stopped, disable & remove this animation from list animstate->setEnabled(false); erase_list.push_back(i->first); } } for (uint i = 0; i < erase_list.size(); ++i) { animations_.erase(erase_list[i]); } // High-priority/low-priority blending code if (entity->hasSkeleton()) { Ogre::SkeletonInstance* skel = entity->getSkeleton(); if (!skel) return; if (highpriority_mask_.size() != skel->getNumBones()) highpriority_mask_.resize(skel->getNumBones()); if (lowpriority_mask_.size() != skel->getNumBones()) lowpriority_mask_.resize(skel->getNumBones()); for (uint i = 0; i < skel->getNumBones(); ++i) { highpriority_mask_[i] = 1.0; lowpriority_mask_[i] = 1.0; } // Loop through all high priority animations & update the lowpriority-blendmask based on their active tracks for (AnimationMap::iterator i = animations_.begin(); i != animations_.end(); ++i) { Ogre::AnimationState* animstate = GetAnimationState(entity, i->first); if (!animstate) continue; // Create blend mask if animstate doesn't have it yet if (!animstate->hasBlendMask()) animstate->createBlendMask(skel->getNumBones()); if ((i->second.high_priority_) && (i->second.weight_ > 0.0)) { // High-priority animations get the full weight blend mask animstate->_setBlendMaskData(&highpriority_mask_[0]); if (!skel->hasAnimation(animstate->getAnimationName())) continue; Ogre::Animation* anim = skel->getAnimation(animstate->getAnimationName()); Ogre::Animation::NodeTrackIterator it = anim->getNodeTrackIterator(); while (it.hasMoreElements()) { Ogre::NodeAnimationTrack* track = it.getNext(); unsigned id = track->getHandle(); // For each active track, reduce corresponding bone weight in lowpriority-blendmask // by this animation's weight if (id < lowpriority_mask_.size()) { lowpriority_mask_[id] -= i->second.weight_; if (lowpriority_mask_[id] < 0.0) lowpriority_mask_[id] = 0.0; } } } } // Now set the calculated blendmask on low-priority animations for (AnimationMap::iterator i = animations_.begin(); i != animations_.end(); ++i) { Ogre::AnimationState* animstate = GetAnimationState(entity, i->first); if (!animstate) continue; if (i->second.high_priority_ == false) animstate->_setBlendMaskData(&lowpriority_mask_[0]); } } }
bool EC_Mesh::SetMesh(QString meshResourceName, bool clone) { if (!ViewEnabled()) return false; if (renderer_.expired()) return false; RendererPtr renderer = renderer_.lock(); std::string mesh_name = meshResourceName.trimmed().toStdString(); RemoveMesh(); // If placeable is not set yet, set it manually by searching it from the parent entity if (!placeable_) { Scene::Entity* entity = GetParentEntity(); if (entity) { ComponentPtr placeable = entity->GetComponent(EC_Placeable::TypeNameStatic()); if (placeable) placeable_ = placeable; } } Ogre::SceneManager* scene_mgr = renderer->GetSceneManager(); Ogre::Mesh* mesh = PrepareMesh(mesh_name, clone); if (!mesh) return false; try { entity_ = scene_mgr->createEntity(renderer->GetUniqueObjectName("EC_Mesh_entity"), mesh->getName()); if (!entity_) { LogError("Could not set mesh " + mesh_name); return false; } entity_->setRenderingDistance(drawDistance.Get()); entity_->setCastShadows(castShadows.Get()); entity_->setUserAny(Ogre::Any(GetParentEntity())); // Set UserAny also on subentities for (uint i = 0; i < entity_->getNumSubEntities(); ++i) entity_->getSubEntity(i)->setUserAny(entity_->getUserAny()); if (entity_->hasSkeleton()) { Ogre::SkeletonInstance* skel = entity_->getSkeleton(); // Enable cumulative mode on skeletal animations if (skel) skel->setBlendMode(Ogre::ANIMBLEND_CUMULATIVE); } // Make sure adjustment node is uptodate if (adjustment_node_) { Transform newTransform = nodeTransformation.Get(); adjustment_node_->setPosition(newTransform.position.x, newTransform.position.y, newTransform.position.z); Quaternion adjust(DEGTORAD * newTransform.rotation.x, DEGTORAD * newTransform.rotation.y, DEGTORAD * newTransform.rotation.z); adjustment_node_->setOrientation(Ogre::Quaternion(adjust.w, adjust.x, adjust.y, adjust.z)); // Prevent Ogre exception from zero scale if (newTransform.scale.x < 0.0000001f) newTransform.scale.x = 0.0000001f; if (newTransform.scale.y < 0.0000001f) newTransform.scale.y = 0.0000001f; if (newTransform.scale.z < 0.0000001f) newTransform.scale.z = 0.0000001f; adjustment_node_->setScale(newTransform.scale.x, newTransform.scale.y, newTransform.scale.z); } // Force a re-apply of all materials to this new mesh. ApplyMaterial(); } catch (Ogre::Exception& e) { LogError("Could not set mesh " + mesh_name + ": " + std::string(e.what())); return false; } AttachEntity(); emit MeshChanged(); return true; }