History: Generic Manual Pose Loading
Source of version: 3 (current)
Copy to clipboard
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:
{CODE(wrap="1", colors="c++")} Ogre::Entity* head;
Ogre::MeshPtr mesh;
map<int, Ogre::VertexPoseKeyFrame*> vertexPoseKeyFrameMap;
const char * poseAnimationStateName = "PoseAnimationState";
{CODE}
Loading Code:
{CODE(wrap="1", colors="c++")} 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);
}
}
{CODE}
Update Code:
{CODE(wrap="1", colors="c++")} /** 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
}
}
{CODE}
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