private void ReloadData() { //Split collision triangles by materials between all the models Dictionary <int, List <Triangle> > triangleList = new Dictionary <int, List <Triangle> >(); foreach (var model in KclFile.Models) { foreach (var prism in model.Prisms) { var triangle = model.GetTriangle(prism); if (!triangleList.ContainsKey(prism.CollisionFlags)) { triangleList.Add(prism.CollisionFlags, new List <Triangle>()); } triangleList[prism.CollisionFlags].Add(triangle); } } Renderer.models.Clear(); Nodes.Clear(); //Load the vertex data for rendering foreach (var triGroup in triangleList) { KCLModel kclmodel = new KCLModel(); kclmodel.Text = $"COL_{triGroup.Key.ToString("X")}"; int faceIndex = 0; var triangles = triGroup.Value; for (int i = 0; i < triangles.Count; i++) { for (int v = 0; v < triangles[i].Vertices.Length; v++) { var positon = triangles[i].Vertices[v]; var normal = triangles[i].Normal; var attribute = triGroup.Key; kclmodel.vertices.Add(new Vertex() { pos = new Vector3(positon.X, positon.Y, positon.Z), nrm = new Vector3(normal.X, normal.Y, normal.Z), col = new Vector4(1, 1, 1, 1), }); kclmodel.faces.Add(faceIndex + v); } faceIndex += 3; } Renderer.models.Add(kclmodel); Nodes.Add(kclmodel); } }
private static void DrawModelWireframe(KCLModel p, ShaderProgram shader) { // use vertex color for wireframe color GL.Uniform1(shader["colorOverride"], 1); GL.PolygonMode(MaterialFace.Front, PolygonMode.Line); GL.Enable(EnableCap.LineSmooth); GL.LineWidth(1.5f); GL.DrawElements(PrimitiveType.Triangles, p.displayFaceSize, DrawElementsType.UnsignedInt, p.Offset); GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill); GL.Uniform1(shader["colorOverride"], 0); }
private static void DrawModelSelection(KCLModel p, Shader shader) { //This part needs to be reworked for proper outline. Currently would make model disappear GL.DrawElements(PrimitiveType.Triangles, p.displayFaceSize, DrawElementsType.UnsignedInt, p.Offset); GL.Enable(EnableCap.StencilTest); // use vertex color for wireframe color shader.SetInt("colorOverride", 1); GL.PolygonMode(MaterialFace.Front, PolygonMode.Line); GL.Enable(EnableCap.LineSmooth); GL.LineWidth(1.5f); GL.DrawElements(PrimitiveType.Triangles, p.displayFaceSize, DrawElementsType.UnsignedInt, p.Offset); GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill); shader.SetInt("colorOverride", 0); GL.Enable(EnableCap.DepthTest); }
static void WriteModel(BinaryDataWriter er, KCLModel mod) { long HeaderPos = er.BaseStream.Position; mod.Header.Write(er); long curpos = er.BaseStream.Position; //Write vertices array position er.BaseStream.Position = HeaderPos; er.Write((uint)(curpos - HeaderPos)); er.BaseStream.Position = curpos; foreach (Vector3D v in mod.Vertices) { er.Write(v); } er.Align(4); curpos = er.BaseStream.Position; //Write normal array position er.BaseStream.Position = HeaderPos + 4; er.Write((uint)(curpos - HeaderPos)); er.BaseStream.Position = curpos; foreach (Vector3D v in mod.Normals) { er.Write(v); } er.Align(4); curpos = er.BaseStream.Position; //Write Triangles offset er.BaseStream.Position = HeaderPos + 8; er.Write((uint)(curpos - HeaderPos)); er.BaseStream.Position = curpos; foreach (KCLModel.KCLPlane p in mod.Planes) { p.Write(er); } curpos = er.BaseStream.Position; //Write Spatial index offset er.BaseStream.Position = HeaderPos + 12; er.Write((uint)(curpos - HeaderPos)); er.BaseStream.Position = curpos; mod.Octree.Write(er); }
public void Read(byte[] file_data) { try { kcl = new KclFile(new MemoryStream(file_data), true, false, Syroot.BinaryData.ByteOrder.LittleEndian); } catch { kcl = new KclFile(new MemoryStream(file_data), true, false, Syroot.BinaryData.ByteOrder.BigEndian); } AllFlags.Clear(); int CurModelIndx = 0; foreach (KclModel mdl in kcl.Models) { KCLModel kclmodel = new KCLModel(); kclmodel.Text = "Model " + CurModelIndx; KclFace[] indicesArray = mdl.Faces; int ft = 0; foreach (KclFace f in mdl.Faces) { Vertex vtx = new Vertex(); Vertex vtx2 = new Vertex(); Vertex vtx3 = new Vertex(); Vector3 CrossA = Vector3.Cross(Vec3F_To_Vec3(mdl.Normals[f.Normal1Index]), Vec3F_To_Vec3(mdl.Normals[f.DirectionIndex])); Vector3 CrossB = Vector3.Cross(Vec3F_To_Vec3(mdl.Normals[f.Normal2Index]), Vec3F_To_Vec3(mdl.Normals[f.DirectionIndex])); Vector3 CrossC = Vector3.Cross(Vec3F_To_Vec3(mdl.Normals[f.Normal3Index]), Vec3F_To_Vec3(mdl.Normals[f.DirectionIndex])); Vector3 normal_a = Vec3F_To_Vec3(mdl.Normals[f.Normal1Index]); Vector3 normal_b = Vec3F_To_Vec3(mdl.Normals[f.Normal2Index]); Vector3 normal_c = Vec3F_To_Vec3(mdl.Normals[f.Normal3Index]); float result1 = Vector3.Dot(new Vector3(CrossB.X, CrossB.Y, CrossB.Z), (new Vector3(normal_c.X, normal_c.Y, normal_c.Z))); float result2 = Vector3.Dot(new Vector3(CrossA.X, CrossA.Y, CrossA.Z), (new Vector3(normal_c.X, normal_c.Y, normal_c.Z))); Vector3 pos = Vec3F_To_Vec3(mdl.Positions[f.PositionIndex]); Vector3 nrm = Vec3F_To_Vec3(mdl.Normals[f.Normal1Index]); Vector3 Vertex1 = pos; Vector3 Vertex2 = pos + CrossB * (f.Length / result1); Vector3 Vertex3 = pos + CrossA * (f.Length / result2); vtx.pos = new Vector3(Vertex1.X, Vertex1.Y, Vertex1.Z); vtx2.pos = new Vector3(Vertex2.X, Vertex2.Y, Vertex2.Z); vtx3.pos = new Vector3(Vertex3.X, Vertex3.Y, Vertex3.Z); var dir = Vector3.Cross(Vertex2 - Vertex1, Vertex3 - Vertex1); var norm = Vector3.Normalize(dir); vtx.nrm = norm; vtx2.nrm = norm; vtx3.nrm = norm; KCLModel.Face face = new KCLModel.Face(); face.Text = f.CollisionFlags.ToString(); face.MaterialFlag = f.CollisionFlags; Color color = SetMaterialColor(face); AllFlags.Add(face.MaterialFlag); Vector3 ColorSet = new Vector3(color.R / 255.0f, color.G / 255.0f, color.B / 255.0f); vtx.col = new Vector3(ColorSet); vtx2.col = new Vector3(ColorSet); vtx3.col = new Vector3(ColorSet); kclmodel.faces.Add(ft); kclmodel.faces.Add(ft + 1); kclmodel.faces.Add(ft + 2); ft += 3; kclmodel.vertices.Add(vtx); kclmodel.vertices.Add(vtx2); kclmodel.vertices.Add(vtx3); } models.Add(kclmodel); Nodes.Add(kclmodel); CurModelIndx++; } List <int> noDupes = AllFlags.Distinct().ToList(); Console.WriteLine("List of all material flags (Not duped)"); foreach (int mat in noDupes) { Console.WriteLine("Mat flag " + (CollisionType_MK8D)mat); } }
public KCL(byte[] Data, ByteOrder bo = ByteOrder.LittleEndian) { BinaryDataReader er = new BinaryDataReader(new MemoryStream(Data)); er.ByteOrder = ByteOrder.BigEndian; if (er.ReadUInt32() != 0x02020000) { throw new Exception("Wrong KCL Header"); } er.ByteOrder = bo; /*uint OctreeOffset = */ er.ReadUInt32(); uint ModelListOff = er.ReadUInt32(); uint ModelCount = er.ReadUInt32(); for (int ModelIndex = 0; ModelIndex < ModelCount; ModelIndex++) { KCLModel mod = new KCLModel(); er.BaseStream.Position = ModelListOff + ModelIndex * 4; uint CurModelOffset = er.ReadUInt32(); er.BaseStream.Position = CurModelOffset; mod.Header = new KCLModel.KCLModelHeader(er); er.BaseStream.Position = mod.Header.VerticesOffset + CurModelOffset; uint nr = (mod.Header.NormalsOffset - mod.Header.VerticesOffset) / 0xC; mod.Vertices = new Vector3D[nr]; for (int i = 0; i < nr; i++) { mod.Vertices[i] = er.ReadVector3D(); } er.BaseStream.Position = mod.Header.NormalsOffset + CurModelOffset; nr = (mod.Header.PlanesOffset - mod.Header.NormalsOffset) / 0xC; mod.Normals = new Vector3D[nr]; for (int i = 0; i < nr; i++) { mod.Normals[i] = er.ReadVector3D(); } er.BaseStream.Position = mod.Header.PlanesOffset + CurModelOffset; nr = (mod.Header.OctreeOffset - mod.Header.PlanesOffset) / 0x14; mod.Planes = new KCLModel.KCLPlane[nr]; for (int i = 0; i < nr; i++) { mod.Planes[i] = new KCLModel.KCLPlane(er); } er.BaseStream.Position = mod.Header.OctreeOffset + CurModelOffset; int nodes = (int)( ((~mod.Header.XMask >> (int)mod.Header.CoordShift) + 1) * ((~mod.Header.YMask >> (int)mod.Header.CoordShift) + 1) * ((~mod.Header.ZMask >> (int)mod.Header.CoordShift) + 1)); mod.Octree = new KCLOctree(er, nodes); //Generate a mesh from the octree //List<OBJ.Face> OctreeNodeToMesh(KCLOctree.KCLOctreeNode node) //{ // List<OBJ.Face> res = new List<OBJ.Face>(); // if (node.IsLeaf) // { // foreach (var tr in node.Triangles) // { // var t = mod.GetTriangle(mod.Planes[tr]); // res.Add(new OBJ.Face() // { // VA = new OBJ.Vertex(t.PointA, t.Normal), // VB = new OBJ.Vertex(t.PointB, t.Normal), // VC = new OBJ.Vertex(t.PointC, t.Normal), // }); // } // } // else // { // for (int i = 0; i < node.SubNodes.Length; i++) // res.AddRange(OctreeNodeToMesh(node.SubNodes[i])); // } // return res; //} //var o = new OBJ(); //for (int i = 0; i < mod.Octree.RootNodes.Length; i++) //{ // var planes = OctreeNodeToMesh(mod.Octree.RootNodes[i]); // if (planes.Count == 0) continue; // o.Faces.AddRange(planes); //} //o.toWritableObj().WriteObj($"F:\\oct{ModelIndex}.obj", null); Models.Add(mod); } }
public static KCL FromOBJ(OBJ o) { KCL res = new KCL(); res.GlobalHeader = new KCLModel.KCLModelHeader(); Vector3D min = new Vector3D(float.MaxValue, float.MaxValue, float.MaxValue); Vector3D max = new Vector3D(float.MinValue, float.MinValue, float.MinValue); var MatDictionary = MaterialSetForm.ShowForm(o.MaterialNames); List <Triangle> Triangles = new List <Triangle>(); foreach (var v in o.Faces) { var coll = MatDictionary.ContainsKey(v.Mat) ? MatDictionary[v.Mat] : (ushort)0; if (coll == ushort.MaxValue) { continue; } Triangle t = new Triangle(v.VA.pos, v.VB.pos, v.VC.pos); t.Collision = coll; #region FindMaxMin if (t.PointA.X < min.X) { min.X = t.PointA.X; } if (t.PointA.Y < min.Y) { min.Y = t.PointA.Y; } if (t.PointA.Z < min.Z) { min.Z = t.PointA.Z; } if (t.PointA.X > max.X) { max.X = t.PointA.X; } if (t.PointA.Y > max.Y) { max.Y = t.PointA.Y; } if (t.PointA.Z > max.Z) { max.Z = t.PointA.Z; } if (t.PointB.X < min.X) { min.X = t.PointB.X; } if (t.PointB.Y < min.Y) { min.Y = t.PointB.Y; } if (t.PointB.Z < min.Z) { min.Z = t.PointB.Z; } if (t.PointB.X > max.X) { max.X = t.PointB.X; } if (t.PointB.Y > max.Y) { max.Y = t.PointB.Y; } if (t.PointB.Z > max.Z) { max.Z = t.PointB.Z; } if (t.PointC.X < min.X) { min.X = t.PointC.X; } if (t.PointC.Y < min.Y) { min.Y = t.PointC.Y; } if (t.PointC.Z < min.Z) { min.Z = t.PointC.Z; } if (t.PointC.X > max.X) { max.X = t.PointC.X; } if (t.PointC.Y > max.Y) { max.Y = t.PointC.Y; } if (t.PointC.Z > max.Z) { max.Z = t.PointC.Z; } #endregion Triangles.Add(t); } max += KCL.MaxOffset; min -= KCL.MinOffset; res.GlobalHeader.OctreeOrigin = min; res.GlobalHeader.OctreeMax = max; var size = max - min; res.GlobalHeader.CoordShift = (uint)KCLOctree.next_exponent(size.X); res.GlobalHeader.YShift = (uint)KCLOctree.next_exponent(size.Y); res.GlobalHeader.ZShift = (uint)KCLOctree.next_exponent(size.Z); var BoxSize = size / 2f; uint baseTriCount = 0; for (int k = 0; k < 2; k++) { for (int l = 0; l < 2; l++) { for (int m = 0; m < 2; m++) { var Boxmin = min + new Vector3D(BoxSize.X * m, BoxSize.Y * l, BoxSize.Z * k); var mod = KCLModel.FromTriangles(Triangles, baseTriCount, Boxmin, BoxSize / 2); res.Models.Add(mod); if (mod != null) { baseTriCount += (uint)mod.Planes.Length; } } } } res.GlobalHeader.Unknown1 = baseTriCount; return(res); }
public void Read(MarioKart.MK7.KCL kcl) { Nodes.Clear(); Renderer.models.Clear(); int CurModelIndx = 0; foreach (MarioKart.MK7.KCL.KCLModel mdl in kcl.Models) { KCLModel kclmodel = new KCLModel(); kclmodel.Text = "Model " + CurModelIndx; int ft = 0; foreach (var plane in mdl.Planes) { var triangle = mdl.GetTriangle(plane); var normal = triangle.Normal; var pointA = triangle.PointA; var pointB = triangle.PointB; var pointC = triangle.PointC; Vertex vtx = new Vertex(); Vertex vtx2 = new Vertex(); Vertex vtx3 = new Vertex(); vtx.pos = new Vector3(Vec3D_To_Vec3(pointA)); vtx2.pos = new Vector3(Vec3D_To_Vec3(pointB)); vtx3.pos = new Vector3(Vec3D_To_Vec3(pointC)); vtx.nrm = new Vector3(Vec3D_To_Vec3(normal)); vtx2.nrm = new Vector3(Vec3D_To_Vec3(normal)); vtx3.nrm = new Vector3(Vec3D_To_Vec3(normal)); KCLModel.Face face = new KCLModel.Face(); face.Text = triangle.Collision.ToString(); face.MaterialFlag = triangle.Collision; var col = MarioKart.MK7.KCLColors.GetMaterialColor(plane.CollisionType); Vector3 ColorSet = new Vector3(col.R, col.G, col.B); vtx.col = new Vector4(ColorSet, 1); vtx2.col = new Vector4(ColorSet, 1); vtx3.col = new Vector4(ColorSet, 1); kclmodel.faces.Add(ft); kclmodel.faces.Add(ft + 1); kclmodel.faces.Add(ft + 2); ft += 3; kclmodel.vertices.Add(vtx); kclmodel.vertices.Add(vtx2); kclmodel.vertices.Add(vtx3); } Renderer.models.Add(kclmodel); Nodes.Add(kclmodel); CurModelIndx++; } }
private void Read(MarioKart.MK7.KCL kcl) { Vector3 min = new Vector3(); Vector3 max = new Vector3(); Nodes.Clear(); Renderer.OctreeNodes.Clear(); Renderer.models.Clear(); Renderer.KclFile = kcl; TreeNode modelTree = new TreeNode("Model Octree"); LoadModelTree(modelTree, kcl.GlobalHeader.ModelOctrees); foreach (var node in modelTree.Nodes) { Renderer.OctreeNodes.Add((OctreeNode)node); } Nodes.Add(modelTree); int CurModelIndx = 0; foreach (MarioKart.MK7.KCL.KCLModel mdl in kcl.Models) { KCLModel kclmodel = new KCLModel(); kclmodel.Text = "Model " + CurModelIndx; int ft = 0; foreach (var plane in mdl.Planes) { var triangle = mdl.GetTriangle(plane); var normal = triangle.Normal; var pointA = triangle.PointA; var pointB = triangle.PointB; var pointC = triangle.PointC; Vertex vtx = new Vertex(); Vertex vtx2 = new Vertex(); Vertex vtx3 = new Vertex(); vtx.pos = new Vector3(Vec3D_To_Vec3(pointA)); vtx2.pos = new Vector3(Vec3D_To_Vec3(pointB)); vtx3.pos = new Vector3(Vec3D_To_Vec3(pointC)); vtx.nrm = new Vector3(Vec3D_To_Vec3(normal)); vtx2.nrm = new Vector3(Vec3D_To_Vec3(normal)); vtx3.nrm = new Vector3(Vec3D_To_Vec3(normal)); KCLModel.Face face = new KCLModel.Face(); face.Text = triangle.Collision.ToString(); face.MaterialFlag = triangle.Collision; var col = MarioKart.MK7.KCLColors.GetMaterialColor(plane.CollisionType); Vector3 ColorSet = new Vector3(col.R, col.G, col.B); vtx.col = new Vector4(ColorSet, 1); vtx2.col = new Vector4(ColorSet, 1); vtx3.col = new Vector4(ColorSet, 1); kclmodel.faces.Add(ft); kclmodel.faces.Add(ft + 1); kclmodel.faces.Add(ft + 2); ft += 3; kclmodel.vertices.Add(vtx); kclmodel.vertices.Add(vtx2); kclmodel.vertices.Add(vtx3); #region FindMaxMin if (triangle.PointA.X < min.X) { min.X = (float)triangle.PointA.X; } if (triangle.PointA.Y < min.Y) { min.Y = (float)triangle.PointA.Y; } if (triangle.PointA.Z < min.Z) { min.Z = (float)triangle.PointA.Z; } if (triangle.PointA.X > max.X) { max.X = (float)triangle.PointA.X; } if (triangle.PointA.Y > max.Y) { max.Y = (float)triangle.PointA.Y; } if (triangle.PointA.Z > max.Z) { max.Z = (float)triangle.PointA.Z; } if (triangle.PointB.X < min.X) { min.X = (float)triangle.PointB.X; } if (triangle.PointB.Y < min.Y) { min.Y = (float)triangle.PointB.Y; } if (triangle.PointB.Z < min.Z) { min.Z = (float)triangle.PointB.Z; } if (triangle.PointB.X > max.X) { max.X = (float)triangle.PointB.X; } if (triangle.PointB.Y > max.Y) { max.Y = (float)triangle.PointB.Y; } if (triangle.PointB.Z > max.Z) { max.Z = (float)triangle.PointB.Z; } if (triangle.PointC.X < min.X) { min.X = (float)triangle.PointC.X; } if (triangle.PointC.Y < min.Y) { min.Y = (float)triangle.PointC.Y; } if (triangle.PointC.Z < min.Z) { min.Z = (float)triangle.PointC.Z; } if (triangle.PointC.X > max.X) { max.X = (float)triangle.PointC.X; } if (triangle.PointC.Y > max.Y) { max.Y = (float)triangle.PointC.Y; } if (triangle.PointC.Z > max.Z) { max.Z = (float)triangle.PointC.Z; } #endregion } Renderer.Max = max; Renderer.Min = min; Renderer.models.Add(kclmodel); Nodes.Add(kclmodel); CurModelIndx++; } }