public bool AreTrianglesAdjacent(DTriangle t1, DTriangle t2) { int match_verts = 0; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if ((vertex[t1.vert[i]] - vertex[t2.vert[j]]).LengthSquared <= MATCH_DIST_SQ) { match_verts += 1; } } } if (match_verts >= 2) { Vector3 n1 = Utility.FindNormal(vertex[t1.vert[0]], vertex[t1.vert[1]], vertex[t1.vert[2]]); Vector3 n2 = Utility.FindNormal(vertex[t2.vert[0]], vertex[t2.vert[1]], vertex[t2.vert[2]]); if (Vector3.Dot(n1, n2) > MATCH_NORMAL) { return(true); } } return(false); }
public List <DTriangle> DeconvertPoly() { // Triange for each vert beyond 2 (0-1-2, 0-2-3, 0-3-4, etc) List <DTriangle> tri_list = new List <DTriangle>(); int[] vrt = new int[3]; Vector3[] nrml = new Vector3[3]; Vector2[] uv = new Vector2[3]; for (int i = 0; i < num_verts - 2; i++) { vrt[0] = vert[0]; vrt[1] = vert[i + 1]; vrt[2] = vert[i + 2]; nrml[0] = normal[0]; nrml[1] = normal[i + 1]; nrml[2] = normal[i + 2]; uv[0] = tex_uv[0]; uv[1] = tex_uv[i + 1]; uv[2] = tex_uv[i + 2]; DTriangle dtri = new DTriangle(vrt, nrml, uv, tex_index); dtri.poly_num = num; dtri.flags = flags; smoothing = 0; tri_list.Add(dtri); } return(tri_list); }
public void CreateTriangle(DTriangle tri, DMesh mesh) { for (int i = 0; i < 3; i++) { GL.TexCoord2(tri.tex_uv[i]); GL.Normal3(tri.normal[i]); GL.Vertex3(mesh.vertex[tri.vert[i]]); } }
public void CreateLinesFromVertNormals(DTriangle tri, DMesh mesh) { GL.Vertex3(mesh.vertex[tri.vert[0]]); GL.Vertex3(mesh.vertex[tri.vert[0]] + tri.normal[0] * 0.1f); GL.Vertex3(mesh.vertex[tri.vert[1]]); GL.Vertex3(mesh.vertex[tri.vert[1]] + tri.normal[1] * 0.1f); GL.Vertex3(mesh.vertex[tri.vert[2]]); GL.Vertex3(mesh.vertex[tri.vert[2]] + tri.normal[2] * 0.1f); }
public void CreateLinesFromTriangle(DTriangle tri, DMesh mesh) { GL.Vertex3(mesh.vertex[tri.vert[0]]); GL.Vertex3(mesh.vertex[tri.vert[1]]); GL.Vertex3(mesh.vertex[tri.vert[1]]); GL.Vertex3(mesh.vertex[tri.vert[2]]); GL.Vertex3(mesh.vertex[tri.vert[2]]); GL.Vertex3(mesh.vertex[tri.vert[0]]); }
public void ReverseWindingOrder() { DTriangle flip_tri = new DTriangle(this, 0); for (int i = 0; i < 3; i++) { vert[i] = flip_tri.vert[2 - i]; normal[i] = flip_tri.normal[2 - i]; tex_uv[i] = flip_tri.tex_uv[2 - i]; } }
public void CreateGMTriangle(DTriangle tri, GMesh mesh) { Vector3 normal = Utility.FindNormal(mesh.m_vertex[tri.vert[0]], mesh.m_vertex[tri.vert[1]], mesh.m_vertex[tri.vert[2]]); for (int i = 0; i < 3; i++) { GL.TexCoord2(tri.tex_uv[i]); //GL.Normal3(tri.normal[i]); GL.Normal3(normal); GL.Vertex3(mesh.m_vertex[tri.vert[i]]); } }
public DTriangle(DTriangle src, int vert_idx_offset) { for (int i = 0; i < 3; i++) { vert[i] = src.vert[i] + vert_idx_offset; normal[i] = src.normal[i]; tex_uv[i] = src.tex_uv[i]; } tex_index = src.tex_index; flags = src.flags; }
public DPoly(DTriangle dtri) { num_verts = 3; flags = dtri.flags; smoothing = 0; ClearLists(); for (int i = 0; i < num_verts; i++) { vert.Add(dtri.vert[i]); normal.Add(dtri.normal[i]); tex_uv.Add(dtri.tex_uv[i]); tex_index = dtri.tex_index; } }
public void AddFaceFromCTriangle(CTriangle ct) { int start_vrt = m_vertex.Count; for (int i = 0; i < 3; i++) { m_vertex.Add(ct.original_verts[i].Position); } bool use_clipped_data = false; DTriangle tri = new DTriangle(ct, start_vrt, 0, use_clipped_data); m_triangle.Add(tri); }
public void AddGeometry(DMesh dm, Vector3 offset) { // Currently, this creates the geometry in World space Matrix4 full_rotation = Matrix4.Mult(Matrix4.CreateRotationX(-Utility.RAD_90), m_base_rot); // Build up the transform to use for the normals // Note: Invert directions because the uvec was setup for texture V coordinates Matrix4 normal_full_rotation = new Matrix4(); normal_full_rotation.M11 = -m_base_rvec.X; normal_full_rotation.M12 = -m_base_rvec.Y; normal_full_rotation.M13 = -m_base_rvec.Z; normal_full_rotation.M14 = 0.0f; normal_full_rotation.M21 = m_base_uvec.X; normal_full_rotation.M22 = m_base_uvec.Y; normal_full_rotation.M23 = m_base_uvec.Z; normal_full_rotation.M24 = 0.0f; normal_full_rotation.M31 = -m_base_normal.X; normal_full_rotation.M32 = -m_base_normal.Y; normal_full_rotation.M33 = -m_base_normal.Z; normal_full_rotation.M34 = 0.0f; normal_full_rotation.M41 = 0.0f; normal_full_rotation.M42 = 0.0f; normal_full_rotation.M43 = 0.0f; normal_full_rotation.M44 = 1.0f; normal_full_rotation = Matrix4.CreateRotationX(-Utility.RAD_90) * normal_full_rotation; int vert_idx_offset = m_vertex.Count; for (int i = 0; i < dm.vertex.Count; i++) { Vector3 rot_pos = Vector3.Transform(dm.vertex[i], full_rotation); m_vertex.Add(rot_pos + offset); } for (int i = 0; i < dm.triangle.Count; i++) { DTriangle d_tri = new DTriangle(dm.triangle[i], vert_idx_offset); for (int v = 0; v < 3; ++v) { d_tri.normal[v] = OpenTK.Vector3.Transform(d_tri.normal[v], normal_full_rotation); } m_triangle.Add(d_tri); } }
public void Copy(DMesh src, bool ignore_light = false) { name = src.name; flags = src.flags; for (int i = 0; i < src.vertex.Count; i++) { vertex.Add(src.vertex[i]); } for (int i = 0; i < src.triangle.Count; i++) { DTriangle dtri = new DTriangle(src.triangle[i], 0); triangle.Add(dtri); } CopyExtraProperties(src); for (int i = 0; i < src.tex_name.Count; i++) { tex_name.Add(src.tex_name[i]); #if OVERLOAD_LEVEL_EDITOR m_tex_gl_id.Add(src.m_tex_gl_id[i]); #endif } if (!ignore_light) { light.Clear(); for (int i = 0; i < src.light.Count; i++) { DLight dl = new DLight(src.light[i]); light.Add(dl); } color.Clear(); for (int i = 0; i < src.color.Count; i++) { color.Add(src.color[i]); } } }
// Assumes the face has 3 verts public void AddFace(int[] vrt_idx, Vector3[] nrml, Vector2[] uv, int tex_idx) { DTriangle tri = new DTriangle(vrt_idx, nrml, uv, tex_idx); m_triangle.Add(tri); }
public static bool CheckAndCleanMeshIssues(ref List <DTriangle> triangle, List <Vector3> vertex, bool removeSmallInvalidTriangles, out string issues) { const float kLengthEpsilon = 0.0001f; const float kDotEpsilon = 0.99999f; const double kUVEpsilon = 0.000001; const double kMaxAreaForAutoRemoval = 0.0003; Vector3[] verts = new Vector3[3]; bool result = false; System.Text.StringBuilder builder = new System.Text.StringBuilder(); List <BadTriangle> badTriangleIndices = new List <BadTriangle>(); foreach (int triIdx in Enumerable.Range(0, triangle.Count)) { var tri = triangle[triIdx]; if (tri.vert.Length != 3) { builder.AppendFormat("-- Polygon is not 3 verts\n"); result = true; badTriangleIndices.Add(new BadTriangle() { index = triIdx, reason = BadTriangleReason.ZeroArea }); continue; } for (int i = 0; i < 3; ++i) { verts[i] = vertex[tri.vert[i]]; } Vector3 edge0 = verts[0] - verts[1]; Vector3 edge1 = verts[2] - verts[1]; Vector3 edge2 = verts[0] - verts[2]; bool isZeroAreaTriangle = false; bool isBadUVTriangle = false; if (edge0.Length <= kLengthEpsilon) { builder.AppendFormat("-- triangle in polygon {3} edge0 is collapsed {0} {1} {2}\n", verts[0].ToString(), verts[1].ToString(), verts[2].ToString(), tri.poly_num.ToString()); isZeroAreaTriangle = true; } if (edge1.Length <= kLengthEpsilon) { builder.AppendFormat("-- triangle in polygon {3} edge1 is collapsed {0} {1} {2}\n", verts[0].ToString(), verts[1].ToString(), verts[2].ToString(), tri.poly_num.ToString()); isZeroAreaTriangle = true; } if (edge2.Length <= kLengthEpsilon) { builder.AppendFormat("-- triangle in polygon {3} edge2 is collapsed {0} {1} {2}\n", verts[0].ToString(), verts[1].ToString(), verts[2].ToString(), tri.poly_num.ToString()); isZeroAreaTriangle = true; } if (!isZeroAreaTriangle) { float edge_dot = Math.Abs(Vector3.Dot(edge0.Normalized(), edge1.Normalized())); if (edge_dot >= kDotEpsilon) { builder.AppendFormat("-- triangle has no area {0} {1} {2}\n", verts[0].ToString(), verts[1].ToString(), verts[2].ToString()); isZeroAreaTriangle = true; } } // Check UVs to make sure there is a gradient Vector2 w1 = tri.tex_uv[0]; Vector2 w2 = tri.tex_uv[1]; Vector2 w3 = tri.tex_uv[2]; double s1 = w2.X - w1.X; double s2 = w3.X - w1.X; double t1 = w2.Y - w1.Y; double t2 = w3.Y - w1.Y; double den = (s1 * t2 - s2 * t1); if (Math.Abs(den) <= kUVEpsilon) { double area = CalculateTriangleArea(edge0, edge1, edge2); if (area <= kMaxAreaForAutoRemoval) { builder.AppendFormat("-- triangle has invalid UVs {0} {1} {2} -- area {3} (REMOVING)\n", w1.ToString(), w2.ToString(), w3.ToString(), area); isZeroAreaTriangle = true; } else { builder.AppendFormat("-- triangle has invalid UVs {0} {1} {2} -- area {3} (FIXING)\n", w1.ToString(), w2.ToString(), w3.ToString(), area); isBadUVTriangle = true; } } if (isZeroAreaTriangle) { result = true; // Calculate the area of the triangle double triangleArea = CalculateTriangleArea(edge0, edge1, edge2); if (triangleArea < kMaxAreaForAutoRemoval) { badTriangleIndices.Add(new BadTriangle() { index = triIdx, reason = BadTriangleReason.ZeroArea }); } } else if (isBadUVTriangle) { result = true; badTriangleIndices.Add(new BadTriangle() { index = triIdx, reason = BadTriangleReason.BadUV }); } } if (removeSmallInvalidTriangles && badTriangleIndices.Count > 0) { List <DTriangle> newTriangles = new List <DTriangle>(); int numRemoved = 0; int numBadTriangles = badTriangleIndices.Count; int badIndex = 0; foreach (int srcTriIndex in Enumerable.Range(0, triangle.Count)) { if (badIndex < numBadTriangles && badTriangleIndices[badIndex].index == srcTriIndex) { bool skipThis = false; switch (badTriangleIndices[badIndex++].reason) { case BadTriangleReason.ZeroArea: { skipThis = true; } break; case BadTriangleReason.BadUV: { DTriangle tri = triangle[srcTriIndex]; tri.tex_uv[1] = tri.tex_uv[1] + new Vector2(0.1f, 0.1f); tri.tex_uv[2] = tri.tex_uv[2] - new Vector2(0.1f, 0.1f); } break; } if (skipThis) { ++numRemoved; continue; } } newTriangles.Add(triangle[srcTriIndex]); } triangle = newTriangles; builder.AppendFormat("Removed {0} triangles\n", numRemoved); } issues = builder.ToString(); return(result); }
public void Deserialize(JObject root) { vertex.Clear(); triangle.Clear(); #if OVERLOAD_LEVEL_EDITOR m_tex_gl_id.Clear(); #endif tex_name.Clear(); Vector3 vec = Vector3.Zero; JArray j_verts = root["verts"].GetArray(); foreach (JObject j_vert in j_verts) { vec.X = j_vert["x"].GetFloat(0.0f); vec.Y = j_vert["y"].GetFloat(0.0f); vec.Z = j_vert["z"].GetFloat(0.0f); vertex.Add(vec); } #if OVERLOAD_LEVEL_EDITOR DeserializePolys(root); #endif JObject j_tris = root["triangles"].GetObject(); foreach (var kvp in j_tris) { JObject j_tri = kvp.Value.GetObject(); DTriangle d_tri = new DTriangle(j_tri); triangle.Add(d_tri); } JArray j_tex_names = root["tex_names"].GetArray(); for (int i = 0; i < j_tex_names.Count; i++) { #if OVERLOAD_LEVEL_EDITOR m_tex_gl_id.Add(-1); #endif tex_name.Add(j_tex_names[i].GetString("")); } JObject j_lights = root["lights"].GetObject(); if (j_lights.Count > 0) { light.Clear(); } int count = 0; foreach (var kvp in j_lights) { JObject j_light = kvp.Value.GetObject(); DLight d_light = new DLight(j_light); if (count < 4) { light.Add(d_light); count += 1; } } int cr, cg, cb; count = 0; JArray j_colors = root["colors"].GetArray(); if (j_colors.Count > 0) { color.Clear(); } foreach (JObject j_color in j_colors) { #if OVERLOAD_LEVEL_EDITOR cr = j_color["r"].GetInt(255); cg = j_color["g"].GetInt(255); cb = j_color["b"].GetInt(255); if (count < 4) { color.Add(Color.FromArgb(cr, cg, cb)); } count += 1; #else cr = j_color["r"].GetInt(255); cg = j_color["g"].GetInt(255); cb = j_color["b"].GetInt(255); color.Add(new Vector3((float)cr / 255.0f, (float)cg / 255.0f, (float)cb / 255.0f)); #endif } #if OVERLOAD_LEVEL_EDITOR for (int i = color.Count; i < NUM_COLORS; i++) { color.Add(Color.White); } #endif smooth_angle_same = root["smooth_same"].GetInt(smooth_angle_same); smooth_angle_diff = root["smooth_diff"].GetInt(smooth_angle_diff); }