public override void AddFaceConnection(int faceIndex, TriangleIndex neighbors) { var face = Mesh.Faces[faceIndex]; var f0 = (neighbors.i0 != -1) ? Mesh.Faces[neighbors.i0] : null; var f1 = (neighbors.i1 != -1) ? Mesh.Faces[neighbors.i1] : null; var f2 = (neighbors.i2 != -1) ? Mesh.Faces[neighbors.i2] : null; foreach (var edge in face.Edge.EnumerateEdges()) { if (SetOppositeEdge(edge, f0)) { break; } } foreach (var edge in face.Edge.EnumerateEdges()) { if (SetOppositeEdge(edge, f1)) { break; } } foreach (var edge in face.Edge.EnumerateEdges()) { if (SetOppositeEdge(edge, f2)) { break; } } }
public override void AddFace(TriangleIndex triangle) { var v0 = Mesh.Vertices[triangle.i0]; var v1 = Mesh.Vertices[triangle.i1]; var v2 = Mesh.Vertices[triangle.i2]; var e0 = new EDGE(); var e1 = new EDGE(); var e2 = new EDGE(); v0.Edge = e0; v1.Edge = e1; v2.Edge = e2; var face = new FACE(); face.Edge = e0; e0.Set(v0, face, e2, e1, null); e1.Set(v1, face, e0, e2, null); e2.Set(v2, face, e1, e0, null); Mesh.Faces.Add(face); Mesh.Edges.Add(e0); Mesh.Edges.Add(e1); Mesh.Edges.Add(e2); }
public override void AddFace(TriangleIndex triangle) { m_mesh.Indices[m_faceIndex * 3 + 0] = triangle.i0; m_mesh.Indices[m_faceIndex * 3 + 1] = triangle.i1; m_mesh.Indices[m_faceIndex * 3 + 2] = triangle.i2; m_faceIndex++; }
public void AddingOneTriangleOutsideBounderiesAddsNoVerticesAndNoIndices() { TriangleIndex ti; ti = new TriangleIndex(-1000f, -1000f, 1000f, 1000f); ti.AddTriangle(CreateTriangleOutsideBoundaries()); Assert.AreEqual <int>(0, ti.GetIndices().Length); Assert.AreEqual <int>(0, ti.GetVerticesPositionColor().Length); }
public void AddingOneTriangleWithDuplicateVerticesAddsOneVerticeAndThreeIndices() { TriangleIndex ti; ti = new TriangleIndex(-1000f, -1000f, 1000f, 1000f); ti.AddTriangle(CreateTriangleWithDuplicateVertices()); Assert.AreEqual <int>(3, ti.GetIndices().Length); Assert.AreEqual <int>(1, ti.GetVerticesPositionColor().Length); }
public void AddingTwoDifferentTrianglesAddsSixVerticesAndSixIndices() { TriangleIndex ti; ti = new TriangleIndex(-1000f, -1000f, 1000f, 1000f); ti.AddTriangle(CreateTriangle()); ti.AddTriangle(CreateOtherTriangle()); Assert.AreEqual <int>(6, ti.GetIndices().Length); Assert.AreEqual <int>(6, ti.GetVerticesPositionColor().Length); }
public override void AddFaceConnection(int faceIndex, TriangleIndex triangle) { var face = Mesh.Faces[faceIndex]; var f0 = (triangle.i0 != -1) ? Mesh.Faces[triangle.i0] : null; var f1 = (triangle.i1 != -1) ? Mesh.Faces[triangle.i1] : null; var f2 = (triangle.i2 != -1) ? Mesh.Faces[triangle.i2] : null; face.Neighbors[0] = f0; face.Neighbors[1] = f1; face.Neighbors[2] = f2; }
public void AddingTwoTrianglesWithSameVerticesInDifferentOrderAddsThreeVerticesAndThreeIndices() { TriangleIndex ti; ti = new TriangleIndex(-1000f, -1000f, 1000f, 1000f); Triangle t = CreateTriangle(); ti.AddTriangle(t); ti.AddTriangle(new Triangle(t.GetP2(), t.GetP3(), t.GetP1())); Assert.AreEqual <int>(3, ti.GetIndices().Length); Assert.AreEqual <int>(3, ti.GetVerticesPositionColor().Length); }
public override void AddFace(TriangleIndex triangle) { var v0 = Mesh.Vertices[triangle.i0]; var v1 = Mesh.Vertices[triangle.i1]; var v2 = Mesh.Vertices[triangle.i2]; FACE face = new FACE(); face.SetSize(3); v0.Face = face; v1.Face = face; v2.Face = face; face.Vertices[0] = v0; face.Vertices[1] = v1; face.Vertices[2] = v2; Mesh.Faces.Add(face); }
private static void CreateMesh <MESH>(IMeshConstructor <MESH> constructor, MeshDescriptor des) { constructor.PushTriangleMesh(des.Vertices, des.Faces); for (int i = 0; i < des.Vertices; i++) { constructor.AddVertex(CGAL_GetPoint2f(i)); } for (int i = 0; i < des.Faces; i++) { TriangleIndex triangle = CGAL_GetTriangle(i); constructor.AddFace(triangle); } for (int i = 0; i < des.Faces; i++) { TriangleIndex triangle = CGAL_GetNeighbor(i); constructor.AddFaceConnection(i, triangle); } }
private static void CreateMesh <MESH>(IMeshConstructor <MESH> constructor, MeshDescriptor des) { constructor.PushTriangleMesh(des.Vertices, des.Faces); for (int i = 0; i < des.Vertices; i++) { constructor.AddVertex(CGAL_GetPoint2f(i)); } for (int i = 0; i < des.Faces; i++) { TriangleIndex triangle = CGAL_GetTriangle(i); Vector2f a = CGAL_GetPoint2f(triangle.i0); Vector2f b = CGAL_GetPoint2f(triangle.i1); Vector2f c = CGAL_GetPoint2f(triangle.i2); Vector2f p = (a + b + c) / 3.0f; if (PolygonIntersection2.ContainsPoint(p)) { constructor.AddFace(triangle); } } }
public TerrainRenderer(int id, IEnumerable<FileInfo> files, ZoneType type, ClientDataWrapper wrapper) : base(id, files, type, wrapper) { // Init Terrain Height Calculator TerrainHeightCache = TerrainHeightCalculator; AddNifCache(TerrainNifs); AddNifInstancesYZSwapped(TerrainFixtures); // Store Terrain var terrain = TerrainHeightMap; var vertices = new List<Vector3>(); var indices = new List<TriangleIndex>(); for (int x = 0 ; x < terrain.Length ; x++) { var yLength = terrain[x].Length; for (int y = 0 ; y < yLength ; y++) { var height = terrain[x][y]; vertices.Add(new Vector3(x, height, y)); } } var width = terrain.Length; for (int x = 0 ; x < terrain.Length - 1 ; x++) { var yLength = terrain[x].Length; for (int y = 0 ; y < yLength - 1 ; y++) { var tri1 = new TriangleIndex { A = (uint)((x + 1) * width + (y + 1)), B = (uint)((x + 1) * width + y), C = (uint)(x * width + y), }; var tri2 = new TriangleIndex { A = (uint)((x + 1) * width + (y + 1)), B = (uint)(x * width + y), C = (uint)(x * width + (y + 1)), }; indices.Add(tri1); indices.Add(tri2); } } // Build Terrain object as a Primitive Nif var Terrain = new TriangleCollection { Vertices = vertices.ToArray(), Indices = indices.ToArray(), }; // Add Terrain like a Nif var insertid = 0; if (NifCache.Count > 0) insertid = NifCache.Max(kv => kv.Key) + 1; NifCache.Add(insertid, new ClientMesh("terrain", Terrain, Terrain, Terrain)); InstancesMatrix = InstancesMatrix.Concat(new [] { new KeyValuePair<int, Matrix>(insertid, Matrix.Identity) }).ToArray(); }
public TerrainRenderer(int id, IEnumerable <FileInfo> files, ZoneType type, ClientDataWrapper wrapper) : base(id, files, type, wrapper) { // Init Terrain Height Calculator TerrainHeightCache = TerrainHeightCalculator; AddNifCache(TerrainNifs); AddNifInstancesYZSwapped(TerrainFixtures); // Store Terrain var terrain = TerrainHeightMap; var vertices = new List <Vector3>(); var indices = new List <TriangleIndex>(); for (int x = 0; x < terrain.Length; x++) { var yLength = terrain[x].Length; for (int y = 0; y < yLength; y++) { var height = terrain[x][y]; vertices.Add(new Vector3(x, height, y)); } } var width = terrain.Length; for (int x = 0; x < terrain.Length - 1; x++) { var yLength = terrain[x].Length; for (int y = 0; y < yLength - 1; y++) { var tri1 = new TriangleIndex { A = (uint)((x + 1) * width + (y + 1)), B = (uint)((x + 1) * width + y), C = (uint)(x * width + y), }; var tri2 = new TriangleIndex { A = (uint)((x + 1) * width + (y + 1)), B = (uint)(x * width + y), C = (uint)(x * width + (y + 1)), }; indices.Add(tri1); indices.Add(tri2); } } // Build Terrain object as a Primitive Nif var Terrain = new TriangleCollection { Vertices = vertices.ToArray(), Indices = indices.ToArray(), }; // Add Terrain like a Nif var insertid = 0; if (NifCache.Count > 0) { insertid = NifCache.Max(kv => kv.Key) + 1; } NifCache.Add(insertid, new ClientMesh("terrain", Terrain, Terrain, Terrain)); InstancesMatrix = InstancesMatrix.Concat(new [] { new KeyValuePair <int, Matrix>(insertid, Matrix.Identity) }).ToArray(); }
public virtual void AddFaceConnection(int faceIndex, TriangleIndex neighbors) { }
public virtual void AddFace(TriangleIndex triangle) { }
public void AddTrianglesIndex(int triangleIndexes) { TriangleIndex.Add(triangleIndexes); }
public static void SetupMesh(OutlineParameters parameters, float baseShift) { if (parameters.BlitMesh == null) { parameters.BlitMesh = parameters.MeshPool.AllocateMesh(); } const int numberOfVertices = 8; var currentIndex = 0; var triangleIndex = 0; var expectedCount = 0; foreach (var outlinable in parameters.OutlinablesToRender) { if (outlinable.DrawingMode != OutlinableDrawingMode.Normal) { continue; } foreach (var target in outlinable.OutlineTargets) { var renderer = target.Renderer; if (!target.ReadyToRender) { continue; } expectedCount += numberOfVertices; } } if (vertices.Length < expectedCount) { Array.Resize(ref vertices, expectedCount * 2); Array.Resize(ref indecies, vertices.Length * 3); } foreach (var outlinable in parameters.OutlinablesToRender) { if (outlinable.DrawingMode != OutlinableDrawingMode.Normal) { continue; } var frontParameters = outlinable.RenderStyle == RenderStyle.FrontBack ? outlinable.FrontParameters : outlinable.OutlineParameters; var backParameters = outlinable.RenderStyle == RenderStyle.FrontBack ? outlinable.BackParameters : outlinable.OutlineParameters; var useDilateDueToSettings = parameters.UseInfoBuffer && (frontParameters.DilateShift > 0.01f || backParameters.DilateShift > 0.01f) || !parameters.UseInfoBuffer; var useBlurDueToSettings = parameters.UseInfoBuffer && (frontParameters.BlurShift > 0.01f || backParameters.BlurShift > 0.01f) || !parameters.UseInfoBuffer; foreach (var target in outlinable.OutlineTargets) { var renderer = target.Renderer; if (!target.ReadyToRender) { continue; } var pretransformedBounds = false; var bounds = new Bounds(); if (target.BoundsMode == BoundsMode.Manual) { bounds = target.Bounds; var size = bounds.size; var rendererScale = renderer.transform.localScale; size.x /= rendererScale.x; size.y /= rendererScale.y; size.z /= rendererScale.z; bounds.size = size; } else { if (target.BoundsMode == BoundsMode.ForceRecalculate) { UpdateBounds(target.Renderer, target); } var meshRenderer = renderer as MeshRenderer; var index = target.RendererType != RendererType.MeshRenderer || !target.RendererIsNotNull ? 0 : meshRenderer.subMeshStartIndex + target.SubmeshIndex; var filter = target.RendererType != RendererType.MeshRenderer || !target.RendererIsNotNull ? null : meshRenderer.GetComponent <MeshFilter>(); var mesh = filter == null ? null : filter.sharedMesh; if (mesh != null && mesh.subMeshCount > index) { bounds = mesh.GetSubMesh(index).bounds; } else if (target.RendererIsNotNull) { pretransformedBounds = true; bounds = renderer.bounds; } } var scale = 0.5f; Vector4 boundsSize = bounds.size * scale; boundsSize.w = 1; var boundsCenter = (Vector4)bounds.center; var additionalScaleToSet = Vector2.zero; if (target.CanUseEdgeDilateShift && target.DilateRenderingMode == DilateRenderMode.EdgeShift) { additionalScaleToSet.x = Mathf.Max(target.BackEdgeDilateAmount, target.FrontEdgeDilateAmount); } Matrix4x4 transformMatrix = Matrix4x4.identity; Matrix4x4 normalTransformMatrix = Matrix4x4.identity; if (!pretransformedBounds && (target.BoundsMode == BoundsMode.Manual || target.RendererIsNotNull && !renderer.isPartOfStaticBatch)) { transformMatrix = target.renderer.transform.localToWorldMatrix; normalTransformMatrix = Matrix4x4.Rotate(renderer.transform.rotation); } indecies[triangleIndex++] = new TriangleIndex() { Index = (ushort)currentIndex }; indecies[triangleIndex++] = new TriangleIndex() { Index = (ushort)(currentIndex + 2) }; indecies[triangleIndex++] = new TriangleIndex() { Index = (ushort)(currentIndex + 1) }; indecies[triangleIndex++] = new TriangleIndex() { Index = (ushort)currentIndex }; indecies[triangleIndex++] = new TriangleIndex() { Index = (ushort)(currentIndex + 3) }; indecies[triangleIndex++] = new TriangleIndex() { Index = (ushort)(currentIndex + 2) }; indecies[triangleIndex++] = new TriangleIndex() { Index = (ushort)(currentIndex + 2) }; indecies[triangleIndex++] = new TriangleIndex() { Index = (ushort)(currentIndex + 3) }; indecies[triangleIndex++] = new TriangleIndex() { Index = (ushort)(currentIndex + 4) }; indecies[triangleIndex++] = new TriangleIndex() { Index = (ushort)(currentIndex + 2) }; indecies[triangleIndex++] = new TriangleIndex() { Index = (ushort)(currentIndex + 4) }; indecies[triangleIndex++] = new TriangleIndex() { Index = (ushort)(currentIndex + 5) }; indecies[triangleIndex++] = new TriangleIndex() { Index = (ushort)(currentIndex + 1) }; indecies[triangleIndex++] = new TriangleIndex() { Index = (ushort)(currentIndex + 2) }; indecies[triangleIndex++] = new TriangleIndex() { Index = (ushort)(currentIndex + 5) }; indecies[triangleIndex++] = new TriangleIndex() { Index = (ushort)(currentIndex + 1) }; indecies[triangleIndex++] = new TriangleIndex() { Index = (ushort)(currentIndex + 5) }; indecies[triangleIndex++] = new TriangleIndex() { Index = (ushort)(currentIndex + 6) }; indecies[triangleIndex++] = new TriangleIndex() { Index = (ushort)currentIndex }; indecies[triangleIndex++] = new TriangleIndex() { Index = (ushort)(currentIndex + 7) }; indecies[triangleIndex++] = new TriangleIndex() { Index = (ushort)(currentIndex + 4) }; indecies[triangleIndex++] = new TriangleIndex() { Index = (ushort)currentIndex }; indecies[triangleIndex++] = new TriangleIndex() { Index = (ushort)(currentIndex + 4) }; indecies[triangleIndex++] = new TriangleIndex() { Index = (ushort)(currentIndex + 3) }; indecies[triangleIndex++] = new TriangleIndex() { Index = (ushort)(currentIndex + 5) }; indecies[triangleIndex++] = new TriangleIndex() { Index = (ushort)(currentIndex + 4) }; indecies[triangleIndex++] = new TriangleIndex() { Index = (ushort)(currentIndex + 7) }; indecies[triangleIndex++] = new TriangleIndex() { Index = (ushort)(currentIndex + 5) }; indecies[triangleIndex++] = new TriangleIndex() { Index = (ushort)(currentIndex + 7) }; indecies[triangleIndex++] = new TriangleIndex() { Index = (ushort)(currentIndex + 6) }; indecies[triangleIndex++] = new TriangleIndex() { Index = (ushort)currentIndex }; indecies[triangleIndex++] = new TriangleIndex() { Index = (ushort)(currentIndex + 6) }; indecies[triangleIndex++] = new TriangleIndex() { Index = (ushort)(currentIndex + 7) }; indecies[triangleIndex++] = new TriangleIndex() { Index = (ushort)currentIndex }; indecies[triangleIndex++] = new TriangleIndex() { Index = (ushort)(currentIndex + 1) }; indecies[triangleIndex++] = new TriangleIndex() { Index = (ushort)(currentIndex + 6) }; for (var index = 0; index < numberOfVertices; index++) { var normal = normalTransformMatrix * normals[index]; var normal3 = new Vector3(normal.x, normal.y, normal.z); var vert = tempVertecies[index]; var scaledVert = new Vector4(vert.x * boundsSize.x, vert.y * boundsSize.y, vert.z * boundsSize.z, 1); vertices[currentIndex++] = new Vertex() { Position = transformMatrix * (boundsCenter + scaledVert), Normal = normal3, AdditionalSize = additionalScaleToSet }; } } } var flags = MeshUpdateFlags.DontNotifyMeshUsers | MeshUpdateFlags.DontRecalculateBounds | MeshUpdateFlags.DontResetBoneBounds | MeshUpdateFlags.DontValidateIndices; parameters.BlitMesh.SetVertexBufferParams(currentIndex, attributes: vertexParams); parameters.BlitMesh.SetVertexBufferData(vertices, 0, 0, currentIndex, 0, flags); parameters.BlitMesh.SetIndexBufferParams(triangleIndex, IndexFormat.UInt16); parameters.BlitMesh.SetIndexBufferData(indecies, 0, 0, triangleIndex, flags); parameters.BlitMesh.subMeshCount = 1; parameters.BlitMesh.SetSubMesh(0, new SubMeshDescriptor(0, triangleIndex, MeshTopology.Triangles), flags); }
private static float SplitAtEdge(out int[] triangles, TrianglePathCache cache, int[] vertexIndices, int vertexIndicesLength, float3[] vertices, float4[] planes) { if (vertexIndicesLength == 3) { var vi0 = vertexIndices[0]; var vi1 = vertexIndices[1]; var vi2 = vertexIndices[2]; if (vi0 < 0 || vi0 >= vertices.Length || vi1 < 0 || vi1 >= vertices.Length || vi2 < 0 || vi2 >= vertices.Length) { triangles = null; return(float.PositiveInfinity); } var triangleIndex = TriangleIndex.Create(vi0, vi1, vi2); Triangle triangle; if (!cache.TriangleIndices.TryGetValue(triangleIndex, out int index)) { triangle = new Triangle { vertexIndices = new[] { vi0, vi1, vi2 }, localPlane = new Plane(vertices[vi0], vertices[vi1], vertices[vi2]) }; index = cache.AllTriangles.Count; cache.TriangleIndices[triangleIndex] = index; cache.AllTriangles.Add(triangle); } //else //triangle = cache.AllTriangles[index]; triangles = new [] { index }; return(GetTriangleHeuristic(cache, planes, vertices, vi0, vi1, vi2)); } TriangulationPath curLeftPath = null; TriangulationPath curRightPath = null; float curHeuristic = float.PositiveInfinity; int[] tempEdges = null; for (var startPoint = 0; startPoint < vertexIndicesLength - 2; startPoint++) { for (var offset = 2; offset < vertexIndicesLength - 1; offset++) { var endPoint = (startPoint + offset) % vertexIndicesLength; int t0, t1; if (endPoint < startPoint) { t0 = endPoint; t1 = startPoint; } else { t0 = startPoint; t1 = endPoint; } var vertexIndex0 = vertexIndices[t0]; var vertexIndex1 = vertexIndices[t1]; var leftPath = cache.Path; var startIndex = -1; // try to find the triangulation in the cache for (var i = t0; i <= t1; i++) { if (leftPath.subPaths == null) { startIndex = i; break; } var index = vertexIndices[i]; var found = false; for (var j = 0; j < leftPath.subPaths.Length; j++) { if (leftPath.subPaths[j].vertexIndex != index) { continue; } found = true; leftPath = leftPath.subPaths[j]; break; } if (found) { continue; } startIndex = i; break; } float leftHeuristic; #region Left Path int[] leftTriangles; if (startIndex != -1 || leftPath.triangles == null) { var length0 = (t1 - t0) + 1; if (tempEdges == null || tempEdges.Length < length0) { tempEdges = new int[length0]; } Array.Copy(vertexIndices, t0, tempEdges, 0, (t1 - t0) + 1); // triangulate for the given vertices leftHeuristic = SplitAtEdge(out leftTriangles, cache, tempEdges, length0, vertices, planes); // store the found triangulation in the cache if (startIndex != -1) { for (var i = startIndex; i <= t1; i++) { var newSubPath = new TriangulationPath { vertexIndex = vertexIndices[i] }; // FIXME: shouldn't this be tempEdges? if (leftPath.subPaths == null) { leftPath.subPaths = new[] { newSubPath }; } else { System.Array.Resize(ref leftPath.subPaths, leftPath.subPaths.Length + 1); leftPath.subPaths[leftPath.subPaths.Length - 1] = newSubPath; } leftPath = newSubPath; } } leftPath.triangles = leftTriangles; leftPath.heuristic = leftHeuristic; } else { leftHeuristic = leftPath.heuristic; leftTriangles = leftPath.triangles; } #endregion var newHeuristic = leftHeuristic; if (newHeuristic >= curHeuristic + kEqualityEpsilon) { continue; } var offsetB = (vertexIndicesLength - t1); var length1 = (t0 + 1) + offsetB; if (tempEdges == null || tempEdges.Length < length1) { tempEdges = new int[length1]; } Array.Copy(vertexIndices, t1, tempEdges, 0, offsetB); Array.Copy(vertexIndices, 0, tempEdges, offsetB, (t0 + 1)); var rightPath = cache.Path; startIndex = -1; // try to find the triangulation in the cache for (int i = 0; i < length1; i++) { if (rightPath.subPaths == null) { startIndex = i; break; } var index = tempEdges[i]; bool found = false; for (int j = 0; j < rightPath.subPaths.Length; j++) { if (rightPath.subPaths[j].vertexIndex == index) { found = true; rightPath = rightPath.subPaths[j]; break; } } if (!found) { startIndex = i; break; } } float rightHeuristic; #region Right Path int[] rightTriangles; if (startIndex != -1 || rightPath.triangles == null) { // triangulate for the given vertices rightHeuristic = SplitAtEdge(out rightTriangles, cache, tempEdges, length1, vertices, planes); // store the found triangulation in the cache if (startIndex != -1) { for (var i = startIndex; i < tempEdges.Length; i++) { var newSubPath = new TriangulationPath { vertexIndex = tempEdges[i] }; if (rightPath.subPaths == null) { rightPath.subPaths = new[] { newSubPath }; } else { System.Array.Resize(ref rightPath.subPaths, rightPath.subPaths.Length + 1); rightPath.subPaths[rightPath.subPaths.Length - 1] = newSubPath; } rightPath = newSubPath; } } rightPath.triangles = rightTriangles; rightPath.heuristic = rightHeuristic; } else { rightHeuristic = rightPath.heuristic; rightTriangles = rightPath.triangles; } #endregion newHeuristic += rightHeuristic; if (newHeuristic >= curHeuristic + kEqualityEpsilon) { continue; } var leftTriangle = FindTriangleWithEdge(leftTriangles, cache, vertexIndex0, vertexIndex1); var rightTriangle = FindTriangleWithEdge(rightTriangles, cache, vertexIndex0, vertexIndex1); if (leftTriangle == null || rightTriangle == null) { continue; } var leftPlane = leftTriangle.localPlane; var rightPlane = rightTriangle.localPlane; var error = Vector3.Dot(leftPlane.normal, rightPlane.normal) - 1; newHeuristic += (error * error); if (!(newHeuristic < curHeuristic - kEqualityEpsilon)) { continue; } curLeftPath = leftPath; curRightPath = rightPath; curHeuristic = newHeuristic; } } if (curLeftPath != null && curRightPath != null) { triangles = new int[curLeftPath.triangles.Length + curRightPath.triangles.Length]; Array.Copy(curLeftPath.triangles, triangles, curLeftPath.triangles.Length); Array.Copy(curRightPath.triangles, 0, triangles, curLeftPath.triangles.Length, curRightPath.triangles.Length); } else { curHeuristic = float.PositiveInfinity; triangles = null; } return(curHeuristic); }