private Mesh ReadShape(FileReader reader) { Mesh mesh = new Mesh(); ushort unk = reader.ReadUInt16(); ushort numPackets = reader.ReadUInt16(); uint packetOffset = reader.ReadUInt32() * 4; using (reader.TemporarySeek(packetOffset, SeekOrigin.Begin)) { for (int j = 0; j < numPackets; j++) { reader.SeekBegin(packetOffset + (j * 12)); Packet packet = new Packet() { Offset = reader.ReadUInt32() * 4, Size = reader.ReadUInt32(), Flags1 = reader.ReadByte(), Flags2 = reader.ReadByte(), MaterialColorIndex = reader.ReadSByte(), TextureIndex = reader.ReadSByte(), }; MeshGroup meshGroup = new MeshGroup() { Packet = packet, TextureIndex = packet.TextureIndex, }; mesh.Groups.Add(meshGroup); // Console.WriteLine($"Material {packet.MaterialColorIndex} TextureIndex {packet.TextureIndex}"); // Console.WriteLine($"Flags1 {packet.Flags1 >> 4} {packet.Flags1 & 0xF} Flags2 {packet.Flags2}"); if (packet.MaterialColorIndex != -1) { using (reader.TemporarySeek(materialColorsOffset + (packet.MaterialColorIndex * 4), SeekOrigin.Begin)) { meshGroup.Color = reader.ReadColor8RGBA(); } } DisplayListHelper.Config config = new DisplayListHelper.Config(); List <GXVertexLayout> layouts = new List <GXVertexLayout>(); if (packet.Flags2 != 3 && packet.Flags2 != 15 && packet.Flags2 != 16 && packet.Flags2 != 14 && packet.Flags2 != 0) { layouts.Add(new GXVertexLayout( GXAttributes.PosNormMatrix, GXComponentType.U8, GXAttributeType.INDEX8, 48)); } if (packet.Flags2 == 18) { layouts.Add(new GXVertexLayout( GXAttributes.Tex0Matrix, GXComponentType.U8, GXAttributeType.INDEX8, 48)); } if (packet.Flags2 == 19) { layouts.Add(new GXVertexLayout( GXAttributes.Tex0Matrix, GXComponentType.U8, GXAttributeType.INDEX8, 48)); layouts.Add(new GXVertexLayout( GXAttributes.Tex1Matrix, GXComponentType.U8, GXAttributeType.INDEX8, 48)); layouts.Add(new GXVertexLayout( GXAttributes.Tex2Matrix, GXComponentType.U8, GXAttributeType.INDEX8, 48)); } layouts.Add(new GXVertexLayout( GXAttributes.Position, GXComponentType.S16, GXAttributeType.INDEX16, positionsOffset)); if (normalsoffset != 0) { layouts.Add(new GXVertexLayout( GXAttributes.Normal, GXComponentType.S16, GXAttributeType.INDEX16, normalsoffset)); } if (packet.Flags2 >= 16) { layouts.Add(new GXVertexLayout( GXAttributes.NormalBinormalTangent, GXComponentType.S16, GXAttributeType.INDEX16, normalsoffset)); layouts.Add(new GXVertexLayout( GXAttributes.NormalBinormalTangent, GXComponentType.S16, GXAttributeType.INDEX16, normalsoffset)); } if (packet.Flags2 == 14 || packet.Flags2 == 15) { layouts.Add(new GXVertexLayout( GXAttributes.NormalBinormalTangent, GXComponentType.S16, GXAttributeType.INDEX16, normalsoffset)); } if (colorsOffset != 0 && packet.Flags2 != 0) { layouts.Add(new GXVertexLayout( GXAttributes.Color0, GXComponentType.RGBA4, GXAttributeType.INDEX16, colorsOffset)); } if (texCoordsOffset != 0 && packet.Flags2 != 0) { layouts.Add(new GXVertexLayout( GXAttributes.TexCoord0, GXComponentType.S16, GXAttributeType.INDEX16, texCoordsOffset) { Divisor = 1024.0f, }); } if (packet.Flags2 == 16 || packet.Flags2 == 17 || packet.Flags2 == 19) { config.OpCodeShift = -2; } var displayListData = new SubStream(reader.BaseStream, packet.Offset, packet.Size); meshGroup.Vertices.AddRange(DisplayListHelper.ReadDisplayLists( displayListData, reader.BaseStream, layouts.ToArray(), config)); } } return(mesh); }