/* 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); }
/* 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; }