Beispiel #1
0
        public static void AddAnimationSpline(ref ModelRoot model, animAnimationBufferCompressed blob, string animName, Stream defferedBuffer, animAnimation animAnimDes)
        {
            //boneidx time value
            var positions = new Dictionary <ushort, Dictionary <float, Vec3> >();
            var rotations = new Dictionary <ushort, Dictionary <float, Quat> >();
            var scales    = new Dictionary <ushort, Dictionary <float, Vec3> >();

            var tracks = new Dictionary <ushort, float>();

            if (animAnimDes.MotionExtraction.Chunk != null)
            {
                ROOT_MOTION.AddRootMotion(ref positions, ref rotations, animAnimDes);
            }

            var   br                = new BinaryReader(defferedBuffer);
            float duration          = blob.Duration;
            uint  numFrames         = blob.NumFrames;
            uint  numJoints         = blob.NumJoints;
            uint  numTracks         = blob.NumTracks;
            uint  numExtraJoints    = blob.NumExtraJoints;
            uint  numAnimKeys       = blob.NumAnimKeys;
            uint  numAnimKeysRaw    = blob.NumAnimKeysRaw;
            uint  NumConstAnimKeys  = blob.NumConstAnimKeys;
            uint  numConstTrackKeys = blob.NumConstTrackKeys;

            defferedBuffer.Seek(0, SeekOrigin.Begin);
            for (uint i = 0; i < numAnimKeys; i++)
            {
                var timeNormalized = br.ReadUInt16() / (float)ushort.MaxValue;
                var bitWiseData    = br.ReadUInt16();
                var wSign          = Convert.ToUInt16((bitWiseData & wSignMask) >> wSignRightShift);
                var component      = Convert.ToUInt16((bitWiseData & componentTypeMask) >> componentRightShift);
                var boneIdx        = Convert.ToUInt16((bitWiseData & boneIdxMask) >> boneIdxRightShift);

                var x = ((1f / 65535f) * br.ReadUInt16() * 2) - 1f;
                var y = ((1f / 65535f) * br.ReadUInt16() * 2) - 1f;
                var z = ((1f / 65535f) * br.ReadUInt16() * 2) - 1f;

                switch (component)
                {
                case 0:
                    if (positions.ContainsKey(boneIdx))
                    {
                        positions[boneIdx].Add(timeNormalized * duration, new Vec3(x, z, -y));
                    }
                    else
                    {
                        var dic = new Dictionary <float, Vec3>
                        {
                            { timeNormalized *duration, new Vec3(x, z, -y) }
                        };
                        positions.Add(boneIdx, dic);
                    }
                    break;

                case 1:
                    var dotPr = (x * x + y * y + z * z);
                    x = x * Convert.ToSingle(Math.Sqrt(2f - dotPr));
                    y = y * Convert.ToSingle(Math.Sqrt(2f - dotPr));
                    z = z * Convert.ToSingle(Math.Sqrt(2f - dotPr));
                    var w = 1f - dotPr;
                    if (wSign == 1)
                    {
                        w = -w;
                    }

                    var q = new Quat(x, z, -y, w);
                    if (rotations.ContainsKey(boneIdx))
                    {
                        rotations[boneIdx].Add(timeNormalized * duration, Quat.Normalize(q));
                    }
                    else
                    {
                        var dic = new Dictionary <float, Quat>
                        {
                            { timeNormalized *duration, Quat.Normalize(q) }
                        };
                        rotations.Add(boneIdx, dic);
                    }
                    break;

                case 2:
                    if (scales.ContainsKey(boneIdx))
                    {
                        scales[boneIdx].Add(timeNormalized * duration, new Vec3(x, z, -y));
                    }
                    else
                    {
                        var dic = new Dictionary <float, Vec3>
                        {
                            { timeNormalized *duration, new Vec3(x, z, -y) }
                        };
                        scales.Add(boneIdx, dic);
                    }
                    break;

                default:
                    break;
                }
            }
            for (uint i = 0; i < numAnimKeysRaw; i++)
            {
                var timeNormalized = br.ReadUInt16() / (float)ushort.MaxValue;
                var bitWiseData    = br.ReadUInt16();
                var wSign          = Convert.ToUInt16((bitWiseData & wSignMask) >> wSignRightShift);
                var component      = Convert.ToUInt16((bitWiseData & componentTypeMask) >> componentRightShift);
                var boneIdx        = Convert.ToUInt16((bitWiseData & boneIdxMask) >> boneIdxRightShift);

                var x = br.ReadSingle();
                var y = br.ReadSingle();
                var z = br.ReadSingle();

                switch (component)
                {
                case 0:
                    if (positions.ContainsKey(boneIdx))
                    {
                        positions[boneIdx].Add(timeNormalized * duration, new Vec3(x, z, -y));
                    }
                    else
                    {
                        var dic = new Dictionary <float, Vec3>
                        {
                            { timeNormalized *duration, new Vec3(x, z, -y) }
                        };
                        positions.Add(boneIdx, dic);
                    }
                    break;

                case 1:
                    var dotPr = (x * x + y * y + z * z);
                    x = x * Convert.ToSingle(Math.Sqrt(2f - dotPr));
                    y = y * Convert.ToSingle(Math.Sqrt(2f - dotPr));
                    z = z * Convert.ToSingle(Math.Sqrt(2f - dotPr));
                    var w = 1f - dotPr;
                    if (wSign == 1)
                    {
                        w = -w;
                    }

                    var q = new Quat(x, z, -y, w);
                    if (rotations.ContainsKey(boneIdx))
                    {
                        rotations[boneIdx].Add(timeNormalized * duration, Quat.Normalize(q));
                    }
                    else
                    {
                        var dic = new Dictionary <float, Quat>
                        {
                            { timeNormalized *duration, Quat.Normalize(q) }
                        };
                        rotations.Add(boneIdx, dic);
                    }
                    break;

                case 2:
                    if (scales.ContainsKey(boneIdx))
                    {
                        scales[boneIdx].Add(timeNormalized * duration, new Vec3(x, z, -y));
                    }
                    else
                    {
                        var dic = new Dictionary <float, Vec3>
                        {
                            { timeNormalized *duration, new Vec3(x, z, -y) }
                        };
                        scales.Add(boneIdx, dic);
                    }
                    break;

                default:
                    break;
                }
            }

            for (uint i = 0; i < NumConstAnimKeys; i++)
            {
                var bitWiseData    = br.ReadUInt16();
                var timeNormalized = br.ReadUInt16() / (float)ushort.MaxValue; // is it some time normalized or some padding garbage data i have no idea
                var wSign          = Convert.ToUInt16((bitWiseData & wSignMask) >> wSignRightShift);
                var component      = Convert.ToUInt16((bitWiseData & componentTypeMask) >> componentRightShift);
                var boneIdx        = Convert.ToUInt16((bitWiseData & boneIdxMask) >> boneIdxRightShift);

                var x = br.ReadSingle();
                var y = br.ReadSingle();
                var z = br.ReadSingle();

                switch (component)
                {
                case 0:
                    if (positions.ContainsKey(boneIdx))
                    {
                        positions[boneIdx].Add(0f, new Vec3(x, z, -y));
                    }
                    else
                    {
                        var dic = new Dictionary <float, Vec3>
                        {
                            { 0f, new Vec3(x, z, -y) }
                        };
                        positions.Add(boneIdx, dic);
                    }
                    break;

                case 1:
                    var dotPr = (x * x + y * y + z * z);
                    x = x * Convert.ToSingle(Math.Sqrt(2f - dotPr));
                    y = y * Convert.ToSingle(Math.Sqrt(2f - dotPr));
                    z = z * Convert.ToSingle(Math.Sqrt(2f - dotPr));
                    var w = 1f - dotPr;
                    if (wSign == 1)
                    {
                        w = -w;
                    }

                    var q = new Quat(x, z, -y, w);
                    if (rotations.ContainsKey(boneIdx))
                    {
                        rotations[boneIdx].Add(0f, Quat.Normalize(q));
                    }
                    else
                    {
                        var dic = new Dictionary <float, Quat>
                        {
                            { 0f, Quat.Normalize(q) }
                        };
                        rotations.Add(boneIdx, dic);
                    }
                    break;

                case 2:
                    if (scales.ContainsKey(boneIdx))
                    {
                        scales[boneIdx].Add(0f, new Vec3(x, z, -y));
                    }
                    else
                    {
                        var dic = new Dictionary <float, Vec3>
                        {
                            { 0f, new Vec3(x, z, -y) }
                        };
                        scales.Add(boneIdx, dic);
                    }
                    break;

                default:
                    break;
                }
            }

            /*
             * for (UInt32 i = 0; i < numConstTrackKeys; i++)
             * {
             *  UInt16 idx = br.ReadUInt16();
             *  br.ReadUInt16(); //is it time or some garbage idk
             *  float value = br.ReadSingle();
             * }
             */
            var anim = model.CreateAnimation(animName);

            for (ushort i = 0; i < numJoints - numExtraJoints; i++)
            {
                if (positions.ContainsKey(i))
                {
                    anim.CreateTranslationChannel(model.LogicalNodes[i], positions[i]);
                }
                if (rotations.ContainsKey(i))
                {
                    anim.CreateRotationChannel(model.LogicalNodes[i], rotations[i]);
                }
                if (scales.ContainsKey(i))
                {
                    anim.CreateScaleChannel(model.LogicalNodes[i], scales[i]);
                }
            }
        }
Beispiel #2
0
        public static void AddAnimationSIMD(ref ModelRoot model, animAnimationBufferSimd blob, string animName, Stream defferedBuffer, animAnimation animAnimDes)
        {
            var rootPositions = new Dictionary <ushort, Dictionary <float, Vec3> >();
            var rootRotations = new Dictionary <ushort, Dictionary <float, Quat> >();
            var hasRootMotion = animAnimDes.MotionExtraction.Chunk is not null;

            if (hasRootMotion)
            {
                ROOT_MOTION.AddRootMotion(ref rootPositions, ref rootRotations, animAnimDes);
            }
            var br = new BinaryReader(defferedBuffer);

            var jointsCountAligned    = (blob.NumJoints + 3U) & (~3U);                          // simd 4 alignment
            var totalFloatCount       = (blob.NumFrames * jointsCountAligned * 3 + 3U) & (~3U); // simd 4 alignment
            var rotCompressedBuffSize = totalFloatCount * blob.QuantizationBits / 8U;

            rotCompressedBuffSize = (rotCompressedBuffSize + 15U) & (~15U); // 16byte padding aligment
            var mask = (1U << blob.QuantizationBits) - 1U;

            var floatsPacked = new ushort[totalFloatCount];

            for (uint i = 0; i < totalFloatCount; i++)
            {
                var bitOff  = i * blob.QuantizationBits;
                var byteOff = bitOff / 8;
                var shift   = (bitOff % 8);
                defferedBuffer.Position = byteOff;
                var val = br.ReadUInt32();
                val             = val >> (int)shift;
                floatsPacked[i] = Convert.ToUInt16(val & mask);
            }
            var floatsDecompressed = new float[totalFloatCount];

            for (uint i = 0; i < totalFloatCount; i++)
            {
                floatsDecompressed[i] = ((1f / mask) * floatsPacked[i] * 2) - 1f;
            }
            var Rotations = new Quat[blob.NumFrames, blob.NumJoints];

            for (uint i = 0; i < blob.NumFrames; i++)
            {
                for (uint e = 0; e < blob.NumJoints; e += 4)
                {
                    for (uint eye = 0; eye < 4; eye++)
                    {
                        var q = new Quat
                        {
                            X = floatsDecompressed[i * jointsCountAligned * 3 + e * 3 + eye],
                            Y = floatsDecompressed[i * jointsCountAligned * 3 + e * 3 + 4 + eye],
                            Z = floatsDecompressed[i * jointsCountAligned * 3 + e * 3 + 8 + eye]
                        };

                        var dotPr = (q.X * q.X + q.Y * q.Y + q.Z * q.Z);
                        q.X = q.X * Convert.ToSingle(Math.Sqrt(2f - dotPr));
                        q.Y = q.Y * Convert.ToSingle(Math.Sqrt(2f - dotPr));
                        q.Z = q.Z * Convert.ToSingle(Math.Sqrt(2f - dotPr));
                        q.W = 1f - dotPr;
                        q   = Quat.Normalize(q);
                        if (e + eye < blob.NumJoints)
                        {
                            Rotations[i, e + eye] = new Quat(q.X, q.Z, -q.Y, q.W);
                        }
                    }
                }
            }
            var EvalAlignedPositions = new float[blob.NumFrames * blob.NumTranslationsToEvalAlignedToSimd * 3];

            defferedBuffer.Position = rotCompressedBuffSize;
            for (uint i = 0; i < blob.NumFrames * blob.NumTranslationsToEvalAlignedToSimd * 3; i++)
            {
                EvalAlignedPositions[i] = br.ReadSingle();
            }
            var Scales = new Vec3[blob.NumFrames, blob.NumJoints];

            if (blob.IsScaleConstant)
            {
                var scalesRaw = new float[4];
                for (uint i = 0; i < 4; i++)
                {
                    scalesRaw[i] = br.ReadSingle();
                }
                for (uint i = 0; i < blob.NumFrames; i++)
                {
                    for (uint e = 0; e < blob.NumJoints; e++)
                    {
                        var v = new Vec3
                        {
                            X = scalesRaw[0],
                            Y = scalesRaw[1],
                            Z = scalesRaw[2]
                        };
                        Scales[i, e] = v;
                    }
                }
            }
            else
            {
                var scalesRaw = new float[blob.NumFrames * jointsCountAligned * 3];
                for (uint i = 0; i < blob.NumFrames * jointsCountAligned * 3; i++)
                {
                    scalesRaw[i] = br.ReadSingle();
                }
                for (uint i = 0; i < blob.NumFrames; i++)
                {
                    for (uint e = 0; e < blob.NumJoints; e += 4)
                    {
                        for (uint eye = 0; eye < 4; eye++)
                        {
                            var v = new Vec3
                            {
                                X = scalesRaw[i * jointsCountAligned * 3 + e * 3 + eye],
                                Y = scalesRaw[i * jointsCountAligned * 3 + e * 3 + 4 + eye],
                                Z = scalesRaw[i * jointsCountAligned * 3 + e * 3 + 8 + eye]
                            };
                            Scales[i, e + eye] = v;
                        }
                    }
                }
            }
            if (blob.NumTracks > 0)
            {
                if (!blob.IsTrackConstant)
                {
                    uint asas = ((blob.NumTracks + 3U) & (~3U)) * blob.NumFrames * 4;
                    defferedBuffer.Seek(asas, SeekOrigin.Current);
                }
                else
                {
                    defferedBuffer.Seek(4, SeekOrigin.Current);
                }
            }

            var positionToCopy = new Vec3[blob.NumTranslationsToCopy];

            for (uint e = 0; e < blob.NumTranslationsToCopy; e++)
            {
                positionToCopy[e].X = br.ReadSingle();
                positionToCopy[e].Y = br.ReadSingle();
                positionToCopy[e].Z = br.ReadSingle();
            }

            var evalIndices = new short[blob.NumTranslationsToEvalAlignedToSimd];
            var copyIndices = new short[blob.NumTranslationsToCopy];

            for (uint e = 0; e < blob.NumTranslationsToCopy; e++)
            {
                copyIndices[e] = br.ReadInt16();
            }

            for (uint e = 0; e < blob.NumTranslationsToEvalAlignedToSimd; e++)
            {
                evalIndices[e] = br.ReadInt16();
            }

            var Positions = new Vec3[blob.NumFrames, blob.NumJoints];

            for (uint i = 0; i < blob.NumFrames; i++)
            {
                for (uint e = 0; e < blob.NumTranslationsToEvalAlignedToSimd; e += 4)
                {
                    for (uint eye = 0; eye < 4; eye++)
                    {
                        var v = new Vec3
                        {
                            X = EvalAlignedPositions[i * blob.NumTranslationsToEvalAlignedToSimd * 3 + e * 3 + eye],
                            Y = EvalAlignedPositions[i * blob.NumTranslationsToEvalAlignedToSimd * 3 + e * 3 + 4 + eye],
                            Z = EvalAlignedPositions[i * blob.NumTranslationsToEvalAlignedToSimd * 3 + e * 3 + 8 + eye]
                        };

                        if (evalIndices[e + eye] > -1)
                        {
                            Positions[i, evalIndices[e + eye]] = new Vec3(v.X, v.Z, -v.Y);
                        }
                    }
                }
                for (uint e = 0; e < copyIndices.Length; e++)
                {
                    var v = new Vec3
                    {
                        X = positionToCopy[e].X,
                        Y = positionToCopy[e].Y,
                        Z = positionToCopy[e].Z
                    };

                    Positions[i, copyIndices[e]] = new Vec3(v.X, v.Z, -v.Y);
                }
            }
            var a = model.CreateAnimation(animName);

            for (var e = 0; e < blob.NumJoints - blob.NumExtraJoints; e++)
            {
                var pos  = new Dictionary <float, Vec3>();
                var rot  = new Dictionary <float, Quat>();
                var sca  = new Dictionary <float, Vec3>();
                var diff = blob.Duration / (blob.NumFrames - 1);
                for (var i = 0; i < blob.NumFrames; i++)
                {
                    pos.Add(i * diff, Positions[i, e]);
                    rot.Add(i * diff, Rotations[i, e]);
                    sca.Add(i * diff, Scales[i, e]);
                }
                a.CreateRotationChannel(model.LogicalNodes[e], rot);
                a.CreateTranslationChannel(model.LogicalNodes[e], pos);
                a.CreateScaleChannel(model.LogicalNodes[e], sca);
            }
        }
Beispiel #3
0
        public static void AddAnimationSIMD(ref ModelRoot model, animAnimationBufferSimd blob, string animName, Stream defferedBuffer, animAnimation animAnimDes)
        {
            Dictionary <UInt16, Dictionary <float, Vec3> > rootPositions = new Dictionary <ushort, Dictionary <float, Vec3> >();
            Dictionary <UInt16, Dictionary <float, Quat> > rootRotations = new Dictionary <ushort, Dictionary <float, Quat> >();
            bool hasRootMotion = animAnimDes.MotionExtraction.IsSerialized;

            if (hasRootMotion)
            {
                ROOT_MOTION.AddRootMotion(ref rootPositions, ref rootRotations, animAnimDes);
            }
            BinaryReader br = new BinaryReader(defferedBuffer);

            UInt32 jointsCountAligned    = (blob.NumJoints.Value + 3U) & (~3U);                          // simd 4 alignment
            UInt32 totalFloatCount       = (blob.NumFrames.Value * jointsCountAligned * 3 + 3U) & (~3U); // simd 4 alignment
            UInt32 rotCompressedBuffSize = totalFloatCount * blob.QuantizationBits.Value / 8U;

            rotCompressedBuffSize = (rotCompressedBuffSize + 15U) & (~15U); // 16byte padding aligment
            UInt32 mask = (1U << blob.QuantizationBits.Value) - 1U;

            UInt16[] floatsPacked = new UInt16[totalFloatCount];
            for (UInt32 i = 0; i < totalFloatCount; i++)
            {
                UInt32 bitOff  = i * blob.QuantizationBits.Value;
                UInt32 byteOff = bitOff / 8;
                UInt32 shift   = (bitOff % 8);
                defferedBuffer.Position = byteOff;
                UInt32 val = br.ReadUInt32();
                val             = val >> (int)shift;
                floatsPacked[i] = Convert.ToUInt16(val & mask);
            }
            float[] floatsDecompressed = new float[totalFloatCount];
            for (UInt32 i = 0; i < totalFloatCount; i++)
            {
                floatsDecompressed[i] = ((1f / mask) * floatsPacked[i] * 2) - 1f;
            }
            Quat[,] Rotations = new Quat[blob.NumFrames.Value, blob.NumJoints.Value];
            for (UInt32 i = 0; i < blob.NumFrames.Value; i++)
            {
                for (UInt32 e = 0; e < blob.NumJoints.Value; e += 4)
                {
                    for (UInt32 eye = 0; eye < 4; eye++)
                    {
                        Quat q = new Quat();
                        q.X = floatsDecompressed[i * jointsCountAligned * 3 + e * 3 + eye];
                        q.Y = floatsDecompressed[i * jointsCountAligned * 3 + e * 3 + 4 + eye];
                        q.Z = floatsDecompressed[i * jointsCountAligned * 3 + e * 3 + 8 + eye];

                        float dotPr = (q.X * q.X + q.Y * q.Y + q.Z * q.Z);
                        q.X = q.X * Convert.ToSingle(Math.Sqrt(2f - dotPr));
                        q.Y = q.Y * Convert.ToSingle(Math.Sqrt(2f - dotPr));
                        q.Z = q.Z * Convert.ToSingle(Math.Sqrt(2f - dotPr));
                        q.W = 1f - dotPr;
                        q   = Quat.Normalize(q);
                        if (e + eye < blob.NumJoints.Value)
                        {
                            Rotations[i, e + eye] = new Quat(q.X, q.Z, -q.Y, q.W);
                        }
                    }
                }
            }
            float[] EvalAlignedPositions = new float[blob.NumFrames.Value * blob.NumTranslationsToEvalAlignedToSimd.Value * 3];
            defferedBuffer.Position = rotCompressedBuffSize;
            for (UInt32 i = 0; i < blob.NumFrames.Value * blob.NumTranslationsToEvalAlignedToSimd.Value * 3; i++)
            {
                EvalAlignedPositions[i] = br.ReadSingle();
            }
            Vec3[,] Scales = new Vec3[blob.NumFrames.Value, blob.NumJoints.Value];
            if (blob.IsScaleConstant.Value)
            {
                float[] scalesRaw = new float[4];
                for (UInt32 i = 0; i < 4; i++)
                {
                    scalesRaw[i] = br.ReadSingle();
                }
                for (UInt32 i = 0; i < blob.NumFrames.Value; i++)
                {
                    for (UInt32 e = 0; e < blob.NumJoints.Value; e++)
                    {
                        Vec3 v = new Vec3();
                        v.X          = scalesRaw[0];
                        v.Y          = scalesRaw[1];
                        v.Z          = scalesRaw[2];
                        Scales[i, e] = v;
                    }
                }
            }
            else
            {
                float[] scalesRaw = new float[blob.NumFrames.Value * jointsCountAligned * 3];
                for (UInt32 i = 0; i < blob.NumFrames.Value * jointsCountAligned * 3; i++)
                {
                    scalesRaw[i] = br.ReadSingle();
                }
                for (UInt32 i = 0; i < blob.NumFrames.Value; i++)
                {
                    for (UInt32 e = 0; e < blob.NumJoints.Value; e += 4)
                    {
                        for (UInt32 eye = 0; eye < 4; eye++)
                        {
                            Vec3 v = new Vec3();
                            v.X = scalesRaw[i * jointsCountAligned * 3 + e * 3 + eye];
                            v.Y = scalesRaw[i * jointsCountAligned * 3 + e * 3 + 4 + eye];
                            v.Z = scalesRaw[i * jointsCountAligned * 3 + e * 3 + 8 + eye];
                            Scales[i, e + eye] = v;
                        }
                    }
                }
            }
            if (blob.NumTracks.Value > 0)
            {
                if (!blob.IsTrackConstant.Value)
                {
                    UInt32 asas = ((blob.NumTracks.Value + 3U) & (~3U)) * blob.NumFrames.Value * 4;
                    defferedBuffer.Seek(asas, SeekOrigin.Current);
                }
                else
                {
                    defferedBuffer.Seek(4, SeekOrigin.Current);
                }
            }

            Vec3[] positionToCopy = new Vec3[blob.NumTranslationsToCopy.Value];
            for (UInt32 e = 0; e < blob.NumTranslationsToCopy.Value; e++)
            {
                positionToCopy[e].X = br.ReadSingle();
                positionToCopy[e].Y = br.ReadSingle();
                positionToCopy[e].Z = br.ReadSingle();
            }

            Int16[] evalIndices = new Int16[blob.NumTranslationsToEvalAlignedToSimd.Value];
            Int16[] copyIndices = new Int16[blob.NumTranslationsToCopy.Value];
            for (UInt32 e = 0; e < blob.NumTranslationsToCopy.Value; e++)
            {
                copyIndices[e] = br.ReadInt16();
            }
            for (UInt32 e = 0; e < blob.NumTranslationsToEvalAlignedToSimd.Value; e++)
            {
                evalIndices[e] = br.ReadInt16();
            }

            Vec3[,] Positions = new Vec3[blob.NumFrames.Value, blob.NumJoints.Value];
            for (UInt32 i = 0; i < blob.NumFrames.Value; i++)
            {
                for (UInt32 e = 0; e < blob.NumTranslationsToEvalAlignedToSimd.Value; e += 4)
                {
                    for (UInt32 eye = 0; eye < 4; eye++)
                    {
                        Vec3 v = new Vec3();
                        v.X = EvalAlignedPositions[i * blob.NumTranslationsToEvalAlignedToSimd.Value * 3 + e * 3 + eye];
                        v.Y = EvalAlignedPositions[i * blob.NumTranslationsToEvalAlignedToSimd.Value * 3 + e * 3 + 4 + eye];
                        v.Z = EvalAlignedPositions[i * blob.NumTranslationsToEvalAlignedToSimd.Value * 3 + e * 3 + 8 + eye];

                        if (evalIndices[e + eye] > -1)
                        {
                            Positions[i, evalIndices[e + eye]] = new Vec3(v.X, v.Z, -v.Y);
                        }
                    }
                }
                for (UInt32 e = 0; e < copyIndices.Length; e++)
                {
                    Vec3 v = new Vec3();
                    v.X = positionToCopy[e].X;
                    v.Y = positionToCopy[e].Y;
                    v.Z = positionToCopy[e].Z;

                    Positions[i, copyIndices[e]] = new Vec3(v.X, v.Z, -v.Y);
                }
            }
            var a = model.CreateAnimation(animName);

            for (int e = 0; e < blob.NumJoints.Value - blob.NumExtraJoints.Value; e++)
            {
                var   pos  = new Dictionary <float, Vec3>();
                var   rot  = new Dictionary <float, Quat>();
                var   sca  = new Dictionary <float, Vec3>();
                float diff = blob.Duration.Value / (blob.NumFrames.Value - 1);
                for (int i = 0; i < blob.NumFrames.Value; i++)
                {
                    pos.Add(i * diff, Positions[i, e]);
                    rot.Add(i * diff, Rotations[i, e]);
                    sca.Add(i * diff, Scales[i, e]);
                }
                a.CreateRotationChannel(model.LogicalNodes[e], rot);
                a.CreateTranslationChannel(model.LogicalNodes[e], pos);
                a.CreateScaleChannel(model.LogicalNodes[e], sca);
            }
        }