Ejemplo n.º 1
0
        private void SerializeStreamedData(FArchive Ar, bool bHasVertexColors)
        {
            var stripDataFlags = Ar.Read <FStripDataFlags>();

            Indices             = new FMultisizeIndexContainer(Ar);
            VertexBufferGPUSkin = new FSkeletalMeshVertexBuffer {
                bUseFullPrecisionUVs = true
            };

            var positionVertexBuffer   = new FPositionVertexBuffer(Ar);
            var staticMeshVertexBuffer = new FStaticMeshVertexBuffer(Ar);
            var skinWeightVertexBuffer = new FSkinWeightVertexBuffer(Ar, VertexBufferGPUSkin.bExtraBoneInfluences);

            if (bHasVertexColors)
            {
                var newColorVertexBuffer = new FColorVertexBuffer(Ar);
                ColorVertexBuffer = new FSkeletalMeshVertexColorBuffer(newColorVertexBuffer.Data);
            }

            if (FUE5ReleaseStreamObjectVersion.Get(Ar) < FUE5ReleaseStreamObjectVersion.Type.RemovingTessellation && !stripDataFlags.IsClassDataStripped((byte)EClassDataStripFlag.CDSF_AdjacencyData))
            {
                AdjacencyIndexBuffer = new FMultisizeIndexContainer(Ar);
            }

            if (HasClothData())
            {
                ClothVertexBuffer = new FSkeletalMeshVertexClothBuffer(Ar);
            }

            var skinWeightProfilesData = new FSkinWeightProfilesData(Ar);

            if (Ar.Game >= EGame.GAME_UE5_0) // Note: This was added in UE4.27, but we're only reading it on UE5 for compatibility with Fortnite
            {
                var rayTracingData = Ar.ReadArray <byte>();
            }

            NumVertices  = positionVertexBuffer.NumVertices;
            NumTexCoords = staticMeshVertexBuffer.NumTexCoords;

            VertexBufferGPUSkin.VertsFloat = new FGPUVertFloat[NumVertices];
            for (var i = 0; i < VertexBufferGPUSkin.VertsFloat.Length; i++)
            {
                VertexBufferGPUSkin.VertsFloat[i] = new FGPUVertFloat
                {
                    Pos    = positionVertexBuffer.Verts[i],
                    Infs   = skinWeightVertexBuffer.Weights[i],
                    Normal = staticMeshVertexBuffer.UV[i].Normal,
                    UV     = staticMeshVertexBuffer.UV[i].UV
                };
            }
        }
Ejemplo n.º 2
0
        public FStaticLODModel(FAssetArchive Ar, bool bHasVertexColors) : this()
        {
            if (Ar.Game == EGame.GAME_SEAOFTHIEVES)
            {
                Ar.Position += 4;
            }
            var stripDataFlags = Ar.Read <FStripDataFlags>();
            var skelMeshVer    = FSkeletalMeshCustomVersion.Get(Ar);

            if (Ar.Game == EGame.GAME_SEAOFTHIEVES)
            {
                Ar.Position += 4;
            }

            Sections = Ar.ReadArray(Ar.Read <int>(), () => new FSkelMeshSection(Ar));

            if (skelMeshVer < FSkeletalMeshCustomVersion.Type.SplitModelAndRenderData)
            {
                Indices = new FMultisizeIndexContainer(Ar);
            }
            else
            {
                // UE4.19+ uses 32-bit index buffer (for editor data)
                Indices = new FMultisizeIndexContainer {
                    Indices32 = Ar.ReadBulkArray <uint>()
                };
            }

            ActiveBoneIndices = Ar.ReadArray <short>();

            if (skelMeshVer < FSkeletalMeshCustomVersion.Type.CombineSectionWithChunk)
            {
                Chunks = Ar.ReadArray(() => new FSkelMeshChunk(Ar));
            }

            Size = Ar.Read <int>();
            if (!stripDataFlags.IsDataStrippedForServer())
            {
                NumVertices = Ar.Read <int>();
            }

            RequiredBones = Ar.ReadArray <short>();
            if (!stripDataFlags.IsEditorDataStripped())
            {
                RawPointIndices = new FIntBulkData(Ar);
            }

            if (Ar.Game != EGame.GAME_SOD2 && Ar.Ver >= UE4Version.VER_UE4_ADD_SKELMESH_MESHTOIMPORTVERTEXMAP)
            {
                MeshToImportVertexMap = Ar.ReadArray <int>();
                MaxImportVertex       = Ar.Read <int>();
            }

            if (!stripDataFlags.IsDataStrippedForServer())
            {
                NumTexCoords = Ar.Read <int>();
                if (skelMeshVer < FSkeletalMeshCustomVersion.Type.SplitModelAndRenderData)
                {
                    VertexBufferGPUSkin = new FSkeletalMeshVertexBuffer(Ar);
                    if (skelMeshVer >= FSkeletalMeshCustomVersion.Type.UseSeparateSkinWeightBuffer)
                    {
                        var skinWeights = new FSkinWeightVertexBuffer(Ar, VertexBufferGPUSkin.bExtraBoneInfluences);
                        if (skinWeights.Weights.Length > 0)
                        {
                            // Copy data to VertexBufferGPUSkin
                            if (VertexBufferGPUSkin.bUseFullPrecisionUVs)
                            {
                                for (var i = 0; i < NumVertices; i++)
                                {
                                    VertexBufferGPUSkin.VertsFloat[i].Infs = skinWeights.Weights[i];
                                }
                            }
                            else
                            {
                                for (var i = 0; i < NumVertices; i++)
                                {
                                    VertexBufferGPUSkin.VertsHalf[i].Infs = skinWeights.Weights[i];
                                }
                            }
                        }
                    }

                    if (bHasVertexColors)
                    {
                        if (skelMeshVer < FSkeletalMeshCustomVersion.Type.UseSharedColorBufferFormat)
                        {
                            ColorVertexBuffer = new FSkeletalMeshVertexColorBuffer(Ar);
                        }
                        else
                        {
                            var newColorVertexBuffer = new FColorVertexBuffer(Ar);
                            ColorVertexBuffer = new FSkeletalMeshVertexColorBuffer(newColorVertexBuffer.Data);
                        }
                    }

                    if (Ar.Ver < UE4Version.VER_UE4_REMOVE_EXTRA_SKELMESH_VERTEX_INFLUENCES)
                    {
                        throw new ParserException("Unsupported: extra SkelMesh vertex influences (old mesh format)");
                    }

                    // https://github.com/gildor2/UEViewer/blob/master/Unreal/UnrealMesh/UnMesh4.cpp#L1415
                    if (Ar.Game == EGame.GAME_SOD2)
                    {
                        Ar.Position += 8;
                        return;
                    }

                    if (Ar.Game == EGame.GAME_SEAOFTHIEVES)
                    {
                        var arraySize = Ar.Read <int>();
                        Ar.Position += arraySize * 44;

                        for (var i = 0; i < 4; i++)
                        {
                            Ar.ReadArray <int>(); // 4 arrays worth
                        }

                        Ar.Position += 13;
                    }

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

                    if (Ar.Ver >= UE4Version.VER_UE4_APEX_CLOTH && HasClothData())
                    {
                        ClothVertexBuffer = new FSkeletalMeshVertexClothBuffer(Ar);
                    }
                }
            }

            if (Ar.Game == EGame.GAME_SEAOFTHIEVES)
            {
                var _ = new FMultisizeIndexContainer(Ar);
            }
        }
Ejemplo n.º 3
0
        public void SerializeRenderItem(FAssetArchive Ar, bool bHasVertexColors, byte numVertexColorChannels)
        {
            if (Ar.Game < EGame.GAME_UE4_24)
            {
                SerializeRenderItem_Legacy(Ar, bHasVertexColors, numVertexColorChannels);
                return;
            }

            var stripDataFlags  = Ar.Read <FStripDataFlags>();
            var bIsLODCookedOut = Ar.ReadBoolean();
            var bInlined        = Ar.ReadBoolean();

            RequiredBones = Ar.ReadArray <short>();
            if (!stripDataFlags.IsDataStrippedForServer() && !bIsLODCookedOut)
            {
                Sections = new FSkelMeshSection[Ar.Read <int>()];
                for (var i = 0; i < Sections.Length; i++)
                {
                    Sections[i] = new FSkelMeshSection();
                    Sections[i].SerializeRenderItem(Ar);
                }

                ActiveBoneIndices = Ar.ReadArray <short>();
                Ar.Position      += 4; //var buffersSize = Ar.Read<uint>();

                if (bInlined)
                {
                    SerializeStreamedData(Ar, bHasVertexColors);
                    if (Ar.Game == EGame.GAME_ROGUECOMPANY)
                    {
                        Ar.Position += 10; // FStripDataFlags, ElementSize, ElementCount
                        Ar.SkipBulkArrayData();
                        Ar.Position += 10;
                    }
                }
                else
                {
                    var bulk = new FByteBulkData(Ar);
                    if (bulk.Header.ElementCount > 0)
                    {
                        using (var tempAr = new FByteArchive("LodReader", bulk.Data, Ar.Versions))
                        {
                            SerializeStreamedData(tempAr, bHasVertexColors);
                        }

                        var skipBytes = 5;
                        if (FUE5ReleaseStreamObjectVersion.Get(Ar) < FUE5ReleaseStreamObjectVersion.Type.RemovingTessellation && !stripDataFlags.IsClassDataStripped((byte)EClassDataStripFlag.CDSF_AdjacencyData))
                        {
                            skipBytes += 5;
                        }
                        skipBytes   += 4 * 4 + 2 * 4 + 2 * 4;
                        skipBytes   += FSkinWeightVertexBuffer.MetadataSize(Ar);
                        Ar.Position += skipBytes;

                        if (HasClothData())
                        {
                            var clothIndexMapping = Ar.ReadArray <long>();
                            Ar.Position += 2 * 4;
                        }

                        var profileNames = Ar.ReadArray(Ar.ReadFName);
                    }
                }
            }
        }
Ejemplo n.º 4
0
        private void SerializeRenderItem_Legacy(FAssetArchive Ar, bool bHasVertexColors, byte numVertexColorChannels)
        {
            var stripDataFlags = Ar.Read <FStripDataFlags>();

            Sections = new FSkelMeshSection[Ar.Read <int>()];
            for (var i = 0; i < Sections.Length; i++)
            {
                Sections[i] = new FSkelMeshSection();
                Sections[i].SerializeRenderItem(Ar);
            }

            Indices             = new FMultisizeIndexContainer(Ar);
            VertexBufferGPUSkin = new FSkeletalMeshVertexBuffer {
                bUseFullPrecisionUVs = true
            };

            ActiveBoneIndices = Ar.ReadArray <short>();
            RequiredBones     = Ar.ReadArray <short>();

            if (!stripDataFlags.IsDataStrippedForServer() && !stripDataFlags.IsClassDataStripped((byte)EClassDataStripFlag.CDSF_MinLodData))
            {
                var positionVertexBuffer   = new FPositionVertexBuffer(Ar);
                var staticMeshVertexBuffer = new FStaticMeshVertexBuffer(Ar);
                var skinWeightVertexBuffer = new FSkinWeightVertexBuffer(Ar, VertexBufferGPUSkin.bExtraBoneInfluences);

                if (!bHasVertexColors && Ar.Game == EGame.GAME_BORDERLANDS3)
                {
                    for (var i = 0; i < numVertexColorChannels; i++)
                    {
                        var newColorVertexBuffer = new FColorVertexBuffer(Ar);
                        ColorVertexBuffer = new FSkeletalMeshVertexColorBuffer(newColorVertexBuffer.Data);
                    }
                }
                else if (bHasVertexColors)
                {
                    var newColorVertexBuffer = new FColorVertexBuffer(Ar);
                    ColorVertexBuffer = new FSkeletalMeshVertexColorBuffer(newColorVertexBuffer.Data);
                }

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

                if (HasClothData())
                {
                    ClothVertexBuffer = new FSkeletalMeshVertexClothBuffer(Ar);
                }

                NumVertices  = positionVertexBuffer.NumVertices;
                NumTexCoords = staticMeshVertexBuffer.NumTexCoords;

                VertexBufferGPUSkin.VertsFloat = new FGPUVertFloat[NumVertices];
                for (var i = 0; i < VertexBufferGPUSkin.VertsFloat.Length; i++)
                {
                    VertexBufferGPUSkin.VertsFloat[i] = new FGPUVertFloat
                    {
                        Pos    = positionVertexBuffer.Verts[i],
                        Infs   = skinWeightVertexBuffer.Weights[i],
                        Normal = staticMeshVertexBuffer.UV[i].Normal,
                        UV     = staticMeshVertexBuffer.UV[i].UV
                    };
                }
            }

            if (Ar.Game >= EGame.GAME_UE4_23)
            {
                var skinWeightProfilesData = new FSkinWeightProfilesData(Ar);
            }
        }
Ejemplo n.º 5
0
        // UE ref https://github.com/EpicGames/UnrealEngine/blob/26450a5a59ef65d212cf9ce525615c8bd673f42a/Engine/Source/Runtime/Engine/Private/SkeletalMeshLODRenderData.cpp#L710
        public void SerializeRenderItem(FAssetArchive Ar, bool bHasVertexColors, byte numVertexColorChannels)
        {
            var stripDataFlags  = Ar.Read <FStripDataFlags>();
            var bIsLODCookedOut = false;

            if (Ar.Game != EGame.GAME_Splitgate)
            {
                bIsLODCookedOut = Ar.ReadBoolean();
            }
            var bInlined = Ar.ReadBoolean();

            RequiredBones = Ar.ReadArray <short>();
            if (!stripDataFlags.IsDataStrippedForServer() && !bIsLODCookedOut)
            {
                Sections = new FSkelMeshSection[Ar.Read <int>()];
                for (var i = 0; i < Sections.Length; i++)
                {
                    Sections[i] = new FSkelMeshSection();
                    Sections[i].SerializeRenderItem(Ar);
                }

                ActiveBoneIndices = Ar.ReadArray <short>();

                if (Ar.Game == EGame.GAME_KenaBridgeofSpirits)
                {
                    Ar.ReadArray <byte>(); // EAssetType_array1
                }
                Ar.Position += 4;          //var buffersSize = Ar.Read<uint>();

                if (bInlined)
                {
                    SerializeStreamedData(Ar, bHasVertexColors);
                    if (Ar.Game == EGame.GAME_RogueCompany)
                    {
                        Ar.Position += 12; // 1 (Long) + 2^16 (Int)
                        var elementSize  = Ar.Read <int>();
                        var elementCount = Ar.Read <int>();
                        if (elementSize > 0 && elementCount > 0)
                        {
                            Ar.SkipBulkArrayData();
                        }
                    }
                }
                else
                {
                    var bulk = new FByteBulkData(Ar);
                    if (bulk.Header.ElementCount > 0)
                    {
                        using (var tempAr = new FByteArchive("LodReader", bulk.Data, Ar.Versions))
                        {
                            SerializeStreamedData(tempAr, bHasVertexColors);
                        }

                        var skipBytes = 5;
                        if (FUE5ReleaseStreamObjectVersion.Get(Ar) < FUE5ReleaseStreamObjectVersion.Type.RemovingTessellation && !stripDataFlags.IsClassDataStripped((byte)EClassDataStripFlag.CDSF_AdjacencyData))
                        {
                            skipBytes += 5;
                        }
                        skipBytes   += 4 * 4 + 2 * 4 + 2 * 4;
                        skipBytes   += FSkinWeightVertexBuffer.MetadataSize(Ar);
                        Ar.Position += skipBytes;

                        if (HasClothData())
                        {
                            var clothIndexMapping = Ar.ReadArray <long>();
                            Ar.Position += 2 * 4;
                        }

                        var profileNames = Ar.ReadArray(Ar.ReadFName);
                    }
                }
            }

            if (Ar.Game == EGame.GAME_ReadyOrNot)
            {
                Ar.Position += 4;
            }
        }