Esempio n. 1
0
Ogre::SkeletonPtr MilkshapePlugin::doExportSkeleton(msModel* pModel, Ogre::MeshPtr& mesh)
{
    Ogre::LogManager &logMgr = Ogre::LogManager::getSingleton();
    Ogre::String msg;

    //
    // choose filename
    //
    OPENFILENAME ofn;
    memset (&ofn, 0, sizeof (OPENFILENAME));

    char szFile[MS_MAX_PATH];
    char szFileTitle[MS_MAX_PATH];
    char szDefExt[32] = "skeleton";
    char szFilter[128] = "OGRE .skeleton Files (*.skeleton)\0*.skeleton\0All Files (*.*)\0*.*\0\0";
    szFile[0] = '\0';
    szFileTitle[0] = '\0';

    ofn.lStructSize = sizeof (OPENFILENAME);
    ofn.lpstrDefExt = szDefExt;
    ofn.lpstrFilter = szFilter;
    ofn.lpstrFile = szFile;
    ofn.nMaxFile = MS_MAX_PATH;
    ofn.lpstrFileTitle = szFileTitle;
    ofn.nMaxFileTitle = MS_MAX_PATH;
    ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST;
    ofn.lpstrTitle = "Export to OGRE Skeleton";

    if (!::GetSaveFileName (&ofn))
        return Ogre::SkeletonPtr();

    // Strip off the path
    Ogre::String skelName = szFile;
    size_t lastSlash = skelName.find_last_of("\\");
    skelName = skelName.substr(lastSlash+1);

    // Set up
    logMgr.logMessage("Trying to create Skeleton object");
    Ogre::SkeletonPtr ogreskel = Ogre::SkeletonManager::getSingleton().create(skelName, 
        Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
    logMgr.logMessage("Skeleton object created");

    // Complete the details

    // Do the bones
    int numBones = msModel_GetBoneCount(pModel);
	msg = "Number of bones: " + Ogre::StringConverter::toString(numBones);
    logMgr.logMessage(msg);

    int i;
    // Create all the bones in turn
    for (i = 0; i < numBones; ++i)
    {
        msBone* bone = msModel_GetBoneAt(pModel, i);
        Ogre::Bone* ogrebone = ogreskel->createBone(bone->szName);

        msVec3 msBonePos, msBoneRot;
        msBone_GetPosition(bone, msBonePos);
        msBone_GetRotation(bone, msBoneRot);

        Ogre::Vector3 bonePos(msBonePos[0], msBonePos[1], msBonePos[2]);
        ogrebone->setPosition(bonePos);
        // Hmm, Milkshape has chosen a Euler angle representation of orientation which is not smart
        // Rotation Matrix or Quaternion would have been the smarter choice
        // Might we have Gimbal lock here? What order are these 3 angles supposed to be applied?
        // Grr, we'll try our best anyway...
        Ogre::Quaternion qx, qy, qz, qfinal;
        qx.FromAngleAxis(Ogre::Radian(msBoneRot[0]), Ogre::Vector3::UNIT_X);
        qy.FromAngleAxis(Ogre::Radian(msBoneRot[1]), Ogre::Vector3::UNIT_Y);
        qz.FromAngleAxis(Ogre::Radian(msBoneRot[2]), Ogre::Vector3::UNIT_Z);

        // Assume rotate by x then y then z
        qfinal = qz * qy * qx;
        ogrebone->setOrientation(qfinal);

		Ogre::LogManager::getSingleton().stream()
			<< "Bone #" << i << ": " <<
            "Name='" << bone->szName << "' " <<
            "Position: " << bonePos << " " <<
            "Ms3d Rotation: {" << msBoneRot[0] << ", " << msBoneRot[1] << ", " << msBoneRot[2] << "} " <<
            "Orientation: " << qfinal;


    }
    // Now we've created all the bones, link them up
    logMgr.logMessage("Establishing bone hierarchy..");
    for (i = 0; i < numBones; ++i)
    {
        msBone* bone = msModel_GetBoneAt(pModel, i);

        if (strlen(bone->szParentName) == 0)
        {
            // Root bone
            msg = "Root bone detected: Name='" + Ogre::String(bone->szName) + "' Index=" 
				+ Ogre::StringConverter::toString(i);
            logMgr.logMessage(msg);
        }
        else
        {
            Ogre::Bone* ogrechild = ogreskel->getBone(bone->szName);
            Ogre::Bone* ogreparent = ogreskel->getBone(bone->szParentName);

            if (ogrechild == 0)
            {
                msg = "Error: could not locate child bone '" +
					Ogre::String(bone->szName) + "'";
                logMgr.logMessage(msg);
                continue;
            }
            if (ogreparent == 0)
            {
                msg = "Error: could not locate parent bone '"
					+ Ogre::String(bone->szParentName) + "'";
                logMgr.logMessage(msg);
                continue;
            }
            // Make child
            ogreparent->addChild(ogrechild);
        }


    }
    logMgr.logMessage("Bone hierarchy established.");

    // Create the Animation(s)
    doExportAnimations(pModel, ogreskel);



    // Create skeleton serializer & export
    Ogre::SkeletonSerializer serializer;
    msg = "Exporting skeleton to " + Ogre::String(szFile);
    logMgr.logMessage(msg);
    serializer.exportSkeleton(ogreskel.getPointer(), szFile);
    logMgr.logMessage("Skeleton exported");


    msg = "Linking mesh to skeleton file '" + skelName + "'";
    Ogre::LogManager::getSingleton().logMessage(msg);

    mesh->_notifySkeleton(ogreskel);

    return ogreskel;

}
Esempio n. 2
0
CalVector CMilkBoneNode::GetRelativeTranslation(float time)
{
  // get the position
  msVec3 position;
  msBone_GetPosition(m_pIBone, position);

  CalVector initial_translation;
  initial_translation[0] = position[0];
  initial_translation[1] = position[1];
  initial_translation[2] = position[2];


  // return if the initial state is requested or if there are no keyframes
  if((time < 0.0f) || (msBone_GetPositionKeyCount(m_pIBone) == 0))
  {
    return initial_translation;
  }


  // calculate the real frame time
  // REMEMBER: milkshape starts at 1.0!
  float frameTime;
  frameTime = 1.0f + time * (float)theExporter.GetInterface()->GetFps();

  // find the keyframe just before the requested time
  msPositionKey *pKeyBefore;

  pKeyBefore = msBone_GetPositionKeyAt(m_pIBone,
                                       msBone_GetPositionKeyCount(m_pIBone)-1);


  int keyId;
  for(keyId = 0; keyId < msBone_GetPositionKeyCount(m_pIBone); keyId++)
  {
    // get the keyframe
    msPositionKey *pKey;
    pKey = msBone_GetPositionKeyAt(m_pIBone, keyId);

    // stop if we are over the requested time
    if(pKey->fTime > frameTime) break;

    pKeyBefore = pKey;
  }



  // get the keyframe just after the requested time
  msPositionKey *pKeyAfter;
  pKeyAfter = msBone_GetPositionKeyAt(m_pIBone, 0);

  if(keyId < msBone_GetPositionKeyCount(m_pIBone))
  {
    pKeyAfter = msBone_GetPositionKeyAt(m_pIBone, keyId);
  }


  // calculate the "just before" translation component
  CalVector translationBefore;
  if(pKeyBefore != 0)
  {
    //translationBefore = ConvertToVector(pKeyBefore->Translation);

    translationBefore[0] = pKeyBefore->Position[0];
    translationBefore[1] = pKeyBefore->Position[1];
    translationBefore[2] = pKeyBefore->Position[2];

    // return if there is no key after this one
    if(pKeyAfter == 0)
    {
      return initial_translation + translationBefore;
    }
  }


  // calculate the "just after" translation component
  CalVector translationAfter;
  if(pKeyAfter != 0)
  {
    //translationAfter = ConvertToVector(pKeyAfter->Translation);
    translationAfter[0] = pKeyAfter->Position[0];
    translationAfter[1] = pKeyAfter->Position[1];
    translationAfter[2] = pKeyAfter->Position[2];

    // return if there is no key before this one
    if(pKeyBefore == 0) return initial_translation + translationAfter;
  }


  // return if both keys are actually the same
  if(pKeyBefore == pKeyAfter)
  {
    return initial_translation + translationAfter;
  }

  // calculate the blending factor
  float factor;
  factor = (frameTime - pKeyBefore->fTime) / (pKeyAfter->fTime - pKeyBefore->fTime);


  // Have to blend the two translations.
  translationBefore = translationBefore + (translationAfter - translationBefore);

  return initial_translation + translationBefore;
}