Example #1
0
        private static void ReadKeyLerpData(FArchive reader, UAnimSequence animSequence, CAnimTrack track, int trackIndex, bool hasTimeTracks)
        {
            var compressedData = (FUECompressedAnimData)animSequence.CompressedDataStructure;
            var transOffset    = compressedData.CompressedTrackOffsets[trackIndex * 4];
            var transKeys      = compressedData.CompressedTrackOffsets[trackIndex * 4 + 1];
            var rotOffset      = compressedData.CompressedTrackOffsets[trackIndex * 4 + 2];
            var rotKeys        = compressedData.CompressedTrackOffsets[trackIndex * 4 + 3];

            track.KeyPos  = new FVector[transKeys];
            track.KeyQuat = new FQuat[rotKeys];

            var mins   = FVector.ZeroVector;
            var ranges = FVector.ZeroVector;

            // read translation keys
            if (transKeys > 0)
            {
                reader.Position = transOffset;
                var translationCompressionFormat = compressedData.TranslationCompressionFormat;
                if (transKeys == 1)
                {
                    translationCompressionFormat = ACF_None; // single key is stored without compression
                }
                // read mins/ranges
                if (translationCompressionFormat == ACF_IntervalFixed32NoW)
                {
                    mins   = reader.Read <FVector>();
                    ranges = reader.Read <FVector>();
                }

                for (var keyIndex = 0; keyIndex < transKeys; keyIndex++)
                {
                    track.KeyPos[keyIndex] = translationCompressionFormat switch
                    {
                        ACF_None => reader.Read <FVector>(),
                        ACF_Float96NoW => reader.Read <FVector>(),
                        ACF_IntervalFixed32NoW => reader.ReadVectorIntervalFixed32(mins, ranges),
                        ACF_Fixed48NoW => reader.ReadVectorFixed48(),
                        ACF_Identity => FVector.ZeroVector,
                        _ => throw new ParserException($"Unknown translation compression method: {(int) translationCompressionFormat} ({translationCompressionFormat})")
                    };
                }

                // align to 4 bytes
                reader.Position = reader.Position.Align(4);
                if (hasTimeTracks)
                {
                    ReadTimeArray(reader, transKeys, out track.KeyPosTime, animSequence.NumFrames);
                }
            }
            else
            {
                // A.KeyPos.Add(FVector.ZeroVector);
                // appNotify("No translation keys!");
            }

            // read rotation keys
            reader.Position = rotOffset;
            var rotationCompressionFormat = compressedData.RotationCompressionFormat;

            if (rotKeys == 1)
            {
                rotationCompressionFormat = ACF_Float96NoW; // single key is stored without compression
            }
            else if (rotKeys > 1 && rotationCompressionFormat == ACF_IntervalFixed32NoW)
            {
                // Mins/Ranges are read only when needed - i.e. for ACF_IntervalFixed32NoW
                mins   = reader.Read <FVector>();
                ranges = reader.Read <FVector>();
            }

            for (var k = 0; k < rotKeys; k++)
            {
                track.KeyQuat[k] = rotationCompressionFormat switch
                {
                    ACF_None => reader.Read <FQuat>(),
                    ACF_Float96NoW => reader.ReadQuatFloat96NoW(),
                    ACF_Fixed48NoW => reader.ReadQuatFixed48NoW(),
                    ACF_Fixed32NoW => reader.ReadQuatFixed32NoW(),
                    ACF_IntervalFixed32NoW => reader.ReadQuatIntervalFixed32NoW(mins, ranges),
                    ACF_Float32NoW => reader.ReadQuatFloat32NoW(),
                    ACF_Identity => FQuat.Identity,
                    _ => throw new ParserException($"Unknown rotation compression method: {(int) rotationCompressionFormat} ({rotationCompressionFormat})")
                };
            }

            if (hasTimeTracks)
            {
                // align to 4 bytes
                reader.Position = reader.Position.Align(4);
                ReadTimeArray(reader, rotKeys, out track.KeyQuatTime, animSequence.NumFrames);
            }
        }
Example #2
0
        private static void ReadPerTrackData(FArchive reader, UAnimSequence animSequence, CAnimTrack track, int trackIndex)
        {
            var compressedData = (FUECompressedAnimData)animSequence.CompressedDataStructure;

            // this format uses different key storage
            Trace.Assert(compressedData.TranslationCompressionFormat == ACF_Identity);
            Trace.Assert(compressedData.RotationCompressionFormat == ACF_Identity);

            var transOffset = compressedData.CompressedTrackOffsets[trackIndex * 2];
            var rotOffset   = compressedData.CompressedTrackOffsets[trackIndex * 2 + 1];
            var scaleOffset = compressedData.CompressedScaleOffsets.IsValid() ? compressedData.CompressedScaleOffsets.OffsetData[trackIndex] : -1;

            // read translation keys
            if (transOffset == -1)
            {
                track.KeyPos = new[] { FVector.ZeroVector };
            }
            else
            {
                reader.Position = transOffset;
                ReadPerTrackVectorData(reader, "translation", ref track.KeyPos, ref track.KeyPosTime, animSequence.NumFrames);
            }

            // read rotation keys
            if (rotOffset == -1)
            {
                track.KeyQuat = new[] { FQuat.Identity };
            }
            else
            {
                reader.Position = rotOffset;
                ReadPerTrackQuatData(reader, "rotation", ref track.KeyQuat, ref track.KeyQuatTime, animSequence.NumFrames);
            }

            // read scale keys
            if (scaleOffset != -1)
            {
                reader.Position = scaleOffset;
                ReadPerTrackVectorData(reader, "scale", ref track.KeyScale, ref track.KeyScaleTime, animSequence.NumFrames);
            }
        }