Beispiel #1
0
        private void ConformAnimationBindPoses(Skeleton skeleton, Skeleton conformToSkeleton)
        {
            foreach (var trackGroup in Root.TrackGroups)
            {
                for (var i = 0; i < trackGroup.TransformTracks.Count; i++)
                {
                    var track = trackGroup.TransformTracks[i];
                    var bone  = skeleton.GetBoneByName(track.Name);
                    if (bone == null)
                    {
                        string msg = String.Format("Animation track references bone '{0}' that cannot be found in the skeleton.", track.Name);
                        throw new ExportException(msg);
                    }

                    var conformingBone = conformToSkeleton.GetBoneByName(track.Name);
                    if (conformingBone == null)
                    {
                        string msg = String.Format("Animation track references bone '{0}' that cannot be found in the conforming skeleton.", track.Name);
                        throw new ExportException(msg);
                    }

                    var keyframes = track.ToKeyframes();
                    keyframes.SwapBindPose(bone.OriginalTransform, conformingBone.Transform.ToMatrix4());
                    var newTrack = TransformTrack.FromKeyframes(keyframes);
                    newTrack.Flags                = track.Flags;
                    newTrack.Name                 = track.Name;
                    newTrack.ParentAnimation      = track.ParentAnimation;
                    trackGroup.TransformTracks[i] = newTrack;
                }
            }
        }
        public List <animation> ExportTrack(TransformTrack track)
        {
            var anims = new List <animation>();
            var name  = "Bone_" + track.Name.Replace(' ', '_');

            // Export all tracks in a single transform
            anims.AddRange(ExportKeyframeTrack(track, name + "_Transform", name + "/Transform"));

            return(anims);
        }
        private void ConformAnimationBindPoses(Skeleton skeleton, Skeleton conformToSkeleton)
        {
            if (Root.TrackGroups == null)
            {
                return;
            }

            foreach (var trackGroup in Root.TrackGroups)
            {
                for (var i = 0; i < trackGroup.TransformTracks.Count; i++)
                {
                    var track = trackGroup.TransformTracks[i];
                    var bone  = skeleton.GetBoneByName(track.Name);
                    if (bone == null)
                    {
                        //Dummy_Foot -> Dummy_Foot_01
                        bone = skeleton.GetBoneByName(track.Name + "_01");
                    }

                    if (bone == null)
                    {
                        throw new ExportException($"Animation track references bone '{track.Name}' that cannot be found in the skeleton '{skeleton.Name}'.");
                    }

                    var conformingBone = conformToSkeleton.GetBoneByName(bone.Name);
                    if (conformingBone == null)
                    {
                        throw new ExportException($"Animation track references bone '{bone.Name}' that cannot be found in the conforming skeleton '{conformToSkeleton.Name}'.");
                    }

                    var keyframes = track.ToKeyframes();
                    keyframes.SwapBindPose(bone.OriginalTransform, conformingBone.Transform.ToMatrix4());
                    var newTrack = TransformTrack.FromKeyframes(keyframes);
                    newTrack.Flags                = track.Flags;
                    newTrack.Name                 = track.Name;
                    newTrack.ParentAnimation      = track.ParentAnimation;
                    trackGroup.TransformTracks[i] = newTrack;
                }
            }
        }
        public static TransformTrack FromKeyframes(KeyframeTrack keyframes)
        {
            var track = new TransformTrack();

            track.Flags = 0;

            var translateTimes = keyframes.Keyframes.Where(f => f.Value.HasTranslation).Select(f => f.Key).ToList();
            var translations   = keyframes.Keyframes.Where(f => f.Value.HasTranslation).Select(f => f.Value.Translation).ToList();

            if (translateTimes.Count == 1)
            {
                var posCurve = new D3Constant32f();
                posCurve.CurveDataHeader_D3Constant32f = new CurveDataHeader {
                    Format = (int)CurveFormat.D3Constant32f, Degree = 2
                };
                posCurve.Controls = new float[3] {
                    translations[0].X, translations[0].Y, translations[0].Z
                };
                track.PositionCurve = new AnimationCurve {
                    CurveData = posCurve
                };
            }
            else
            {
                var posCurve = new DaK32fC32f();
                posCurve.CurveDataHeader_DaK32fC32f = new CurveDataHeader {
                    Format = (int)CurveFormat.DaK32fC32f, Degree = 2
                };
                posCurve.SetKnots(translateTimes);
                posCurve.SetPoints(translations);
                track.PositionCurve = new AnimationCurve {
                    CurveData = posCurve
                };
            }

            var rotationTimes = keyframes.Keyframes.Where(f => f.Value.HasRotation).Select(f => f.Key).ToList();
            var rotations     = keyframes.Keyframes.Where(f => f.Value.HasRotation).Select(f => f.Value.Rotation).ToList();

            if (rotationTimes.Count == 1)
            {
                var rotCurve = new D4Constant32f();
                rotCurve.CurveDataHeader_D4Constant32f = new CurveDataHeader {
                    Format = (int)CurveFormat.D4Constant32f, Degree = 2
                };
                rotCurve.Controls = new float[4] {
                    rotations[0].X, rotations[0].Y, rotations[0].Z, rotations[0].W
                };
                track.OrientationCurve = new AnimationCurve {
                    CurveData = rotCurve
                };
            }
            else
            {
                var rotCurve = new DaK32fC32f();
                rotCurve.CurveDataHeader_DaK32fC32f = new CurveDataHeader {
                    Format = (int)CurveFormat.DaK32fC32f, Degree = 2
                };
                rotCurve.SetKnots(rotationTimes);
                rotCurve.SetQuaternions(rotations);
                track.OrientationCurve = new AnimationCurve {
                    CurveData = rotCurve
                };
            }

            var scaleTimes = keyframes.Keyframes.Where(f => f.Value.HasScaleShear).Select(f => f.Key).ToList();
            var scales     = keyframes.Keyframes.Where(f => f.Value.HasScaleShear).Select(f => f.Value.ScaleShear).ToList();

            if (scaleTimes.Count == 1)
            {
                var scaleCurve = new DaConstant32f();
                scaleCurve.CurveDataHeader_DaConstant32f = new CurveDataHeader {
                    Format = (int)CurveFormat.DaConstant32f, Degree = 2
                };
                var m = scales[0];
                scaleCurve.Controls = new List <float>
                {
                    m[0, 0], m[0, 1], m[0, 2],
                    m[1, 0], m[1, 1], m[1, 2],
                    m[2, 0], m[2, 1], m[2, 2]
                };
                track.ScaleShearCurve = new AnimationCurve {
                    CurveData = scaleCurve
                };
            }
            else
            {
                var scaleCurve = new DaK32fC32f();
                scaleCurve.CurveDataHeader_DaK32fC32f = new CurveDataHeader {
                    Format = (int)CurveFormat.DaK32fC32f, Degree = 2
                };
                scaleCurve.SetKnots(scaleTimes);
                scaleCurve.SetMatrices(scales);
                track.ScaleShearCurve = new AnimationCurve {
                    CurveData = scaleCurve
                };
            }

            return(track);
        }
Beispiel #5
0
        public TransformTrack MakeTrack()
        {
            var track = new TransformTrack();
            track.Flags = 0;
            track.Name = Bone.Name;

            var positions = Transforms.Select(m => m.ExtractTranslation()).ToList();
            var rotations = Transforms.Select(m => m.ExtractRotation()).ToList();
            var scales = Transforms.Select(m => ScaleToScaleShear(m.ExtractScale())).ToList();

            // Quaternion sign fixup
            // Since GR2 interpolation operates on the raw XYZ values of the quaternion, two subsequent quaternions
            // that express the same rotation (eg. [1, 0.5, 0.5, -0.5] and [1, -0.5, -0.5, 0.5]) will result in a 360 deg
            // rotation during the animation. Shuffle XYZ signs around to make this less likely to happen
            for (var i = 1; i < rotations.Count; i++)
            {
                var r0 = rotations[i - 1];
                var r1 = rotations[i];
                var dot = r0.W * r1.W + r0.X * r1.X + r0.Y * r1.Y + r0.Z * r1.Z;
                if (dot < 0.0)
                {
                    rotations[i] = new Quaternion(-r1.X, -r1.Y, -r1.Z, r1.W);
                }
            }

            var posTimes = Times;
            var minPositions = positions;
            RemoveTrivialFrames(ref posTimes, ref minPositions);
            if (minPositions.Count == 1)
            {
                var posCurve = new D3Constant32f();
                posCurve.CurveDataHeader_D3Constant32f = new CurveDataHeader { Format = (int)CurveFormat.D3Constant32f, Degree = 2 };
                posCurve.Controls = new float[3] { positions[0].X, positions[0].Y, positions[0].Z };
                track.PositionCurve = new AnimationCurve { CurveData = posCurve };
            }
            else
            {
                var posCurve = new DaK32fC32f();
                posCurve.CurveDataHeader_DaK32fC32f = new CurveDataHeader { Format = (int)CurveFormat.DaK32fC32f, Degree = 2 };
                posCurve.SetKnots(Times);
                posCurve.SetPoints(positions);
                track.PositionCurve = new AnimationCurve { CurveData = posCurve };
            }

            var rotTimes = Times;
            var minRotations = rotations;
            RemoveTrivialFrames(ref rotTimes, ref minRotations);
            if (minRotations.Count == 1)
            {
                var rotCurve = new D4Constant32f();
                rotCurve.CurveDataHeader_D4Constant32f = new CurveDataHeader { Format = (int)CurveFormat.D4Constant32f, Degree = 2 };
                rotCurve.Controls = new float[4] { rotations[0].X, rotations[0].Y, rotations[0].Z, rotations[0].W };
                track.OrientationCurve = new AnimationCurve { CurveData = rotCurve };
            }
            else
            {
                var rotCurve = new DaK32fC32f();
                rotCurve.CurveDataHeader_DaK32fC32f = new CurveDataHeader { Format = (int)CurveFormat.DaK32fC32f, Degree = 2 };
                rotCurve.SetKnots(Times);
                rotCurve.SetQuaternions(rotations);
                track.OrientationCurve = new AnimationCurve { CurveData = rotCurve };
            }

            var scaleTimes = Times;
            var minScales = scales;
            RemoveTrivialFrames(ref scaleTimes, ref minScales);
            if (minScales.Count == 1)
            {
                var scaleCurve = new DaConstant32f();
                scaleCurve.CurveDataHeader_DaConstant32f = new CurveDataHeader { Format = (int)CurveFormat.DaConstant32f, Degree = 2 };
                var m = minScales[0];
                scaleCurve.Controls = new List<float>
                {
                    m[0, 0], m[0, 1], m[0, 2],
                    m[1, 0], m[1, 1], m[1, 2],
                    m[2, 0], m[2, 1], m[2, 2]
                };
                track.ScaleShearCurve = new AnimationCurve { CurveData = scaleCurve };
            }
            else
            {
                var scaleCurve = new DaK32fC32f();
                scaleCurve.CurveDataHeader_DaK32fC32f = new CurveDataHeader { Format = (int)CurveFormat.DaK32fC32f, Degree = 2 };
                scaleCurve.SetKnots(Times);
                scaleCurve.SetMatrices(scales);
                track.ScaleShearCurve = new AnimationCurve { CurveData = scaleCurve };
            }

            return track;
        }
        public List <animation> ExportKeyframeTrack(TransformTrack transformTrack, string name, string target)
        {
            var track = transformTrack.ToKeyframes();

            track.MergeAdjacentFrames();
            track.InterpolateFrames();

            var anims  = new List <animation>();
            var inputs = new List <InputLocal>();

            var outputs = new List <float>(track.Keyframes.Count * 16);

            foreach (var keyframe in track.Keyframes.Values)
            {
                var transform = keyframe.ToTransform().ToMatrix4();
                transform.Transpose();
                for (int i = 0; i < 4; i++)
                {
                    for (int j = 0; j < 4; j++)
                    {
                        outputs.Add(transform[i, j]);
                    }
                }
            }

            var interpolations = new List <string>(track.Keyframes.Count);

            for (int i = 0; i < track.Keyframes.Count; i++)
            {
                interpolations.Add("LINEAR");
            }

            var knots = new List <float>(track.Keyframes.Count);

            foreach (var keyframe in track.Keyframes)
            {
                knots.Add(keyframe.Key);
            }

            /*
             * Fix up animations that have only one keyframe by adding another keyframe at
             * the end of the animation.
             * (This mainly applies to DaIdentity and DnConstant32f)
             */
            if (track.Keyframes.Count == 1)
            {
                knots.Add(transformTrack.ParentAnimation.Duration);
                for (int i = 0; i < 16; i++)
                {
                    outputs.Add(outputs[i]);
                }
                interpolations.Add(interpolations[0]);
            }

            var knotsSource = ColladaUtils.MakeFloatSource(name, "inputs", new string[] { "TIME" }, knots.ToArray());
            var knotsInput  = new InputLocal();

            knotsInput.semantic = "INPUT";
            knotsInput.source   = "#" + knotsSource.id;
            inputs.Add(knotsInput);

            var outSource = ColladaUtils.MakeFloatSource(name, "outputs", new string[] { "TRANSFORM" }, outputs.ToArray(), 16, "float4x4");
            var outInput  = new InputLocal();

            outInput.semantic = "OUTPUT";
            outInput.source   = "#" + outSource.id;
            inputs.Add(outInput);

            var interpSource = ColladaUtils.MakeNameSource(name, "interpolations", new string[] { "INTERPOLATION" }, interpolations.ToArray());

            var interpInput = new InputLocal();

            interpInput.semantic = "INTERPOLATION";
            interpInput.source   = "#" + interpSource.id;
            inputs.Add(interpInput);

            var sampler = new sampler();

            sampler.id    = name + "_sampler";
            sampler.input = inputs.ToArray();

            var channel = new channel();

            channel.source = "#" + sampler.id;
            channel.target = target;

            var animation = new animation();

            animation.id   = name;
            animation.name = name;
            var animItems = new List <object>();

            animItems.Add(knotsSource);
            animItems.Add(outSource);
            animItems.Add(interpSource);
            animItems.Add(sampler);
            animItems.Add(channel);
            animation.Items = animItems.ToArray();
            anims.Add(animation);
            return(anims);
        }
Beispiel #7
0
        public TransformTrack MakeTrack()
        {
            var track = new TransformTrack();

            track.Flags = 0;
            track.Name  = Bone.Name;

            var positions = Transforms.Select(m => m.ExtractTranslation()).ToList();
            var rotations = Transforms.Select(m => m.ExtractRotation()).ToList();
            var scales    = Transforms.Select(m => ScaleToScaleShear(m.ExtractScale())).ToList();

            // Quaternion sign fixup
            // Since GR2 interpolation operates on the raw XYZ values of the quaternion, two subsequent quaternions
            // that express the same rotation (eg. [1, 0.5, 0.5, -0.5] and [1, -0.5, -0.5, 0.5]) will result in a 360 deg
            // rotation during the animation. Shuffle XYZ signs around to make this less likely to happen
            for (var i = 1; i < rotations.Count; i++)
            {
                var r0  = rotations[i - 1];
                var r1  = rotations[i];
                var dot = r0.W * r1.W + r0.X * r1.X + r0.Y * r1.Y + r0.Z * r1.Z;
                if (dot < 0.0)
                {
                    rotations[i] = new Quaternion(-r1.X, -r1.Y, -r1.Z, r1.W);
                }
            }

            var posTimes     = Times;
            var minPositions = positions;

            RemoveTrivialFrames(ref posTimes, ref minPositions);
            if (minPositions.Count == 1)
            {
                var posCurve = new D3Constant32f();
                posCurve.CurveDataHeader_D3Constant32f = new CurveDataHeader {
                    Format = (int)CurveFormat.D3Constant32f, Degree = 2
                };
                posCurve.Controls = new float[3] {
                    positions[0].X, positions[0].Y, positions[0].Z
                };
                track.PositionCurve = new AnimationCurve {
                    CurveData = posCurve
                };
            }
            else
            {
                var posCurve = new DaK32fC32f();
                posCurve.CurveDataHeader_DaK32fC32f = new CurveDataHeader {
                    Format = (int)CurveFormat.DaK32fC32f, Degree = 2
                };
                posCurve.SetKnots(Times);
                posCurve.SetPoints(positions);
                track.PositionCurve = new AnimationCurve {
                    CurveData = posCurve
                };
            }

            var rotTimes     = Times;
            var minRotations = rotations;

            RemoveTrivialFrames(ref rotTimes, ref minRotations);
            if (minRotations.Count == 1)
            {
                var rotCurve = new D4Constant32f();
                rotCurve.CurveDataHeader_D4Constant32f = new CurveDataHeader {
                    Format = (int)CurveFormat.D4Constant32f, Degree = 2
                };
                rotCurve.Controls = new float[4] {
                    rotations[0].X, rotations[0].Y, rotations[0].Z, rotations[0].W
                };
                track.OrientationCurve = new AnimationCurve {
                    CurveData = rotCurve
                };
            }
            else
            {
                var rotCurve = new DaK32fC32f();
                rotCurve.CurveDataHeader_DaK32fC32f = new CurveDataHeader {
                    Format = (int)CurveFormat.DaK32fC32f, Degree = 2
                };
                rotCurve.SetKnots(Times);
                rotCurve.SetQuaternions(rotations);
                track.OrientationCurve = new AnimationCurve {
                    CurveData = rotCurve
                };
            }

            var scaleTimes = Times;
            var minScales  = scales;

            RemoveTrivialFrames(ref scaleTimes, ref minScales);
            if (minScales.Count == 1)
            {
                var scaleCurve = new DaConstant32f();
                scaleCurve.CurveDataHeader_DaConstant32f = new CurveDataHeader {
                    Format = (int)CurveFormat.DaConstant32f, Degree = 2
                };
                var m = minScales[0];
                scaleCurve.Controls = new List <float>
                {
                    m[0, 0], m[0, 1], m[0, 2],
                    m[1, 0], m[1, 1], m[1, 2],
                    m[2, 0], m[2, 1], m[2, 2]
                };
                track.ScaleShearCurve = new AnimationCurve {
                    CurveData = scaleCurve
                };
            }
            else
            {
                var scaleCurve = new DaK32fC32f();
                scaleCurve.CurveDataHeader_DaK32fC32f = new CurveDataHeader {
                    Format = (int)CurveFormat.DaK32fC32f, Degree = 2
                };
                scaleCurve.SetKnots(Times);
                scaleCurve.SetMatrices(scales);
                track.ScaleShearCurve = new AnimationCurve {
                    CurveData = scaleCurve
                };
            }

            return(track);
        }