public GenericMesh DisplayListToGenericMesh(N64DisplayList DL) { GenericMesh mesh = new GenericMesh(); mesh.Name = "Mesh" + DL.faces.Count; foreach (int f in DL.faces) { mesh.Triangles.Add((uint)f); } foreach (N64Vertex_Normal nv in DL.verts) { mesh.Vertices.Add(new GenericVertex() { Pos = nv.pos, Nrm = nv.color.Xyz, UV0 = nv.uv, Bones = new Vector4(nv.bone, 0, 0, 0), Weights = new Vector4(1, 0, 0, 0) }); } return(mesh); }
private static GenericMesh ReadMesh(DataReader r, uint infoOffset, uint bufferOffset) { GenericMesh mesh = new GenericMesh(); var meshEntry = r.ReadStruct <Entry>(); if (meshEntry.ID == 4) { r.Seek(infoOffset + meshEntry.Offset); var lodCount = r.ReadInt32(); r.Seek(infoOffset + meshEntry.Offset + 0x10); r.PrintPosition(); var indexEntryIndex = r.ReadUInt32(); r.Seek(0x30 + indexEntryIndex * 0x10); var indexInfoEntry = r.ReadStruct <Entry>(); r.Seek(infoOffset + indexInfoEntry.Offset + 4); var indexBufferEntryIndex = r.ReadUInt32(); r.Seek(0x30 + indexBufferEntryIndex * 0x10); var indexBufferEntry = r.ReadStruct <Entry>(); r.Seek(infoOffset + indexBufferEntry.Offset); r.PrintPosition(); var indexDataBufferEntry = r.ReadStruct <Entry>(); if (indexBufferEntry.Flags == 0x010A || lodCount > 1) { return(null); } r.Seek(bufferOffset + indexDataBufferEntry.Offset); for (uint j = 0; j < indexDataBufferEntry.Size / 0x20; j++) { GenericVertex v = new GenericVertex(); v.Pos = new OpenTK.Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle()); r.Skip(0x14); mesh.Vertices.Add(v); mesh.Triangles.Add(j); } Console.WriteLine(meshEntry.Hash.ToString("X") + " " + meshEntry.ID); Console.WriteLine("\t" + lodCount + " " + indexBufferEntry.Flags.ToString("X") + " " + (bufferOffset + indexDataBufferEntry.Offset).ToString("X")); /*r.Seek(infoOffset + meshEntry.Offset + 0x30); * var vertexEntryIndex = r.ReadUInt32(); * * r.Seek(0x30 + vertexEntryIndex * 0x10 + 0x08); * var vertexBufferEntryIndex = r.ReadUInt32(); * * r.Seek(0x30 + indexBufferEntryIndex * 0x10); * r.Seek(0x30 + indexBufferEntryIndex * 0x10);*/ return(mesh); } return(null); }
public GenericModel ToGenericModel() { var model = new GenericModel(); var verts = GetVertexData(); int indexOffset = 0; int vertexOffset = 0; foreach (var m in Mesh.SubMesh) { var mesh = new GenericMesh(); mesh.Name = m.FirstVertex + "_Mesh"; model.Meshes.Add(mesh); for (int f = 0; f < m.IndexCount; f++) { mesh.Triangles.Add(Mesh.IndexBuffer[indexOffset + f]); } for (int v = 0; v < m.VertexCount; v++) { mesh.Vertices.Add(verts[v + vertexOffset]); } indexOffset += m.IndexCount; vertexOffset += m.VertexCount; } return(model); }
public void Open(FileItem file) { model.Skeleton = new GenericSkeleton(); using (DataReader r = new DataReader(file)) { r.BigEndian = false; r.Seek(0xCC); var somecount = r.ReadInt32(); var section1Size = r.ReadInt32(); var section2Size = r.ReadInt32(); r.ReadInt16(); var section3Size = r.ReadInt32(); r.Skip(0x0A); var section4Size = r.ReadInt32(); var section5Size = r.ReadInt32(); r.Skip(0x18); r.Skip((uint)section1Size); var mesh = new GenericMesh(); mesh.Name = "mesh1"; model.Meshes.Add(mesh); for (int i = 0; i < section2Size / 4; i++) { var v1 = r.ReadSByte(); var v2 = r.ReadSByte(); var v3 = r.ReadSByte(); var v4 = (float)r.ReadByte() / 255f; var v = new GenericVertex() { Pos = new OpenTK.Vector3(v1, v2, v3) * v4, Clr = new OpenTK.Vector4(1, 1, 1, 1) }; if (float.IsNaN(v.Pos.X) || float.IsInfinity(v.Pos.Y)) { v.Pos = new OpenTK.Vector3(); } mesh.Vertices.Add(v); Console.WriteLine(v.Pos.ToString()); } mesh.PrimitiveType = OpenTK.Graphics.OpenGL.PrimitiveType.TriangleStrip; for (uint i = 0; i < mesh.Vertices.Count; i++) { mesh.Triangles.Add(i); } for (int i = 0; i < section3Size / 12; i++) { Console.WriteLine(r.ReadHalfSingle() + " " + r.ReadHalfSingle() + " " + r.ReadHalfSingle() + " " + r.ReadInt16().ToString("X") + " " + r.ReadHalfSingle() + " " + r.ReadHalfSingle()); } } }
/// <summary> /// Draws the mesh while forcing a primitive type instead of using the mesh type. /// </summary> /// <param name="modelType">The type, as what the object should be rendered.</param> /// <param name="mesh">The mesh.</param> /// <param name="amount">The amounts for instancing.</param> public static void DrawObject(PrimitiveType modelType, GenericMesh mesh, int amount = 1) { if (mesh.Indices != null) { GL.DrawElementsInstanced(modelType, 0, DrawElementsType.UnsignedInt, mesh.Indices, amount); } else { GL.DrawArraysInstanced(modelType, 0, mesh.Vertex.Count, amount); } }
public GenericMesh ToGenericMesh() { GenericMesh mesh = new GenericMesh(); mesh.Name = Name; mesh.MaterialName = MaterialName; mesh.Triangles = ParseIndexBuffer(PolygonVertexIndexBuffer); mesh.Vertices = ParseBuffer(PolygonVertexBuffer); return(mesh); }
public GenericModel ToGenericModel() { var model = new GenericModel(); model.Skeleton = skeleton; var mesh = new GenericMesh(); for (int i = 0; i < PositionBuffer.Length; i++) { var vertex = new GenericVertex() { Pos = PositionBuffer[i].Xyz }; if (UV0Buffer.Length == PositionBuffer.Length) { vertex.UV0 = UV0Buffer[i]; } if (UV1Buffer.Length == PositionBuffer.Length) { vertex.UV1 = UV1Buffer[i]; } if (UV2Buffer.Length == PositionBuffer.Length) { vertex.UV2 = UV2Buffer[i]; } mesh.Vertices.Add(vertex); } List <short> tris = new List <short>(); tris.AddRange(IndexBuffer); TriangleConverter.StripToList(tris, out tris); short max = 0; foreach (var t in tris) { if (t > mesh.VertexCount) { break; } max = Math.Max(max, t); mesh.Triangles.Add((uint)t); } Console.WriteLine(max.ToString("X") + " " + mesh.VertexCount.ToString("X")); model.Meshes.Add(mesh); return(model); }
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; } }
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); } }
public void Open(FileItem File) { using (DataReader r = new DataReader(File)) { r.BigEndian = false; r.Seek(0x34); var skelTableOffset = r.Position + r.ReadUInt32(); Model = new GenericModel(); Model.Skeleton = new GenericSkeleton(); r.Seek(skelTableOffset + 8); var boneCount = r.ReadInt32(); for (int i = 0; i < boneCount; i++) { var temp = r.Position + 4; r.Seek(r.Position + r.ReadUInt32()); //r.PrintPosition(); var unk1 = r.ReadInt32(); var unk2 = r.ReadInt32(); GenericBone bone = new GenericBone(); bone.Transform = new OpenTK.Matrix4(r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle()); var boneInfoOffset = r.Position + r.ReadUInt32(); var boneFlag = r.ReadInt32(); var parentCount = r.ReadInt32(); var childCount = r.ReadUInt32(); r.Skip(4 * childCount); // parent count intofmration r.Seek(boneInfoOffset); var parentName = r.ReadString(r.ReadInt32()); r.Skip(1); r.Align(4); bone.Name = r.ReadString(r.ReadInt32()); r.Skip(1); r.Align(4); if (parentName != "") { bone.ParentIndex = Model.Skeleton.IndexOf(Model.Skeleton.Bones.Find(e => e.Name == parentName)); } Model.Skeleton.Bones.Add(bone); r.Seek(temp); } r.Seek(0x48); var objectCount = r.ReadInt32(); var unkOffset = r.Position + r.ReadUInt32(); var vcount = 0; for (int i = 0; i < objectCount - 1; i++) { GenericMesh mesh = new GenericMesh(); Model.Meshes.Add(mesh); var temp = r.Position + 4; r.Seek(r.Position + r.ReadUInt32()); r.Skip(8); mesh.Name = r.ReadString(r.Position + r.ReadUInt32() + 4, -1); var nameOff2 = r.Position + r.ReadUInt32(); var parentBoneOff = r.Position + r.ReadUInt32(); mesh.MaterialName = r.ReadString(r.Position + r.ReadUInt32() + 12, -1); var transform = new OpenTK.Matrix4(r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle()); var boneTableOffset = r.Position + r.ReadUInt32(); // bonetable offset r.ReadInt32(); // some matrix table? r.Skip(0x18); // floats var somecount = r.ReadInt32(); var indexTableOffset = r.Position + r.ReadUInt32(); var attributeBuffer = r.Position + r.ReadUInt32(); var vertCount = r.ReadInt32(); var primType = r.ReadInt32(); var unkownOffset2 = r.ReadUInt32(); if (unkownOffset2 > 0xFFFF) { r.ReadInt32(); } else { r.ReadInt16(); } var t = r.Position; r.Seek(attributeBuffer); var attributes = r.ReadStructArray <AttributeBuffer>(r.ReadInt32()); foreach (var a in attributes) { Console.WriteLine(a.Format + " " + a.Type + " " + a.Size); } r.Seek(t); for (int v = 0; v < vertCount; v++) { var vert = new GenericVertex(); foreach (var a in attributes) { float[] values = new float[a.Size]; for (int vi = 0; vi < values.Length; vi++) { switch (a.Format) { case 0x00: values[vi] = r.ReadSingle(); break; case 0x07: values[vi] = r.ReadInt16() / (float)short.MaxValue; break; case 0x06: values[vi] = r.ReadSByte(); break; case 0x0B: values[vi] = r.ReadUInt16() / (float)ushort.MaxValue; break; case 0x0E: values[vi] = r.ReadByte() / (float)255; break; default: throw new NotSupportedException("Unknown Attribute Format " + a.Format); } } switch (a.Type) { case 0: vert.Pos = new OpenTK.Vector3(values[0], values[1], values[2]); break; case 1: vert.Clr = new OpenTK.Vector4(values[0], values[1], values[2], values[3]); break; case 3: vert.UV0 = new OpenTK.Vector2(values[0], values[1]); break; case 15: vert.Bones = new OpenTK.Vector4(values[0], values[1], values[2], values[3]); break; case 16: vert.Weights = new OpenTK.Vector4(values[0], values[1], values[2], values[3]); break; //default: // throw new NotSupportedException("Unknown vertex attribute " + a.Type); } } mesh.Vertices.Add(vert); } r.Seek(indexTableOffset); var indexBufferSize = r.ReadInt32(); var indexCount = (indexBufferSize - 6) / 2; if (indexBufferSize > 0xFFFF) { r.ReadInt32(); } else { r.ReadInt16(); } for (int j = 0; j < indexCount; j++) { var v = r.ReadUInt16(); mesh.Triangles.Add(mesh.VertexCount < 0xFF ? (uint)(v & 0xFF) : v); } //r.PrintPosition(); Console.WriteLine(mesh.Name + " " + mesh.VertexCount.ToString("X") + " " + mesh.Triangles.Min().ToString("X") + " " + mesh.Triangles.Max().ToString("X")); //mesh.PrimitiveType = OpenTK.Graphics.OpenGL.PrimitiveType.TriangleStrip; r.Seek(temp); } } }
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 void Open(FileItem file) { using (DataReader r = new DataReader(file)) { r.BigEndian = true; r.Skip(0xC); // magic var faceOffset = r.ReadUInt32(); var faceLength = r.ReadInt32(); var vertexLength = r.ReadInt32(); var boneTableOffset = r.ReadUInt32(); r.ReadInt32(); // some flag usually 1 var vertOffset = r.ReadUInt32(); var faceOffset2 = r.ReadUInt32(); r.ReadInt32(); // some flag usually 1 var nameCount = r.ReadInt32(); var boneCount = r.ReadInt32(); var polyCount = r.ReadInt32(); var matLength = r.ReadInt32(); var polyNameCount2 = r.ReadInt32(); var polyNameCount3 = r.ReadInt32(); var boneTableCount = r.ReadInt32(); var boneTableCount2 = r.ReadInt32(); var stringCount = r.ReadInt32(); var UnkOffset = r.ReadInt32(); var unk = r.ReadInt32(); var boneOffset = r.ReadUInt32(); var polyInfoOffset = r.ReadUInt32(); var materialOffset = r.ReadUInt32(); var unkOffset2 = r.ReadUInt32(); var materialOffset2 = r.ReadUInt32(); var matrixOffset = r.ReadUInt32(); r.ReadInt32(); // same matrix offset var stringOffset = r.ReadInt32(); r.Seek(boneOffset); for (int i = 0; i < boneCount; i++) { GenericBone bone = new GenericBone(); bone.Name = r.ReadString(r.ReadUInt32(), -1); r.ReadInt32(); // hash var parentName = r.ReadString(r.ReadUInt32(), -1); r.ReadInt32(); // hash r.Skip(0x14); // various unimportant stuff var pos = new Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle()); var sca = new Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle()); r.Skip(0x14); // various unimportant stuff var inverseMatrix = new Matrix4(r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle()); var matrix = new Matrix4(r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle()); r.Skip(0xC); // various unimportant stuff bone.Transform = inverseMatrix.Inverted(); bone.Position = pos; bone.ParentIndex = Skeleton.Bones.FindIndex(e => e.Name == parentName); Skeleton.Bones.Add(bone); } r.Seek(materialOffset); for (int i = 0; i < matLength / 6; i++) { GenericMaterial mat = new GenericMaterial(); r.PrintPosition(); var name = r.ReadString(r.ReadUInt32(), -1); if (name == "") { name = "null"; } r.Skip(0x110); mat.TextureDiffuse = r.ReadString(r.ReadUInt32(), -1); r.Skip(0x110); if (Generic.MaterialBank.ContainsKey(name)) { name += "_" + i; } if (!Generic.TextureBank.ContainsKey(mat.TextureDiffuse)) { Generic.TextureBank.Add(mat.TextureDiffuse, new GenericTexture() { Name = mat.TextureDiffuse }); } Generic.MaterialBank.Add(name, mat); } r.Seek(faceOffset); var Indices = new ushort[faceLength / 2]; for (int i = 0; i < Indices.Length; i++) { Indices[i] = r.ReadUInt16(); } r.Seek(vertOffset); var Vertices = new GenericVertex[vertexLength / 44]; for (int i = 0; i < Vertices.Length; i++) { Vertices[i] = new GenericVertex() { Pos = new Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle()), Nrm = new Vector3(r.ReadByte() / 255f, r.ReadByte() / 255f, r.ReadByte() / 255f), Extra = new Vector4(r.ReadByte()), Clr = new Vector4(r.ReadByte() / 255f, r.ReadByte() / 255f, r.ReadByte() / 255f, r.ReadByte() / 255f), UV0 = new Vector2(r.ReadHalfSingle(), r.ReadHalfSingle()), UV1 = new Vector2(r.ReadHalfSingle(), r.ReadHalfSingle()), Bones = new Vector4(r.ReadByte(), r.ReadByte(), r.ReadByte(), r.ReadByte()), Weights = new Vector4(r.ReadByte() / 255f, r.ReadByte() / 255f, r.ReadByte() / 255f, r.ReadByte() / 255f), Extra2 = new Vector4(r.ReadSingle(), r.ReadSingle(), 0, 0) }; } var indexOffset = 0; var vertexOffset = 0; r.Seek(polyInfoOffset); for (int i = 0; i < polyCount; i++) { GenericMesh mesh = new GenericMesh(); mesh.Name = r.ReadString(r.ReadUInt32(), -1); r.ReadInt32();//hash var myboneTableOffset = r.ReadUInt32(); var myPolyOffset = r.ReadInt32(); r.Skip(8); var indexCount = r.ReadInt32(); var vertCount = r.ReadInt32(); var boneIDCount = r.ReadInt32(); var materialID = r.ReadInt32(); r.Skip(8); mesh.MaterialName = Generic.MaterialBank.Keys.ToList()[materialID]; // read bone table var temp = r.Position; var boneTable = new int[boneIDCount]; r.Seek(myboneTableOffset); for (int j = 0; j < boneIDCount; j++) { boneTable[j] = r.ReadInt32(); } // get indices for (int j = 0; j < indexCount; j++) { mesh.Triangles.Add(Indices[indexOffset + j]); } indexOffset += indexCount; // get vertices for (int j = 0; j < vertCount; j++) { var vert = Vertices[vertexOffset + j]; if (boneIDCount == 1) { vert.Weights = new Vector4(1, 0, 0, 0); vert.Bones = new Vector4(0, 0, 0, 0); } if (boneIDCount != 0) { for (int k = 0; k < 4; k++) { if (vert.Weights[k] > 0) { vert.Bones[k] = boneTable[(int)vert.Bones[k]]; } } } if (vert.Weights[0] == 1 && boneIDCount == 1) { vert.Pos = Vector3.TransformPosition(vert.Pos, Skeleton.GetWorldTransform(Skeleton.Bones[(int)vert.Bones[0]])); vert.Nrm = Vector3.TransformNormal(vert.Nrm, Skeleton.GetWorldTransform(Skeleton.Bones[(int)vert.Bones[0]])); } vert.Nrm.Normalize(); mesh.Vertices.Add(vert); } vertexOffset += vertCount; r.Seek(temp); //Console.WriteLine(mesh.Name + " " + (myPolyOffset / 2).ToString("X") + " " + myboneTableOffset.ToString("X")); Generic.Meshes.Add(mesh); } } }
public GenericModel GetGenericModel() { var ml = new List <GenericMesh>(); int offset = 0; int MaxBoneIndex = 0; foreach (var gr in meshGroups) { foreach (var mo in gr) { var mesh = new GenericMesh(); mesh.Name = "mesh" + ml.Count.ToString("X"); mesh.MaterialName = "material"; mesh.Vertices = new List <GenericVertex>(); mesh.Triangles = new List <uint>(); var stringToMorph = new Dictionary <string, GenericMorph>(); for (int i = offset; i < offset + mo.VertexCount; i++) { mesh.Vertices.Add(vertices[i]); mesh.Triangles.Add((uint)(i - offset)); // Morphs foreach (var m in _morphs) { //contains vertex if (m.Value.ContainsKey(i)) { if (!stringToMorph.ContainsKey(m.Key)) { GenericMorph morph = new GenericMorph() { Name = m.Key }; mesh.Morphs.Add(morph); stringToMorph.Add(m.Key, morph); } var morp = stringToMorph[m.Key]; morp.Vertices.Add(new MorphVertex() { VertexIndex = mesh.Vertices.Count - 1, Vertex = m.Value[i] }); } } } offset += mo.VertexCount; if (mo.PrimitiveType == 4) { mesh.PrimitiveType = PrimitiveType.Triangles; ml.Add(mesh); } if (mo.PrimitiveType == 5) { mesh.PrimitiveType = PrimitiveType.TriangleStrip; ml.Add(mesh); } foreach (var boneindex in mo.BoneIndices) { MaxBoneIndex = Math.Max(boneindex, MaxBoneIndex); } } } Console.WriteLine("Bones: " + MaxBoneIndex + " " + Skeleton.Bones.Count); Console.WriteLine("Vertices: " + offset + " " + vertices.Count); var model = new GenericModel() { Skeleton = Skeleton, Meshes = ml }; model.MaterialBank.Add("material", new GenericMaterial()); return(model); }
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(); }
public void Open(FileItem file) { Model = new GenericModel(); Model.Skeleton = new GenericSkeleton(); using (DataReader r = new DataReader(file)) { r.Seek(0x0A); while (r.Position < r.Length) { var type = r.ReadByte(); switch (type) { case 0: // nothing? break; case 1: // SomeCount at beginning of file r.ReadInt16(); break; case 2: // material var materialName = r.ReadString(r.ReadByte()); r.Skip(0x0C); break; case 3: // texture var textureName = r.ReadString(r.ReadByte()); break; case 0x0A: // Bone var boneName = r.ReadString(r.ReadByte()); Model.Skeleton.Bones.Add(new GenericBone() { Name = boneName }); break; case 0x0C: // Appears After bone but before mesh break; case 0x14: // mesh GenericMesh mesh = new GenericMesh(); Model.Meshes.Add(mesh); mesh.Name = r.ReadString(r.ReadByte()); var c1 = r.ReadByte(); var numOfPositions = r.ReadInt16(); for (uint i = 0; i < numOfPositions; i++) { mesh.Vertices.Add(new GenericVertex() { Pos = new OpenTK.Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle()) }); mesh.Triangles.Add(i); } r.Skip(4); break; case 0x16: // normal buffer var numOfUVs = r.ReadByte(); r.ReadByte(); for (uint i = 0; i < numOfUVs; i++) { r.Skip(8); } r.Skip(4); break; case 0x19: // mesh material entry var meshMaterialName = r.ReadString(r.ReadByte()); r.Skip(8); break; default: r.PrintPosition(); Console.WriteLine("Unknown Type 0x" + type.ToString("X2")); r.Position = (uint)r.Length; break; } } } }
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(); } } }
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) { 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 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); } } }
/// <summary> /// /// </summary> /// <returns></returns> public GenericModel ToGenericModel() { var model = new GenericModel(); model.Skeleton = Skeleton; var tindex = 0; foreach (var t in Textures) { model.TextureBank.Add("T" + tindex.ToString("X3"), t); tindex++; } foreach (var g1m in Models) { var mod = g1m.G1MG; var nuno = g1m.NUNO; var nunv = g1m.NUNV; model.Skeleton = g1m.Skeleton.Skeleton; var idTonunoBoneToBone33 = new List <Dictionary <int, int> >(); List <int> nunoParents = new List <int>(); //var idTonunoBoneToBone32 = new List<int>(); var entries = new List <NUNO.NUNOv33Entry>(); var nunoIndexOffset = 0; if (nunv != null) { nunoIndexOffset = nunv.V33Entries.Count; } if (nunv != null) { entries.AddRange(nunv.V33Entries); } if (nuno != null) { entries.AddRange(nuno.V33Entries); } foreach (var entry in entries) { var boneStart = model.Skeleton.Bones.Count; var parentBone = mod.BindMatches[entry.ParentBoneID - 1][0]; nunoParents.Add(parentBone); Dictionary <int, int> nunoBoneToBone = new Dictionary <int, int>(); idTonunoBoneToBone33.Add(nunoBoneToBone); GenericMesh driverMesh = new GenericMesh(); driverMesh.Name = "driver_" + (idTonunoBoneToBone33.Count - 1) + "_" + model.Skeleton.Bones[parentBone].Name; model.Meshes.Add(driverMesh); driverMesh.Visible = false; for (int pointIndex = 0; pointIndex < entry.Points.Count; pointIndex++) { // fake bone generation var p = entry.Points[pointIndex]; var link = entry.Influences[pointIndex]; GenericBone b = new GenericBone(); b.Name = $"CP_{idTonunoBoneToBone33.Count}_{model.Skeleton.Bones[parentBone].Name}_{pointIndex}"; b.Transform = Matrix4.Identity; nunoBoneToBone.Add(pointIndex, model.Skeleton.Bones.Count); model.Skeleton.Bones.Add(b); b.Position = p.Xyz; b.ParentIndex = link.P3; if (b.ParentIndex == -1) { b.ParentIndex = parentBone; } else { b.ParentIndex += boneStart; b.Position = Vector3.TransformPosition(p.Xyz, model.Skeleton.GetWorldTransform(parentBone) * model.Skeleton.GetWorldTransform(b.ParentIndex).Inverted()); } // fake driver mesh generation driverMesh.Vertices.Add(new GenericVertex() { Pos = Vector3.TransformPosition(Vector3.Zero, model.Skeleton.GetWorldTransform(model.Skeleton.Bones.Count - 1)), Weights = new Vector4(1, 0, 0, 0), Bones = new Vector4(model.Skeleton.Bones.Count - 1, 0, 0, 0) }); if (link.P1 > 0 && link.P3 > 0) { driverMesh.Triangles.Add((uint)pointIndex); driverMesh.Triangles.Add((uint)link.P1); driverMesh.Triangles.Add((uint)link.P3); } if (link.P2 > 0 && link.P4 > 0) { driverMesh.Triangles.Add((uint)pointIndex); driverMesh.Triangles.Add((uint)link.P2); driverMesh.Triangles.Add((uint)link.P4); } } } foreach (var group in mod.Lods[0].Groups) { var isCloth = (group.ID & 0xF) == 1; var isPoint = (group.ID & 0xF) == 2; var NunSection = (group.ID2 - (group.ID2 % 10000)) / 10000; Console.WriteLine(group.Name + " " + group.ID + " " + group.ID2 + " " + NunSection); foreach (var polyindex in group.Indices) { if (polyindex > mod.Polygons.Count) { continue; } var poly = mod.Polygons[polyindex]; GenericMesh mesh = new GenericMesh(); mesh.Name = System.Text.RegularExpressions.Regex.Replace(group.Name, @"\p{C}+", string.Empty) + model.Meshes.Count;// + "_" + polyindex; model.MaterialBank.Add("MP_" + polyindex, new GenericMaterial() { MaterialInfo = mod.Materials[poly.MaterialIndex].ToString(), TextureDiffuse = "T" + mod.TextureBanks[poly.TextureBankIndex].DiffuseTextureIndex.ToString("X3"), EnableBlend = false, }); mesh.MaterialName = "MP_" + polyindex; mesh.Vertices = mod.GetVertices(poly, out mesh.Triangles, !isCloth); if (isPoint) { for (int i = 0; i < mesh.VertexCount; i++) { var vert = mesh.Vertices[i]; vert.Nrm = Vector3.TransformNormal(vert.Nrm, model.Skeleton.GetWorldTransform(mod.BindMatches[poly.BoneTableIndex][0])); vert.Pos = Vector3.TransformPosition(vert.Pos, model.Skeleton.GetWorldTransform(mod.BindMatches[poly.BoneTableIndex][0])); mesh.Vertices[i] = vert; } } if (isCloth) { Dictionary <int, int> nunoBoneToBone = idTonunoBoneToBone33[group.ID2 & 0xF]; if (NunSection == 2 && nunv != null && nuno != null) { nunoBoneToBone = idTonunoBoneToBone33[(group.ID2 & 0xF) + nunoIndexOffset]; } //mesh.Name += "_driver_" + (group.ID2 & 0xF); for (int i = 0; i < mesh.VertexCount; i++) { var vert = mesh.Vertices[i]; if (vert.Bit == Vector4.Zero) { //Console.WriteLine(vert.Weights.ToString() + " " + vert.Bones.ToString()); vert.Pos = Vector3.TransformPosition(vert.Pos, model.Skeleton.GetWorldTransform(mod.BindMatches[poly.BoneTableIndex][0])); vert.Nrm = Vector3.TransformNormal(vert.Nrm, model.Skeleton.GetWorldTransform(mod.BindMatches[poly.BoneTableIndex][0])); //vert.Weights = new Vector4(1, 0, 0, 0); vert.Bones = new Vector4(mod.BindMatches[poly.BoneTableIndex][(int)vert.Bones.X / 3], mod.BindMatches[poly.BoneTableIndex][(int)vert.Bones.Y / 3], mod.BindMatches[poly.BoneTableIndex][(int)vert.Bones.Z / 3], mod.BindMatches[poly.BoneTableIndex][(int)vert.Bones.W / 3]); mesh.Vertices[i] = vert; continue; } Vector3 finpos = Vector3.Zero; //Console.WriteLine(vert.Nrm + " " + vert.Nrm.Normalized()); var tempb = new GenericBone(); tempb.Transform = Matrix4.Identity; tempb.Rotation = vert.Clr1.Xyz; var weights1 = new Vector4(vert.Pos, vert.Extra3.X); { var pos = Vector3.Zero; var d4 = Vector3.Zero; d4 += Weight(pos, model.Skeleton, weights1, vert.Bones, nunoBoneToBone) * vert.Weights.X; d4 += Weight(pos, model.Skeleton, weights1, vert.Extra, nunoBoneToBone) * vert.Weights.Y; d4 += Weight(pos, model.Skeleton, weights1, vert.Fog, nunoBoneToBone) * vert.Weights.Z; d4 += Weight(pos, model.Skeleton, weights1, vert.Extra2, nunoBoneToBone) * vert.Weights.W; var d5 = Vector3.Zero; d5 += Weight(pos, model.Skeleton, weights1, vert.Bones, nunoBoneToBone) * vert.Clr1.X; d5 += Weight(pos, model.Skeleton, weights1, vert.Extra, nunoBoneToBone) * vert.Clr1.Y; d5 += Weight(pos, model.Skeleton, weights1, vert.Fog, nunoBoneToBone) * vert.Clr1.Z; d5 += Weight(pos, model.Skeleton, weights1, vert.Extra2, nunoBoneToBone) * vert.Clr1.W; var d6 = Vector3.Zero; d6 += Weight(pos, model.Skeleton, vert.Bit, vert.Bones, nunoBoneToBone) * vert.Weights.X; d6 += Weight(pos, model.Skeleton, vert.Bit, vert.Extra, nunoBoneToBone) * vert.Weights.Y; d6 += Weight(pos, model.Skeleton, vert.Bit, vert.Fog, nunoBoneToBone) * vert.Weights.Z; d6 += Weight(pos, model.Skeleton, vert.Bit, vert.Extra2, nunoBoneToBone) * vert.Weights.W; vert.Pos = Vector3.Cross(d5, d6) * (vert.Extra3.Y) + d4; } vert.Weights = Vector4.Zero; // new Vector4(1, 0, 0, 0); vert.Bones = Vector4.Zero; // new Vector4(mod.BindMatches[poly.BoneTableIndex][0], 0, 0, 0); //RigMe(vert.Pos, model.Skeleton, nunoBoneToBone, out vert.Bones, out vert.Weights); mesh.Vertices[i] = vert; } } mesh.PrimitiveType = OpenTK.Graphics.OpenGL.PrimitiveType.TriangleStrip; model.Meshes.Add(mesh); } } } return(model); }
public void Open(FileItem File) { var Data = File.GetFileBinary(); Model = new GenericModel(); Model.Skeleton = new GenericSkeleton(); Model.Skeleton.RotationOrder = RotationOrder.ZYX; // decompress using (DataReader reader = new DataReader(new MemoryStream(Data))) { reader.BigEndian = true; if (reader.BaseStream.Length < 8 || !reader.ReadString(8).Equals("PERS-SZP")) { // not compressed } else { reader.BigEndian = true; uint compressedoffset = reader.ReadUInt32(); reader.Seek(compressedoffset); Data = Tools.Decompress.YAY0(reader.ReadBytes((int)(reader.BaseStream.Length - compressedoffset))); } } // decode file contents using (DataReader reader = new DataReader(new MemoryStream(Data))) { reader.BigEndian = true; reader.Seek(0x8); if (!reader.ReadString(8).Equals("FRAGMENT")) { return; } reader.Seek(0x10); uint DataOffset = reader.ReadUInt32(); uint RelocationTableOffset = reader.ReadUInt32(); reader.Skip(4); // filesize reader.Skip(4); // tableOffset again // Relocation Table reader.Seek(RelocationTableOffset); int entryCount = reader.ReadInt32(); int[] offsets = new int[entryCount]; for (int i = 0; i < entryCount; i++) { int mask = 0xFFFF; offsets[i] = reader.ReadInt32(); if (RelocationTableOffset > 0xFFFF) { mask = 0x1FFFF; // hack } uint temp = reader.Position; reader.Seek((uint)(offsets[i] & 0x1FFFF)); reader.WriteInt32At(reader.ReadInt32() & mask, offsets[i] & 0x1FFFF); reader.Seek((uint)(offsets[i] & 0x1FFFF)); reader.Seek(temp); } // main data reader.Seek(DataOffset); reader.Skip(0x10); uint mainOffset = reader.ReadUInt32(); // main stuff reader.Seek(mainOffset); reader.Skip(8); // i dunno uint offsetToTextureOffset = reader.ReadUInt32(); reader.Seek(offsetToTextureOffset); uint textureOffset = reader.ReadUInt32(); // may be objects instead of just textures reader.Seek(textureOffset); int TextureCount = reader.ReadInt32() & 0xFFFF; // should have 0x17 in front int PaletteCount = reader.ReadInt16(); int VertexCount = reader.ReadInt16(); uint TextureOffset = reader.ReadUInt32(); uint PaletteOffset = reader.ReadUInt32(); uint VertexOffset = reader.ReadUInt32(); reader.Skip(0x1C); //I dunno uint objectOffset = reader.ReadUInt32(); // Textures------------------------------------------------------- List <GenericTexture> Textures = new List <GenericTexture>(); List <byte[]> Palettes = new List <byte[]>(); //Read Palettes reader.Seek(PaletteOffset); for (int i = 0; i < PaletteCount; i++) { int colorcount = reader.ReadInt32(); uint OffsetData = reader.ReadUInt32(); int OffsetSomething = reader.ReadInt32(); Palettes.Add(reader.GetSection(OffsetData, colorcount * 2)); } // Read Textures? reader.Seek(TextureOffset); //Console.WriteLine(reader.pos().ToString("x")); for (int i = 0; i < TextureCount; i++) { int format = reader.ReadByte(); int bitsize = reader.ReadByte(); uint width = reader.ReadUInt16(); uint height = reader.ReadUInt16(); uint size = reader.ReadUInt16(); // sometimes 8 maybe an id? pointer? uint texDataOffset = reader.ReadUInt32() & 0x1FFFF; Console.WriteLine("Texture " + format + " " + bitsize + " " + size + " " + width + " " + height); GenericTexture tex = new GenericTexture(); Textures.Add(tex); tex.Name = "Texture_" + i; byte[] data; tex.Width = width; tex.Height = height; tex.PixelFormat = PixelFormat.Rgba; if (format == 4) { // Raw if (bitsize == 1) //RGBA { data = reader.GetSection(texDataOffset, (int)size * bitsize); tex.Mipmaps.Add(data); tex.InternalFormat = PixelInternalFormat.Luminance8; tex.PixelFormat = PixelFormat.Luminance; } } else if (format == 2) { // Paletted if (bitsize == 0) //4bpp { data = reader.GetSection(texDataOffset, (int)size / 2); tex.Mipmaps.Add(data); tex.InternalFormat = PixelInternalFormat.Alpha4; } else if (bitsize == 1) //8bpp { data = reader.GetSection(texDataOffset, (int)size * bitsize); tex.Mipmaps.Add(data); tex.InternalFormat = PixelInternalFormat.Alpha8; } } else { if (bitsize == 2) { data = reader.GetSection(texDataOffset, (int)size * bitsize); // swap endian for (int j = 0; j < data.Length / 2; j++) { byte temp = data[j * 2]; data[j * 2] = data[(j * 2) + 1]; data[(j * 2) + 1] = temp; } tex.Mipmaps.Add(data); tex.InternalFormat = PixelInternalFormat.Rgb5A1; } else if (bitsize == 3) { tex.InternalFormat = PixelInternalFormat.Rgba8; data = reader.GetSection(texDataOffset, (int)size * 4); tex.Mipmaps.Add(data); } } } // Objects-------------------------------------------------------- // now parse until end bool done = false; Stack <GenericBone> boneStack = new Stack <GenericBone>(); GenericBone parentBone = null; reader.Seek(objectOffset); reader.Skip(4); // idk int maybeCount = reader.ReadInt32(); string currentMaterialName = ""; GenericMaterial currentMaterial = new GenericMaterial(); GenericBone CurrentBone = null; while (!done) { int doff, temp; //Console.WriteLine(reader.Position().ToString("x") + " " + reader.ReadByte().ToString("x")); reader.ReadByte(); reader.Seek(reader.Position - 1); switch (reader.ReadByte()) { case 0x03: // Perhaps some object offset? Offset goes to beginning of file. Material maybe? reader.Skip(0x08 - 1); break; case 0x05: reader.Skip(0x04 - 1); boneStack.Push(CurrentBone); parentBone = boneStack.Peek(); break; case 0x06: reader.Skip(0x04 - 1); if (boneStack.Count > 0) { boneStack.Pop(); if (boneStack.Count > 0) { parentBone = boneStack.Peek(); } } break; case 0x08: reader.Skip(4 - 1); int s1 = reader.ReadByte() & 0x7F; reader.Skip(1); int s2 = reader.ReadInt16(); reader.Skip(4); // pops matrix // maybe pop until you get to this bone? //Also maybe some texture thing? Console.WriteLine("What dis?" + " " + s1 + " " + s2); //throw new Exception("Weird Special Thing"); /*for (int i = popto - s1; i < popto + s2; i++) * { * Bone bo = skel.GetBoneByID(i); * boneStack.Push(bo); * }*/ break; case 0x18: // idk has 4 values reader.Skip(0x08 - 1); break; case 0x1D: int id = reader.ReadByte(); int what = reader.ReadByte(); int parent = (sbyte)reader.ReadByte(); // read bone properties Vector3 trans = new Vector3((short)reader.ReadInt16(), (short)reader.ReadInt16(), (short)reader.ReadInt16()); Vector3 rot = new Vector3((short)reader.ReadInt16() / 180, ((short)reader.ReadInt16()) / 180, (short)reader.ReadInt16() / 180); // to radians rot.X = (rot.X * (float)Math.PI) / 180f; rot.Y = (rot.Y * (float)Math.PI) / 180f; rot.Z = (rot.Z * (float)Math.PI) / 180f; //rot = new Vector3(rot.Z, rot.X, rot.Y); Vector3 scale = new Vector3(); scale.X = reader.ReadInt16() + reader.ReadInt16() / (float)0xFFFF; scale.Y = reader.ReadInt16() + reader.ReadInt16() / (float)0xFFFF; scale.Z = reader.ReadInt16() + reader.ReadInt16() / (float)0xFFFF; int parent2 = boneStack.Count; GenericBone b = new GenericBone(); b.Name = "Bone_" + id; if (parentBone != null) { b.ParentIndex = Model.Skeleton.IndexOf(parentBone); } else { b.ParentIndex = -1; } b.ID = id; b.Scale = new Vector3(1, 1, 1); // scale b.Position = trans; b.Rotation = rot; CurrentBone = b; Model.Skeleton.Bones.Add(b); //Console.WriteLine(reader.Position().ToString("x") + " " + b.Name + " " + b.p1 + " " + what + " " + parent + " " + boneStack.Count + " " + trans.ToString() + " " + rot.ToString() + " " + scale.ToString()); //Console.WriteLine(b.transform.ToString()); break; case 0x1E: //reader.Skip(3); reader.Skip(1); int w = reader.ReadInt16(); // bone index doff = reader.ReadInt32(); temp = (int)reader.Position; reader.Seek((uint)doff); { GenericMesh mesh = DisplayListToGenericMesh(N64Tools.ReadDisplayList(reader, Model.Skeleton.IndexOf(Model.Skeleton.GetBoneByID(w)), Model.Skeleton.GetWorldTransform(Model.Skeleton.GetBoneByID(w)))); mesh.MaterialName = currentMaterialName; Model.Meshes.Add(mesh); } reader.Seek((uint)temp); break; case 0x22: int materialIndex = reader.ReadByte(); int ww = (short)reader.ReadInt16(); doff = reader.ReadInt32(); temp = (int)reader.Position; if (doff == 0) { continue; } reader.Seek((uint)doff); { GenericMesh mesh = DisplayListToGenericMesh(N64Tools.ReadDisplayList(reader, Model.Skeleton.IndexOf(parentBone), Model.Skeleton.GetWorldTransform(parentBone))); mesh.MaterialName = currentMaterialName; Model.Meshes.Add(mesh); } reader.Seek((uint)temp); //((DisplayList)DisplayLists.Nodes[DisplayLists.Nodes.Count - 1]).Mat = unk; //Console.WriteLine("Material Maybe 0x" + reader.pos().ToString("x") + " " + unk + " " + .Count); break; case 0x23: reader.Skip(1); int tidunk = (short)reader.ReadInt16(); int texOff = reader.ReadInt32(); //& 0x1FFFF Material Offset? int tid = (short)reader.ReadInt16(); int pid = (short)reader.ReadInt16(); reader.Skip(4); // 0xFF padding //Console.WriteLine("TextureCount " + tid + " " + pid + " " + tidunk + " " + texOfreader.ToString("x")); if (tid != -1) { currentMaterial = new GenericMaterial(); currentMaterialName = "material_" + Model.MaterialBank.Count; var diffuse = BakeTexturePalette(Textures[tid], pid, Palettes); diffuse.Name = "texture_" + Model.TextureBank.Count; currentMaterial.TextureDiffuse = diffuse.Name; Model.TextureBank.Add(diffuse.Name, diffuse); Model.MaterialBank.Add(currentMaterialName, currentMaterial); } else { var currentTexture = currentMaterial.TextureDiffuse; currentMaterial = new GenericMaterial(); currentMaterialName = "material_" + Model.MaterialBank.Count; currentMaterial.TextureDiffuse = currentTexture; Model.MaterialBank.Add(currentMaterialName, currentMaterial); } // Read Texture Info At Offset int tt = (int)reader.Position; reader.Seek((uint)texOff); ReadTextureCodes(reader, currentMaterial); reader.Seek((uint)tt); break; // Texture Binding case 0x24: reader.Skip(3); break; // has to do with matrix popping case 0x25: reader.Skip(0x04 - 1); //Console.WriteLine("Unknown 0x" + reader.pos().ToString("x")); break; default: done = true; break; } ; } } // Post Process // optimized texture sharing Dictionary <string, string> newTexName = new Dictionary <string, string>(); Dictionary <string, GenericTexture> newTexBank = new Dictionary <string, GenericTexture>(); Dictionary <byte[], string> TextureBank = new Dictionary <byte[], string>(); foreach (var tex in Model.TextureBank) { if (!TextureBank.ContainsKey(tex.Value.Mipmaps[0])) { string newName = "texture_" + newTexName.Count; newTexName.Add(tex.Key, newName); newTexBank.Add(newName, tex.Value); TextureBank.Add(tex.Value.Mipmaps[0], newName); } else { newTexName.Add(tex.Key, TextureBank[tex.Value.Mipmaps[0]]); } } Model.TextureBank = newTexBank; foreach (var mesh in Model.Meshes) { var material = Model.GetMaterial(mesh); if (material != null && material.TextureDiffuse != null) { material.TextureDiffuse = newTexName[material.TextureDiffuse]; } } Console.WriteLine(TextureBank.Count + " total textures"); // Transform Verts /*int meshindex = 0; * foreach(GenericMesh mesh in Model.Meshes) * { * mesh.Name = "Mesh_" + meshindex; * GenericVertex[] CorrectedVertices = mesh.Vertices.ToArray(); * for(int i =0; i < CorrectedVertices.Length; i++) * { * CorrectedVertices[i].Pos = Vector3.TransformPosition(CorrectedVertices[i].Pos, Model.Skeleton.GetWorldTransform((int)CorrectedVertices[i].Bones.X)); * } * mesh.Vertices.Clear(); * mesh.Vertices.AddRange(CorrectedVertices); * }*/ }
public GenericModel ToGenericModel() { var mdl = new GenericModel() { Skeleton = Skeleton };; byte[] Data = File.ReadAllBytes(@"chr0020_model.npki"); byte[] ImageData = File.ReadAllBytes(@"chr0020_model.npkv"); foreach (var t in TXRs) { GenericTexture tex = new GenericTexture(); tex.Width = (uint)t.Width; tex.Height = (uint)t.Height; var buf = new byte[t.Width * t.Height / 2]; Array.Copy(ImageData, t.BufferOffsets[0], buf, 0, buf.Length); buf = VitaSwizzle.UnswizzlePS4(buf, t.Width, t.Height); tex.Mipmaps.Add(buf); tex.InternalFormat = OpenTK.Graphics.OpenGL.PixelInternalFormat.CompressedRgbS3tcDxt1Ext; if (!mdl.TextureBank.ContainsKey(t.Name)) { mdl.TextureBank.Add(t.Name, tex); } Console.WriteLine(tex.Width + " " + tex.Height + " " + t.Unknown.ToString("X") + " " + t.BufferOffsets[0].ToString("X") + " " + t.BufferSizes[0].ToString("X")); } foreach (var v in VTXs) { if (v.BufferSizes.Length < 2) { continue; } GenericMesh m = new GenericMesh(); mdl.Meshes.Add(m); m.Name = v.Name; using (DataReader r = new DataReader(Data)) { for (uint i = 0; i < v.BufferSizes[1]; i += 2) { r.Seek((uint)v.BufferOffsets[1] + i); //r.PrintPosition(); var index = r.ReadInt16(); GenericVertex vert = new GenericVertex(); foreach (var attr in v.Attribtues) { r.Seek((uint)(v.BufferOffsets[0] + v.BufferInfos[attr.RESBufferIndex].Offset + index * v.BufferInfos[attr.RESBufferIndex].Stride + attr.BufferOffset)); switch (attr.AttributeName) { case 1: vert.Pos = new OpenTK.Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle()); break; case 2: vert.Nrm = new OpenTK.Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle()); break; case 5: vert.UV0 = new OpenTK.Vector2(r.ReadSingle(), r.ReadSingle()); break; case 8: var b1 = v.Bones[r.ReadInt32()]; var b2 = v.Bones[r.ReadInt32()]; var b3 = v.Bones[r.ReadInt32()]; var b4 = v.Bones[r.ReadInt32()]; vert.Bones = new OpenTK.Vector4(Skeleton.IndexOf(Skeleton.GetBoneByName(b1)), Skeleton.IndexOf(Skeleton.GetBoneByName(b2)), Skeleton.IndexOf(Skeleton.GetBoneByName(b3)), Skeleton.IndexOf(Skeleton.GetBoneByName(b4))); break; case 7: vert.Weights = new OpenTK.Vector4(r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle()); break; } } if (v.Bones.Count == 1) { vert.Bones = new OpenTK.Vector4(Skeleton.IndexOf(Skeleton.GetBoneByName(v.Bones[0])), 0, 0, 0); vert.Weights = new OpenTK.Vector4(1, 0, 0, 0); } m.Vertices.Add(vert); m.Triangles.Add(i / 2); //Console.WriteLine(index + " " + v.BufferOffsets[0].ToString("X") + " " + v.BufferInfos[0].Offset + " " + v.BufferInfos[0].Stride); } //m.Optimize(); } } return(mdl); }