Beispiel #1
0
/* PMDModel::getBone: find bone data by name */
PMDBone *PMDModel::getBone(const char *name)
{
   PMDBone *match = (PMDBone *) m_name2bone.findNearest(name);

   if (match && MMDFiles_strequal(match->getName(), name) == true)
      return match;
   else
      return NULL;
}
/* MotionManager::startMotionSub: initialize a motion */
void MotionManager::startMotionSub(VMD * vmd, MotionPlayer * m)
{
   btVector3 offset;
   PMDBone *centerBone;
   btTransform tr;
   btVector3 pos;

   btVector3 centerPos;
   btVector3 rootOffset;

   /* initialize and setup motion controller */
   m->mc.setup(m_pmd, vmd);

   /* reset values */
   m->mc.reset();

   /* base motion does treat the bones with single motion frame at 0th frame as the same as normal bones */
   m->mc.setIgnoreSingleMotion(m->ignoreStatic);

   /* reset work area */
   m->vmd = vmd;
   m->active = true;
   m->endingBoneBlend = 0.0f;
   m->endingFaceBlend = 0.0f;
   /* when motion is changed, speed acceleration is turned off */
   m->accelerationStatusFlag = ACCELERATION_STATUS_CONSTANT;

   /* set model offset */
   if (m->enableSmooth) {
      offset.setZero();
      if (m->mc.hasCenter() && m->enableRePos) {
         /* when the started motion has center motion, the center position of the model will be moved to the current position */
         /* The current global position of the center bone will become the new offset of the root bone, and the local center position will be reset */
         centerBone = m_pmd->getCenterBone();
         /* calculate relative origin of center bone from model root bone */
         tr = m_pmd->getRootBone()->getTransform()->inverse();
         pos = tr * centerBone->getTransform()->getOrigin();
         /* get the translation vector */
         centerBone->getOriginPosition(&centerPos);
         offset = pos - centerPos;
         offset.setY(0.0f); /* Y axis should be set to zero to place model on ground */
         /* save the current pos/rot for smooth motion changing, resetting center location */
         m->mc.setOverrideFirst(&offset);
         /* add the offset to the root bone */
         m_pmd->getRootBone()->getOffset(&rootOffset);
         rootOffset += offset;
         m_pmd->getRootBone()->setOffset(&rootOffset);
         m_pmd->getRootBone()->update();
      } else {
         /* save the current pos/rot for smooth motion changing */
         m->mc.setOverrideFirst(NULL) ;
      }
   }
}
/* PMDObject::updateModelRootRotation: update model rotation of root bone */
bool PMDObject::updateModelRootRotation(float fps)
{
   btQuaternion tmpRot;
   PMDBone *b;
   bool ret = false;
   btQuaternion r;
   float diff;
   float maxStep;

   if (m_isEnable == false) return false;

   m_isRotating = false;

   /* get root bone */
   b = m_pmd.getRootBone();
   /* target rotation is m_offsetRot */
   /* turn rotation of root bone closer to m_offsetRot */
   b->getCurrentRotation(&r);
   if (m_offsetRot != r) {
      /* difference calculation */
      r = r - m_offsetRot;
      diff = r.length();
      if (diff > PMDOBJECT_MINSPINDIFF) {
         if (m_spinSpeed >= 0.0f && fps != 0.0f) {
            /* max turn speed */
            maxStep = MMDFILES_RAD(m_spinSpeed) / fps;
            if (diff > maxStep) {
               b->getCurrentRotation(&tmpRot);
               tmpRot = tmpRot.slerp(m_offsetRot, maxStep / diff);
               b->setCurrentRotation(&tmpRot);
               m_isRotating = true;
            } else {
               b->setCurrentRotation(&m_offsetRot);
               ret = true;
            }
         } else {
            /* current * 0.95 + target * 0.05 */
            b->getCurrentRotation(&tmpRot);
            tmpRot = tmpRot.slerp(m_offsetRot, 1.0f - PMDOBJECT_SPINSPEEDRATE);
            b->setCurrentRotation(&tmpRot);
            m_isRotating = true;
         }
      } else {
         /* set target offset directory if small difference */
         b->setCurrentRotation(&m_offsetRot);
         ret = true;
      }
      b->update();
   }

   return ret;
}
/* PMDObject::updateModel: update model position of root bone */
bool PMDObject::updateModelRootOffset(float fps)
{
   bool ret = false;
   PMDBone *b;
   btVector3 pos, pos2;
   float diff;
   float maxStep;

   if (m_isEnable == false) return false;

   /* get root bone */
   b = m_pmd.getRootBone();

   /* target position is m_offsetPos */
   /* move offset of root bone closer to m_offsetPos */
   b->getOffset(&pos);
   m_isMoving = false;
   if (m_offsetPos != pos) {
      /* if there is difference then update */
      diff = pos.distance(m_offsetPos);
      if (diff > PMDOBJECT_MINMOVEDIFF) {
         if (m_moveSpeed >= 0.0f && fps != 0.0f) {
            /* max speed */
            maxStep = m_moveSpeed / fps;
            if (diff > maxStep) {
               pos2 = pos.lerp(m_offsetPos, maxStep / diff);
               m_isMoving = true;
            } else {
               pos2 = m_offsetPos;
               ret = true;
            }
         } else {
            /* current * 0.9 + target * 0.1 */
            pos2 = pos.lerp(m_offsetPos, 1.0f - PMDOBJECT_MOVESPEEDRATE);
            m_isMoving = true;
         }
      } else {
         /* set target offset directory if small difference */
         pos2 = m_offsetPos;
         ret = true;
      }
      m_pmd.getRootBone()->setOffset(&pos2);
      m_pmd.getRootBone()->update();
   }

   return ret;
}
/* PMDObject::updateRootBone: update root bone if assigned to a base bone */
void PMDObject::updateRootBone()
{
   btVector3 pos;
   btVector3 posAbs;
   PMDBone *b;
   btTransform tr;

   if (!m_baseBone) return;

   /* relative position */
   pos = m_offsetPos;
   /* if absolute flag is true, fix relative position from root bone */
   posAbs = m_offsetPos + m_origBasePos - m_baseBone->getTransform()->getOrigin();
   if (m_absPosFlag[0]) pos.setX(posAbs.x());
   if (m_absPosFlag[1]) pos.setY(posAbs.y());
   if (m_absPosFlag[2]) pos.setZ(posAbs.z());

   /* set root bone */
   b = m_pmd.getRootBone();
   b->setCurrentPosition(&pos);
   b->setCurrentRotation(&m_offsetRot);
   b->update();
   /* update transform for base position */
   tr = (*m_baseBone->getTransform()) * (*b->getTransform());
   b->setTransform(&tr);
}