public static void CleanOrphanVertices(IList <Vector3> vertices, IList <Triangle3Indexed> triangles, out IList <Vector3> cleanVertices, out IList <Triangle3Indexed> cleanTriangles) { Vector3 minCoordinate = new Vector3(float.MaxValue); Vector3 maxCoordinate = new Vector3(float.MinValue); // First we build non-indexed triangles so we can re-index them after the cleanup IList <Triangle3> triangleList = new List <Triangle3>(); for (var i = 0; i < triangles.Count; i++) { Triangle3Indexed indexed = triangles[i]; if (!IsVertexValid(vertices[indexed.A]) || !IsVertexValid(vertices[indexed.B]) || !IsVertexValid(vertices[indexed.C])) { // This triangle has invalid vertices, ignore Logger.Warn("- Triangle Vertex out of safe range, skipping!"); continue; } Triangle3 nonIndexed = new Triangle3(vertices[indexed.A], vertices[indexed.B], vertices[indexed.C]); triangleList.Add(nonIndexed); BuildMinCoordinate(ref minCoordinate, nonIndexed.A); BuildMinCoordinate(ref minCoordinate, nonIndexed.B); BuildMinCoordinate(ref minCoordinate, nonIndexed.C); BuildMaxCoordinate(ref maxCoordinate, nonIndexed.A); BuildMaxCoordinate(ref maxCoordinate, nonIndexed.B); BuildMaxCoordinate(ref maxCoordinate, nonIndexed.C); } cleanVertices = new List <Vector3>(); cleanTriangles = new List <Triangle3Indexed>(); //float size = Math.Abs((maxCoordinate - minCoordinate).Length()); Octree <MeshSpatialInfo> cleanTree = new Octree <MeshSpatialInfo>(1, minCoordinate, 1); for (var i = 0; i < triangleList.Count; i++) { Triangle3 triangle = triangleList[i]; uint indexA; uint indexB; uint indexC; if (!IndexOfVertex(cleanTree, triangle.A, out indexA)) { indexA = AddNewVertex(cleanVertices, triangle.A, cleanTree); } if (!IndexOfVertex(cleanTree, triangle.B, out indexB)) { indexB = AddNewVertex(cleanVertices, triangle.B, cleanTree); } if (!IndexOfVertex(cleanTree, triangle.C, out indexC)) { indexC = AddNewVertex(cleanVertices, triangle.C, cleanTree); } cleanTriangles.Add(new Triangle3Indexed(indexA, indexB, indexC)); } if (cleanVertices.Count != vertices.Count) { Logger.Info("- {0} orphan vertices", vertices.Count - cleanVertices.Count); } }
// ------------------------------------------------------------------- // Private // ------------------------------------------------------------------- private void DoJoin(IList <Vector3> vertices, IList <Vector3> normals, IDictionary <uint, uint[]> normalMapping, IList <Triangle3Indexed> triangles, Vector3 offset) { bool[] vertexInvalidMap = new bool[vertices.Count]; uint[] indexMap = new uint[vertices.Count]; uint[] normalMap = new uint[normals.Count]; Logger.Info("- {0} vertices", vertices.Count); bool check = this.Vertices.Count > 0; int skipped = 0; for (var i = 0; i < vertices.Count; i++) { Vector3 finalVertex = vertices[i] + offset; if (finalVertex.Length() > MathUtils.MaxFloat) { // Create a zero vertex, we will skip the triangles anyway indexMap[i] = MeshUtils.AddNewVertex(this.Vertices, new Vector3(0), this.mergeTree); vertexInvalidMap[i] = false; Logger.Warn("- Vertex out of Safe Range: " + finalVertex); skipped++; continue; } if (!check) { indexMap[i] = MeshUtils.AddNewVertex(this.Vertices, finalVertex, this.mergeTree); continue; } uint index; if (MeshUtils.IndexOfVertex(this.mergeTree, finalVertex, out index)) { indexMap[i] = index; skipped++; continue; } indexMap[i] = MeshUtils.AddNewVertex(this.Vertices, finalVertex, this.mergeTree); } if (skipped > 0) { Logger.Info(" {0} duplicates", skipped); } Logger.Info("- {0} normals", normals.Count); bool checkNormals = this.Normals.Count > 0; skipped = 0; for (var i = 0; i < normals.Count; i++) { var normal = normals[i]; if (!checkNormals) { normalMap[i] = MeshUtils.AddNewNormal(this.Normals, normal, this.mergeTree); continue; } uint index; if (MeshUtils.IndexOfNormal(this.mergeTree, normal, out index)) { normalMap[i] = index; skipped++; continue; } normalMap[i] = MeshUtils.AddNewNormal(this.Normals, normal, this.mergeTree); } if (skipped > 0) { Logger.Info(" {0} duplicates", skipped); } Logger.Info("- {0} triangles", triangles.Count); for (var i = 0; i < triangles.Count; i++) { Triangle3Indexed triangle = triangles[i]; if (vertexInvalidMap[triangle.A] || vertexInvalidMap[triangle.B] || vertexInvalidMap[triangle.C]) { Logger.Warn("Triangle had invalid index mapping, possibly skipped vertices, skipping triangle"); continue; } if (check) { // Re-index the triangle this.Triangles.Add(new Triangle3Indexed(indexMap[triangle.A], indexMap[triangle.B], indexMap[triangle.C])); } else { this.Triangles.Add(triangle); } // Remap the normals for this triangle and if (normalMapping.Count > 0) { uint[] map = new uint[3]; for (var n = 0; n < 3; n++) { uint normalIndex = normalMapping[(uint)i][n]; map[n] = normalMap[normalIndex]; } this.NormalMapping.Add((uint)this.Triangles.Count - 1, map); } } this.RecalculateBounds(); }