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));
            }
        }
Esempio n. 2
0
        public override void Deserialize(FAssetArchive Ar, long validPos)
        {
            base.Deserialize(Ar, validPos);
            bHasVertexColors       = GetOrDefault <bool>(nameof(bHasVertexColors));
            NumVertexColorChannels = GetOrDefault <byte>(nameof(NumVertexColorChannels));

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

            ImportedBounds    = Ar.Read <FBoxSphereBounds>();
            Materials         = Ar.ReadArray(() => new FSkeletalMaterial(Ar));
            ReferenceSkeleton = new FReferenceSkeleton(Ar);

            if (FSkeletalMeshCustomVersion.Get(Ar) < FSkeletalMeshCustomVersion.Type.SplitModelAndRenderData)
            {
                LODModels = Ar.ReadArray(() => new FStaticLODModel(Ar, bHasVertexColors));
            }
            else
            {
                if (!stripDataFlags.IsEditorDataStripped())
                {
                    LODModels = Ar.ReadArray(() => new FStaticLODModel(Ar, bHasVertexColors));
                }

                var bCooked = Ar.ReadBoolean();
                if (Ar.Game >= EGame.GAME_UE4_27)
                {
                    var minMobileLODIdx = Ar.Read <int>();
                }

                if (bCooked && LODModels == null)
                {
                    LODModels = new FStaticLODModel[Ar.Read <int>()];
                    for (var i = 0; i < LODModels.Length; i++)
                    {
                        LODModels[i] = new FStaticLODModel();
                        LODModels[i].SerializeRenderItem(Ar, bHasVertexColors, NumVertexColorChannels);
                    }

                    if (Ar.Game >= EGame.GAME_UE4_24)
                    {
                        var numInlinedLODs     = Ar.Read <byte>();
                        var numNonOptionalLODs = Ar.Read <byte>();
                    }
                }
            }

            if (Ar.Ver < UE4Version.VER_UE4_REFERENCE_SKELETON_REFACTOR)
            {
                var length = Ar.Read <int>();
                Ar.Position += 12 * length; // TMap<FName, int32> DummyNameIndexMap
            }

            var dummyObjs = Ar.ReadArray(() => new FPackageIndex(Ar));
        }
Esempio n. 3
0
 public void SerializeForGPU(FAssetArchive Ar, bool bExtraBoneInfluences)
 {
     Normal    = new FPackedNormal[3];
     Normal[0] = new FPackedNormal(Ar);
     Normal[2] = new FPackedNormal(Ar);
     if (FSkeletalMeshCustomVersion.Get(Ar) < FSkeletalMeshCustomVersion.Type.UseSeparateSkinWeightBuffer)
     {
         // serialized as separate buffer starting with UE4.15
         Infs = new FSkinWeightInfo(Ar, bExtraBoneInfluences);
     }
     Pos = Ar.Read <FVector>();
 }
 public void SerializeForGPU(FAssetArchive Ar)
 {
     Normal    = new FPackedNormal[3];
     Normal[0] = new FPackedNormal(Ar);
     Normal[2] = new FPackedNormal(Ar);
     if (FSkeletalMeshCustomVersion.Get(Ar) < FSkeletalMeshCustomVersion.Type.UseSeparateSkinWeightBuffer)
     {
         // serialized as separate buffer starting with UE4.15
         Infs = new FSkinWeightInfo(Ar, Ar.Ver >= UE4Version.VER_UE4_SUPPORT_8_BONE_INFLUENCES_SKELETAL_MESHES);
     }
     Pos = Ar.Read <FVector>();
 }
        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>();
            }
        }
Esempio n. 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>();
            }
        }
Esempio n. 7
0
        public FSkinWeightVertexBuffer(FArchive Ar, bool numSkelCondition)
        {
            var bNewWeightFormat = FAnimObjectVersion.Get(Ar) >= FAnimObjectVersion.Type.UnlimitedBoneInfluences;

            #region FSkinWeightDataVertexBuffer
            var dataStripFlags = Ar.Read <FStripDataFlags>();

            #region FSkinWeightDataVertexBuffer::SerializeMetaData
            bool bVariableBonesPerVertex;
            bool bExtraBoneInfluences;
            uint maxBoneInfluences;
            bool bUse16BitBoneIndex;
            uint numVertices;
            uint numBones;

            if (Ar.Game < EGame.GAME_UE4_24)
            {
                bExtraBoneInfluences = Ar.ReadBoolean();
                numVertices          = Ar.Read <uint>();
                maxBoneInfluences    = bExtraBoneInfluences ? 8u : 4u;
            }
            else if (!bNewWeightFormat)
            {
                bExtraBoneInfluences = Ar.ReadBoolean();
                if (FSkeletalMeshCustomVersion.Get(Ar) >= FSkeletalMeshCustomVersion.Type.SplitModelAndRenderData)
                {
                    Ar.Position += 4; // var stride = Ar.Read<uint>();
                }
                numVertices             = Ar.Read <uint>();
                maxBoneInfluences       = bExtraBoneInfluences ? 8u : 4u;
                numBones                = maxBoneInfluences * numVertices;
                bVariableBonesPerVertex = false;
            }
            else
            {
                bVariableBonesPerVertex = Ar.ReadBoolean();
                maxBoneInfluences       = Ar.Read <uint>();
                numBones             = Ar.Read <uint>();
                numVertices          = Ar.Read <uint>();
                bExtraBoneInfluences = maxBoneInfluences > _NUM_INFLUENCES_UE4;
                // bUse16BitBoneIndex doesn't exist before version IncreaseBoneIndexLimitPerChunk
                if (FAnimObjectVersion.Get(Ar) >= FAnimObjectVersion.Type.IncreaseBoneIndexLimitPerChunk)
                {
                    bUse16BitBoneIndex = Ar.ReadBoolean();
                }
            }
            #endregion

            byte[] newData = Array.Empty <byte>();
            if (!dataStripFlags.IsDataStrippedForServer())
            {
                if (!bNewWeightFormat)
                {
                    Weights = Ar.ReadBulkArray(() => new FSkinWeightInfo(Ar, bExtraBoneInfluences));
                }
                else
                {
                    newData = Ar.ReadBulkArray <byte>();
                }
            }
            else
            {
                bExtraBoneInfluences = numSkelCondition;
            }
            #endregion

            if (bNewWeightFormat)
            {
                #region FSkinWeightLookupVertexBuffer
                var lookupStripFlags = Ar.Read <FStripDataFlags>();

                #region FSkinWeightLookupVertexBuffer::SerializeMetaData
                //if (bNewWeightFormat)
                //{
                var numLookupVertices = Ar.Read <int>();
                //}
                #endregion

                if (!lookupStripFlags.IsDataStrippedForServer())
                {
                    Ar.ReadBulkArray <uint>(); // LookupData
                }
                #endregion

                // Convert influence data
                if (newData.Length > 0)
                {
                    using var tempAr = new FByteArchive("WeightsReader", newData, Ar.Versions);
                    Weights          = new FSkinWeightInfo[numVertices];
                    for (var i = 0; i < Weights.Length; i++)
                    {
                        Weights[i] = new FSkinWeightInfo(tempAr, bExtraBoneInfluences);
                    }
                }
            }
        }
Esempio n. 8
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);
            }
        }
Esempio n. 9
0
        public FSkelMeshSection(FAssetArchive Ar) : this()
        {
            var stripDataFlags = Ar.Read <FStripDataFlags>();
            var skelMeshVer    = FSkeletalMeshCustomVersion.Get(Ar);

            MaterialIndex = Ar.Read <short>();

            if (skelMeshVer < FSkeletalMeshCustomVersion.Type.CombineSectionWithChunk)
            {
                Ar.Position += 2; // ChunkIndex
            }
            if (!stripDataFlags.IsDataStrippedForServer())
            {
                BaseIndex    = Ar.Read <int>();
                NumTriangles = Ar.Read <int>();
            }
            if (skelMeshVer < FSkeletalMeshCustomVersion.Type.RemoveTriangleSorting)
            {
                Ar.Position += 1; // TEnumAsByte<ETriangleSortOption>
            }
            if (Ar.Ver >= UE4Version.VER_UE4_APEX_CLOTH)
            {
                if (skelMeshVer < FSkeletalMeshCustomVersion.Type.DeprecateSectionDisabledFlag)
                {
                    bDisabled = Ar.ReadBoolean();
                }
                if (skelMeshVer < FSkeletalMeshCustomVersion.Type.RemoveDuplicatedClothingSections)
                {
                    CorrespondClothSectionIndex = Ar.Read <short>();
                }
            }

            if (Ar.Ver >= UE4Version.VER_UE4_APEX_CLOTH_LOD)
            {
                Ar.Position += 1; // bEnableClothLOD_DEPRECATED
            }
            if (FRecomputeTangentCustomVersion.Get(Ar) >= FRecomputeTangentCustomVersion.Type.RuntimeRecomputeTangent)
            {
                Ar.Position += 4; // bRecomputeTangent
            }
            if (FRecomputeTangentCustomVersion.Get(Ar) >= FRecomputeTangentCustomVersion.Type.RecomputeTangentVertexColorMask)
            {
                Ar.Position += 1; // RecomputeTangentsVertexMaskChannel
            }
            if (FEditorObjectVersion.Get(Ar) >= FEditorObjectVersion.Type.RefactorMeshEditorMaterials)
            {
                bCastShadow = Ar.ReadBoolean();
            }

            HasClothData = false;
            if (skelMeshVer >= FSkeletalMeshCustomVersion.Type.CombineSectionWithChunk)
            {
                if (!stripDataFlags.IsDataStrippedForServer())
                {
                    BaseVertexIndex = Ar.Read <uint>();
                }

                if (!stripDataFlags.IsEditorDataStripped())
                {
                    if (skelMeshVer < FSkeletalMeshCustomVersion.Type.CombineSoftAndRigidVerts)
                    {
                        Ar.ReadArray(() => new FRigidVertex(Ar)); // RigidVertices
                    }
                    SoftVertices = Ar.ReadArray(() => new FSoftVertex(Ar));
                }

                BoneMap = Ar.ReadArray <ushort>();
                if (skelMeshVer >= FSkeletalMeshCustomVersion.Type.SaveNumVertices)
                {
                    NumVertices = Ar.Read <int>();
                }
                if (skelMeshVer < FSkeletalMeshCustomVersion.Type.CombineSoftAndRigidVerts)
                {
                    Ar.Position += 8; // NumRigidVerts, NumSoftVerts
                }
                MaxBoneInfluences = Ar.Read <int>();

                FVector[] physicalMeshVertices, physicalMeshNormals;
                var       clothMappingData = Ar.ReadArray(() => new FApexClothPhysToRenderVertData(Ar));
                if (skelMeshVer < FSkeletalMeshCustomVersion.Type.RemoveDuplicatedClothingSections)
                {
                    physicalMeshVertices = Ar.ReadArray <FVector>();
                    physicalMeshNormals  = Ar.ReadArray <FVector>();
                }

                short clothAssetSubmeshIndex;
                var   correspondClothAssetIndex = Ar.Read <short>();
                if (skelMeshVer < FSkeletalMeshCustomVersion.Type.NewClothingSystemAdded)
                {
                    clothAssetSubmeshIndex = Ar.Read <short>();
                }
                else
                {
                    // UE4.16+
                    Ar.Read <FClothingSectionData>();
                }

                HasClothData = clothMappingData.Length > 0;

                if (FOverlappingVerticesCustomVersion.Get(Ar) >= FOverlappingVerticesCustomVersion.Type.DetectOVerlappingVertices)
                {
                    var size = Ar.Read <int>();
                    var overlappingVertices = new Dictionary <int, int[]>();
                    for (var i = 0; i < size; i++)
                    {
                        overlappingVertices[i] = Ar.ReadArray <int>();
                    }
                }
                if (FReleaseObjectVersion.Get(Ar) >= FReleaseObjectVersion.Type.AddSkeletalMeshSectionDisable)
                {
                    bDisabled = Ar.ReadBoolean();
                }
                if (FSkeletalMeshCustomVersion.Get(Ar) >= FSkeletalMeshCustomVersion.Type.SectionIgnoreByReduceAdded)
                {
                    GenerateUpToLodIndex = Ar.Read <int>();
                }
            }
        }