/// <inheritdoc />
        public void Deserialize(Stream stream, Controller controller)
        {
            MeshAnimationController mac = EnsureControllerType(controller);

            using (var reader = new BinaryReader(stream, FileEncoding.Default, true))
            {
                // Read n frames.
                ushort frameCount = reader.ReadUInt16();
                mac.Frames = new List <AnimationKeyFrame>(frameCount);
                for (int i = 0; i < frameCount; i++)
                {
                    mac.Frames.Add(
                        new AnimationKeyFrame
                    {
                        Time        = reader.ReadSingle(),
                        FrameNumber = reader.ReadUInt16()
                    });
                }

                // Get the number of compressed frames and vertices.
                int compressedFrameCount = reader.ReadInt32();
                int vertexCount          = reader.ReadInt32();

                mac.CompressedFrames = new List <CompressedVectors>(compressedFrameCount);
                for (int frameIndex = 0; frameIndex < compressedFrameCount; frameIndex++)
                {
                    var cv = new CompressedVectors
                    {
                        Scale       = reader.ReadSingle(),
                        Translation = reader.ReadSingle(),
                        Vectors     = new List <short>(vertexCount)
                    };

                    for (int vertexIndex = 0; vertexIndex < vertexCount; vertexIndex++)
                    {
                        cv.Vectors.Add(reader.ReadInt16());
                    }

                    mac.CompressedFrames.Add(cv);
                }

                if (stream.Position != stream.Length)
                {
                    mac.Unknown0 = reader.ReadBytes((int)(stream.Length - stream.Position));
                }
            }
        }
Пример #2
0
        /// <summary>
        /// Decompresses the compressed vectors into an enumerable of <typeparamref name="T" />.
        /// </summary>
        /// <typeparam name="T">A class/structure of <see cref="float" /> fields, like <see cref="Vector2" /> or <see cref="Vector3" />.</typeparam>
        /// <returns>An enumerable of <typeparamref name="T" />.</returns>
        public static IEnumerable <T> Decompress <T>(this CompressedVectors compressedVectors)
            where T : struct
        {
            CheckIfSupportedVectorType(typeof(T));

            FieldInfo[] fields = typeof(T).GetFields(BindingFlags.Instance | BindingFlags.Public);
            for (int i = 0; i < compressedVectors.Vectors.Count; i += fields.Length)
            {
                // Box value type.
                var inst = (object)new T();
                for (int j = 0; j < fields.Length; j++)
                {
                    float val = compressedVectors.Scale * compressedVectors.Vectors[i + j] + compressedVectors.Translation;
                    fields[j].SetValue(inst, val);
                }

                yield return((T)inst);
            }
        }
Пример #3
0
        /// <summary>
        /// Compresses vectors into an array where each float component of each vector is represented by an Int16 value, based one scale and translation.
        /// </summary>
        /// <typeparam name="T">A class/structure of <see cref="float" /> fields, like <see cref="Vector2" /> or <see cref="Vector3" />.</typeparam>
        /// <param name="vectors"></param>
        /// <param name="padToCount">Optional argument, to pad the result array of vectors to. This is useful for animation sequences where each animation frame requires the same amount of vectors, but should otherwise be omitted.</param>
        /// <returns>A <see cref="CompressedVectors" /> with the compressed vectors.</returns>
        public static CompressedVectors Compress <T>(ICollection <T> vectors, int padToCount = -1)
            where T : struct
        {
            CheckIfSupportedVectorType(typeof(T));

            FieldInfo[] fields = typeof(T).GetFields(BindingFlags.Instance | BindingFlags.Public);

            GetCompressionRange(vectors, out float bias, out float scale);

            var compressedMeshTransform = new CompressedVectors
            {
                Scale       = scale,
                Translation = bias,
                Vectors     = new List <short>(padToCount > 0 ? padToCount * fields.Length : 0)
            };

            foreach (float floatValue in vectors
                     .SelectMany(v => fields
                                 .Select(f => (float)f.GetValue(v))
                                 )
                     )
            {
                compressedMeshTransform.Vectors.Add(
                    (short)Math.Round(
                        ((double)floatValue - bias) / scale
                        )
                    );
            }

            // Add extra zeroes, in case a fixed length of vectors is required. Animation sequences require each frame to have the same number of vectors. Note however, that adding zeroes will break the mesh animation.
            // This is an edge case that's simply as a fix to prevent crashes, but is not an actual solution and should typically be handled externally.
            if (padToCount > 0)
            {
                for (int i = 0; i < (padToCount - vectors.Count) * fields.Length; i++)
                {
                    compressedMeshTransform.Vectors.Add(0);
                }
            }

            return(compressedMeshTransform);
        }