def __init__(self, reader: BinaryStream): StripFlags = FStripDataFlags( reader, Versions.VER_UE4_STATIC_SKELETAL_MESH_SERIALIZATION_FIX) self.NumTexCoords = reader.readInt32() self.Strides = reader.readInt32() if reader.game < GAME_UE4(19) else -1 self.NumVertices = reader.readInt32() self.UseFullPrecisionUVs = reader.readBool() self.UseHighPrecisionTangentBasis = reader.readBool( ) if reader.game >= GAME_UE4(12) else False if not StripFlags.isDataStrippedForServer(): if reader.game < GAME_UE4(19): self.UV = reader.readTArray_W_Arg( FStaticMeshUVItem().read, reader, self.UseHighPrecisionTangentBasis, self.NumTexCoords, self.UseFullPrecisionUVs) else: # reader.readBulkTArray() itemSize = reader.readInt32() itemCount = reader.readInt32() if itemCount != self.NumVertices: raise ParserException( f"{itemCount=} != {self.NumVertices=}") pos = reader.tell() self.UV = [ FStaticMeshUVItem().construct( FStaticMeshUVItem().serialize_tangents( reader, self.UseHighPrecisionTangentBasis), []) for _ in range(self.NumVertices) ] if reader.tell() - pos != itemSize * itemCount: raise ParserException( f"Read incorrect amount of tangent bytes, at {reader.tell()}, should be: {pos + itemSize * itemCount} behind: {pos + (itemSize * itemCount) - pos}" ) itemSize = reader.readInt32() itemCount = reader.readInt32() if itemCount != self.NumVertices * self.NumTexCoords: raise ParserException( f"{itemCount=} != NumVertices * NumTexCoords = {self.NumVertices * self.NumTexCoords}" ) pos = reader.tell() for i in range(self.NumVertices): self.UV[i].UV = FStaticMeshUVItem().serialize_texcoords( reader, self.NumTexCoords, self.UseFullPrecisionUVs) if reader.tell() - pos != itemSize * itemCount: raise ParserException( f"Read incorrect amount of Texture Coordinate bytes, at {reader.tell()}, should be: {pos + itemSize * itemCount} behind: {pos + (itemSize * itemCount) - pos}" ) else: self.UV = []
def __init__(self, reader: BinaryStream): if reader.version < Versions.VER_UE4_SUPPORT_32BIT_STATIC_MESH_INDICES: self.indices16 = reader.readBulkTArray(reader.readUInt16) self.indices32 = [] else: is32bit = reader.readBool() data = bytearray(reader.readBulkTArray(reader.readInt8)) tr = BinaryStream(data) tr.game = reader.game tr.version = reader.version if reader.game >= GAME_UE4(25): reader.readBool() if len(data) == 0: self.indices16 = [] self.indices32 = [] return if is32bit: count = int(len(data) / 4) self.indices32 = [tr.readUInt32() for _ in range(count)] self.indices16 = [] else: count = int(len(data) / 2) self.indices16 = [tr.readUInt16() for _ in range(count)] self.indices32 = []
def serializeBuffer(self, reader: BinaryStream): stripFlags = FStripDataFlags(reader) self.positionVertexBuffer = FPositionVertexBuffer(reader) self.vertexBuffer = FStaticMeshVertexBuffer(reader) self.colorVertexBuffer = FColorVertexBuffer(reader) self.indexBuffer = FRawStaticIndexBuffer(reader) if not stripFlags.isClassDataStripped(CDSF_ReversedIndexBuffer): self.reversedIndexBuffer = FRawStaticIndexBuffer(reader) self.depthOnlyIndexBuffer = FRawStaticIndexBuffer(reader) if not stripFlags.isClassDataStripped(CDSF_ReversedIndexBuffer): self.reversedDepthOnlyIndexBuffer = FRawStaticIndexBuffer(reader) if not stripFlags.isEditorDataStripped(): self.wireframeIndexBuffer = FRawStaticIndexBuffer(reader) if not stripFlags.isClassDataStripped(CDSF_AdjancencyData): self.adjacencyIndexBuffer = FRawStaticIndexBuffer(reader) # UE 4.25+ if reader.game >= GAME_UE4(25) and not stripFlags.isClassDataStripped( CDSF_RaytracingResources): reader.readBulkTArray(reader.readByte) # Raw data # 25178 for i in range(len(self.sections)): FWeightedRandomSampler( reader) # FStaticMeshSectionAreaWeightedTriangleSampler FWeightedRandomSampler(reader) # FStaticMeshAreaWeightedSectionSampler
def __init__(self, reader: Optional[BinaryStream] = None): if reader is None: return self.value = reader.readUInt32() if reader.game >= GAME_UE4(20): self.value = self.value ^ 0x80808080
def deserialize(self, validpos): reader = self.reader bulk = reader.ubulk_stream bulkOffset = reader.bulk_offset super().deserialize(validpos) FStripDataFlags(reader) FStripDataFlags(reader) bIsCooked = reader.version >= Versions.VER_UE4_ADD_COOKED_TO_TEXTURE2D and reader.readBool( ) # 203 if bIsCooked: PixelFormatName = reader.readFName() pos = reader.base_stream.tell() while not PixelFormatName.isNone: SkipOffset = reader.readInt32() if reader.game >= GAME_UE4(20): SkipOffsetH = reader.readInt32() assert SkipOffsetH == 0 data = FTexturePlatformData(reader, ubulk=bulk, ubulkOffset=bulkOffset) self.data.append(data) PixelFormatName = reader.readFName() try: EPixelFormat[PixelFormatName.GetValue()] except: break
def __init__(self, reader: BinaryStream): self.X = reader.readUInt16() self.Y = reader.readUInt16() self.Z = reader.readUInt16() self.W = reader.readUInt16() if reader.game >= GAME_UE4(20): self.X = self.X ^ 0x8000 self.Y = self.Y ^ 0x8000 self.Z = self.Z ^ 0x8000 self.W = self.W ^ 0x8000
def __init__(self, reader: BinaryStream): self.stripFlags = FStripDataFlags(reader) self.sections = reader.readTArray_W_Arg(FStaticMeshSection, reader) self.maxDeviation = reader.readFloat() if reader.game < GAME_UE4(23): if not self.stripFlags.isDataStrippedForServer( ) and not self.stripFlags.isClassDataStripped(CDSF_MinLodData): self.serializeBuffer_legacy(reader) return self.is_lod_cooked_out = reader.readBool() self.inlined = reader.readBool() if not self.stripFlags.isDataStrippedForServer( ) and not self.is_lod_cooked_out: pos = reader.tellfake() if self.inlined: self.serializeBuffer(reader) else: bulk: FByteBulkData = FByteBulkData( reader, ubulk=reader.ubulk_stream, bulkOffset=reader.PackageReader.PackageFileSummary. BulkDataStartOffset) if bulk.Header.ElementCount > 0: tr = BinaryStream(bulk.Data) tr.game = reader.game tr.version = reader.version self.serializeBuffer(tr) reader.readUInt32() # DepthOnlyNumTriangles reader.readUInt32() # PackedData reader.seek(4 * 4 + 2 * 4 + 2 * 4 + 6 * (2 * 4), 1) """ StaticMeshVertexBuffer = 2x int32, 2x bool PositionVertexBuffer = 2x int32 ColorVertexBuffer = 2x int32 IndexBuffer = int32 + bool ReversedIndexBuffer DepthOnlyIndexBuffer ReversedDepthOnlyIndexBuffer WireframeIndexBuffer AdjacencyIndexBuffer """ # FStaticMeshBuffersSize reader.readUInt32() # SerializedBuffersSize reader.readUInt32() # DepthOnlyIBSize reader.readUInt32() # ReversedIBsSize
def deserialize(self, reader: BinaryStream, ubulk: BinaryStream, ubulkOffset: int): self.SizeX = reader.readInt32() self.SizeY = reader.readInt32() self.NumSlices = reader.readInt32() # 1 for normal textures self.PixelFormat = EPixelFormat[reader.readFString()] self.FirstMipToSerialize = reader.readInt32() - 1 self.Mips = reader.readTArray_W_Arg(FTexture2DMipMap, reader, ubulk, ubulkOffset) if reader.game >= GAME_UE4(23): self.bIsVirtual = reader.readInt32() != 0 if self.bIsVirtual: raise NotImplementedError( "Virtual Textures ar not Not implemented")
def __init__(self, reader: BinaryStream): super().__init__() if reader.game >= GAME_UE4(16): self.CompressedDistanceFieldVolume = reader.readTArray( reader.readByteToInt) self.Size = FIntVector(reader) self.LocalBoundingBox = FBox(reader) self.DistanceMinMax = FVector(reader) self.MeshWasClosed = reader.readBool() self.BuiltAsIfTwoSided = reader.readBool() self.MeshwasPlane = reader.readBool() self.DistanceFieldVolume = [] else: self.DistanceFieldVolume = reader.readTArray(reader.readUInt16) self.Size = FIntVector(reader) self.LocalBoundingBox = FBox(reader) self.MeshWasClosed = reader.readBool() self.BuiltAsIfTwoSided = reader.readBool( ) if reader.version >= Versions.VER_UE4_RENAME_CROUCHMOVESCHARACTERDOWN else False self.MeshwasPlane = reader.readBool( ) if reader.version >= Versions.VER_UE4_DEPRECATE_UMG_STYLE_ASSETS else False self.CompressedDistanceFieldVolume = [] self.DistanceMinMax = FVector2D().construct(0, 0)
def get(self, reader: BinaryStream): version = reader.game if version < GAME_UE4(12): return self.BeforeCustomVersionWasAdded elif version < GAME_UE4(13): return 2 elif version < GAME_UE4(14): return 4 elif version < GAME_UE4(16): return 12 # 4.14 and 4.15 elif version < GAME_UE4(17): return 15 elif version < GAME_UE4(18): return 19 elif version < GAME_UE4(19): return 20 elif version < GAME_UE4(20): return 25 elif version < GAME_UE4(21): return self.IncreaseNormalPrecision elif version < GAME_UE4(22): return 27 elif version < GAME_UE4(23): return 28 elif version < GAME_UE4(24): return 31 elif version < GAME_UE4(25): return 36 elif version < GAME_UE4(26): return 43 else: return EUEVersion.LATEST
def deserialize(self, validpos) -> None: super().deserialize(validpos) reader = self.reader self.StripData = FStripDataFlags(reader) bCooked = reader.readBool() self.BodySetup = reader.readObject() if reader.version >= Versions.VER_UE4_STATIC_MESH_STORE_NAV_COLLISION: self.NavCollision = reader.readObject() if not self.StripData.isEditorDataStripped(): if reader.version < Versions.VER_UE4_DEPRECATED_STATIC_MESH_THUMBNAIL_PROPERTIES_REMOVED: FRotator(reader) # dummyThumbnailAngle reader.readFloat() # dummyThumbnailDistance highResSourceMeshName = reader.readString( ) # highResSourceMeshName highResSourceMeshCRC = reader.readUInt32() # self.LightingGuid = FGuid(reader) self.Sockets = reader.readTArray(reader.readObject) if not self.StripData.isEditorDataStripped: raise ParserException("Mesh with editor data not supported") # FStaticMeshRenderData if bCooked: if not bCooked: # how possible pass # https://github.com/FabianFG/JFortniteParse/blob/558fb2b96985aad5b90c96c8f28950021cf801a0/src/main/kotlin/me/fungames/jfortniteparse/ue4/assets/exports/UStaticMesh.kt#L59 # if unversioned MinMobileLODIdx int32 self.LODs = reader.readTArray_W_Arg(FStaticMeshLODResources, reader) #TODO fix this if reader.game >= GAME_UE4(23): NumInlinedLODs = reader.readUInt8() if bCooked: if reader.version >= Versions.VER_UE4_RENAME_CROUCHMOVESCHARACTERDOWN: isStripped = False if reader.version >= Versions.VER_UE4_RENAME_WIDGET_VISIBILITY: stripflag = FStripDataFlags(reader) isStripped = stripflag.isDataStrippedForServer() if reader.game >= GAME_UE4(21): # 4.21 uses additional strip flag for distance field distanceFieldDataStripFlag = 1 isStripped = isStripped | stripflag.isClassDataStripped( distanceFieldDataStripFlag) # ? if not isStripped: # serialize FDistanceFieldVolumeData for each LOD for _ in range(len(self.LODs) - 1): # wut why hasDistanceDataField = reader.readBool() if hasDistanceDataField: FDistanceFieldVolumeData(reader) # VolumeData self.Bounds = FBoxSphereBounds(reader) if reader.game != GAME_UE4(15): self.LODsShareStaticLighting = reader.readBool() if reader.game < GAME_UE4(15): reader.readBool() # bReducedBySimplygon if FRenderingObjectVersion().get( reader ) < FRenderingObjectVersion.TextureStreamingMeshUVChannelData: for _ in range( MAX_STATIC_UV_SETS_UE4): # StreamingTextureFactors reader.readFloat( ) # StreamingTextureFactor for each UV set reader.readFloat() # MaxStreamingTextureFactor if bCooked: maxNumLods = MAX_STATIC_LODS_UE4 if reader.game >= GAME_UE4( 9) else 4 for x in range(maxNumLods): if reader.game >= GAME_UE4(20): reader.readBool() # bFloatCooked self.ScreenSize.append(reader.readFloat()) # End of FStaticMeshRenderData if bCooked and reader.game >= GAME_UE4(20): hasOccluderData = reader.readBool() if hasOccluderData: reader.readTArray(FVector, reader) # Vertices reader.readTArray(reader.readUInt16) # Indics if reader.game >= GAME_UE4(14): hasSpeedTreeWind = reader.readBool() if hasSpeedTreeWind: pass # ignore else: if FEditorObjectVersion().get( reader ) >= FEditorObjectVersion.RefactorMeshEditorMaterials: # UE4.14+ - "Materials" are deprecated, added StaticMaterials self.StaticMaterials = reader.readTArray_W_Arg( FStaticMaterial, reader) if len(self.Materials) == 0 and len(self.StaticMaterials) > 0: material: FStaticMaterial for material in self.StaticMaterials: self.Materials.append(material.MaterialInterface)