예제 #1
0
        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;
                }
            }
        }
예제 #2
0
        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);
        }
예제 #3
0
 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);
        }
예제 #7
0
        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);
        }
예제 #9
0
        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);
        }
예제 #10
0
        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);
            }
        }
예제 #11
0
        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);
                }
            }
        }
예제 #12
0
        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();
        }
예제 #13
0
        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();
        }
예제 #14
0
 public virtual void AddFaceConnection(int faceIndex, TriangleIndex neighbors)
 {
 }
예제 #15
0
 public virtual void AddFace(TriangleIndex triangle)
 {
 }
예제 #16
0
 public void AddTrianglesIndex(int triangleIndexes)
 {
     TriangleIndex.Add(triangleIndexes);
 }
예제 #17
0
        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);
        }
예제 #18
0
        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);
        }