public override void LoadFile() { // We can ensure based on content-type that files are models if (FileInfo.Type != FileType.Model) { Console.WriteLine($"Attempted to load {FilePath} of content type {FileInfo.Type} as a model, returning..."); return; } FileHeader = MdlStructs.ModelFileHeader.Read(Reader); VertexDeclarations = new MdlStructs.VertexDeclarationStruct[FileHeader.VertexDeclarationCount]; for (int i = 0; i < FileHeader.VertexDeclarationCount; i++) { VertexDeclarations[i] = MdlStructs.VertexDeclarationStruct.Read(Reader); } StringCount = Reader.ReadUInt16(); Reader.ReadUInt16(); uint stringSize = Reader.ReadUInt32(); Strings = Reader.ReadBytes((int)stringSize); ModelHeader = Reader.ReadStructure <MdlStructs.ModelHeader>(); ElementIds = new MdlStructs.ElementIdStruct[ModelHeader.ElementIdCount]; Meshes = new MdlStructs.MeshStruct[ModelHeader.MeshCount]; BoneTables = new MdlStructs.BoneTableStruct[ModelHeader.BoneTableCount]; Shapes = new MdlStructs.ShapeStruct[ModelHeader.ShapeCount]; BoneBoundingBoxes = new MdlStructs.BoundingBoxStruct[ModelHeader.BoneCount]; for (int i = 0; i < ModelHeader.ElementIdCount; i++) { ElementIds[i] = MdlStructs.ElementIdStruct.Read(Reader); } Lods = Reader.ReadStructuresAsArray <MdlStructs.LodStruct>(3); if (ModelHeader.ExtraLodEnabled) { ExtraLods = Reader.ReadStructuresAsArray <MdlStructs.ExtraLodStruct>(3); } for (int i = 0; i < ModelHeader.MeshCount; i++) { Meshes[i] = MdlStructs.MeshStruct.Read(Reader); } AttributeNameOffsets = Reader.ReadStructures <UInt32>(ModelHeader.AttributeCount).ToArray(); TerrainShadowMeshes = Reader.ReadStructuresAsArray <MdlStructs.TerrainShadowMeshStruct>(ModelHeader.TerrainShadowMeshCount); Submeshes = Reader.ReadStructuresAsArray <MdlStructs.SubmeshStruct>(ModelHeader.SubmeshCount); TerrainShadowSubmeshes = Reader.ReadStructuresAsArray <MdlStructs.TerrainShadowSubmeshStruct>(ModelHeader.TerrainShadowSubmeshCount); MaterialNameOffsets = Reader.ReadStructures <UInt32>(ModelHeader.MaterialCount).ToArray(); BoneNameOffsets = Reader.ReadStructures <UInt32>(ModelHeader.BoneCount).ToArray(); for (int i = 0; i < ModelHeader.BoneTableCount; i++) { BoneTables[i] = MdlStructs.BoneTableStruct.Read(Reader); } for (int i = 0; i < ModelHeader.ShapeCount; i++) { Shapes[i] = MdlStructs.ShapeStruct.Read(Reader); } ShapeMeshes = Reader.ReadStructuresAsArray <MdlStructs.ShapeMeshStruct>(ModelHeader.ShapeMeshCount); ShapeValues = Reader.ReadStructuresAsArray <MdlStructs.ShapeValueStruct>(ModelHeader.ShapeValueCount); uint submeshBoneMapSize = Reader.ReadUInt32(); SubmeshBoneMap = Reader.ReadStructures <UInt16>((int)submeshBoneMapSize / 2).ToArray(); byte paddingAmount = Reader.ReadByte(); Reader.Seek(Reader.BaseStream.Position + paddingAmount); // Dunno what this first one is for? BoundingBoxes = MdlStructs.BoundingBoxStruct.Read(Reader); ModelBoundingBoxes = MdlStructs.BoundingBoxStruct.Read(Reader); WaterBoundingBoxes = MdlStructs.BoundingBoxStruct.Read(Reader); VerticalFogBoundingBoxes = MdlStructs.BoundingBoxStruct.Read(Reader); for (int i = 0; i < ModelHeader.BoneCount; i++) { BoneBoundingBoxes[i] = MdlStructs.BoundingBoxStruct.Read(Reader); } }
public MdlFile(byte[] data) { using var stream = new MemoryStream(data); using var r = new BinaryReader(stream); var header = LoadModelFileHeader(r); LodCount = header.LodCount; VertexBufferSize = header.VertexBufferSize; IndexBufferSize = header.IndexBufferSize; VertexOffset = header.VertexOffset; IndexOffset = header.IndexOffset; for (var i = 0; i < 3; ++i) { if (VertexOffset[i] > 0) { VertexOffset[i] -= header.RuntimeSize; } if (IndexOffset[i] > 0) { IndexOffset[i] -= header.RuntimeSize; } } VertexDeclarations = new MdlStructs.VertexDeclarationStruct[header.VertexDeclarationCount]; for (var i = 0; i < header.VertexDeclarationCount; ++i) { VertexDeclarations[i] = MdlStructs.VertexDeclarationStruct.Read(r); } var(offsets, strings) = LoadStrings(r); var modelHeader = LoadModelHeader(r); ElementIds = new MdlStructs.ElementIdStruct[modelHeader.ElementIdCount]; for (var i = 0; i < modelHeader.ElementIdCount; i++) { ElementIds[i] = MdlStructs.ElementIdStruct.Read(r); } Lods = r.ReadStructuresAsArray <MdlStructs.LodStruct>(3); ExtraLods = modelHeader.ExtraLodEnabled ? r.ReadStructuresAsArray <MdlStructs.ExtraLodStruct>(3) : Array.Empty <MdlStructs.ExtraLodStruct>(); Meshes = new MdlStructs.MeshStruct[modelHeader.MeshCount]; for (var i = 0; i < modelHeader.MeshCount; i++) { Meshes[i] = MdlStructs.MeshStruct.Read(r); } Attributes = new string[modelHeader.AttributeCount]; for (var i = 0; i < modelHeader.AttributeCount; ++i) { var offset = r.ReadUInt32(); var stringIdx = offsets.AsSpan().IndexOf(offset); Attributes[i] = stringIdx >= 0 ? strings[stringIdx] : string.Empty; } TerrainShadowMeshes = r.ReadStructuresAsArray <MdlStructs.TerrainShadowMeshStruct>(modelHeader.TerrainShadowMeshCount); SubMeshes = r.ReadStructuresAsArray <MdlStructs.SubmeshStruct>(modelHeader.SubmeshCount); TerrainShadowSubMeshes = r.ReadStructuresAsArray <MdlStructs.TerrainShadowSubmeshStruct>(modelHeader.TerrainShadowSubmeshCount); Materials = new string[modelHeader.MaterialCount]; for (var i = 0; i < modelHeader.MaterialCount; ++i) { var offset = r.ReadUInt32(); var stringIdx = offsets.AsSpan().IndexOf(offset); Materials[i] = stringIdx >= 0 ? strings[stringIdx] : string.Empty; } Bones = new string[modelHeader.BoneCount]; for (var i = 0; i < modelHeader.BoneCount; ++i) { var offset = r.ReadUInt32(); var stringIdx = offsets.AsSpan().IndexOf(offset); Bones[i] = stringIdx >= 0 ? strings[stringIdx] : string.Empty; } BoneTables = new MdlStructs.BoneTableStruct[modelHeader.BoneTableCount]; for (var i = 0; i < modelHeader.BoneTableCount; i++) { BoneTables[i] = MdlStructs.BoneTableStruct.Read(r); } Shapes = new Shape[modelHeader.ShapeCount]; for (var i = 0; i < modelHeader.ShapeCount; i++) { Shapes[i] = new Shape(MdlStructs.ShapeStruct.Read(r), offsets, strings); } ShapeMeshes = r.ReadStructuresAsArray <MdlStructs.ShapeMeshStruct>(modelHeader.ShapeMeshCount); ShapeValues = r.ReadStructuresAsArray <MdlStructs.ShapeValueStruct>(modelHeader.ShapeValueCount); var submeshBoneMapSize = r.ReadUInt32(); SubMeshBoneMap = r.ReadStructures <ushort>(( int )submeshBoneMapSize / 2).ToArray(); var paddingAmount = r.ReadByte(); r.Seek(r.BaseStream.Position + paddingAmount); // Dunno what this first one is for? BoundingBoxes = MdlStructs.BoundingBoxStruct.Read(r); ModelBoundingBoxes = MdlStructs.BoundingBoxStruct.Read(r); WaterBoundingBoxes = MdlStructs.BoundingBoxStruct.Read(r); VerticalFogBoundingBoxes = MdlStructs.BoundingBoxStruct.Read(r); BoneBoundingBoxes = new MdlStructs.BoundingBoxStruct[modelHeader.BoneCount]; for (var i = 0; i < modelHeader.BoneCount; i++) { BoneBoundingBoxes[i] = MdlStructs.BoundingBoxStruct.Read(r); } RemainingData = r.ReadBytes(( int )(r.BaseStream.Length - r.BaseStream.Position)); }