/// <summary> /// xna will use this function to read my own .xnb file /// </summary> /// <param name="reader"></param> public void Load(ContentReader reader) { //read the speed of animation AnimationSpeed = reader.ReadSingle(); //first of all:it's bones count BonesCount = reader.ReadInt32(); VmdAnimationFrames = new Dictionary <string, List <VmdKeyframe> >(); for (int i = 0; i < BonesCount; i++) { //for each bone //1 bone name string boneName = reader.ReadString(); List <VmdKeyframe> framesOfThisBone = new List <VmdKeyframe>(); //2 keyframe count int keyframeCountOfThisBone = reader.ReadInt32(); //3 get all frame of this bone and push them into VmdFrames for (int j = 0; j < keyframeCountOfThisBone; j++) { //get pos and rotation VmdKeyframe keyframe = new VmdKeyframe(); //read time keyframe.Time = reader.ReadSingle(); keyframe.Position = reader.ReadVector3(); keyframe.Rotation = reader.ReadQuaternion(); //push it into array framesOfThisBone.Add(keyframe); } VmdAnimationFrames[boneName] = framesOfThisBone; } #region Face Frames //face frame count int faceFrameCount = reader.ReadInt32(); //just a copy of sth VmdFaceFrames = new VmdFaceFrame[faceFrameCount]; for (int i = 0; i < faceFrameCount; i++) { VmdFaceFrames[i].MorphName = reader.ReadString(); VmdFaceFrames[i].IndexOfFrame = reader.ReadSingle(); VmdFaceFrames[i].WeightOfBaseVertex = reader.ReadSingle(); } #endregion }
/// <summary> /// update animation /// change the customBoneTransformation /// </summary> /// <param name="gameTime"></param> private void UpdateAnimation(GameTime gameTime) { if (currentAnimation == null) { return; } //according the keyframes in the animation //change the customBoneTransformation //parameter:0.00005 is adjust for real situation in real world g_time += gameTime.ElapsedGameTime.Milliseconds * 0.00005f * currentAnimation.AnimationSpeed; //now we have tha animation //whether loop the animation if (g_time > 1.0f) { if (LoopAnimation) { g_time = 0.0f; } } //check every bone and find their keyfram according to time for (int i = 0; i < bonesNameList.Count; i++) { //if not exist the current bone if (!currentAnimation.VmdAnimationFrames.ContainsKey(bonesNameList[i])) { boneLocalTransform[i] = boneLocalPose[i]; continue; } List <VmdKeyframe> frames = currentAnimation.VmdAnimationFrames[bonesNameList[i]]; if (frames == null) { continue;//if we couldn't find the bone } //find the frame index int index = 0; while ((index < frames.Count) && (frames[index].Time < g_time)) { index++; } if (index == 0) { Vector3 internalPos = frames[0].Position; Quaternion internalRot = frames[0].Rotation;; customBoneTransformation[i] = (new Transform(new Vector3(0, 0, 0), internalRot)) * (new Transform(internalPos, Quaternion.Identity)); //customBoneTransformation[i] = new Transform(internalPos, internalRot); //customBoneTransformation[i] = Matrix.CreateFromQuaternion(internalRot) * Matrix.CreateTranslation(internalPos); } else if (index >= frames.Count) { Vector3 internalPos = frames[frames.Count - 1].Position; Quaternion internalRot = frames[frames.Count - 1].Rotation; customBoneTransformation[i] = (new Transform(new Vector3(0, 0, 0), internalRot)) * (new Transform(internalPos, Quaternion.Identity)); //customBoneTransformation[i] = new Transform(internalPos, internalRot); //customBoneTransformation[i] = Matrix.CreateFromQuaternion(internalRot) * Matrix.CreateTranslation(internalPos); } else { //interpolate frame //1 position VmdKeyframe current = frames[index - 1]; VmdKeyframe next = frames[index]; float ratio = (g_time - frames[index - 1].Time) / (frames[index].Time - frames[index - 1].Time); Vector3 internalPos = current.Position * (1 - ratio) + ratio * next.Position; Quaternion internalRot = Quaternion.Lerp(current.Rotation, next.Rotation, ratio); //change customBoneTransformation customBoneTransformation[i] = (new Transform(new Vector3(0, 0, 0), internalRot)) * (new Transform(internalPos, Quaternion.Identity)); //customBoneTransformation[i] = new Transform(internalPos, internalRot); //customBoneTransformation[i] = Matrix.CreateFromQuaternion(internalRot) * Matrix.CreateTranslation(internalPos); } boneLocalTransform[i] = customBoneTransformation[i] * boneLocalPose[i]; } }