/// <summary>
        /// Constructs a new animation player.
        /// </summary>
        public AnimationPlayer(SkinningData skinningData)
        {
            if (skinningData == null)
                throw new ArgumentNullException("skinningData");

            skinningDataValue = skinningData;

            boneTransforms = new Matrix[skinningData.BindPose.Count];
            worldTransforms = new Matrix[skinningData.BindPose.Count];
            skinTransforms = new Matrix[skinningData.BindPose.Count];
        }
Beispiel #2
0
        public List<string> GetBoneMapList(SkinningData skinData)
        {
            IDictionary<string, int> boneMap = skinData.BoneMap;

            // Convert to an array so we can loop through
            string[] keys = new string[boneMap.Keys.Count];
            boneMap.Keys.CopyTo(keys, 0);
            int[] values = new int[boneMap.Values.Count];
            boneMap.Values.CopyTo(values, 0);

            // Create the list to store the results
            List<string> results = new List<string>();
            // Add the headings
            results.Add("Bone = #  [ Parent = # ]");
            results.Add("========================");
            // Add the value pairs to the list
            for (int i = 0; i < boneMap.Count; i++)
            {
                int parent = skinData.SkeletonHierarchy[values[i]];
                if (parent >= 0 && parent < keys.Length)
                {
                    results.Add(String.Format("{0} = {1}  [ {2} = {3} ]", keys[i], values[i], keys[parent], parent));
                }
                else
                {
                    results.Add(String.Format("{0} = {1}  [ Root ]", keys[i], values[i]));
                }
            }
            return results;
        }
        // The input only contains the local bone transform
        // This processor adds the bind pose
        private AnimationClip ProcessOneClip(string[] input, SkinningData skinningData, Matrix rotation)
        {
            // This should start at the first line FOLLOWING the clip name
            string[] data = ParseData.SplitNumbersAtSpaces(input[readLine]);
            readLine++;
            // This contains the number of bones in the animation...
            int count = ParseData.IntFromString(data[0]);
            // and the duration of the animation.
            TimeSpan duration = ParseData.TimeFromString(data[1]);
            // There will be no steps in a Blender Action this is just used as a placeholder
            List<TimeSpan> steps = new List<TimeSpan>();
            // Each frame containing the bone and the transform
            // This contains the transform including the bind pose relative to the parent bone
            IList<Keyframe> poseKeyFrames = new List<Keyframe>();
            if (readLine >= input.Length)
            {
                form.AddMessageLine("There are no key frames in this file!");
                return null;
            }

            // To store the current pose
            bindTransforms = new Matrix[skinningData.BindPose.Count];
            poseTransforms = new Matrix[skinningData.BindPose.Count];
            // Now process add all the frames
            localKeyFrames.Clear();
            // Start from the line following the header information
            while (readLine < input.Length)
            {
                // If the line starts with an "=" it is the next clip
                if (input[readLine].Substring(0, 1) == "=")
                {
                    break;
                }
                string[] item = ParseData.SplitItemByDivision(input[readLine]);
                data = ParseData.SplitNumbersAtSpaces(item[0]);
                // The Blender Action clip exports the name of the bone not the index
                // this is to avoid accidentally having a different bone map order
                AddSortedKeyFrame(skinningData.BoneMap[data[0]],
                                    ParseData.TimeFromString(data[1]),
                                    ParseData.StringToMatrix(item[1]));
                readLine++;
            }
            if (localKeyFrames.Count < 1)
            {
                return null;
            }

            // Rotate
            /*
            for (int r = localKeyFrames.Count - 1; r >= 0; r--)
            {
                Matrix changed = Matrix.Identity;
                if (localKeyFrames[r].Bone > 0)
                {
                    int parentBone = skinningData.SkeletonHierarchy[localKeyFrames[r].Bone];
                    Matrix parentInvert = Matrix.Invert(localKeyFrames[parentBone].Transform);
                    // Move to parent space
                    changed = localKeyFrames[r].Transform * parentInvert;
                    changed = rotation * changed;
                }
                else
                {
                    // Root
                    changed = rotation * localKeyFrames[r].Transform;
                }
                localKeyFrames[r] = new Keyframe(localKeyFrames[r].Bone, localKeyFrames[r].Time, changed);
            }
            */

            // Get the bind pose
            skinningData.BindPose.CopyTo(bindTransforms, 0);
            // Start the pose off in the bind pose
            skinningData.BindPose.CopyTo(poseTransforms, 0);
            // Add the bind pose to the local key frames
            poseKeyFrames.Clear();
            // The local key frames are already sorted in to order
            for (int k = 0; k < localKeyFrames.Count; k++)
            {
                int boneID = localKeyFrames[k].Bone;
                TimeSpan time = localKeyFrames[k].Time;
                Matrix transform = localKeyFrames[k].Transform;
                poseTransforms[boneID] = transform * bindTransforms[boneID];
                /*
                if (boneID == 0)
                {
                    // Root bone
                    poseTransforms[boneID] = transform * bindTransforms[boneID];
                }
                else
                {
                    int parentBone = skinningData.SkeletonHierarchy[boneID];
                    Matrix parentInvert = Matrix.Invert(rotation * bindTransforms[parentBone]);
                    // (rotation * parent[frame]).Invert * (rotation * self[frame])
                    // Tried
                    // Matrix parentInvert = Matrix.Invert(rotation * bindTransforms[parentBone]);
                    // (parentInvert * (rotation * transform)) * bindTransforms[boneID];
                    //poseTransforms[boneID] = transform * bindTransforms[boneID];
                    poseTransforms[boneID] = (parentInvert * (rotation * transform)) * bindTransforms[boneID];
                }
                 * */
                poseKeyFrames.Add(new Keyframe(boneID, time, poseTransforms[boneID]));
            }
            // Create the animation clip
            return new AnimationClip(count, duration, poseKeyFrames, steps);
        }
        private Dictionary<string, AnimationClip> ProcessData(string[] input, string fullFile, SkinningData skinningData, Matrix rotation)
        {
            // If there is nothing do not process anything
            if (input.Length < 1)
            {
                return null;
            }

            Dictionary<string, AnimationClip> resultClips = new Dictionary<string,AnimationClip>();

            form.AddMessageLine("Reading file: " + fullFile);

            while (readLine < input.Length)
            {
                // First line of each clip should contain the clip name
                // in the format "=ClipName"
                string clipName = input[readLine];
                if (clipName.Length > 1 && clipName.Substring(0, 1) == "=")
                {
                    // Remove the "=" sign
                    clipName = clipName.Substring(1);
                    readLine++;
                }
                else
                {
                    // Unique clip name based on the current date and time
                    clipName = DateTime.Now.ToString(GlobalSettings.timeFormat);
                    readLine++;
                }
                // Create the animation clip
                form.AddMessageLine("Processing action: " + clipName);
                AnimationClip thisClip = ProcessOneClip(input, skinningData, rotation);
                if (thisClip != null)
                {
                    resultClips.Add(clipName, thisClip);
                }
            }
            return resultClips;
        }