/// <summary> /// /// </summary> /// <param name="jobj"></param> public static void CalculateCollisionFlags(this KAR_grCollisionNode coll) { var verts = coll.Vertices; var tris = coll.Triangles; foreach (var tri in tris) { // calculate surface normal var v0 = GXTranslator.toVector3(verts[tri.V1]); var v1 = GXTranslator.toVector3(verts[tri.V2]); var v2 = GXTranslator.toVector3(verts[tri.V3]); var faceNrm = Vector3.Cross(v1 - v0, v2 - v0).Normalized(); tri.Flags &= ~0x7; // guess flag if (faceNrm.Y > 0.5f) { tri.Flags |= 0x04; } else if (faceNrm.Y <= 0.5f && faceNrm.Y > -0.5f) { tri.Flags |= 0x02; } else { tri.Flags |= 0x01; } } coll.Triangles = tris; }
public void Clear() { Node = null; Vertices = null; Triangles = null; Joints = null; ZoneVertices = null; ZoneTriangles = null; ZoneJoints = null; }
/// <summary> /// /// </summary> /// <param name="node"></param> private void LoadZones(KAR_grCollisionNode node) { var vertices = node.ZoneVertices; var faces = node.ZoneTriangles; foreach (var j in node.ZoneJoints) { // create collision joint var c = new GrZoneJoint() { JointIndex = j.BoneID, }; c.Mtx[0] = j.Mtx00; c.Mtx[1] = j.Mtx10; c.Mtx[2] = j.Mtx20; c.Mtx[3] = j.Mtx30; c.Mtx[4] = j.Mtx01; c.Mtx[5] = j.Mtx11; c.Mtx[6] = j.Mtx21; c.Mtx[7] = j.Mtx31; c.Mtx[8] = j.Mtx02; c.Mtx[9] = j.Mtx12; c.Mtx[10] = j.Mtx22; c.Mtx[11] = j.Mtx32; // unknown data if (j._s.References.ContainsKey(0x14)) { c.Unknown = j._s.References[0x14]; } if (j._s.References.ContainsKey(0x18)) { c.Params = j._s.References[0x18]; } // convert faces for (int i = j.ZoneFaceStart; i < j.ZoneFaceStart + j.ZoneFaceSize; i++) { var face = faces[i]; c.Faces.Add(new GrZoneFace() { CollFlag = face.CollFlags, TypeFlag = face.TypeFlags, UnknownFlag = face.UnkFlags, p0 = vertices[face.V1], p1 = vertices[face.V2], p2 = vertices[face.V3], }); } // add to collection ZoneJoints.Add(c); } }
public void Render(HSDAccessor a, int windowWidth, int windowHeight) { if (a is KAR_grCollisionNode cn && cn != Node) { Node = cn; Vertices = Node.Vertices; Triangles = Node.Triangles; Joints = Node.Joints; ZoneVertices = Node.ZoneVertices; ZoneTriangles = Node.ZoneTriangles; ZoneJoints = Node.ZoneJoints; } if (Node == null) { return; } GL.PushAttrib(AttribMask.AllAttribBits); GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); GL.Begin(PrimitiveType.Triangles); foreach (var t in Triangles) { if ((t.Flags & 0x1) == 0x1) { GL.Color4(1f, 0f, 0f, 0.5f); } if ((t.Flags & 0x2) == 0x2) { GL.Color4(0f, 1f, 0f, 0.5f); } if ((t.Flags & 0x4) == 0x4) { GL.Color4(0f, 0f, 1f, 0.5f); } GL.Vertex3(GXTranslator.toVector3(Vertices[t.V1])); GL.Vertex3(GXTranslator.toVector3(Vertices[t.V2])); GL.Vertex3(GXTranslator.toVector3(Vertices[t.V3])); } GL.End(); GL.PopAttrib(); }
public static KAR_grCollisionTree GenerateBucketPartition(KAR_grCollisionNode coll) { var v = coll.Vertices; var bucketGen = new BucketGen( v.Min(e => e.X) - 10, Math.Min(-1000, v.Min(e => e.Y) - 10), v.Min(e => e.Z) - 10, v.Max(e => e.X) + 10, Math.Max(1000, v.Min(e => e.Y) + 10), v.Max(e => e.Z) + 10); var tris = coll.Triangles.ToList(); foreach (var t in tris) { bucketGen.AddTriangle(t, v[t.V1], v[t.V2], v[t.V3]); } return(bucketGen.ProcessBuckets(tris)); }
/// <summary> /// /// </summary> /// <param name="node"></param> private void LoadCollisions(KAR_grCollisionNode node) { var vertices = node.Vertices; var faces = node.Triangles; foreach (var j in node.Joints) { // create collision joint var c = new GrCollisionJoint() { JointIndex = j.BoneID, Flags = j.Flags }; // unknown data if (j._s.References.ContainsKey(0x18)) { c.Unknown = j._s.References[0x18]; } // convert faces for (int i = j.FaceStart; i < j.FaceStart + j.FaceSize; i++) { var face = faces[i]; c.Faces.Add(new GrCollisionFace() { Flags = face.Flags, Material = face.Material, p0 = vertices[face.V1], p1 = vertices[face.V2], p2 = vertices[face.V3], }); } // add to collection CollisionJoints.Add(c); } }
public static KAR_grCollisionNode KCLtoKAR(string kclFile, out KAR_grCollisionTree tree) { KAR_grCollisionNode node = new KAR_grCollisionNode(); List <KAR_CollisionTriangle> tris = new List <KAR_CollisionTriangle>(); List <GXVector3> verts = new List <GXVector3>(); using (FileStream f = new FileStream(kclFile, FileMode.Open)) using (BinaryReaderExt r = new BinaryReaderExt(f)) { r.BigEndian = true; var posOffset = r.ReadInt32(); var nrmOffset = r.ReadInt32(); var triOffset = r.ReadInt32() + 0x10; var partOffste = r.ReadInt32(); var triCount = (partOffste - triOffset) / 0x10; for (int i = 0; i < triCount; i++) { r.Seek((uint)(triOffset + i * 0x10)); var length = r.ReadSingle(); var pi = r.ReadUInt16(); var di = r.ReadUInt16(); var n1 = r.ReadUInt16(); var n2 = r.ReadUInt16(); var n3 = r.ReadUInt16(); var fl = r.ReadUInt16(); r.Seek((uint)(posOffset + pi * 0xC)); var position = new Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle()); r.Seek((uint)(nrmOffset + di * 0xC)); var direction = new Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle()); r.Seek((uint)(nrmOffset + n1 * 0xC)); var normalA = new Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle()); r.Seek((uint)(nrmOffset + n2 * 0xC)); var normalB = new Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle()); r.Seek((uint)(nrmOffset + n3 * 0xC)); var normalC = new Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle()); var crossA = Vector3.Cross(normalA, direction); var crossB = Vector3.Cross(normalB, direction); var vertex1 = position; var vertex2 = position + crossB * (length / Vector3.Dot(crossB, normalC)); var vertex3 = position + crossA * (length / Vector3.Dot(crossA, normalC)); tris.Add(new KAR_CollisionTriangle() { Flags = 0x81, V1 = verts.Count + 2, V2 = verts.Count + 1, V3 = verts.Count }); // scale vertex1 *= Scale; vertex2 *= Scale; vertex3 *= Scale; vertex1.Y += YTrans; vertex2.Y += YTrans; vertex3.Y += YTrans; verts.Add(new GXVector3() { X = vertex1.X, Y = vertex1.Y, Z = vertex1.Z }); verts.Add(new GXVector3() { X = vertex2.X, Y = vertex2.Y, Z = vertex2.Z }); verts.Add(new GXVector3() { X = vertex3.X, Y = vertex3.Y, Z = vertex3.Z }); } } { var height = verts.Min(e => e.Y) - 10; var v1 = new Vector3(-10000, height, -10000); var v2 = new Vector3(10000, height, -10000); var v3 = new Vector3(10000, height, 10000); var v4 = new Vector3(-10000, height, 10000); tris.Add(new KAR_CollisionTriangle() { Flags = 0x81, V1 = verts.Count, V2 = verts.Count + 1, V3 = verts.Count + 2 }); verts.Add(new GXVector3() { X = v1.X, Y = v1.Y, Z = v1.Z }); verts.Add(new GXVector3() { X = v2.X, Y = v2.Y, Z = v2.Z }); verts.Add(new GXVector3() { X = v3.X, Y = v3.Y, Z = v3.Z }); tris.Add(new KAR_CollisionTriangle() { Flags = 0x81, V1 = verts.Count, V2 = verts.Count + 1, V3 = verts.Count + 2 }); verts.Add(new GXVector3() { X = v1.X, Y = v1.Y, Z = v1.Z }); verts.Add(new GXVector3() { X = v3.X, Y = v3.Y, Z = v3.Z }); verts.Add(new GXVector3() { X = v4.X, Y = v4.Y, Z = v4.Z }); } node.Triangles = tris.ToArray(); node.Vertices = verts.ToArray(); node.Joints = new KAR_CollisionJoint[] { new KAR_CollisionJoint() { VertexStart = 0, VertexSize = verts.Count, FaceStart = 0, FaceSize = tris.Count } }; tree = BucketGen.GenerateBucketPartition(node); return(node); }
/// <summary> /// /// </summary> /// <param name="node"></param> public void LoadFromCollision(KAR_grCollisionNode node) { LoadCollisions(node); LoadZones(node); }
/// <summary> /// /// </summary> /// <param name="collNode"></param> private void ProcessZones(KAR_grCollisionNode collNode) { // collect triangles and optimize points KAR_ZoneCollisionJoint[] joints = new KAR_ZoneCollisionJoint[ZoneJoints.Count]; // collect points and faces List <GXVector3> points = new List <GXVector3>(); List <KAR_ZoneCollisionTriangle> faces = new List <KAR_ZoneCollisionTriangle>(); // process collision joints var faceIndex = 0; var vertexIndex = 0; for (int i = 0; i < joints.Length; i++) { // convert collision joint var j = ZoneJoints[i]; var joint = new KAR_ZoneCollisionJoint() { BoneID = j.JointIndex, Mtx00 = j.Mtx[0], Mtx10 = j.Mtx[1], Mtx20 = j.Mtx[2], Mtx30 = j.Mtx[3], Mtx01 = j.Mtx[4], Mtx11 = j.Mtx[5], Mtx21 = j.Mtx[6], Mtx31 = j.Mtx[7], Mtx02 = j.Mtx[8], Mtx12 = j.Mtx[9], Mtx22 = j.Mtx[10], Mtx32 = j.Mtx[11], ZoneVertexStart = vertexIndex, ZoneFaceStart = faceIndex, }; if (j.Unknown != null) { joint._s.SetReferenceStruct(0x14, j.Unknown); } if (j.Params != null) { joint._s.SetReferenceStruct(0x18, j.Params); } joints[i] = joint; // add points and triangles Dictionary <GXVector3, int> pointToIndex = new Dictionary <GXVector3, int>(); foreach (var tri in j.Faces) { // generate and add face var face = new KAR_ZoneCollisionTriangle() { CollFlags = tri.CollFlag, TypeFlags = tri.TypeFlag, UnkFlags = tri.UnknownFlag, V1 = GetPointIndex(tri.p0, ref pointToIndex, ref points), V2 = GetPointIndex(tri.p1, ref pointToIndex, ref points), V3 = GetPointIndex(tri.p2, ref pointToIndex, ref points), }; faces.Add(face); } // update vertex and face sizes joint.ZoneFaceSize = j.Faces.Count; joint.ZoneVertexSize = pointToIndex.Count; // increment vertex and face size vertexIndex += joint.ZoneVertexSize; faceIndex += joint.ZoneFaceSize; } // collNode.ZoneVertices = points.ToArray(); collNode.ZoneVertexCount = points.Count; collNode.ZoneTriangles = faces.ToArray(); collNode.ZoneTriangleCount = faces.Count; collNode.ZoneJoints = joints; collNode.ZoneJointCount = joints.Length; }
/// <summary> /// /// </summary> public void ExportCollisions(out KAR_grCollisionNode collNode, out KAR_grCollisionTreeNode treeNode) { collNode = new KAR_grCollisionNode(); treeNode = new KAR_grCollisionTreeNode(); // collect triangles and optimize points KAR_CollisionJoint[] collJoints = new KAR_CollisionJoint[CollisionJoints.Count]; // collect points and faces List <GXVector3> points = new List <GXVector3>(); List <KAR_CollisionTriangle> faces = new List <KAR_CollisionTriangle>(); // process collision joints var faceIndex = 0; var vertexIndex = 0; for (int i = 0; i < collJoints.Length; i++) { // convert collision joint var j = CollisionJoints[i]; var joint = new KAR_CollisionJoint() { BoneID = j.JointIndex, Flags = j.Flags, VertexStart = vertexIndex, FaceStart = faceIndex, }; if (j.Unknown != null) { joint._s.SetReferenceStruct(0x18, j.Unknown); } collJoints[i] = joint; // add points and triangles Dictionary <GXVector3, int> pointToIndex = new Dictionary <GXVector3, int>(); foreach (var tri in j.Faces) { // generate and add face var face = new KAR_CollisionTriangle() { Flags = tri.Flags, Material = tri.Material, V1 = GetPointIndex(tri.p0, ref pointToIndex, ref points), V2 = GetPointIndex(tri.p1, ref pointToIndex, ref points), V3 = GetPointIndex(tri.p2, ref pointToIndex, ref points), }; faces.Add(face); } // update vertex and face sizes joint.FaceSize = j.Faces.Count; joint.VertexSize = pointToIndex.Count; // increment vertex and face size vertexIndex += joint.VertexSize; faceIndex += joint.FaceSize; } // generate partition buckets treeNode.Partition = GenerateBucketPartition(points, faces); collNode.Vertices = points.ToArray(); collNode.VertexCount = points.Count; collNode.Triangles = faces.ToArray(); collNode.TriangleCount = faces.Count; collNode.Joints = collJoints; collNode.JointCount = collJoints.Length; ProcessZones(collNode); }
/// <summary> /// /// </summary> /// <param name="coll"></param> public void LoadCollision(KAR_grCollisionNode coll) { // Load Collisions var tris = coll.Triangles; var verts = coll.Vertices; Joints = new JointCollision[coll.JointCount]; for(int i = 0; i < coll.JointCount; i++) { var joint = coll.Joints[i]; Joints[i] = new JointCollision() { Bone = joint.BoneID, Faces = new CollisionFace[joint.FaceSize] }; for (int j = joint.FaceStart; j < joint.FaceStart + joint.FaceSize; j++) { var face = tris[j]; var v1 = verts[face.V1]; var v2 = verts[face.V2]; var v3 = verts[face.V3]; Joints[i].Faces[j - joint.FaceStart] = new CollisionFace() { Flags = face.Flags, Unknown = face.Unknown, v1 = new Vector3(v1.X, v1.Y, v1.Z), v2 = new Vector3(v2.X, v2.Y, v2.Z), v3 = new Vector3(v3.X, v3.Y, v3.Z), }; } } // Load Zones var ztris = coll.ZoneTriangles; verts = coll.ZoneVertices; ZoneJoints = new ZoneJointCollision[coll.ZoneJointCount]; for (int i = 0; i < coll.ZoneJointCount; i++) { var joint = coll.ZoneJoints[i]; ZoneJoints[i] = new ZoneJointCollision() { Bone = joint.BoneID, Faces = new ZoneCollisionFace[joint.ZoneFaceSize], ZoneJoint = joint }; for (int j = 0; j < joint.ZoneFaceSize; j++) { var face = ztris[j + joint.ZoneFaceStart]; var v1 = verts[face.V1]; var v2 = verts[face.V2]; var v3 = verts[face.V3]; Joints[i].Faces[j] = new ZoneCollisionFace() { Flags = face.Color, Unknown = face.Unknown, UnknownZone = face.UnknownZone, v1 = new Vector3(v1.X, v1.Y, v1.Z), v2 = new Vector3(v2.X, v2.Y, v2.Z), v3 = new Vector3(v3.X, v3.Y, v3.Z), }; } } }