// saves needed animation frames at the current save-time private bool SaveAnimFrame(int jointIndex, Transform jointTransform, StringBuilder sbDebug) { if (jointTransform == null) { return(false); } string sJointName = jointTransform.name; bool bSuccess = true; float fSaveTime = (float)iSavedFrame / fGlobalFps; if (jointIndex == 0 && !dontSaveRootPos) { // save avatar position Vector3 currentPos = jointTransform.position - initialPos; currentPos.x = -currentPos.x; currentPos.y += initialPos.y; float distToLast = (currentPos - lastSavedPos[jointIndex]).magnitude; if (distToLast >= jointDistanceThreshold) { lastSavedPos[jointIndex] = currentPos; if (sbDebug != null) { sbDebug.AppendFormat("{0}:{1:F2} ", jointIndex, distToLast); } Vector3 vJointPos = currentPos * fUnityScale * fFbxScale; bSuccess &= MocapFbxWrapper.SetAnimCurveTrans(sJointName, fSaveTime, ref vJointPos); } } // save joint orientation Quaternion qJointRot = jointTransform.localRotation; float angleToLast = Quaternion.Angle(lastSavedRot[jointIndex], qJointRot); if (angleToLast >= jointAngleThreshold) { lastSavedRot[jointIndex] = qJointRot; if (sbDebug != null) { sbDebug.AppendFormat("{0}:{1:F0} ", jointIndex, angleToLast); } if (alJointPreRots != null && alJointPostRots != null) { Quaternion qJointPreRot = alJointPreRots[jointIndex]; Quaternion qJointPostRot = alJointPostRots[jointIndex]; qJointRot = Quaternion.Inverse(qJointPreRot) * qJointRot * Quaternion.Inverse(qJointPostRot); } qJointRot.x = -qJointRot.x; qJointRot.w = -qJointRot.w; Vector3 vJointRot = Vector3.zero; MocapFbxWrapper.Quat2Rot(ref qJointRot, ref vJointRot); bSuccess &= MocapFbxWrapper.SetAnimCurveRot(sJointName, fSaveTime, ref vJointRot); } if (iSavedFrame == 0) { // save the node scale in the first frame only Vector3 vJointScale = jointTransform.localScale; MocapFbxWrapper.SetAnimCurveScale(sJointName, 0f, ref vJointScale); } return(bSuccess); }