private void ReadPolygons(DataReader reader) { uint polyStartOffset = reader.Position; reader.Position += 0x14; uint uvOffset = polyStartOffset + reader.ReadUInt32(); uint triangleOffset = polyStartOffset + reader.ReadUInt32(); uint uvTriangledataSize = polyStartOffset + reader.ReadUInt32(); int polyCount = reader.ReadInt16(); reader.ReadInt16(); uint polyOffset = polyStartOffset + reader.ReadUInt32(); reader.Seek(polyOffset); for (int i = 0; i < polyCount; i++) { reader.PrintPosition(); var polyStruct = reader.ReadStruct <PolyStruct>(); var mesh = new GenericMesh(); Meshes.Add(mesh); mesh.Name = "Mesh_" + i; var temp = reader.Position; reader.Position = (uint)(triangleOffset + 3); Console.WriteLine(mesh.Name); for (int j = 0; j < polyStruct.FCount; j++) { var v = new GenericVertex(); var pos = Vertices[reader.ReadInt16()]; v.Pos = pos.Pos; v.Nrm = pos.Nrm; v.Bones = pos.Bones; v.Weights = pos.Weights; //TODO: uv and ?color? reader.ReadInt16(); // uv reader.ReadInt16(); // color mesh.Vertices.Add(v); } mesh.Optimize(); reader.Position = temp; triangleOffset += polyStruct.SectionSize; } }
public void Open(FileItem File) { var igb = new IGBFile(File.GetFileBinary()); var igbSkel = new IGSkeleton(igb); Matrix4[] transforms = new Matrix4[igbSkel.Bones.Count]; Matrix4[] inverts = new Matrix4[igbSkel.Bones.Count]; int boneIndex = 0; foreach (var v in igbSkel.Bones) { if (v == null) continue; GenericBone b = new GenericBone(); b.Name = v.Name; b.ParentIndex = v.ParentIndex; transforms[boneIndex] = new Matrix4( v.WorldInverseMatrix.M11, v.WorldInverseMatrix.M12, v.WorldInverseMatrix.M13, v.WorldInverseMatrix.M14, v.WorldInverseMatrix.M21, v.WorldInverseMatrix.M22, v.WorldInverseMatrix.M23, v.WorldInverseMatrix.M24, v.WorldInverseMatrix.M31, v.WorldInverseMatrix.M32, v.WorldInverseMatrix.M33, v.WorldInverseMatrix.M34, v.WorldInverseMatrix.M41, v.WorldInverseMatrix.M42, v.WorldInverseMatrix.M43, v.WorldInverseMatrix.M44); inverts[boneIndex] = transforms[boneIndex].Inverted(); b.Transform = inverts[boneIndex]; boneIndex++; Skeleton.Bones.Add(b); } foreach (var b in Skeleton.Bones) { if (b.ParentIndex != -1) { b.Transform = inverts[b.ParentIndex] * transforms[Skeleton.Bones.IndexOf(b)]; b.Transform = b.Transform.Inverted(); var position = igbSkel.Bones[Skeleton.Bones.IndexOf(b)].Position; b.Position = new Vector3(position.X, position.Y, position.Z); } } var vertexBuffers = IGVertexAccessor.ToDivaModels(igb); Model.Skeleton = Skeleton; Console.WriteLine(vertexBuffers.Count); foreach (var model in vertexBuffers) { GenericMesh m = new GenericMesh(); m.Name = model.Name; if (m.Name.Equals("")) m.Name = "Mesh_" + vertexBuffers.IndexOf(model); Console.WriteLine(m.Name + " " + !(model.Texture==null)); if(model.Texture != null) { GenericTexture t = new GenericTexture(); t.Name = System.IO.Path.GetFileNameWithoutExtension(model.Texture.Name); t.Width = (uint)model.Texture.Width; t.Height = (uint)model.Texture.Height; t.Mipmaps.Add(model.Texture.RGBA); if(!Model.MaterialBank.ContainsKey(t.Name)) Model.TextureBank.Add(t.Name, t); GenericMaterial mat = new GenericMaterial(); mat.TextureDiffuse = t.Name; if (!Model.MaterialBank.ContainsKey(t.Name)) Model.MaterialBank.Add(t.Name, mat); m.MaterialName = t.Name; } foreach (var mesh in model.Mesh) { var vertices = ToGenericVertices(mesh.Vertices); foreach (var dl in mesh.DisplayList) { if (dl.PrimitiveType == PrimType.Triangles) { foreach(var f in dl.Indices) m.Vertices.Add(vertices[f]); } if (dl.PrimitiveType == PrimType.TriangleStrip) { var tempList = new List<GenericVertex>(); foreach (var f in dl.Indices) tempList.Add(vertices[f]); Tools.TriangleConverter.StripToList(tempList, out tempList); m.Vertices.AddRange(tempList); } } } if(model.SingleBindBone != null && model.SingleBindBone != "") { var singleBone = Skeleton.Bones.Find(e => e.Name.Equals(model.SingleBindBone)); var singleBindTransform = Skeleton.GetWorldTransform(singleBone); var singleBindIndex = Skeleton.Bones.IndexOf(singleBone); for (int i = 0; i < m.VertexCount;i++) { var vert = m.Vertices[i]; vert.Pos = Vector3.TransformPosition(vert.Pos, singleBindTransform); vert.Nrm = Vector3.TransformNormal(vert.Nrm, singleBindTransform); vert.Bones = new Vector4(singleBindIndex, 0, 0, 0); vert.Weights = new Vector4(1, 0, 0, 0); m.Vertices[i] = vert; } } m.Optimize(); Model.Meshes.Add(m); } }
public GenericModel ToGenericModel() { GenericSkeleton skel = new GenericSkeleton(); foreach (var node in Nodes) { GenericBone bone = new GenericBone() { Name = node.Name, Position = node.Position, Rotation = node.Rotation, Scale = node.Scale, ParentIndex = node.ParentIndex }; skel.Bones.Add(bone); } GenericModel m = new GenericModel(); m.Skeleton = skel; // Textures var tindex = 0; foreach (var tex in Textures) { if (m.TextureBank.ContainsKey(tex.Name)) { tex.Name += "_" + tindex++; } m.TextureBank.Add(tex.Name, tex); } int index = -1; foreach (var meshObject in MeshObjects) { index++; Dictionary <int, List <GenericVertex> > MaterialToVertexBank = new Dictionary <int, List <GenericVertex> >(); //Console.WriteLine($"{meshObject.Key} {skel.Bones[meshObject.Value.SingleBind].Name}"); foreach (var d in meshObject.Value.Primitives) { if (!MaterialToVertexBank.ContainsKey(d.Material)) { MaterialToVertexBank.Add(d.Material, new List <GenericVertex>()); } var vertices = MaterialToVertexBank[d.Material]; switch (d.PrimitiveType) { case 0x02: // Triangle vertices.Add(GetVertex(meshObject.Value, d.Vertices[0], skel)); vertices.Add(GetVertex(meshObject.Value, d.Vertices[1], skel)); vertices.Add(GetVertex(meshObject.Value, d.Vertices[2], skel)); break; case 0x03: // Quad vertices.Add(GetVertex(meshObject.Value, d.Vertices[0], skel)); vertices.Add(GetVertex(meshObject.Value, d.Vertices[1], skel)); vertices.Add(GetVertex(meshObject.Value, d.Vertices[2], skel)); vertices.Add(GetVertex(meshObject.Value, d.Vertices[1], skel)); vertices.Add(GetVertex(meshObject.Value, d.Vertices[3], skel)); vertices.Add(GetVertex(meshObject.Value, d.Vertices[2], skel)); break; case 0x04: // Triangle Strip var verts = new List <GenericVertex>(); foreach (var dv in d.Vertices) { verts.Add(GetVertex(meshObject.Value, dv, skel)); } Tools.TriangleConverter.StripToList(verts, out verts); vertices.AddRange(verts); break; default: throw new Exception("Unsupported Primitive Type " + d.PrimitiveType.ToString("X")); } } foreach (var v in MaterialToVertexBank) { GenericMesh mesh = new GenericMesh(); mesh.Name = meshObject.Key; if (MaterialToVertexBank.Count > 1) { mesh.Name += "_" + m.Meshes.Count;// Textures[Materials[Materials1[v.Key].MaterialIndex].TextureIndex].Name; } GenericMaterial mat = new GenericMaterial(); mesh.MaterialName = "material_" + m.MaterialBank.Count; m.MaterialBank.Add(mesh.MaterialName, mat); var mat1Index = Materials1[v.Key].MaterialIndex; mat1Index = Math.Min(mat1Index, Materials.Count - 1); var textureIndex = Materials[mat1Index].TextureIndex; mat.TextureDiffuse = Textures[textureIndex].Name; m.Meshes.Add(mesh); mesh.Vertices.AddRange(v.Value); //Console.WriteLine(mesh.Name + " " + v.Key + " " + Materials[v.Key].TextureIndex + " " + Textures.Count + " " + Materials.Count); mesh.Optimize(); } } return(m); }
public void Open(FileItem File) { dynamic stuff = JObject.Parse(System.Text.Encoding.UTF8.GetString(File.GetFileBinary())); Model = new GenericModel(); Model.Skeleton = new GenericSkeleton(); var skeletons = stuff.skeletons; foreach (var skel in skeletons) { if (((string)skel.name).Contains("carryable")) { foreach (var bone in skel.bones) { var gBone = new GenericBone(); Model.Skeleton.Bones.Add(gBone); gBone.Name = "Bone_" + bone.index; gBone.ParentIndex = bone.parent; gBone.Position = new OpenTK.Vector3((float)bone.local.position[0], (float)bone.local.position[1], (float)bone.local.position[2]); gBone.QuaternionRotation = new OpenTK.Quaternion((float)bone.local.rotation[0], (float)bone.local.rotation[1], (float)bone.local.rotation[2], (float)bone.local.rotation[3]).Inverted(); gBone.Scale = new OpenTK.Vector3((float)bone.local.scale[0], (float)bone.local.scale[1], (float)bone.local.scale[2]); } break; } } var models = stuff.models; foreach (var modl in models) { foreach (var batch in modl.batches) { GenericMesh mesh = new GenericMesh(); Model.Meshes.Add(mesh); mesh.Name = batch.id; foreach (int index in batch.indices) { var vertex = new GenericVertex(); if (((JArray)batch.positions).Count > 0) { vertex.Pos = new OpenTK.Vector3((float)batch.positions[index * 3 + 0], (float)batch.positions[index * 3 + 1], (float)batch.positions[index * 3 + 2]); } if (((JArray)batch.normals).Count > 0) { vertex.Nrm = new OpenTK.Vector3((float)batch.normals[index * 3 + 0], (float)batch.normals[index * 3 + 1], (float)batch.normals[index * 3 + 2]); } if (((JArray)batch.uvs).Count > 0) { vertex.UV0 = new OpenTK.Vector2((float)batch.uvs[index * 2 + 0], (float)batch.uvs[index * 2 + 1]); } if (((JArray)batch.uvs2).Count > 0) { vertex.UV1 = new OpenTK.Vector2((float)batch.uvs2[index * 2 + 0], (float)batch.uvs2[index * 2 + 1]); } if (((JArray)batch.uvs3).Count > 0) { vertex.UV2 = new OpenTK.Vector2((float)batch.uvs3[index * 2 + 0], (float)batch.uvs3[index * 2 + 1]); } if (((JArray)batch.colors).Count > 0) { vertex.Clr = new OpenTK.Vector4((float)batch.colors[index * 4 + 0] * 255, (float)batch.colors[index * 4 + 1] * 255, (float)batch.colors[index * 4 + 2] * 255, (float)batch.colors[index * 4 + 3] * 255); } if (((JArray)batch.bindings).Count > 0) { vertex.Bones = new OpenTK.Vector4((int)batch.bindings[index * 4 + 0], (int)batch.bindings[index * 4 + 1], (int)batch.bindings[index * 4 + 2], (int)batch.bindings[index * 4 + 3]); } if (((JArray)batch.weights).Count > 0) { vertex.Weights = new OpenTK.Vector4(((int)batch.weights[index * 4 + 0]) / 255f, ((int)batch.weights[index * 4 + 1]) / 255f, ((int)batch.weights[index * 4 + 2]) / 255f, ((int)batch.weights[index * 4 + 3]) / 255f); } mesh.Vertices.Add(vertex); } mesh.Optimize(); } } }
private void ParseMDLD(byte[] data) { using (DataReader r = new DataReader(data)) { r.BigEndian = false; r.ReadInt32(); // magic var offset1 = r.ReadUInt32(); var polyInfoOffset = r.ReadUInt32(); var polyInfoCount = r.ReadInt32(); var boneOffset = r.ReadUInt32(); var boneCount = r.ReadInt32(); var bufferOffset = r.ReadUInt32(); var bufferLength = r.ReadInt32(); var vertexCount = r.ReadInt32(); var att = r.ReadString(0x68, -1).Split('_'); r.Seek(boneOffset); model.Skeleton = new GenericSkeleton(); for (int i = 0; i < boneCount; i++) { var bone = new GenericBone(); bone.Name = r.ReadString(r.Position, -1); r.Skip(0x20); bone.Transform = Matrix4.Identity; bone.QuaternionRotation = new Quaternion(r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle()); bone.Position = new Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle()); bone.Scale = new Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle()); bone.ParentIndex = r.ReadInt32(); model.Skeleton.Bones.Add(bone); } model.Skeleton.TransformWorldToRelative(); List <GenericVertex> vertices = new List <GenericVertex>(); for (uint i = 0; i < vertexCount; i++) { r.Seek(bufferOffset + 60 * i); var vert = new GenericVertex(); var stop = false; foreach (var va in att) { switch (va) { case "vp3": vert.Pos = new OpenTK.Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle()); break; case "vc": vert.Clr = new OpenTK.Vector4(r.ReadByte() / 255f, r.ReadByte() / 255f, r.ReadByte() / 255f, r.ReadByte() / 255f); break; case "vn": vert.Nrm = new OpenTK.Vector3(r.ReadHalfSingle(), r.ReadHalfSingle(), r.ReadHalfSingle()); r.ReadHalfSingle(); break; case "vt": vert.UV0 = new OpenTK.Vector2(r.ReadHalfSingle(), r.ReadHalfSingle()); break; case "von": r.Skip(8); break; case "vb4": vert.Bones = new OpenTK.Vector4(r.ReadInt16(), r.ReadInt16(), r.ReadInt16(), r.ReadInt16()); vert.Weights = new OpenTK.Vector4(r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle()); break; case "vs": break; default: stop = true; break; } if (stop) { break; } } vertices.Add(vert); } r.Seek(polyInfoOffset); for (int i = 0; i < polyInfoCount; i++) { GenericMesh mesh = new GenericMesh(); model.Meshes.Add(mesh); mesh.Name = r.ReadString(r.Position, -1); r.Skip(0x40); var polyBufferOffset = r.ReadUInt32(); var polyBufferLength = r.ReadUInt32(); var polyBufferCount = r.ReadUInt32(); var primType = r.ReadInt32(); r.Skip(0x60); var temp = r.Position; r.Seek(polyBufferOffset); for (int j = 0; j < polyBufferCount; j++) { if (primType == 4) { mesh.Vertices.Add(vertices[r.ReadInt32()]); } } mesh.Optimize(); r.Seek(temp); } } }
public void Open(FileItem File) { var skelPath = File.FilePath.Replace(".mdg", ".anm"); var skelAngPath = File.FilePath.Replace(".mdg", ".ang"); var modelPath = File.FilePath.Replace(".mdg", ".mdl"); var texPath = File.FilePath.Replace(".mdg", ".tex"); if (!System.IO.File.Exists(skelPath)) { System.Windows.Forms.MessageBox.Show("Missing Skeleton File " + Path.GetFileName(skelPath)); return; } if (!System.IO.File.Exists(skelAngPath)) { System.Windows.Forms.MessageBox.Show("Missing Skeleton File " + Path.GetFileName(skelAngPath)); return; } if (!System.IO.File.Exists(modelPath)) { System.Windows.Forms.MessageBox.Show("Missing Model File " + Path.GetFileName(modelPath)); return; } Model = new GenericModel(); Model.Skeleton = new GenericSkeleton(); if (System.IO.File.Exists(texPath)) { using (DataReader r = new DataReader(new FileStream(texPath, FileMode.Open))) { r.BigEndian = true; var unk = r.ReadInt32(); var width = r.ReadInt32(); var height = r.ReadInt32(); var dataLength = r.ReadInt32(); var padding = r.ReadInt32(); var format = r.ReadByte(); var data = r.GetSection(0x20, (int)(r.BaseStream.Length - 0x20)); var bmp = HSDLib.Helpers.TPL.ConvertFromTextureMelee(data, width, height, (int)TPL_TextureFormat.CMP, null, 0, 0); GenericTexture t = new GenericTexture(); t.FromBitmap(bmp); bmp.Dispose(); Model.TextureBank.Add("texture", t); Model.MaterialBank.Add("material", new GenericMaterial() { TextureDiffuse = "texture" }); } } using (DataReader r = new DataReader(new FileStream(skelPath, FileMode.Open))) { r.BigEndian = false; r.ReadInt32(); // magic r.ReadInt32(); // header var boneCount = r.ReadInt32(); var boneOffset = r.ReadUInt32(); using (DataReader angr = new DataReader(new FileStream(skelAngPath, FileMode.Open))) { angr.BigEndian = false; for (int i = 0; i < boneCount; i++) { r.Seek(boneOffset + (uint)(i * 0x20)); var bone = new GenericBone(); bone.Position = new OpenTK.Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle()); r.ReadSingle(); //r.Skip(0x10); // inverted world position bone.Name = r.ReadString(r.ReadUInt32(), -1); bone.ParentIndex = r.ReadInt32(); var flags = r.ReadInt32(); var angOffset = r.ReadUInt32(); /*angr.Seek(angOffset); * angr.Skip(4); * var posOff = angr.ReadUInt32(); * var rotOff = angr.ReadUInt32(); * var scaOff = angr.ReadUInt32(); * angr.Seek(posOff); * bone.Position = new OpenTK.Vector3(angr.ReadSingle(), angr.ReadSingle(), angr.ReadSingle()); * angr.Seek(rotOff); * bone.Rotation = new OpenTK.Vector3(angr.ReadSingle(), angr.ReadSingle(), angr.ReadSingle()); * angr.Seek(scaOff); * bone.Scale = new OpenTK.Vector3(angr.ReadSingle(), angr.ReadSingle(), angr.ReadSingle());*/ Model.Skeleton.Bones.Add(bone); } } } Model.Skeleton.TransformWorldToRelative(); using (DataReader r = new DataReader(new FileStream(modelPath, FileMode.Open))) { r.BigEndian = true; r.ReadInt32(); // magic int boneCount = r.ReadInt16(); var meshCount = r.ReadInt16(); boneCount = r.ReadInt32(); var meshOffset = r.ReadUInt32(); r.ReadUInt32(); var boneOffset = r.ReadUInt32(); for (int i = 0; i < meshCount; i++) { r.Seek(meshOffset + (uint)(i * 80)); r.Skip(0x30); // bounding stuff var mesh = new GenericMesh(); mesh.MaterialName = "material"; mesh.Name = r.ReadString(r.ReadUInt32(), -1); r.Skip(4 * 4); var datInfoOffset = r.ReadUInt32(); Model.Meshes.Add(mesh); r.Seek(datInfoOffset); var flag = r.ReadInt32(); var bufferOffset = r.ReadUInt32(); var someCount = r.ReadInt32(); var primCount = r.ReadInt32(); using (DataReader buffer = new DataReader(new FileStream(File.FilePath, FileMode.Open))) { buffer.BigEndian = true; if (new string(buffer.ReadChars(4)) == "MDG5") { buffer.Seek(0x10); } else { buffer.Seek(0); } buffer.Skip(bufferOffset); for (int p = 0; p < primCount; p++) { var primitiveType = buffer.ReadInt16(); var pcount = buffer.ReadInt16(); if (primitiveType != 0x98) { throw new NotSupportedException("Unknown prim type " + primitiveType.ToString("X")); } var strip = new List <GenericVertex>(); for (int v = 0; v < pcount; v++) { var vert = new GenericVertex(); vert.Pos = new OpenTK.Vector3(buffer.ReadSingle(), buffer.ReadSingle(), buffer.ReadSingle()); vert.Nrm = new OpenTK.Vector3(buffer.ReadSByte(), buffer.ReadSByte(), buffer.ReadSByte()); vert.Nrm.Normalize(); // Color? int col = buffer.ReadInt16(); var R = (col >> 12) & 0xF; var G = (col >> 8) & 0xF; var B = (col >> 4) & 0xF; var A = (col) & 0xF; vert.Clr = new OpenTK.Vector4( (R | R << 4) / (float)0xFF, (G | G << 4) / (float)0xFF, (B | B << 4) / (float)0xFF, (A | A << 4) / (float)0xFF); vert.UV0 = new OpenTK.Vector2(buffer.ReadInt16() / (float)0xFFF, buffer.ReadInt16() / (float)0xFFF); var weight1 = buffer.ReadByte() / (float)0xFF; float weight2 = 0; if (weight1 != 1) { weight2 = 1 - weight1; } var bone1 = buffer.ReadByte(); var bone2 = buffer.ReadByte(); vert.Bones = new OpenTK.Vector4(bone1, bone2, 0, 0); vert.Weights = new OpenTK.Vector4(weight1, weight2, 0, 0); strip.Add(vert); } TriangleConverter.StripToList(strip, out strip); mesh.Vertices.AddRange(strip); } } mesh.Optimize(); } } }
private void ParseSubMesh(DataReader r) { GenericMesh mesh = new GenericMesh(); Model.Meshes.Add(mesh); Console.WriteLine(r.Position.ToString("X")); //0x3C size // 5 floats r.Position += 4 * 5; int index1 = r.ReadInt32(); int index2 = r.ReadInt32(); r.ReadInt32(); // 0 r.ReadInt32(); // 1 var someOffset1 = r.ReadUInt32(); // 0x38 structure var someOffset2 = r.ReadUInt32(); // 0x8 structure flag->offset to 0x60 structure r.ReadInt32(); // 0 var skinDataOffset = r.ReadUInt32(); mesh.Name = r.ReadString(r.ReadUInt32() + 4, -1); r.ReadInt32(); // 0x1C structure Console.WriteLine("\t\t" + mesh.Name + " " + someOffset1.ToString("X") + " " + someOffset2.ToString("X") + " " + skinDataOffset.ToString("X")); r.Seek(someOffset2); r.ReadInt32(); // flag or count r.Seek(r.ReadUInt32()); var vectorSize = r.ReadInt16(); var vectorCount = r.ReadInt16(); var vectorOffset = r.ReadUInt32(); Console.WriteLine(vectorOffset.ToString("x") + " " + vectorCount.ToString("X")); r.Seek(vectorOffset); for (int i = 0; i < vectorCount; i++) { var vert = new GenericVertex(); vert.Pos = new Vector3(r.ReadInt16() / (float)short.MaxValue, r.ReadInt16() / (float)short.MaxValue, r.ReadInt16() / (float)short.MaxValue) * 100; vert.Nrm = new Vector3(r.ReadInt16() / (float)short.MaxValue, r.ReadInt16() / (float)short.MaxValue, r.ReadInt16() / (float)short.MaxValue); mesh.Vertices.Add(vert); } r.Seek(someOffset1); r.Skip(0x1C); var dlCount = r.ReadInt16() + 1; r.Skip(0xE); var displayListPointerListOffset = r.ReadUInt32(); r.Skip(0x8); //TODO: needs attributes to read properly r.Seek(displayListPointerListOffset); for (int j = 0; j < dlCount; j++) { var off = r.ReadUInt32(); var temp = r.Position; r.Seek(off); var primType = r.ReadByte(); var primCount = r.ReadInt16(); for (int k = 0; k < primCount; k++) { //var index = r.ReadByte(); // TODO: not always bytes } r.Seek(temp); } mesh.Optimize(); }
private void ParseDOBJs(IHSDNode node, HSD_JOBJ parent, List <HSD_JOBJ> BoneList) { if (node is HSD_JOBJ jobj) { if (jobj.DOBJ != null) { foreach (var child in jobj.DOBJ.List) { ParseDOBJs(child, jobj, BoneList); } } foreach (var child in jobj.Children) { ParseDOBJs(child, child, BoneList); } } if (node is HSD_DOBJ dobj) { Console.WriteLine("DOBJ found"); GenericMesh mesh = new GenericMesh(); mesh.Name = "Mesh_" + outModel.Meshes.Count; GenericMaterial mat = new GenericMaterial(); mesh.MaterialName = "material_" + outModel.MaterialBank.Count; outModel.MaterialBank.Add(mesh.MaterialName, mat); var Xscale = 1; var Yscale = 1; if (dobj.MOBJ != null) { if (dobj.MOBJ.Textures != null) { var tobj = dobj.MOBJ.Textures; mat.SWrap = GXTranslator.toWrapMode(tobj.WrapS); mat.TWrap = GXTranslator.toWrapMode(tobj.WrapT); Xscale = tobj.WScale; Yscale = tobj.HScale; if (!tobjToIndex.ContainsKey(tobj.ImageData.Data)) { Bitmap B = null; if (tobj.ImageData != null) { if (tobj.Tlut != null) { B = TPL.ConvertFromTextureMelee(tobj.ImageData.Data, tobj.ImageData.Width, tobj.ImageData.Height, (int)tobj.ImageData.Format, tobj.Tlut.Data, tobj.Tlut.ColorCount, (int)tobj.Tlut.Format); } else { B = TPL.ConvertFromTextureMelee(tobj.ImageData.Data, tobj.ImageData.Width, tobj.ImageData.Height, (int)tobj.ImageData.Format, null, 0, 0); } } GenericTexture t = new GenericTexture(); t.FromBitmap(B); B.Dispose(); tobjToIndex.Add(tobj.ImageData.Data, outModel.TextureBank.Count); outModel.TextureBank.Add("texture_" + outModel.TextureBank.Count, t); } mat.TextureDiffuse = outModel.TextureBank.Keys.ToArray()[tobjToIndex[tobj.ImageData.Data]]; } } outModel.Meshes.Add(mesh); if (dobj.POBJ != null) { foreach (HSD_POBJ pobj in dobj.POBJ.List) { // Decode the Display List Data GXDisplayList DisplayList = new GXDisplayList(pobj.DisplayListBuffer, pobj.VertexAttributes); var Vertices = ToGenericVertex(VertexAccessor.GetDecodedVertices(pobj), BoneList, pobj.BindGroups != null ? new List <HSD_JOBJWeight>(pobj.BindGroups.Elements) : null, parent); int bufferOffset = 0; foreach (GXPrimitiveGroup g in DisplayList.Primitives) { var primitiveType = GXTranslator.toPrimitiveType(g.PrimitiveType); var strip = new List <GenericVertex>(); for (int i = bufferOffset; i < bufferOffset + g.Count; i++) { strip.Add(Vertices[i]); } bufferOffset += g.Count; switch (primitiveType) { case OpenTK.Graphics.OpenGL.PrimitiveType.TriangleStrip: Tools.TriangleConverter.StripToList(strip, out strip); break; case OpenTK.Graphics.OpenGL.PrimitiveType.Quads: Tools.TriangleConverter.QuadToList(strip, out strip); break; case OpenTK.Graphics.OpenGL.PrimitiveType.Triangles: break; default: Debug.WriteLine("Error converting primitive type " + primitiveType); break; } mesh.Vertices.AddRange(strip); } } } for (int i = 0; i < mesh.Vertices.Count; i++) { var vert = mesh.Vertices[i]; vert.UV0 = new Vector2(vert.UV0.X * Xscale, vert.UV0.Y * Yscale); mesh.Vertices[i] = vert; } mesh.Optimize(); Tools.TriangleConverter.ReverseFaces(mesh.Triangles, out mesh.Triangles); } }