Пример #1
0
        private static void LoadRawAnimationFromFile(Animation anim, string directory, string filename)
        {
            Debug.Log("Loading Motion from file \"" + filename + "\"");

            // Open given file and split the lines
            TextAsset moCapAsset = Resources.Load <TextAsset>(directory + "/" + filename);

            if (moCapAsset == null)
            {
                Debug.LogError("Unable to load MoCap file: " + filename);
                return;
            }

            string[] data = moCapAsset.text.Split(
                new[] { "\r\n", "\r", "\n" },
                StringSplitOptions.None
                );

            // Read Bone names (Frame 0)
            var bonesLine = data[0];
            var bones     = bonesLine.Split(',');

            // Add all frames to the current Animation (excl. first line (Titles) and last line (empty))
            for (var currentFrame = 1; currentFrame < data.Length - 1; currentFrame += CharacterController.SkipFrames)
            {
                // Pass the current timestamp to the Frame constructor
                var   dataFrame = data[currentFrame].Split(',');
                Frame newFrame  = new Frame(float.Parse(dataFrame[0]));

                // Every bone has data in 7 columns (3 position, 4 rotation)
                foreach (Bone.Type bt in Enum.GetValues(typeof(Bone.Type)))
                {
                    int       off             = (int)bt * 7;
                    Bone.Data currentBoneData = new Bone.Data(
                        new Vector3(
                            float.Parse(dataFrame[off + 1]),    // Start from 1 because of the Timestamp on 0
                            float.Parse(dataFrame[off + 2]),
                            float.Parse(dataFrame[off + 3])
                            ),
                        new Quaternion(
                            float.Parse(dataFrame[off + 4]),
                            float.Parse(dataFrame[off + 5]),
                            float.Parse(dataFrame[off + 6]),
                            float.Parse(dataFrame[off + 7])
                            )
                        );

                    // Create the new Frame
                    newFrame.boneDataDict.Add(bt, currentBoneData);
                }

                // Add the new Frame to the current Motion
                anim.frameList.Add(newFrame);
            }

            Debug.Log("Motion contains " + anim.frameList.Count + " frames");

            // Unload Asset to free Memory
            Resources.UnloadAsset(moCapAsset);
        }
Пример #2
0
 private static (Vector3S, Quaternion) LerpFrame(Bone.Data a, Bone.Data b, float t)
 {
     return(Vector3.Lerp((Vector3)a.position, (Vector3)b.position, t),
            Quaternion.Lerp((Quaternion)a.rotation, (Quaternion)b.rotation, t));
 }
Пример #3
0
        private static void ComputeRootTransform(Animation anim)
        {
            List <Bone.Data> rootSamples = new List <Bone.Data>();

            // 1. Sample the root transform every SampleWindow frames
            for (
                int currentFrame = 0;
                currentFrame + SampleWindow < anim.frameList.Count;
                currentFrame += SampleWindow)
            {
                Bone.Data sample = SampleFromFrame(anim, currentFrame);
                rootSamples.Add(sample);
            }

            // 2. Use sample to determine intermediate values
            // Left padding
            for (
                int currentFrame = 0;
                currentFrame < SampleWindow / 2;
                currentFrame++)
            {
                // Lerp to find a smooth transform
                (Vector3S position, Quaternion rotation) = LerpFrame(
                    anim.frameList[0].boneDataDict[Bone.Type.hips],
                    rootSamples[0],
                    (float)currentFrame / (SampleWindow / 2));

                /// Store found value
                anim.frameList[currentFrame].boneDataDict[Bone.Type.root].position = position;
                anim.frameList[currentFrame].boneDataDict[Bone.Type.root].rotation = rotation;
            }

            // Intermediate frames
            for (
                int currentSample = 0;
                currentSample < rootSamples.Count - 1;
                currentSample++)
            {
                for (
                    int currentFrame = 0;
                    currentFrame < SampleWindow;
                    currentFrame++)
                {
                    // Compute current offset
                    int currentOffset = currentSample * SampleWindow + currentFrame + SampleWindow / 2;

                    // Lerp to find a smooth transform
                    (Vector3S position, Quaternion rotation) = LerpFrame(
                        rootSamples[currentSample],
                        rootSamples[currentSample + 1],
                        currentFrame / SampleWindow);

                    /// Store found value
                    anim.frameList[currentOffset].boneDataDict[Bone.Type.root].position = position;
                    anim.frameList[currentOffset].boneDataDict[Bone.Type.root].rotation = rotation;

                    Debug.Log("root rotation: " + anim.frameList[currentOffset].boneDataDict[Bone.Type.root].rotation.eulerAngles);
                }
            }

            // Right padding
            int rightPaddingFrames = SampleWindow / 2 + anim.frameList.Count % SampleWindow;
            int firstPaddingFrame  = anim.frameList.Count - rightPaddingFrames;

            for (
                int currentFrameOffset = 0;
                currentFrameOffset < rightPaddingFrames;
                currentFrameOffset++)
            {
                // Compute current offset
                int currentOffset = firstPaddingFrame + currentFrameOffset;

                // Lerp to find a smooth transform
                (Vector3S position, Quaternion rotation) = LerpFrame(
                    rootSamples[rootSamples.Count - 1],
                    anim.frameList[anim.frameList.Count - 1].boneDataDict[Bone.Type.hips],
                    currentFrameOffset / rightPaddingFrames);

                /// Store found value
                anim.frameList[currentOffset].boneDataDict[Bone.Type.root].position = position;
                anim.frameList[currentOffset].boneDataDict[Bone.Type.root].rotation = rotation;
            }

            // 3. Recalibrate hips to comply with root's rotation
            //for (
            //    int currentFrame = 0;
            //    currentFrame < anim.frameList.Count;
            //    currentFrame++)
            //{
            //    anim.frameList[currentFrame].boneDataDict[Bone.Type.hips].position -=
            //        anim.frameList[currentFrame].boneDataDict[Bone.Type.root].position;
            //    anim.frameList[currentFrame].boneDataDict[Bone.Type.hips].rotation =
            //        anim.frameList[currentFrame].boneDataDict[Bone.Type.hips].rotation *
            //        Quaternion.Inverse(anim.frameList[currentFrame].boneDataDict[Bone.Type.root].rotation);
            //}
        }