public void Read(FileReader reader, LM2_ARCADE_Model root) { Skeleton = new STSkeleton(); DrawableRenderer = new GenericModelRenderer(); root.DrawableContainer.Drawables.Add(Skeleton); root.DrawableContainer.Drawables.Add(DrawableRenderer); reader.ReadSignature(4, "VM61"); ushort Type = reader.ReadUInt16(); ushort Unknown = reader.ReadUInt16(); if (Type == 0) { } else if ((Type == 1)) { throw new Exception("Animation files not supported yet!"); } else { throw new Exception("Unknown type found! " + Type); } Alignment = reader.ReadUInt32(); uint Padding = reader.ReadUInt32(); ulong MaterialCount = reader.ReadUInt64(); HeaderSize = reader.ReadUInt64(); ulong TextureMapsCount = reader.ReadUInt64(); ulong TextureMapsOffset = reader.ReadUInt64(); ulong BoneCount = reader.ReadUInt64(); ulong BoneOffset = reader.ReadUInt64(); ulong FirstNodeOffset = reader.ReadUInt64(); //Either an offset or the total size of section up to the node ulong LinkNodeCount = reader.ReadUInt64(); ulong LinkNodeOffset = reader.ReadUInt64(); ulong TotalNodeCount = reader.ReadUInt64(); ulong TotalNodeOffset = reader.ReadUInt64(); ulong Padding2 = reader.ReadUInt64(); root.Nodes.Add("Materials"); root.Nodes.Add("Root"); root.Nodes.Add("All Nodes"); long pos = reader.Position; if (TextureMapsOffset != 0) { reader.SeekBegin(TextureMapsOffset); for (int i = 0; i < (int)TextureMapsCount; i++) { TextureMaps.Add(reader.ReadNameOffset(false, typeof(ulong))); } } reader.SeekBegin(pos); for (int i = 0; i < (int)MaterialCount; i++) { Material mat = new Material(); mat.Read(reader); Materials.Add(mat); var genericMat = new STGenericMaterial(); genericMat.Text = mat.Name; for (int t = 0; t < mat.TextureIndices.Length; t++) { if (mat.TextureIndices[t] != -1) { Console.WriteLine("TextureIndices " + mat.TextureIndices[t]); string Texture = TextureMaps[mat.TextureIndices[t]]; var textureMap = new STGenericMatTexture(); textureMap.Name = Texture; genericMat.TextureMaps.Add(textureMap); if (Texture.EndsWith("col.dds")) { textureMap.Type = STGenericMatTexture.TextureType.Diffuse; } if (Texture.EndsWith("col.mot")) { textureMap.Type = STGenericMatTexture.TextureType.Diffuse; } } } root.Nodes[0].Nodes.Add(genericMat); } if (TotalNodeCount != 0) { for (int i = 0; i < (int)TotalNodeCount; i++) { reader.SeekBegin((int)TotalNodeOffset + (i * 16)); string NodeName = reader.ReadNameOffset(false, typeof(ulong)); var Offset = reader.ReadUInt64(); Console.WriteLine($"{NodeName}"); if (Offset != 0) { reader.SeekBegin(Offset); Node node = new Node(); node.Name = NodeName; node.Read(reader); TotalNodes.Add(node); } } } if (BoneCount != 0) { for (int i = 0; i < (int)BoneCount; i++) { reader.SeekBegin((int)BoneOffset + (i * 16)); string NodeName = reader.ReadNameOffset(false, typeof(ulong)); ulong Offset = reader.ReadUInt64(); if (Offset != 0) { reader.SeekBegin(Offset); Node node = new Node(); node.Name = NodeName; node.Read(reader); BoneList.Add(node); //This list is for mapping to meshes } } } foreach (var node in TotalNodes) { // TreeNode lowerWrapper = new TreeNode($"{node.Name}"); // root.Nodes[3].Nodes.Add(lowerWrapper); LoadChildern(TotalNodes, node, root.Nodes[2]); } if (FirstNodeOffset != 0) { reader.SeekBegin(FirstNodeOffset); ulong NodeOffset = reader.ReadUInt64(); reader.SeekBegin(NodeOffset); Node node = new Node(); node.Name = GetNodeName(TotalNodes, node); node.Read(reader); LoadBones(TotalNodes, node, root.Nodes[1]); } if (LinkNodeCount != 0) { root.Nodes.Add("Links"); for (int i = 0; i < (int)LinkNodeCount; i++) { TreeNode linkWrapper = new TreeNode($"Link {i}"); root.Nodes[3].Nodes.Add(linkWrapper); reader.SeekBegin((int)LinkNodeOffset + (i * 16)); ulong NodeOffset1 = reader.ReadUInt64(); ulong NodeOffset2 = reader.ReadUInt64(); reader.SeekBegin(NodeOffset1); Node node1 = new Node(); node1.Name = GetNodeName(TotalNodes, node1); node1.Read(reader); reader.SeekBegin(NodeOffset2); Node node2 = new Node(); node2.Name = GetNodeName(TotalNodes, node1); node2.Read(reader); // LoadChildern(TotalNodes, node1, linkWrapper); // LoadChildern(TotalNodes, node2, linkWrapper); LinkNodes.Add(Tuple.Create(node1, node2)); } } Skeleton.update(); Skeleton.reset(); }
public void Load(System.IO.Stream stream) { fileSize = stream.Length; using (var reader = new FileReader(stream)) { pmdlCount = 0; ptexCount = 0; ptexList.Clear(); ddsList.Clear(); // Read header for data locations files.Clear(); reader.Position = 4; reader.ByteOrder = byteOrder; if (reader.ReadUInt32() != 2001) { byteOrder = ByteOrder.BigEndian; } reader.ByteOrder = byteOrder; reader.Position = 0; header.version = reader.ReadUInt32(4); reader.Position += 4; header.flag1 = reader.ReadUInt16(); header.flag2 = reader.ReadUInt16(); header.dataInfoCount = reader.ReadUInt32(); header.dataInfoSize = reader.ReadUInt32(); header.tagCount = reader.ReadUInt32(); header.tagSize = reader.ReadUInt32(); header.relocationDataOffset = reader.ReadUInt32(); header.relocationDataSize = reader.ReadInt32(); reader.Position += 92; // Create arrays for multiple data and tag info objects DataInfo[] dataInfos = new DataInfo[header.dataInfoCount]; TagInfo[] tagInfos = new TagInfo[header.tagCount]; for (int i = 0; i < header.dataInfoCount; i++) { // Create and assign properties to a new DataInfo until the count specified in the header is reached dataInfos[i] = new DataInfo() { unknown1 = reader.ReadUInt32(), textOffset = reader.ReadUInt32(), unknown2 = reader.ReadUInt32(), unknown3 = reader.ReadUInt32(), dataSize = reader.ReadInt32(), dataSize2 = reader.ReadUInt32(), dataOffset = reader.ReadInt32(), unknown4 = reader.ReadUInt32(), zero1 = reader.ReadUInt32(), zero2 = reader.ReadUInt32(), zero3 = reader.ReadUInt32(), zero4 = reader.ReadUInt32() }; } saveData = dataInfos; for (int i = 0; i < header.tagCount; i++) { // Get tags for file extensions, data, and names tagInfos[i] = new TagInfo() { magic = System.Text.Encoding.ASCII.GetString(reader.ReadBytes(4)), dataOffset = reader.ReadInt32(), flag = reader.ReadUInt32(), textOffset = reader.ReadInt32(), name = "default" }; } // Get extra data, currently unused except for saving the file if (header.dataInfoCount > 2) { reader.Position = dataInfos[2].dataOffset; extraData = reader.ReadBytes(dataInfos[2].dataSize); } // Get relocation data and write to byte array reader.Position = header.relocationDataOffset; relocationData = reader.ReadBytes(header.relocationDataSize); // Compile filenames and add as files for (long i = 0; i < header.tagCount - 1; i++) { reader.Position = dataInfos[0].dataOffset + tagInfos[i].textOffset; string filename = reader.ReadZeroTerminatedString(); tagInfos[i].name = filename; saveTag = tagInfos; if (!tagInfos[i].magic.StartsWith("\0")) { filename = filename + "." + tagInfos[i].magic.ToLower(); } reader.Position = dataInfos[1].dataOffset + tagInfos[i].dataOffset; FileEntry file = new FileEntry() { FileName = filename, FileData = reader.ReadBytes(tagInfos[i + 1].dataOffset - tagInfos[i].dataOffset) }; reader.Position = dataInfos[1].dataOffset + tagInfos[i].dataOffset; // Load textures as a dds using the PTEX pointer if (tagInfos[i].magic == "PTEX") { reader.Position += 88; Ptex ptex = new Ptex() { ptexOffset = reader.Position, width = reader.ReadUInt32(), height = reader.ReadUInt32(), unknown = reader.ReadUInt32(), ddsOffset = reader.ReadUInt32(), ddsSize = reader.ReadInt32() }; reader.Position = dataInfos[header.dataInfoCount - 1].dataOffset; reader.Position += ptex.ddsOffset; DDS dds = new DDS(reader.ReadBytes(ptex.ddsSize)) { WiiUSwizzle = false, FileType = FileType.Image, Text = filename + ".dds", FileName = filename, CanReplace = true }; reader.Position = dataInfos[header.dataInfoCount - 1].dataOffset; reader.Position += ptex.ddsOffset; ptexList.Add(ptex); Nodes.Add(dds); ddsList.Add(dds); FileType = FileType.Image; ptexCount++; } if (tagInfos[i].magic == "PMDL") { reader.Position += 8; Pmdl pmdl = new Pmdl() { relocationDataCount = reader.ReadInt16(), pmdlSize = reader.ReadInt16() }; reader.Position += 4; pmdl.modelTextOffset = reader.ReadInt32(); reader.Position += 36; pmdl.sumVertCount = reader.ReadInt32(); pmdl.faceStartOffsetRelative = reader.ReadInt32(); pmdl.vertexStartOffset = reader.ReadInt32(); reader.Position += 4; pmdl.sumFaceCount = reader.ReadInt32(); pmdl.faceStartOffset = reader.ReadInt32(); reader.Position += 48; pmdl.subInfoCount = reader.ReadInt32(); pmdl.offsetToSubInfosStart = reader.ReadInt32(); pmdl.endOfSubInfos = reader.ReadInt32(); reader.Position = pmdl.offsetToSubInfosStart + dataInfos[1].dataOffset; int[] subInfoStarts = new int[pmdl.subInfoCount]; subInfoStarts = reader.ReadInt32s(pmdl.subInfoCount); SubInfoData[] subInfoDatas = new SubInfoData[pmdl.subInfoCount]; for (int t = 0; t < pmdl.subInfoCount; t++) { reader.Position = subInfoStarts[t] + dataInfos[1].dataOffset; SubInfoData subInfoData = new SubInfoData() { unknown1 = reader.ReadInt32(), unknown2 = reader.ReadInt32(), unknown3 = reader.ReadInt32(), unknown4 = reader.ReadInt32(), unknown5 = reader.ReadInt32(), unknown6 = reader.ReadInt32(), vertexCount = reader.ReadInt32(), unknown8 = reader.ReadInt32(), previousFaceCount = reader.ReadInt32(), faceCount = reader.ReadInt32(), unknown11 = reader.ReadInt32(), unknown12 = reader.ReadInt32(), vertexOffsetRelative = reader.ReadInt32(), normalUVOffset = reader.ReadInt32(), faceOffset = reader.ReadInt32(), sameSizeorOffset = reader.ReadInt32(), sameSizeorOffset2 = reader.ReadInt32(), sameSizeorOffset3 = reader.ReadInt32(), sameSizeorOffset4 = reader.ReadInt32(), sameSizeorOffset5 = reader.ReadInt32() }; pmdl.verticesCount = subInfoData.vertexCount; pmdl.facesCount = subInfoData.faceCount; subInfoDatas[t] = subInfoData; } var renderedMesh = new GenericRenderedObject(); var renderer = new GenericModelRenderer(); renderedMesh.ImageKey = "mesh"; renderedMesh.SelectedImageKey = "mesh"; renderedMesh.Checked = true; int[] normalUVSize = new int[pmdl.subInfoCount]; if (pmdl.subInfoCount > 1) { int remember = 0; for (int a = 0; a + 1 < pmdl.subInfoCount; a++) { pmdl.normalUVStart = subInfoDatas[a].normalUVOffset; pmdl.normalUVEnd = subInfoDatas[a + 1].normalUVOffset; normalUVSize[a] = (int)(pmdl.normalUVEnd - pmdl.normalUVStart); remember = a; } pmdl.normalUVStart = subInfoDatas[remember + 1].normalUVOffset; pmdl.normalUVEnd = subInfoDatas[remember + 1].normalUVOffset; } else if (pmdl.subInfoCount >= 1) { for (int x = 0; x < pmdl.subInfoCount; x++) { int stride = (int)(normalUVSize[x] / subInfoDatas[x].vertexCount); reader.Position = pmdl.vertexStartOffset + subInfoDatas[x].vertexOffsetRelative; for (int j = 0; j < subInfoDatas[x].vertexCount; j++) { Vertex vert = new Vertex(); vert.pos = new OpenTK.Vector3(reader.ReadInt32(), reader.ReadInt32(), reader.ReadInt32()); } } } } files.Add(file); } // For the last file, read until the end of the raw data section TagInfo lastTag = tagInfos[header.tagCount - 1]; reader.Position = dataInfos[0].dataOffset + lastTag.textOffset; string filename2 = reader.ReadZeroTerminatedString(); tagInfos[header.tagCount - 1].name = filename2; saveTag = tagInfos; if (!lastTag.magic.StartsWith("\0")) { filename2 = filename2 + "." + lastTag.magic.ToLower(); } reader.Position = dataInfos[1].dataOffset + lastTag.dataOffset; FileEntry file2 = new FileEntry() { FileName = filename2, FileData = reader.ReadBytes(dataInfos[1].dataSize - lastTag.dataOffset) }; if (tagInfos[header.tagCount - 1].magic == "PTEX") { reader.Position = dataInfos[1].dataOffset + tagInfos[header.tagCount - 1].dataOffset + 88; Ptex ptex = new Ptex() { ptexOffset = reader.Position, width = reader.ReadUInt32(), height = reader.ReadUInt32(), unknown = reader.ReadUInt32(), ddsOffset = reader.ReadUInt32(), ddsSize = reader.ReadInt32() }; reader.Position = dataInfos[header.dataInfoCount - 1].dataOffset; reader.Position += ptex.ddsOffset; DDS dds = new DDS(reader.ReadBytes(ptex.ddsSize)) { WiiUSwizzle = false, FileType = FileType.Image, Text = filename2 + ".dds", FileName = filename2, CanReplace = true, }; reader.Position = dataInfos[header.dataInfoCount - 1].dataOffset; reader.Position += ptex.ddsOffset; ptexList.Add(ptex); Nodes.Add(dds); ddsList.Add(dds); FileType = FileType.Image; ptexCount++; } if (tagInfos[0].magic == "enti") { reader.Position = dataInfos[1].dataOffset + tagInfos[0].dataOffset; var position = reader.Position; var entityHeader = new Entity.EntityHeader() { entitiesOffset = reader.ReadUInt32(), entitiesCount = reader.ReadUInt32(), unknown1 = reader.ReadUInt32(), unknown2 = reader.ReadUInt32() }; reader.Position = position + entityHeader.entitiesOffset; var properties = new Entity.Property[entityHeader.entitiesCount]; //var entities = new Entity.Entity[entityHeader.entitiesCount]; //for (int i = 0; i < entityHeader.entitiesCount; i++) //{ // entities[i].entityNameOffset = reader.ReadUInt32(); // entities[i].propertiesCount = reader.ReadUInt16(); // entities[i].propertiesCount2 = reader.ReadUInt16(); // entities[i].propertiesOffset = reader.ReadUInt32(); // entities[i].matrixOffset = reader.ReadUInt32(); // entities[i].positionOffset = reader.ReadUInt32(); // entities[i].unknown = reader.ReadUInt32(); // entities[i].flag = reader.ReadUInt32(); // entities[i].valuesOffset = reader.ReadUInt32(); //} var entities = new Entity.Entity[entityHeader.entitiesCount]; for (int i = 0; i < entityHeader.entitiesCount; i++) { reader.Position = position + entities[i].propertiesOffset; } } files.Add(file2); } }