/* PMDModel::getFace: find face data by name */ PMDFace *PMDModel::getFace(const char *name) { PMDFace *match = (PMDFace *) m_name2face.findNearest(name); if (match && MMDFiles_strequal(match->getName(), name) == true) return match; else return NULL; }
/* MotionController::setup: initialize and set up controller */ void MotionController::setup(PMDModel *pmd, VMD *vmd) { BoneMotionLink *bmlink; BoneMotion *bm; PMDBone *b; FaceMotionLink *fmlink; FaceMotion *fm; PMDFace *f; clear(); m_hasCenterBoneMotion = false; m_overrideFirst = false; /* store maximum frame len */ m_maxFrame = vmd->getMaxFrame(); /* allocate bone controller */ m_numBoneCtrl = vmd->getNumBoneKind(); if (m_numBoneCtrl > pmd->getNumBone()) /* their maximum will be smaller one between pmd and vmd */ m_numBoneCtrl = pmd->getNumBone(); m_boneCtrlList = (MotionControllerBoneElement *) malloc(sizeof(MotionControllerBoneElement) * m_numBoneCtrl); /* check all bone definitions in vmd to match the pmd, and store if match */ m_numBoneCtrl = 0; for (bmlink = vmd->getBoneMotionLink(); bmlink; bmlink = bmlink->next) { bm = &(bmlink->boneMotion); if ((b = pmd->getBone(bm->name))) { m_boneCtrlList[m_numBoneCtrl].bone = b; m_boneCtrlList[m_numBoneCtrl].motion = bm; m_numBoneCtrl++; if (bm->numKeyFrame > 1 && MMDFiles_strequal(bm->name, MOTIONCONTROLLER_CENTERBONENAME) == true) { /* This motion has more than 1 key frames for Center Bone, so need re-location */ m_hasCenterBoneMotion = true; } } } /* allocate face controller */ m_numFaceCtrl = vmd->getNumFaceKind(); if (m_numFaceCtrl > pmd->getNumFace()) /* their maximum will be smaller one between pmd and vmd */ m_numFaceCtrl = pmd->getNumFace(); m_faceCtrlList = (MotionControllerFaceElement *) malloc(sizeof(MotionControllerFaceElement) * m_numFaceCtrl); /* check all face definitions in vmd to match the pmd, and store if match */ m_numFaceCtrl = 0; for (fmlink = vmd->getFaceMotionLink(); fmlink; fmlink = fmlink->next) { fm = &(fmlink->faceMotion); if ((f = pmd->getFace(fm->name))) { m_faceCtrlList[m_numFaceCtrl].face = f; m_faceCtrlList[m_numFaceCtrl].motion = fm; m_numFaceCtrl++; } } }
/* PMDBone::setMotionIndependency: check if this bone does not be affected by other controller bones */ void PMDBone::setMotionIndependency() { int i; const char *names[] = {PMDBONE_ADDITIONALROOTNAME}; if (! m_parentBone || m_parentIsRoot) { /* if no parent bone in the model, return true */ m_motionIndependent = true; return; } /* some models has additional model root bone or offset bones, they should be treated specially */ for (i = 0; i < PMDBONE_NADDITIONALROOTNAME; i++) { if (MMDFiles_strequal(m_parentBone->m_name, names[i]) == true) { m_motionIndependent = true; return; } } m_motionIndependent = false; }
/* MotionManager::deleteMotion: delete a motion */ bool MotionManager::deleteMotion(const char *name) { MotionPlayer *m; if (name == NULL) return false; for (m = m_playerList; m; m = m->next) { if (m->active && MMDFiles_strequal(m->name, name) == true) { if (m->enableSmooth) { /* enter the ending status, gradually decreasing the blend rate */ m->endingBoneBlend = m->endingBoneBlendFrames; m->endingFaceBlend = m->endingFaceBlendFrames; } else { /* will deactivate this motion player at the next update */ m->endingBoneBlend = 0.0001f; m->endingFaceBlend = 0.0001f; } return true; } } return false; }
/* MotionManager::setMotionSpeedRate: set motion speed rate */ bool MotionManager::setMotionSpeedRate(const char *name, float speedRate, float changeLength, float targetFrameIndex) { MotionPlayer *m; if (name == NULL || speedRate < 0.0f || changeLength < 0.0f) return false; for (m = m_playerList; m; m = m->next) { if (m->active && MMDFiles_strequal(m->name, name) == true) { m->targetSpeedRate = speedRate; if (targetFrameIndex < 0.0f) { m->remainingFramesForStartOfAcceleration = 0.0f; m->remainingFramesForEndOfAcceleration = changeLength; } else { m->remainingFramesForStartOfAcceleration = targetFrameIndex - (float) m->mc.getCurrentFrame(); if (m->remainingFramesForStartOfAcceleration < 0.0f) m->remainingFramesForStartOfAcceleration += m->vmd->getMaxFrame(); m->remainingFramesForEndOfAcceleration = m->remainingFramesForStartOfAcceleration + changeLength; } m->accelerationStatusFlag = ACCELERATION_STATUS_WAITING; return true; } } return false; }
/* MotionManager::swapMotion: swap a motion, keeping parameters */ bool MotionManager::swapMotion(VMD * vmd, const char * name) { MotionPlayer *m; if (vmd == NULL || name == NULL) return false; /* purge inactive motion managers */ purgeMotion(); /* find the motion player to change */ for (m = m_playerList; m; m = m->next) if (MMDFiles_strequal(m->name, name) == true) break; if (!m) return false; /* not found */ startMotionSub(vmd, m); /* set reset timer for bones/faces that are not controlled by the given base motion */ if (!m->ignoreStatic) m_beginningNonControlledBlend = 10.0f; return true; }
/* MMDAgent_strequal: string matching */ bool MMDAgent_strequal(const char *str1, const char *str2) { return MMDFiles_strequal(str1, str2); }