bool CalCoreTrack::getState(float time, CalVector& translation, CalQuaternion& rotation) const { std::vector<CalCoreKeyframe*>::const_iterator iteratorCoreKeyframeBefore; std::vector<CalCoreKeyframe*>::const_iterator iteratorCoreKeyframeAfter; // get the keyframe after the requested time iteratorCoreKeyframeAfter = getUpperBound(time); // check if the time is after the last keyframe if(iteratorCoreKeyframeAfter == m_keyframes.end()) { // return the last keyframe state --iteratorCoreKeyframeAfter; rotation = (*iteratorCoreKeyframeAfter)->getRotation(); translation = (*iteratorCoreKeyframeAfter)->getTranslation(); return true; } // check if the time is before the first keyframe if(iteratorCoreKeyframeAfter == m_keyframes.begin()) { // return the first keyframe state rotation = (*iteratorCoreKeyframeAfter)->getRotation(); translation = (*iteratorCoreKeyframeAfter)->getTranslation(); return true; } // get the keyframe before the requested one iteratorCoreKeyframeBefore = iteratorCoreKeyframeAfter; --iteratorCoreKeyframeBefore; // get the two keyframe pointers CalCoreKeyframe *pCoreKeyframeBefore; pCoreKeyframeBefore = *iteratorCoreKeyframeBefore; CalCoreKeyframe *pCoreKeyframeAfter; pCoreKeyframeAfter = *iteratorCoreKeyframeAfter; // calculate the blending factor between the two keyframe states float blendFactor; blendFactor = (time - pCoreKeyframeBefore->getTime()) / (pCoreKeyframeAfter->getTime() - pCoreKeyframeBefore->getTime()); // blend between the two keyframes translation = pCoreKeyframeBefore->getTranslation(); translation.blend(blendFactor, pCoreKeyframeAfter->getTranslation()); rotation = pCoreKeyframeBefore->getRotation(); rotation.blend(blendFactor, pCoreKeyframeAfter->getRotation()); return true; }
bool CalCoreTrack::getState(float time, CalVector& translation, CalQuaternion& rotation) { rde::sorted_vector<float, CalCoreKeyframe *>::iterator iteratorCoreKeyframeBefore; rde::sorted_vector<float, CalCoreKeyframe *>::iterator iteratorCoreKeyframeAfter; // get the keyframe after the requested time iteratorCoreKeyframeAfter = m_mapCoreKeyframe.upper_bound(time); // check if the time is after the last keyframe if(iteratorCoreKeyframeAfter == m_mapCoreKeyframe.end()) { // return the last keyframe state --iteratorCoreKeyframeAfter; rotation = (iteratorCoreKeyframeAfter->second)->getRotation(); translation = (iteratorCoreKeyframeAfter->second)->getTranslation(); return true; } // check if the time is before the first keyframe if(iteratorCoreKeyframeAfter == m_mapCoreKeyframe.begin()) { // return the first keyframe state rotation = (iteratorCoreKeyframeAfter->second)->getRotation(); translation = (iteratorCoreKeyframeAfter->second)->getTranslation(); return true; } // get the keyframe before the requested one iteratorCoreKeyframeBefore = iteratorCoreKeyframeAfter; --iteratorCoreKeyframeBefore; // get the two keyframe pointers CalCoreKeyframe *pCoreKeyframeBefore; pCoreKeyframeBefore = iteratorCoreKeyframeBefore->second; CalCoreKeyframe *pCoreKeyframeAfter; pCoreKeyframeAfter = iteratorCoreKeyframeAfter->second; // calculate the blending factor between the two keyframe states float blendFactor; blendFactor = (time - pCoreKeyframeBefore->getTime()) / (pCoreKeyframeAfter->getTime() - pCoreKeyframeBefore->getTime()); // blend between the two keyframes translation = pCoreKeyframeBefore->getTranslation(); translation.blend(blendFactor, pCoreKeyframeAfter->getTranslation()); rotation = pCoreKeyframeBefore->getRotation(); rotation.blend(blendFactor, pCoreKeyframeAfter->getRotation()); return true; }
bool CalCoreTrack::keyframeEliminatable( CalCoreKeyframe * prev, CalCoreKeyframe * p, CalCoreKeyframe * next, double transTolerance, double rotTolerance ) { CalVector translation; CalQuaternion rotation; assert( prev && p && next ); float time = p->getTime(); float blendFactor; blendFactor = ( time - prev->getTime() ) / ( next->getTime() - prev->getTime() ); // blend between the two keyframes translation = prev->getTranslation(); translation.blend( blendFactor, next->getTranslation() ); rotation = prev->getRotation(); rotation.blend( blendFactor, next->getRotation() ); CalVector const ppos = p->getTranslation(); CalQuaternion const pori = p->getRotation(); return Near( translation, rotation, ppos, pori, transTolerance, rotTolerance ); }
CalQuaternion CMilkBoneNode::GetRelativeRotation(float time) { // get the initial rotation component msVec3 orientation; msBone_GetRotation(m_pIBone, orientation); // calculate the initial rotation component CalQuaternion initialRotation; initialRotation = ConvertToQuaternion(orientation); // return if the initial state is requested or if there are no keyframes if((time < 0.0f) || (msBone_GetRotationKeyCount(m_pIBone) == 0)) return initialRotation; // 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 msRotationKey *pKeyBefore; pKeyBefore = msBone_GetRotationKeyAt(m_pIBone, msBone_GetRotationKeyCount(m_pIBone) - 1); int keyId; for(keyId = 0; keyId < msBone_GetRotationKeyCount(m_pIBone); keyId++) { // get the keyframe msRotationKey *pKey; pKey = msBone_GetRotationKeyAt(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 msRotationKey *pKeyAfter; pKeyAfter = msBone_GetRotationKeyAt(m_pIBone, 0); if(keyId < msBone_GetRotationKeyCount(m_pIBone)) { pKeyAfter = msBone_GetRotationKeyAt(m_pIBone, keyId); } // calculate the "just before" rotation component CalQuaternion rotationBefore; if(pKeyBefore != 0) { rotationBefore = ConvertToQuaternion(pKeyBefore->Rotation); // return if there is no key after this one if(pKeyAfter == 0) return initialRotation * rotationBefore; } // calculate the "just after" rotation component CalQuaternion rotationAfter; if(pKeyAfter != 0) { rotationAfter = ConvertToQuaternion(pKeyAfter->Rotation); // return if there is no key before this one if(pKeyBefore == 0) return initialRotation * rotationAfter; } // return if both keys are actually the same if(pKeyBefore == pKeyAfter) return initialRotation * rotationAfter; // calculate the blending factor float factor; factor = (frameTime - pKeyBefore->fTime) / (pKeyAfter->fTime - pKeyBefore->fTime); // blend the two rotation components rotationBefore.blend(factor, rotationAfter); return initialRotation * rotationBefore; }