/// <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 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(); }
/// <summary> /// /// </summary> /// <param name="pobj"></param> private Mesh ProcessPOBJ(HSD_POBJ pobj, HSD_JOBJ parent, HSD_JOBJ singleBind) { Mesh m = new Mesh(); m.Name = "pobj"; m.PrimitiveType = PrimitiveType.Triangle; m.MaterialIndex = 0; var dl = pobj.ToDisplayList(); var envelopes = pobj.EnvelopeWeights; var parentTransform = Matrix4.Identity; if (parent != null) { parentTransform = WorldTransforms[jobjToIndex[parent]]; } var singleBindTransform = Matrix4.Identity; if (singleBind != null) { singleBindTransform = WorldTransforms[jobjToIndex[singleBind]]; } Dictionary <HSD_JOBJ, Bone> jobjToBone = new Dictionary <HSD_JOBJ, Bone>(); if (envelopes != null) { foreach (var jobj in Jobjs) { var bone = new Bone(); bone.Name = JobjNodes[jobjToIndex[jobj]].Name; bone.OffsetMatrix = Matrix4ToMatrix4x4(WorldTransforms[jobjToIndex[jobj]].Inverted()); m.Bones.Add(bone); jobjToBone.Add(jobj, bone); } } /*foreach (var en in envelopes) * { * foreach (var jobj in en.JOBJs) * { * if (!jobjToBone.ContainsKey(jobj)) * { * var bone = new Bone(); * bone.Name = JobjNodes[jobjToIndex[jobj]].Name; * bone.OffsetMatrix = Matrix4ToMatrix4x4(WorldTransforms[jobjToIndex[jobj]].Inverted()); * m.Bones.Add(bone); * jobjToBone.Add(jobj, bone); * } * } * }*/ if (singleBind != null && !jobjToBone.ContainsKey(singleBind)) { var bone = new Bone(); bone.Name = JobjNodes[jobjToIndex[singleBind]].Name; bone.OffsetMatrix = Matrix4ToMatrix4x4(WorldTransforms[jobjToIndex[singleBind]].Inverted()); m.Bones.Add(bone); jobjToBone.Add(singleBind, bone); } int offset = 0; var vIndex = -1; foreach (var prim in dl.Primitives) { var verts = dl.Vertices.GetRange(offset, prim.Count); offset += prim.Count; switch (prim.PrimitiveType) { case GXPrimitiveType.Quads: verts = TriangleConverter.QuadToList(verts); break; case GXPrimitiveType.TriangleStrip: verts = TriangleConverter.StripToList(verts); break; case GXPrimitiveType.Triangles: break; default: Console.WriteLine(prim.PrimitiveType); break; } for (int i = m.VertexCount; i < m.VertexCount + verts.Count; i += 3) { var f = new Face(); f.Indices.Add(i); f.Indices.Add(i + 1); f.Indices.Add(i + 2); m.Faces.Add(f); } foreach (var v in verts) { vIndex++; if (singleBind != null) { var vertexWeight = new VertexWeight(); vertexWeight.VertexID = vIndex; vertexWeight.Weight = 1; jobjToBone[singleBind].VertexWeights.Add(vertexWeight); } Matrix4 weight = Matrix4.Identity; foreach (var a in pobj.Attributes) { switch (a.AttributeName) { case GXAttribName.GX_VA_PNMTXIDX: var en = envelopes[v.PNMTXIDX / 3]; for (int w = 0; w < en.EnvelopeCount; w++) { var vertexWeight = new VertexWeight(); vertexWeight.VertexID = vIndex; vertexWeight.Weight = en.Weights[w]; jobjToBone[en.JOBJs[w]].VertexWeights.Add(vertexWeight); } if (en.EnvelopeCount == 1 && jobjToIndex[parent] == 0) { weight = WorldTransforms[jobjToIndex[en.JOBJs[0]]]; } break; case GXAttribName.GX_VA_POS: var vert = Vector3.TransformPosition(GXTranslator.toVector3(v.POS), parentTransform); vert = Vector3.TransformPosition(vert, weight); vert = Vector3.TransformPosition(vert, singleBindTransform); m.Vertices.Add(new Vector3D(vert.X, vert.Y, vert.Z)); break; case GXAttribName.GX_VA_NRM: var nrm = Vector3.TransformNormal(GXTranslator.toVector3(v.NRM), parentTransform); nrm = Vector3.TransformNormal(nrm, weight); nrm = Vector3.TransformNormal(nrm, singleBindTransform); m.Normals.Add(new Vector3D(nrm.X, nrm.Y, nrm.Z)); break; case GXAttribName.GX_VA_CLR0: m.VertexColorChannels[0].Add(new Color4D(v.CLR0.R, v.CLR0.G, v.CLR0.B, v.CLR0.A)); break; case GXAttribName.GX_VA_CLR1: m.VertexColorChannels[1].Add(new Color4D(v.CLR1.R, v.CLR1.G, v.CLR1.B, v.CLR1.A)); break; case GXAttribName.GX_VA_TEX0: m.TextureCoordinateChannels[0].Add(new Vector3D(v.TEX0.X, v.TEX0.Y, 1)); break; case GXAttribName.GX_VA_TEX1: m.TextureCoordinateChannels[1].Add(new Vector3D(v.TEX1.X, v.TEX1.Y, 1)); break; case GXAttribName.GX_VA_TEX2: m.TextureCoordinateChannels[2].Add(new Vector3D(v.TEX2.X, v.TEX2.Y, 1)); break; case GXAttribName.GX_VA_TEX3: m.TextureCoordinateChannels[3].Add(new Vector3D(v.TEX3.X, v.TEX3.Y, 1)); break; case GXAttribName.GX_VA_TEX4: m.TextureCoordinateChannels[4].Add(new Vector3D(v.TEX4.X, v.TEX4.Y, 1)); break; case GXAttribName.GX_VA_TEX5: m.TextureCoordinateChannels[5].Add(new Vector3D(v.TEX5.X, v.TEX5.Y, 1)); break; case GXAttribName.GX_VA_TEX6: m.TextureCoordinateChannels[6].Add(new Vector3D(v.TEX6.X, v.TEX6.Y, 1)); break; case GXAttribName.GX_VA_TEX7: m.TextureCoordinateChannels[7].Add(new Vector3D(v.TEX7.X, v.TEX7.Y, 1)); break; } } } } return(m); }