This code is for manually loading and updating poses.
This is a generic pose loader, it should be able to load any mesh with poses on its submeshes. It will not load poses on shared geometry. There is also an update method which will traverse your mesh and update all of the poses that have the name provided. Be sure your exporter names your poses correctly in your .mesh, otherwise the updatePose will not work.
Required Variables:
Copy to clipboard
Ogre::Entity* head; Ogre::MeshPtr mesh; map<int, Ogre::VertexPoseKeyFrame*> vertexPoseKeyFrameMap; const char * poseAnimationStateName = "PoseAnimationState";
Loading Code:
Copy to clipboard
void MeshPoseManager::loadHead(std::string meshFile){ try{ // Pre-load the mesh so that we can tweak it with a manual animation mesh = MeshManager::getSingleton().load(meshFile, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); //we'll read through this list while loading PoseList poseList = mesh->getPoseList(); //used to loop through each submesh int numSubMeshes = mesh->getNumSubMeshes(); int curPoseIndex = 0; //create the animation on the mesh Animation* anim = mesh->createAnimation(poseAnimationStateName, 0); //skip submesh 0 since it is the shared geometry, and we have no poses on that for(int curSubMesh = 1; curSubMesh <= numSubMeshes; curSubMesh++){ //create the VertexTrack on this animation Ogre::VertexAnimationTrack *vt = anim->createVertexTrack(curSubMesh, VAT_POSE); //create the keyframe we will use to update this vertex track //keep all our keyframes in a map for later updating vertexPoseKeyFrameMap[curSubMesh] = vt->createVertexPoseKeyFrame(0); //add the references to each pose that applies to this subMesh while(poseList[curPoseIndex]->getTarget() == curSubMesh-1){ //create a pose reference for each pose vertexPoseKeyFrameMap[curSubMesh]->addPoseReference(curPoseIndex, 0.0f); curPoseIndex++; } } //create the head head = mSceneMgr->createEntity("Head", meshFile); head->getAnimationState(poseAnimationStateName)->setTimePosition(0); head->getAnimationState(poseAnimationStateName)->setEnabled(true); //put entity in scene SceneNode* headNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(); headNode->attachObject(head); } catch(runtime_error err){ std::string error = "ERROR: "; error.append(__FILE__); error.append(err.what()); LogManager::getSingleton().logMessage(error); } }
Update Code:
Copy to clipboard
/** Goes through all the submeshes and all the poses finding and updating poses with this name*/ void MeshPoseManager::updatePose(std::string poseName, float weight){ //get the pose list PoseList poseList = mesh->getPoseList(); int curPoseIndex = 0; //loop through each submesh int numSubMeshes = mesh->getNumSubMeshes(); //skip submesh 0 since it is the shared geometry, and we have no poses on that for(int curSubMesh = 1; curSubMesh <= numSubMeshes; curSubMesh++){ //while the poses apply to the current submesh, check to see if the current pose matches the name, then get the next pose while(poseList[curPoseIndex]->getTarget() == curSubMesh-1){ //get next pose and check if it's the one we want to update if(!poseList[curPoseIndex]->getName().compare(poseName)){ //We found our pose, update it vertexPoseKeyFrameMap[curSubMesh]->updatePoseReference(curPoseIndex, weight); // Dirty animation state since we're fudging this manually //If we don't notify dirty, Ogre doesn't know to update this state //and nothing happens head->getAnimationState(poseAnimationStateName)->getParent()->_notifyDirty(); } curPoseIndex++; //go to the next pose } //go to the next submesh } }
As you can see, the mesh I was loading was a head, but the solution should generalize to any mesh with poses on its submeshes. Please post here http://www.ogre3d.org/phpBB2/viewtopic.php?t=24587 if you have any troubles with the code above.
Hope this is useful.
-brentrossen