internal static KCLModel FromTriangles(List <Triangle> triangles, uint baseTriCount, Vector3D BoxMin, Vector3D QuarterSize) { List <Triangle> modelTri = new List <Triangle>(); List <Vector3D> Vertices = new List <Vector3D>(); List <Vector3D> Normals = new List <Vector3D>(); List <KCLPlane> Planes = new List <KCLPlane>(); for (int i = 0; i < triangles.Count; i++) { if (!KCLExt.KCL.TriangleBoxIntersect.triBoxOverlap(BoxMin + QuarterSize, QuarterSize, triangles[i])) { continue; } modelTri.Add(triangles[i]); var tri = triangles[i]; KCLModel.KCLPlane p = new KCLModel.KCLPlane(); p.CollisionType = triangles[i].Collision; p.VertexIndex = AddIfNotContainsVector3D(tri.PointA, Vertices); var direction = (tri.PointB - tri.PointA).Cross(tri.PointC - tri.PointA).GetNormalize(); p.DirectionIndex = AddIfNotContainsVector3D(direction, Normals); p.NormalAIndex = AddIfNotContainsVector3D(direction.Cross(tri.PointC - tri.PointA).GetNormalize(), Normals); p.NormalBIndex = AddIfNotContainsVector3D((-(direction.Cross(tri.PointB - tri.PointA))).GetNormalize(), Normals); p.NormalCIndex = AddIfNotContainsVector3D(direction.Cross(tri.PointB - tri.PointC).GetNormalize(), Normals); p.Length = (tri.PointB - tri.PointA).Dot(Normals[p.NormalCIndex]); p.TriangleIndex = baseTriCount + (uint)Planes.Count; Planes.Add(p); } if (modelTri.Count == 0) { return(null); } if (modelTri.Count > 65535) { throw new Exception("Too many triangles"); } KCLModel resMod = new KCLModel(); resMod.Vertices = Vertices.ToArray(); resMod.Normals = Normals.ToArray(); if (Planes.Count != modelTri.Count) { throw new Exception(); } resMod.Planes = Planes.ToArray(); resMod.Header = new KCLModelHeader(); resMod.Octree = KCLOctree.FromTriangles(modelTri.ToArray(), resMod.Header); resMod.Header.Unknown1 = 40f; //odyssey values resMod.Header.Unknown2 = 0; return(resMod); }
public KCL(byte[] Data) { EndianBinaryReader er = new EndianBinaryReader(new MemoryStream(Data), Endianness.LittleEndian); try { Header = new MK7KCLHeader(er); er.BaseStream.Position = Header.VerticesOffset; uint nr = (Header.NormalsOffset - Header.VerticesOffset) / 0xC; Vertices = new Vector3[nr]; for (int i = 0; i < nr; i++) { Vertices[i] = er.ReadVector3(); } er.BaseStream.Position = Header.NormalsOffset; nr = (Header.PlanesOffset - Header.NormalsOffset) / 0xC; Normals = new Vector3[nr]; for (int i = 0; i < nr; i++) { Normals[i] = er.ReadVector3(); } er.BaseStream.Position = Header.PlanesOffset; nr = (Header.OctreeOffset - Header.PlanesOffset) / 0x10; Planes = new KCLPlane[nr]; for (int i = 0; i < nr; i++) { Planes[i] = new KCLPlane(er); } er.BaseStream.Position = Header.OctreeOffset; int nodes = (int)( ((~Header.XMask >> (int)Header.CoordShift) + 1) * ((~Header.YMask >> (int)Header.CoordShift) + 1) * ((~Header.ZMask >> (int)Header.CoordShift) + 1)); Octree = new KCLOctree(er, nodes); } finally { er.Close(); } }
public static KCLOctree FromTriangles(Triangle[] Triangles, MK7KCLHeader Header, int MaxRootSize = 2048, int MinRootSize = 128, int MinCubeSize = 32, int MaxNrTris = 10)//35) { Header.Unknown1 = 30; Header.Unknown2 = 25; Vector3 min = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); Vector3 max = new Vector3(float.MinValue, float.MinValue, float.MinValue); Dictionary <ushort, Triangle> tt = new Dictionary <ushort, Triangle>(); ushort index = 0; foreach (var t in Triangles) { 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; } tt.Add(index, t); index++; } //in real mkds, 25 is subtracted from the min pos min -= new Vector3(25, 25, 25); //TODO: after that, from some of the components (may be more than one) 30 is subtracted aswell => How do I know from which ones I have to do that? //Assume the same is done for max: max += new Vector3(25, 25, 25); //TODO: +30 Header.OctreeOrigin = min; Vector3 size = max - min; float mincomp = Math.Min(Math.Min(size.X, size.Y), size.Z); int CoordShift = MathUtil.GetNearest2Power(mincomp); if (CoordShift > MathUtil.GetNearest2Power(MaxRootSize)) { CoordShift = MathUtil.GetNearest2Power(MaxRootSize); } //else if (CoordShift < Get2Power(MinRootSize)) CoordShift = Get2Power(MinRootSize); Header.CoordShift = (uint)CoordShift; int cubesize = 1 << CoordShift; int NrX = (1 << MathUtil.GetNearest2Power(size.X)) / cubesize; int NrY = (1 << MathUtil.GetNearest2Power(size.Y)) / cubesize; int NrZ = (1 << MathUtil.GetNearest2Power(size.Z)) / cubesize; if (NrX <= 0) { NrX = 1; } if (NrY <= 0) { NrY = 1; } if (NrZ <= 0) { NrZ = 1; } Header.YShift = (uint)(MathUtil.GetNearest2Power(size.X) - CoordShift); Header.ZShift = (uint)(MathUtil.GetNearest2Power(size.X) - CoordShift + MathUtil.GetNearest2Power(size.Y) - CoordShift); Header.XMask = 0xFFFFFFFF << MathUtil.GetNearest2Power(size.X); Header.YMask = 0xFFFFFFFF << MathUtil.GetNearest2Power(size.Y); Header.ZMask = 0xFFFFFFFF << MathUtil.GetNearest2Power(size.Z); KCLOctree k = new KCLOctree(); k.RootNodes = new KCLOctreeNode[NrX * NrY * NrZ]; int i = 0; int maxOCtree = NrX * NrY * NrZ; for (int z = 0; z < NrZ; z++) { for (int y = 0; y < NrY; y++) { for (int x = 0; x < NrX; x++) { Vector3 pos = min + ((float)cubesize) * new Vector3(x, y, z); k.RootNodes[i] = KCLOctreeNode.Generate(tt, pos, cubesize, MaxNrTris, MinCubeSize, maxOCtree, i + 1); i++; } } } return(k); }
public List <String> CreateFromFile(byte[] Data) //Return mat count to create pa { OBJ o = new OBJ(Data); List <String> matnames = new List <string>(); foreach (var v in o.Faces) { if (!matnames.Contains(v.Material)) { matnames.Add(v.Material); } } Dictionary <string, ushort> Mapping = new Dictionary <string, ushort>(); Dictionary <string, bool> Colli = new Dictionary <string, bool>(); for (ushort i = 0; i < matnames.Count; i++) { Mapping.Add(matnames[i], i); } foreach (string str in matnames) { Colli.Add(str, true); } List <Vector3> Vertex = new List <Vector3>(); List <Vector3> Normals = new List <Vector3>(); List <KCLPlane> planes = new List <KCLPlane>(); List <Triangle> Triangles = new List <Triangle>(); int face = 0; foreach (var v in o.Faces) { Console.Write("\r -Adding face " + (++face).ToString() + "/" + o.Faces.Count.ToString()); if (Colli[v.Material]) { Triangle t = new Triangle(o.Vertices[v.VertexIndieces[0]], o.Vertices[v.VertexIndieces[1]], o.Vertices[v.VertexIndieces[2]]); Vector3 qq = (t.PointB - t.PointA).Cross(t.PointC - t.PointA); if ((qq.X * qq.X + qq.Y * qq.Y + qq.Z * qq.Z) < 0.01) { continue; } KCLPlane p = new KCLPlane(); p.CollisionType = Mapping[v.Material]; Vector3 a = (t.PointC - t.PointA).Cross(t.Normal); a.Normalize(); a = -a; Vector3 b = (t.PointB - t.PointA).Cross(t.Normal); b.Normalize(); Vector3 c = (t.PointC - t.PointB).Cross(t.Normal); c.Normalize(); p.Length = (t.PointC - t.PointA).Dot(c); int q = ContainsVector3(t.PointA, Vertex); if (q == -1) { p.VertexIndex = (ushort)Vertex.Count; Vertex.Add(t.PointA); } else { p.VertexIndex = (ushort)q; } q = ContainsVector3(t.Normal, Normals); if (q == -1) { p.NormalIndex = (ushort)Normals.Count; Normals.Add(t.Normal); } else { p.NormalIndex = (ushort)q; } q = ContainsVector3(a, Normals); if (q == -1) { p.NormalAIndex = (ushort)Normals.Count; Normals.Add(a); } else { p.NormalAIndex = (ushort)q; } q = ContainsVector3(b, Normals); if (q == -1) { p.NormalBIndex = (ushort)Normals.Count; Normals.Add(b); } else { p.NormalBIndex = (ushort)q; } q = ContainsVector3(c, Normals); if (q == -1) { p.NormalCIndex = (ushort)Normals.Count; Normals.Add(c); } else { p.NormalCIndex = (ushort)q; } planes.Add(p); Triangles.Add(t); } } Vertices = Vertex.ToArray(); this.Normals = Normals.ToArray(); Planes = planes.ToArray(); Header = new MK7KCLHeader(); Octree = KCLOctree.FromTriangles(Triangles.ToArray(), Header, 2048, 128, 128, 50); return(matnames); }
public bool CreateFromFile() { System.Windows.Forms.OpenFileDialog f = new System.Windows.Forms.OpenFileDialog(); f.Filter = OBJ.Identifier.GetFileFilter(); if (f.ShowDialog() == System.Windows.Forms.DialogResult.OK && f.FileName.Length > 0) { OBJ o = new OBJ(File.ReadAllBytes(f.FileName)); List <String> matnames = new List <string>(); foreach (var v in o.Faces) { if (!matnames.Contains(v.Material)) { matnames.Add(v.Material); } } UI.KCLCollisionTypeSelector ty = new UI.KCLCollisionTypeSelector(matnames.ToArray()); ty.DialogResult = System.Windows.Forms.DialogResult.None; ty.ShowDialog(); while (ty.DialogResult != System.Windows.Forms.DialogResult.OK) { ; } Dictionary <string, ushort> Mapping; Dictionary <string, bool> Colli; Mapping = ty.Mapping; Colli = ty.Colli; List <Vector3> Vertex = new List <Vector3>(); List <Vector3> Normals = new List <Vector3>(); List <KCLPlane> planes = new List <KCLPlane>(); List <Triangle> Triangles = new List <Triangle>(); foreach (var v in o.Faces) { if (Colli[v.Material]) { Triangle t = new Triangle(o.Vertices[v.VertexIndieces[0]], o.Vertices[v.VertexIndieces[1]], o.Vertices[v.VertexIndieces[2]]); Vector3 qq = (t.PointB - t.PointA).Cross(t.PointC - t.PointA); if ((qq.X * qq.X + qq.Y * qq.Y + qq.Z * qq.Z) < 0.01) { continue; } KCLPlane p = new KCLPlane(); p.CollisionType = Mapping[v.Material]; Vector3 a = (t.PointC - t.PointA).Cross(t.Normal); a.Normalize(); a = -a; Vector3 b = (t.PointB - t.PointA).Cross(t.Normal); b.Normalize(); Vector3 c = (t.PointC - t.PointB).Cross(t.Normal); c.Normalize(); p.Length = (t.PointC - t.PointA).Dot(c); int q = ContainsVector3(t.PointA, Vertex); if (q == -1) { p.VertexIndex = (ushort)Vertex.Count; Vertex.Add(t.PointA); } else { p.VertexIndex = (ushort)q; } q = ContainsVector3(t.Normal, Normals); if (q == -1) { p.NormalIndex = (ushort)Normals.Count; Normals.Add(t.Normal); } else { p.NormalIndex = (ushort)q; } q = ContainsVector3(a, Normals); if (q == -1) { p.NormalAIndex = (ushort)Normals.Count; Normals.Add(a); } else { p.NormalAIndex = (ushort)q; } q = ContainsVector3(b, Normals); if (q == -1) { p.NormalBIndex = (ushort)Normals.Count; Normals.Add(b); } else { p.NormalBIndex = (ushort)q; } q = ContainsVector3(c, Normals); if (q == -1) { p.NormalCIndex = (ushort)Normals.Count; Normals.Add(c); } else { p.NormalCIndex = (ushort)q; } planes.Add(p); Triangles.Add(t); } } Vertices = Vertex.ToArray(); this.Normals = Normals.ToArray(); Planes = planes.ToArray(); Header = new MK7KCLHeader(); Octree = KCLOctree.FromTriangles(Triangles.ToArray(), Header, 2048, 128, 128, 50); return(true); } return(false); }
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 bool BackGroundWorkerTask(System.ComponentModel.BackgroundWorker worker, object argument) { BGArgs userState = (BGArgs)argument; OBJ o = new OBJ(File.ReadAllBytes(userState.filename)); List <String> matnames = new List <string>(); foreach (var v in o.Faces) { if (!matnames.Contains(v.Material)) { matnames.Add(v.Material); } } UI.KCLCollisionTypeSelector ty = new UI.KCLCollisionTypeSelector(matnames.ToArray(), userState.filename); ty.loadMK7KCLInformations(); ty.DialogResult = System.Windows.Forms.DialogResult.None; ty.ShowDialog(); while (ty.DialogResult != System.Windows.Forms.DialogResult.OK) { ; } roundVertexPositions(o); Dictionary <string, ushort> Mapping; Dictionary <string, bool> Colli; Mapping = ty.Mapping; Colli = ty.Colli; List <Vector3> Vertex = new List <Vector3>(); List <Vector3> Normals = new List <Vector3>(); List <KCLPlane> planes = new List <KCLPlane>(); List <Triangle> Triangles = new List <Triangle>(); userState.state = 1; userState.currProg = 0; userState.totProg = o.Faces.Count; foreach (var v in o.Faces) { if (Colli[v.Material]) { Triangle t = new Triangle(o.Vertices[v.VertexIndieces[0]], o.Vertices[v.VertexIndieces[1]], o.Vertices[v.VertexIndieces[2]]); Vector3 qq = (t.PointB - t.PointA).Cross(t.PointC - t.PointA); if ((qq.X * qq.X + qq.Y * qq.Y + qq.Z * qq.Z) < 0.1) { continue; } KCLPlane p = new KCLPlane(); p.CollisionType = Mapping[v.Material]; Vector3 a = (t.PointC - t.PointA).Cross(t.Normal); a.Normalize(); a = -a; Vector3 b = (t.PointB - t.PointA).Cross(t.Normal); b.Normalize(); Vector3 c = (t.PointC - t.PointB).Cross(t.Normal); c.Normalize(); p.Length = (t.PointC - t.PointA).Dot(c); int q = ContainsVector3(t.PointA, Vertex); if (q == -1) { p.VertexIndex = (ushort)Vertex.Count; Vertex.Add(t.PointA); } else { p.VertexIndex = (ushort)q; } q = ContainsVector3(t.Normal, Normals); if (q == -1) { p.NormalIndex = (ushort)Normals.Count; Normals.Add(t.Normal); } else { p.NormalIndex = (ushort)q; } q = ContainsVector3(a, Normals); if (q == -1) { p.NormalAIndex = (ushort)Normals.Count; Normals.Add(a); } else { p.NormalAIndex = (ushort)q; } q = ContainsVector3(b, Normals); if (q == -1) { p.NormalBIndex = (ushort)Normals.Count; Normals.Add(b); } else { p.NormalBIndex = (ushort)q; } q = ContainsVector3(c, Normals); if (q == -1) { p.NormalCIndex = (ushort)Normals.Count; Normals.Add(c); } else { p.NormalCIndex = (ushort)q; } planes.Add(p); Triangles.Add(t); } userState.currProg++; worker.ReportProgress(0, userState); if (worker.CancellationPending) { return(false); } } Vertices = Vertex.ToArray(); this.Normals = Normals.ToArray(); Planes = planes.ToArray(); Header = new MK7KCLHeader(); Octree = KCLOctree.FromTriangles(Triangles.ToArray(), Header, 2048, 128, 32, 10, userState, worker); if (Octree == null) { return(false); } return(true); }