Exemplo n.º 1
0
        /// <summary>
        ///    Reads animation information from the file.
        /// </summary>
        protected void ReadAnimation(BinaryMemoryReader reader)
        {
            // name of the animation
            string name = ReadString(reader);

            // length in seconds of the animation
            float length = ReadFloat(reader);

            // create an animation from the skeleton
            Animation anim = skeleton.CreateAnimation(name, length);

            // keep reading all keyframes for this track
            if (!IsEOF(reader))
            {
                SkeletonChunkID chunkID = ReadChunk(reader);
                while (!IsEOF(reader) && (chunkID == SkeletonChunkID.AnimationTrack))
                {
                    // read the animation track
                    ReadAnimationTrack(reader, anim);
                    // read the next chunk id
                    // If we're not end of file get the next chunk ID
                    if (!IsEOF(reader))
                    {
                        chunkID = ReadChunk(reader);
                    }
                }
                // backpedal to the start of the chunk
                if (!IsEOF(reader))
                {
                    Seek(reader, -ChunkOverheadSize);
                }
            }
        }
        protected void TransformSkeleton(Matrix4 exportTransform)
        {
            Matrix4 invExportTransform = exportTransform.Inverse();
            Dictionary <string, Matrix4> fullInverseBoneTransforms = new Dictionary <string, Matrix4>();
            Skeleton newSkeleton = new Skeleton(skeleton.Name);

            // Construct new versions of the bones, and build
            // the inverse bind matrix that will be needed.
            for (ushort i = 0; i < skeleton.BoneCount; ++i)
            {
                Bone bone    = skeleton.GetBone(i);
                Bone newBone = newSkeleton.CreateBone(bone.Name, bone.Handle);
                fullInverseBoneTransforms[bone.Name] = bone.BindDerivedInverseTransform;
            }
            //  Build the parenting relationship for the new skeleton
            for (ushort i = 0; i < skeleton.BoneCount; ++i)
            {
                Bone bone       = skeleton.GetBone(i);
                Bone newBone    = newSkeleton.GetBone(i);
                Bone parentBone = (Bone)bone.Parent;
                if (parentBone != null)
                {
                    Bone newParentBone = newSkeleton.GetBone(parentBone.Handle);
                    newParentBone.AddChild(newBone);
                }
            }
            // Set the orientation and position for the various bones
            // B' = T * B * Tinv
            for (ushort i = 0; i < newSkeleton.BoneCount; ++i)
            {
                Bone    bone       = skeleton.GetBone(i);
                string  boneName   = bone.Name;
                string  parentName = (bone.Parent == null) ? null : bone.Parent.Name;
                Matrix4 transform  = GetLocalBindMatrix(fullInverseBoneTransforms, boneName, parentName, true);
                transform = exportTransform * transform * invExportTransform;
                Quaternion orientation = GetRotation(transform);
                Bone       newBone     = newSkeleton.GetBone(i);
                newBone.Orientation = orientation;
                newBone.Position    = transform.Translation;
                //if (newBone.Name == "Lower_Torso_BIND_jjj") {
                //    log.DebugFormat("New Bone Position: {0}", transform.Translation);
                //}
            }
            newSkeleton.SetBindingPose();
            for (int i = 0; i < skeleton.AnimationCount; ++i)
            {
                Animation anim    = skeleton.GetAnimation(i);
                Animation newAnim = newSkeleton.CreateAnimation(anim.Name, anim.Length);
                TransformAnimation(exportTransform, newAnim, anim, newSkeleton);
            }
            skeleton = newSkeleton;
        }
        protected void ReadAnimation(XmlNode node)
        {
            string name   = node.Attributes["name"].Value;
            float  length = float.Parse(node.Attributes["length"].Value);
            // create an animation from the skeleton
            Animation anim = skeleton.CreateAnimation(name, length);

            foreach (XmlNode childNode in node.ChildNodes)
            {
                switch (childNode.Name)
                {
                case "tracks":
                    ReadTracks(childNode, anim);
                    break;

                default:
                    DebugMessage(childNode);
                    break;
                }
            }
        }
        public static void CleanupAnimation(Skeleton skel, Animation anim)
        {
            Animation newAnim = skel.CreateAnimation("_replacement", anim.Length);
            Animation tmpAnim = skel.CreateAnimation("_temporary", anim.Length);

            foreach (NodeAnimationTrack track in anim.NodeTracks.Values)
            {
                Bone bone = skel.GetBone((ushort)track.Handle);
                NodeAnimationTrack newTrack = newAnim.CreateNodeTrack(track.Handle, bone);
                NodeAnimationTrack tmpTrack = tmpAnim.CreateNodeTrack(track.Handle, bone);
                int maxFrame     = track.KeyFrames.Count;
                int lastKeyFrame = -1;
                for (int keyFrameIndex = 0; keyFrameIndex < track.KeyFrames.Count; ++keyFrameIndex)
                {
                    if (anim.InterpolationMode == InterpolationMode.Linear)
                    {
                        // Linear is based on one point before and one after.
                        TransformKeyFrame cur = track.GetTransformKeyFrame(keyFrameIndex);
                        if (keyFrameIndex == 0 ||
                            keyFrameIndex == (track.KeyFrames.Count - 1))
                        {
                            // Add the key frame if it is the first or last keyframe.
                            lastKeyFrame = keyFrameIndex;
                            DuplicateKeyFrame(newTrack, cur);
                        }
                        else
                        {
                            // Make sure tmpTrack is clean.. we just use it for interpolation
                            tmpTrack.RemoveAllKeyFrames();
                            TransformKeyFrame prior = track.GetTransformKeyFrame(lastKeyFrame);
                            TransformKeyFrame next  = track.GetTransformKeyFrame(keyFrameIndex + 1);
                            DuplicateKeyFrame(tmpTrack, prior);
                            DuplicateKeyFrame(tmpTrack, next);
                            // Check to see if removing this last keyframe will throw off
                            // any of the other keyframes that were considered redundant.
                            bool needKeyFrame = false;
                            for (int i = lastKeyFrame + 1; i <= keyFrameIndex; ++i)
                            {
                                TransformKeyFrame orig   = track.GetTransformKeyFrame(i);
                                TransformKeyFrame interp = new TransformKeyFrame(tmpTrack, orig.Time);
                                tmpTrack.GetInterpolatedKeyFrame(orig.Time, interp);
                                // Is this interpolated frame useful or redundant?
                                if (!CompareKeyFrames(interp, cur))
                                {
                                    needKeyFrame = true;
                                    break;
                                }
                            }
                            if (needKeyFrame)
                            {
                                lastKeyFrame = keyFrameIndex;
                                DuplicateKeyFrame(newTrack, cur);
                            }
                        }
                    }
                    else if (anim.InterpolationMode == InterpolationMode.Spline)
                    {
                        // Spline is based on two points before and two after.
                        TransformKeyFrame cur = track.GetTransformKeyFrame(keyFrameIndex);
#if DISABLED_CODE
                        if (keyFrameIndex == 0 ||
                            keyFrameIndex == 1 ||
                            keyFrameIndex == (track.KeyFrames.Count - 1) ||
                            keyFrameIndex == (track.KeyFrames.Count - 2))
                        {
                            // Add the key frame if it is the first, second, last or second to last keyframe.
                            DuplicateKeyFrame(newTrack, cur);
                        }
                        else
                        {
                            // Make sure tmpTrack is clean.. we just use it for interpolation
                            tmpTrack.RemoveAllKeyFrames();
                            TransformKeyFrame prior1 = track.GetTransformKeyFrame(keyFrameIndex - 2);
                            TransformKeyFrame prior2 = track.GetTransformKeyFrame(keyFrameIndex - 1);
                            TransformKeyFrame next1  = track.GetTransformKeyFrame(keyFrameIndex + 1);
                            TransformKeyFrame next2  = track.GetTransformKeyFrame(keyFrameIndex + 2);
                            DuplicateKeyFrame(tmpTrack, prior1);
                            DuplicateKeyFrame(tmpTrack, prior2);
                            DuplicateKeyFrame(tmpTrack, next1);
                            DuplicateKeyFrame(tmpTrack, next2);
                            TransformKeyFrame interp = new TransformKeyFrame(tmpTrack, cur.Time);
                            tmpTrack.GetInterpolatedKeyFrame(cur.Time, interp);
                            // Is this interpolated frame useful or redundant?
                            if (!CompareKeyFrames(interp, cur))
                            {
                                DuplicateKeyFrame(newTrack, cur);
                            }
                        }
#else
                        DuplicateKeyFrame(newTrack, cur);
#endif
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false, "Invalid InterpolationMode: " + anim.InterpolationMode);
                    }
                }
            }
            skel.RemoveAnimation(tmpAnim.Name);
            skel.RemoveAnimation(newAnim.Name);
            skel.RemoveAnimation(anim.Name);

            // Recreate the animation with the proper name (awkward)
            anim = skel.CreateAnimation(anim.Name, anim.Length);
            foreach (NodeAnimationTrack track in newAnim.NodeTracks.Values)
            {
                Bone bone = skel.GetBone((ushort)track.Handle);
                NodeAnimationTrack newTrack = anim.CreateNodeTrack(track.Handle, bone);
                foreach (KeyFrame keyFrame in track.KeyFrames)
                {
                    DuplicateKeyFrame(newTrack, (TransformKeyFrame)keyFrame);
                }
            }
        }