public override void Deserialize(FAssetArchive Ar, long validPos)
        {
            base.Deserialize(Ar, validPos);

            var stripFlags = new FStripDataFlags(Ar);

            if (!stripFlags.IsDataStrippedForServer())
            {
                var numEntries = Ar.Read <int>();
                MeshBuildData = new Dictionary <FGuid, FMeshMapBuildData>(numEntries);
                for (var i = 0; i < numEntries; ++i)
                {
                    MeshBuildData[Ar.Read <FGuid>()] = new FMeshMapBuildData(Ar);
                }

                numEntries = Ar.Read <int>();
                LevelPrecomputedLightVolumeBuildData = new Dictionary <FGuid, FPrecomputedLightVolumeData>(numEntries);
                for (var i = 0; i < numEntries; ++i)
                {
                    LevelPrecomputedLightVolumeBuildData[Ar.Read <FGuid>()] = new FPrecomputedLightVolumeData(Ar);
                }

                if (FRenderingObjectVersion.Get(Ar) >= FRenderingObjectVersion.Type.VolumetricLightmaps)
                {
                    numEntries = Ar.Read <int>();
                    LevelPrecomputedVolumetricLightmapBuildData = new Dictionary <FGuid, FPrecomputedVolumetricLightmapData>(numEntries);
                    for (var i = 0; i < numEntries; ++i)
                    {
                        LevelPrecomputedVolumetricLightmapBuildData[Ar.Read <FGuid>()] = new FPrecomputedVolumetricLightmapData(Ar);
                    }
                }

                numEntries     = Ar.Read <int>();
                LightBuildData = new Dictionary <FGuid, FLightComponentMapBuildData>(numEntries);
                for (var i = 0; i < numEntries; ++i)
                {
                    LightBuildData[Ar.Read <FGuid>()] = new FLightComponentMapBuildData(Ar);
                }

                if (FReflectionCaptureObjectVersion.Get(Ar) >= FReflectionCaptureObjectVersion.Type.MoveReflectionCaptureDataToMapBuildData)
                {
                    numEntries = Ar.Read <int>();
                    ReflectionCaptureBuildData = new Dictionary <FGuid, FReflectionCaptureMapBuildData>(numEntries);
                    for (var i = 0; i < numEntries; ++i)
                    {
                        ReflectionCaptureBuildData[Ar.Read <FGuid>()] = new FReflectionCaptureMapBuildData(Ar);
                    }
                }

                if (FRenderingObjectVersion.Get(Ar) >= FRenderingObjectVersion.Type.SkyAtmosphereStaticLightingVersioning)
                {
                    numEntries             = Ar.Read <int>();
                    SkyAtmosphereBuildData = new Dictionary <FGuid, FSkyAtmosphereMapBuildData>(numEntries);
                    for (var i = 0; i < numEntries; ++i)
                    {
                        SkyAtmosphereBuildData[Ar.Read <FGuid>()] = new FSkyAtmosphereMapBuildData(Ar);
                    }
                }
            }
        }
        public FSkeletalMeshVertexBuffer(FAssetArchive Ar)
        {
            var stripDataFlags = new FStripDataFlags(Ar, (int)UE4Version.VER_UE4_STATIC_SKELETAL_MESH_SERIALIZATION_FIX);

            NumTexCoords         = Ar.Read <int>();
            bUseFullPrecisionUVs = Ar.ReadBoolean();

            if (Ar.Ver >= UE4Version.VER_UE4_SUPPORT_GPUSKINNING_8_BONE_INFLUENCES &&
                FSkeletalMeshCustomVersion.Get(Ar) < FSkeletalMeshCustomVersion.Type.UseSeparateSkinWeightBuffer)
            {
                bExtraBoneInfluences = Ar.ReadBoolean();
            }

            MeshExtension = Ar.Read <FVector>();
            MeshOrigin    = Ar.Read <FVector>();

            if (!bUseFullPrecisionUVs)
            {
                VertsHalf = Ar.ReadBulkArray(() => new FGPUVertHalf(Ar, NumTexCoords));
            }
            else
            {
                VertsFloat = Ar.ReadBulkArray(() => new FGPUVertFloat(Ar, NumTexCoords));
            }
        }
        // Pre-UE4.23 code
        public void SerializeBuffersLegacy(FAssetArchive Ar, FStripDataFlags stripDataFlags)
        {
            PositionVertexBuffer = new FPositionVertexBuffer(Ar);
            VertexBuffer         = new FStaticMeshVertexBuffer(Ar);

            if (Ar.Game == EGame.GAME_BORDERLANDS3)
            {
                var numColorStreams = Ar.Read <int>();
                ColorVertexBuffer = new FColorVertexBuffer(Ar);
                for (var i = 0; i < numColorStreams - 1; i++)
                {
                    var _ = new FColorVertexBuffer(Ar);
                }
            }
            else
            {
                ColorVertexBuffer = new FColorVertexBuffer(Ar);
            }

            IndexBuffer = new FRawStaticIndexBuffer(Ar);

            if (Ar.Ver >= UE4Version.VER_UE4_SOUND_CONCURRENCY_PACKAGE && !stripDataFlags.IsClassDataStripped((byte)EClassDataStripFlag.CDSF_ReversedIndexBuffer))
            {
                ReversedIndexBuffer          = new FRawStaticIndexBuffer(Ar);
                DepthOnlyIndexBuffer         = new FRawStaticIndexBuffer(Ar);
                ReversedDepthOnlyIndexBuffer = new FRawStaticIndexBuffer(Ar);
            }
            else
            {
                // UE4.8 or older, or when has CDSF_ReversedIndexBuffer
                DepthOnlyIndexBuffer = new FRawStaticIndexBuffer(Ar);
            }

            if (Ar.Ver is >= UE4Version.VER_UE4_FTEXT_HISTORY and < UE4Version.VER_UE4_RENAME_CROUCHMOVESCHARACTERDOWN)
            {
                new FDistanceFieldVolumeData(Ar); // distanceFieldData
            }

            if (!stripDataFlags.IsEditorDataStripped())
            {
                WireframeIndexBuffer = new FRawStaticIndexBuffer(Ar);
            }

            if (!stripDataFlags.IsClassDataStripped((byte)EClassDataStripFlag.CDSF_AdjacencyData))
            {
                AdjacencyIndexBuffer = new FRawStaticIndexBuffer(Ar);
            }

            if (Ar.Game >= EGame.GAME_UE4_16)
            {
                for (var i = 0; i < Sections.Length; i++)
                {
                    new FWeightedRandomSampler(Ar);
                }

                new FWeightedRandomSampler(Ar);
            }
        }
Example #4
0
        public override void Deserialize(FAssetArchive Ar, long validPos)
        {
            base.Deserialize(Ar, validPos);
            FirstNode = GetOrDefault <FPackageIndex>(nameof(FirstNode));

            if (Ar.Ver >= EUnrealEngineObjectUE4Version.COOKED_ASSETS_IN_EDITOR_SUPPORT)
            {
                var _ = new FStripDataFlags(Ar);
            }
        }
Example #5
0
        public FSkeletalMeshVertexColorBuffer(FAssetArchive Ar)
        {
            var stripDataFlags = new FStripDataFlags(Ar, (int)UE4Version.VER_UE4_STATIC_SKELETAL_MESH_SERIALIZATION_FIX);

            if (!stripDataFlags.IsDataStrippedForServer())
            {
                Data = Ar.ReadBulkArray <FColor>();
            }
            else
            {
                Data = new FColor[0];
            }
        }
Example #6
0
        public FSkeletalMeshVertexClothBuffer(FArchive Ar)
        {
            var stripDataFlags = new FStripDataFlags(Ar, FPackageFileVersion.CreateUE4Version(EUnrealEngineObjectUE4Version.STATIC_SKELETAL_MESH_SERIALIZATION_FIX));

            if (stripDataFlags.IsDataStrippedForServer())
            {
                return;
            }

            Ar.SkipBulkArrayData();
            if (FSkeletalMeshCustomVersion.Get(Ar) >= FSkeletalMeshCustomVersion.Type.CompactClothVertexBuffer)
            {
                ClothIndexMapping = Ar.ReadArray <ulong>();
            }
        }
        public FSkeletalMeshVertexClothBuffer(FArchive Ar)
        {
            var stripDataFlags = new FStripDataFlags(Ar, (int)UE4Version.VER_UE4_STATIC_SKELETAL_MESH_SERIALIZATION_FIX);

            if (stripDataFlags.IsDataStrippedForServer())
            {
                return;
            }

            Ar.SkipBulkArrayData();
            if (FSkeletalMeshCustomVersion.Get(Ar) >= FSkeletalMeshCustomVersion.Type.CompactClothVertexBuffer)
            {
                ClothIndexMapping = Ar.ReadArray <ulong>();
            }
        }
Example #8
0
        public FColorVertexBuffer(FArchive Ar)
        {
            var stripDataFlags = new FStripDataFlags(Ar, (int)UE4Version.VER_UE4_STATIC_SKELETAL_MESH_SERIALIZATION_FIX);

            Stride      = Ar.Read <int>();
            NumVertices = Ar.Read <int>();

            if (!stripDataFlags.IsDataStrippedForServer() & NumVertices > 0)
            {
                Data = Ar.ReadBulkArray <FColor>();
            }
            else
            {
                Data = new FColor[0];
            }
        }
Example #9
0
        public FColorVertexBuffer(FArchive Ar)
        {
            var stripDataFlags = new FStripDataFlags(Ar, FPackageFileVersion.CreateUE4Version(EUnrealEngineObjectUE4Version.STATIC_SKELETAL_MESH_SERIALIZATION_FIX));

            Stride      = Ar.Read <int>();
            NumVertices = Ar.Read <int>();

            if (!stripDataFlags.IsDataStrippedForServer() & NumVertices > 0)
            {
                Data = Ar.ReadBulkArray <FColor>();
            }
            else
            {
                Data = Array.Empty <FColor>();
            }
        }
Example #10
0
        private void SerializeInlineDataRepresentations(FAssetArchive Ar)
        {
            // Defined class flags for possible stripping
            const byte CardRepresentationDataStripFlag = 2;

            var stripFlags = new FStripDataFlags(Ar);

            if (!stripFlags.IsDataStrippedForServer() && !stripFlags.IsClassDataStripped(CardRepresentationDataStripFlag))
            {
                foreach (var lod in LODs)
                {
                    var bValid = Ar.ReadBoolean();
                    if (bValid)
                    {
                        lod.CardRepresentationData = new FCardRepresentationData(Ar);
                    }
                }
            }
        }
Example #11
0
        public FNaniteResources(FAssetArchive Ar)
        {
            var stripFlags = new FStripDataFlags(Ar);

            if (!stripFlags.IsDataStrippedForServer())
            {
                ResourceFlags          = Ar.Read <uint>();
                RootClusterPage        = Ar.ReadArray <byte>();
                StreamableClusterPages = new FByteBulkData(Ar);
                PageStreamingStates    = Ar.ReadArray <FPageStreamingState>();

                HierarchyNodes       = Ar.ReadArray(() => new FPackedHierarchyNode(Ar));
                HierarchyRootOffsets = Ar.ReadArray <uint>();
                PageDependencies     = Ar.ReadArray <uint>();
                ImposterAtlas        = Ar.ReadArray <ushort>();
                PositionPrecision    = Ar.Read <int>();
                NumInputTriangles    = Ar.Read <uint>();
                NumInputVertices     = Ar.Read <uint>();
                NumInputMeshes       = Ar.Read <ushort>();
                NumInputTexCoords    = Ar.Read <ushort>();
            }
        }
Example #12
0
        public FStaticMeshComponentLODInfo(FArchive Ar)
        {
            var stripFlags = new FStripDataFlags(Ar);

            if (!stripFlags.IsDataStrippedForServer())
            {
                MapBuildDataId = Ar.Read <FGuid>();
            }

            if (!stripFlags.IsClassDataStripped(OverrideColorsStripFlag))
            {
                var bLoadVertexColorData = Ar.Read <byte>();

                if (bLoadVertexColorData == 1)
                {
                    OverrideVertexColors = new FColorVertexBuffer(Ar);
                }
            }

            if (!stripFlags.IsEditorDataStripped())
            {
                PaintedVertices = Ar.ReadArray(() => new FPaintedVertex(Ar));
            }
        }
Example #13
0
        public override void Deserialize(FAssetArchive Ar, long validPos)
        {
            base.Deserialize(Ar, validPos);

            NumFrames = GetOrDefault <int>(nameof(NumFrames));
            BoneCompressionSettings          = GetOrDefault <ResolvedObject>(nameof(BoneCompressionSettings));
            CurveCompressionSettings         = GetOrDefault <ResolvedObject>(nameof(CurveCompressionSettings));
            AdditiveAnimType                 = GetOrDefault <EAdditiveAnimationType>(nameof(AdditiveAnimType));
            RetargetSource                   = GetOrDefault <FName>(nameof(RetargetSource));
            RetargetSourceAssetReferencePose = GetOrDefault <FTransform[]>(nameof(RetargetSourceAssetReferencePose));

            if (BoneCompressionSettings == null && Ar.Game == EGame.GAME_RogueCompany)
            {
                BoneCompressionSettings = new ResolvedLoadedObject(Owner !.Provider !.LoadObject("/Game/Animation/KSAnimBoneCompressionSettings.KSAnimBoneCompressionSettings"));
            }

            var stripFlags = new FStripDataFlags(Ar);

            if (!stripFlags.IsEditorDataStripped())
            {
                RawAnimationData = Ar.ReadArray(() => new FRawAnimSequenceTrack(Ar));
                if (Ar.Ver >= EUnrealEngineObjectUE4Version.ANIMATION_ADD_TRACKCURVES)
                {
                    if (FUE5MainStreamObjectVersion.Get(Ar) < FUE5MainStreamObjectVersion.Type.RemovingSourceAnimationData)
                    {
                        var sourceRawAnimationData = Ar.ReadArray(() => new FRawAnimSequenceTrack(Ar));
                        if (sourceRawAnimationData.Length > 0)
                        {
                            // Set RawAnimationData to Source
                            RawAnimationData = sourceRawAnimationData;
                        }
                    }
                }
            }

            if (FFrameworkObjectVersion.Get(Ar) < FFrameworkObjectVersion.Type.MoveCompressedAnimDataToTheDDC)
            {
                var compressedData = new FUECompressedAnimData();
                CompressedDataStructure = compressedData;

                // Part of data were serialized as properties
                compressedData.CompressedByteStream = Ar.ReadBytes(Ar.Read <int>());
                if (Ar.Game == EGame.GAME_SeaOfThieves && compressedData.CompressedByteStream.Length == 1 && Ar.Length - Ar.Position > 0)
                {
                    // Sea of Thieves has extra int32 == 1 before the CompressedByteStream
                    Ar.Position -= 1;
                    compressedData.CompressedByteStream = Ar.ReadBytes(Ar.Read <int>());
                }

                // Fix layout of "byte swapped" data (workaround for UE4 bug)
                if (compressedData.KeyEncodingFormat == AnimationKeyFormat.AKF_PerTrackCompression && compressedData.CompressedScaleOffsets.OffsetData.Length > 0)
                {
                    compressedData.CompressedByteStream = TransferPerTrackData(compressedData.CompressedByteStream);
                }
            }
            else
            {
                // UE4.12+
                var bSerializeCompressedData = Ar.ReadBoolean();

                if (bSerializeCompressedData)
                {
                    if (Ar.Game < EGame.GAME_UE4_23)
                    {
                        SerializeCompressedData(Ar);
                    }
                    else if (Ar.Game < EGame.GAME_UE4_25)
                    {
                        SerializeCompressedData2(Ar);
                    }
                    else
                    {
                        SerializeCompressedData3(Ar);
                    }

                    bUseRawDataOnly = Ar.ReadBoolean();
                }
            }
        }
Example #14
0
        public FStructFallback CompressedCurveData;                     // FRawCurveTracks

        public override void Deserialize(FAssetArchive Ar, long validPos)
        {
            base.Deserialize(Ar, validPos);
            var stripFlags = new FStripDataFlags(Ar);

            if (!stripFlags.IsEditorDataStripped())
            {
                RawAnimationData = Ar.ReadArray(() => new FRawAnimSequenceTrack(Ar));
                if (Ar.Ver >= UE4Version.VER_UE4_ANIMATION_ADD_TRACKCURVES)
                {
                    //if (FUE5MainStreamObjectVersion.Get(Ar) < FUE5MainStreamObjectVersion.Type.RemovingSourceAnimationData)
                    //{
                    var sourceRawAnimationData = Ar.ReadArray(() => new FRawAnimSequenceTrack(Ar));
                    //}
                }
            }

            if (FFrameworkObjectVersion.Get(Ar) < FFrameworkObjectVersion.Type.MoveCompressedAnimDataToTheDDC)
            {
                /*// Part of data were serialized as properties
                 * CompressedByteStream = Ar.ReadArray<byte>();
                 * if (Ar.Game == EGame.GAME_SEAOFTHIEVES && CompressedByteStream.Num() == 1 && Ar.Length - Ar.Position > 0)
                 * {
                 *  // Sea of Thieves has extra int32 == 1 before the CompressedByteStream
                 *  Ar.Position -= 1;
                 *  CompressedByteStream = Ar.ReadArray<byte>();
                 * }
                 *
                 * // Fix layout of "byte swapped" data (workaround for UE4 bug)
                 * if (KeyEncodingFormat == AnimationKeyFormat.AKF_PerTrackCompression && CompressedScaleOffsets.OffsetData.Length > 0)
                 * {
                 *  TArray<uint8> SwappedData;
                 *  TransferPerTrackData(SwappedData, CompressedByteStream);
                 *  Exchange(SwappedData, CompressedByteStream);
                 * }*/
                throw new NotImplementedException();
            }
            else
            {
                // UE4.12+
                var bSerializeCompressedData = Ar.ReadBoolean();

                if (bSerializeCompressedData)
                {
                    if (Ar.Game < EGame.GAME_UE4_23)
                    {
                        SerializeCompressedData(Ar);
                    }
                    else if (Ar.Game < EGame.GAME_UE4_25)
                    {
                        SerializeCompressedData2(Ar);
                    }
                    else
                    {
                        SerializeCompressedData3(Ar);
                    }

                    bUseRawDataOnly = Ar.ReadBoolean();
                }
            }
        }
        public readonly FStaticMeshUVItem[] UV;  // TangentsData ?

        public FStaticMeshVertexBuffer(FArchive Ar)
        {
            var stripDataFlags = new FStripDataFlags(Ar, FPackageFileVersion.CreateUE4Version(EUnrealEngineObjectUE4Version.STATIC_SKELETAL_MESH_SERIALIZATION_FIX));

            // SerializeMetaData
            NumTexCoords                 = Ar.Read <int>();
            Strides                      = Ar.Game < EGame.GAME_UE4_19 ? Ar.Read <int>() : -1;
            NumVertices                  = Ar.Read <int>();
            UseFullPrecisionUVs          = Ar.ReadBoolean();
            UseHighPrecisionTangentBasis = Ar.Game >= EGame.GAME_UE4_12 && Ar.ReadBoolean();

            if (!stripDataFlags.IsDataStrippedForServer())
            {
                if (Ar.Game < EGame.GAME_UE4_19)
                {
                    UV = Ar.ReadBulkArray(() => new FStaticMeshUVItem(Ar, UseHighPrecisionTangentBasis, NumTexCoords, UseFullPrecisionUVs));
                }
                else
                {
                    var tempTangents = Array.Empty <FPackedNormal[]>();
                    if (Ar.Game == EGame.GAME_StarWarsJediFallenOrder && Ar.ReadBoolean()) // bDropNormals
                    {
                        goto texture_coordinates;
                    }
                    // BulkSerialize
                    var itemSize  = Ar.Read <int>();
                    var itemCount = Ar.Read <int>();
                    var position  = Ar.Position;

                    if (itemCount != NumVertices)
                    {
                        throw new ParserException($"NumVertices={itemCount} != NumVertices={NumVertices}");
                    }

                    tempTangents = Ar.ReadArray(NumVertices, () => FStaticMeshUVItem.SerializeTangents(Ar, UseHighPrecisionTangentBasis));
                    if (Ar.Position - position != itemCount * itemSize)
                    {
                        throw new ParserException($"Read incorrect amount of tangent bytes, at {Ar.Position}, should be: {position + itemSize * itemCount} behind: {position + (itemSize * itemCount) - Ar.Position}");
                    }

texture_coordinates:
                    itemSize  = Ar.Read <int>();
                    itemCount = Ar.Read <int>();
                    position  = Ar.Position;

                    if (itemCount != NumVertices * NumTexCoords)
                    {
                        throw new ParserException($"NumVertices={itemCount} != {NumVertices * NumTexCoords}");
                    }

                    var uv = Ar.ReadArray(NumVertices, () => FStaticMeshUVItem.SerializeTexcoords(Ar, NumTexCoords, UseFullPrecisionUVs));
                    if (Ar.Position - position != itemCount * itemSize)
                    {
                        throw new ParserException($"Read incorrect amount of Texture Coordinate bytes, at {Ar.Position}, should be: {position + itemSize * itemCount} behind: {position + (itemSize * itemCount) - Ar.Position}");
                    }

                    UV = new FStaticMeshUVItem[NumVertices];
                    for (var i = 0; i < NumVertices; i++)
                    {
                        if (Ar.Game == EGame.GAME_StarWarsJediFallenOrder && tempTangents.Length == 0)
                        {
                            UV[i] = new FStaticMeshUVItem(new [] { new FPackedNormal(0), new FPackedNormal(0), new FPackedNormal(0) }, uv[i]);
                        }
                        else
                        {
                            UV[i] = new FStaticMeshUVItem(tempTangents[i], uv[i]);
                        }
                    }
                }
            }
            else
            {
                UV = Array.Empty <FStaticMeshUVItem>();
            }
        }
        public FSkeletalMeshVertexColorBuffer(FAssetArchive Ar)
        {
            var stripDataFlags = new FStripDataFlags(Ar, FPackageFileVersion.CreateUE4Version(EUnrealEngineObjectUE4Version.STATIC_SKELETAL_MESH_SERIALIZATION_FIX));

            Data = !stripDataFlags.IsDataStrippedForServer() ? Ar.ReadBulkArray <FColor>() : new FColor[0];
        }
Example #17
0
        // Pre-UE4.23 code
        public void SerializeBuffersLegacy(FAssetArchive Ar, FStripDataFlags stripDataFlags)
        {
            PositionVertexBuffer = new FPositionVertexBuffer(Ar);
            VertexBuffer         = new FStaticMeshVertexBuffer(Ar);

            if (Ar.Game == EGame.GAME_Borderlands3)
            {
                var numColorStreams = Ar.Read <int>();
                if (numColorStreams != 0)
                {
                    ColorVertexBuffer = new FColorVertexBuffer(Ar);
                    for (var i = 0; i < numColorStreams - 1; i++)
                    {
                        var _ = new FColorVertexBuffer(Ar);
                    }
                }
            }
            else
            {
                ColorVertexBuffer = new FColorVertexBuffer(Ar);
            }

            IndexBuffer = new FRawStaticIndexBuffer(Ar);

            if (Ar.Game != EGame.GAME_PlayerUnknownsBattlegrounds || !stripDataFlags.IsClassDataStripped((byte)EClassDataStripFlag.CDSF_StripIndexBuffers))
            {
                if (Ar.Ver >= EUnrealEngineObjectUE4Version.SOUND_CONCURRENCY_PACKAGE && !stripDataFlags.IsClassDataStripped((byte)EClassDataStripFlag.CDSF_ReversedIndexBuffer))
                {
                    ReversedIndexBuffer          = new FRawStaticIndexBuffer(Ar);
                    DepthOnlyIndexBuffer         = new FRawStaticIndexBuffer(Ar);
                    ReversedDepthOnlyIndexBuffer = new FRawStaticIndexBuffer(Ar);
                }
                else
                {
                    // UE4.8 or older, or when has CDSF_ReversedIndexBuffer
                    DepthOnlyIndexBuffer = new FRawStaticIndexBuffer(Ar);
                }

                if (Ar.Ver >= EUnrealEngineObjectUE4Version.FTEXT_HISTORY && Ar.Ver < EUnrealEngineObjectUE4Version.RENAME_CROUCHMOVESCHARACTERDOWN)
                {
                    var _ = new FDistanceFieldVolumeData(Ar); // distanceFieldData
                }

                if (!stripDataFlags.IsEditorDataStripped())
                {
                    WireframeIndexBuffer = new FRawStaticIndexBuffer(Ar);
                }

                if (!stripDataFlags.IsClassDataStripped((byte)EClassDataStripFlag.CDSF_AdjacencyData))
                {
                    AdjacencyIndexBuffer = new FRawStaticIndexBuffer(Ar);
                }
            }

            if (Ar.Game > EGame.GAME_UE4_16)
            {
                for (var i = 0; i < Sections.Length; i++)
                {
                    var _ = new FWeightedRandomSampler(Ar);
                }

                _ = new FWeightedRandomSampler(Ar);
            }
        }
Example #18
0
        public readonly FStaticMeshUVItem[] UV;  // TangentsData ?

        public FStaticMeshVertexBuffer(FArchive Ar)
        {
            var stripDataFlags = new FStripDataFlags(Ar, (int)UE4Version.VER_UE4_STATIC_SKELETAL_MESH_SERIALIZATION_FIX);

            // SerializeMetaData
            NumTexCoords                 = Ar.Read <int>();
            Strides                      = Ar.Game < EGame.GAME_UE4_19 ? Ar.Read <int>() : -1;
            NumVertices                  = Ar.Read <int>();
            UseFullPrecisionUVs          = Ar.ReadBoolean();
            UseHighPrecisionTangentBasis = Ar.Game >= EGame.GAME_UE4_12 && Ar.ReadBoolean();

            if (!stripDataFlags.IsDataStrippedForServer())
            {
                if (Ar.Game < EGame.GAME_UE4_19)
                {
                    UV = Ar.ReadBulkArray(() => new FStaticMeshUVItem(Ar, UseHighPrecisionTangentBasis, NumTexCoords, UseFullPrecisionUVs));
                }
                else
                {
                    // BulkSerialize
                    var itemSize  = Ar.Read <int>();
                    var itemCount = Ar.Read <int>();
                    var position  = Ar.Position;

                    if (itemCount != NumVertices)
                    {
                        throw new ParserException($"NumVertices={itemCount} != NumVertices={NumVertices}");
                    }

                    var tempTangents = Ar.ReadArray(NumVertices, () => FStaticMeshUVItem.SerializeTangents(Ar, UseHighPrecisionTangentBasis));
                    if (Ar.Position - position != itemCount * itemSize)
                    {
                        throw new ParserException($"Read incorrect amount of tangent bytes, at {Ar.Position}, should be: {position + itemSize * itemCount} behind: {position + (itemSize * itemCount) - Ar.Position}");
                    }

                    itemSize  = Ar.Read <int>();
                    itemCount = Ar.Read <int>();
                    position  = Ar.Position;

                    if (itemCount != NumVertices * NumTexCoords)
                    {
                        throw new ParserException($"NumVertices={itemCount} != {NumVertices * NumTexCoords}");
                    }

                    var uv = Ar.ReadArray(NumVertices, () => FStaticMeshUVItem.SerializeTexcoords(Ar, NumTexCoords, UseFullPrecisionUVs));
                    if (Ar.Position - position != itemCount * itemSize)
                    {
                        throw new ParserException($"Read incorrect amount of Texture Coordinate bytes, at {Ar.Position}, should be: {position + itemSize * itemCount} behind: {position + (itemSize * itemCount) - Ar.Position}");
                    }

                    UV = new FStaticMeshUVItem[NumVertices];
                    for (var i = 0; i < NumVertices; i++)
                    {
                        UV[i] = new FStaticMeshUVItem(tempTangents[i], uv[i]);
                    }
                }
            }
            else
            {
                UV = new FStaticMeshUVItem[0];
            }
        }