コード例 #1
0
ファイル: AnimConverter.cs プロジェクト: FabianFG/CUE4Parse
        private static void ReadPerTrackQuatData(FArchive Ar, string trackKind, ref FQuat[] dstKeys, ref float[] dstTimeKeys, int numFrames)
        {
            var packedInfo    = Ar.Read <uint>();
            var keyFormat     = (AnimationCompressionFormat)(packedInfo >> 28);
            var componentMask = (int)((packedInfo >> 24) & 0xF);
            var numKeys       = (int)(packedInfo & 0xFFFFFF);
            var hasTimeTracks = (componentMask & 8) != 0;

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

            dstKeys = new FQuat[numKeys];
            if (keyFormat == ACF_IntervalFixed32NoW)
            {
                // read mins/maxs
                if ((componentMask & 1) != 0)
                {
                    mins.X   = Ar.Read <float>();
                    ranges.X = Ar.Read <float>();
                }
                if ((componentMask & 2) != 0)
                {
                    mins.Y   = Ar.Read <float>();
                    ranges.Y = Ar.Read <float>();
                }
                if ((componentMask & 4) != 0)
                {
                    mins.Z   = Ar.Read <float>();
                    ranges.Z = Ar.Read <float>();
                }
            }
            for (var keyIndex = 0; keyIndex < numKeys; keyIndex++)
            {
                dstKeys[keyIndex] = keyFormat switch
                {
                    ACF_None or ACF_Float96NoW => Ar.ReadQuatFloat96NoW(),
                                ACF_Fixed48NoW => Ar.ReadQuatFixed48NoW(componentMask),
                    ACF_Fixed32NoW => Ar.ReadQuatFixed32NoW(),
                    ACF_IntervalFixed32NoW => Ar.ReadQuatIntervalFixed32NoW(mins, ranges),
                    ACF_Float32NoW => Ar.ReadQuatFloat32NoW(),
                    ACF_Identity => FQuat.Identity,
                    _ => throw new ParserException(Ar, $"Unknown {trackKind} compression method: {(int) keyFormat} ({keyFormat})")
                };
            }
            // align to 4 bytes
            Ar.Position = Ar.Position.Align(4);
            if (hasTimeTracks)
            {
                ReadTimeArray(Ar, numKeys, out dstTimeKeys, numFrames);
            }
        }
コード例 #2
0
ファイル: AnimConverter.cs プロジェクト: FabianFG/CUE4Parse
        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);
            }
        }