/*! \cond PRIVATE */

        bool triangulate()
        {
            if (Lines.Count == 0)
            {
                Error = "Missing splines to triangulate";
                return(false);
            }

            if (VertexLineOnly)
            {
                return(true);
            }

            mTess = new Tess();

            for (int i = 0; i < Lines.Count; i++)
            {
                if (Lines[i].Spline == null)
                {
                    Error = "Missing Spline";
                    return(false);
                }
                if (!polyLineIsValid(Lines[i]))
                {
                    Error = Lines[i].Spline.name + ": Angle must be >0";
                    return(false);
                }
                Vector3[] verts = Lines[i].GetVertices();
                if (verts.Length < 3)
                {
                    Error = Lines[i].Spline.name + ": At least 3 Vertices needed!";
                    return(false);
                }
                mTess.AddContour(UnityLibTessUtility.ToContourVertex(verts, true), Lines[i].Orientation);
            }
            try
            {
                mTess.Tessellate(Winding, ElementType.Polygons, 3);
                return(true);
            }
            catch (System.Exception e)
            {
                Error = e.Message;
            }

            return(false);
        }
        bool buildMesh()
        {
            mMesh      = new Mesh();
            mMesh.name = MeshName;

            if (VertexLineOnly && Lines.Count > 0 && Lines[0] != null)
            {
                Vector3[] vts = Lines[0].GetVertices();
                for (int i = 0; i < vts.Length; i++)
                {
                    vts[i].z = 0;
                }
                mMesh.vertices = vts;
            }
            else
            {
                mMesh.vertices  = UnityLibTessUtility.FromContourVertex(mTess.Vertices);
                mMesh.triangles = mTess.Elements;
            }
            mMesh.RecalculateBounds();
            return(true);
        }
        /*! \endcond */
        #endregion

        #region ### Public Methods ###

        public override void Refresh()
        {
            base.Refresh();
            CGVolume vol   = InVolume.GetData <CGVolume>();
            var      holes = InVolumeHoles.GetAllData <CGVolume>();

            if (vol)
            {
                bool genStart = (StartCap == CGYesNoAuto.Yes || (StartCap == CGYesNoAuto.Auto && !vol.Seamless));
                bool genEnd   = (EndCap == CGYesNoAuto.Yes || (EndCap == CGYesNoAuto.Auto && !vol.Seamless));

                if (!genStart && !genEnd)
                {
                    OutVMesh.SetData(null);
                    return;
                }

                var       vmesh   = new CGVMesh();
                Vector3[] vtStart = new Vector3[0];
                Vector3[] vtEnd   = new Vector3[0];

                vmesh.AddSubMesh(new CGVSubMesh());
                CGVSubMesh submesh = vmesh.SubMeshes[0];

                if (genStart)
                {
                    #region --- Start Cap ---

                    var tess = new Tess();
                    tess.UsePooling = true;
                    tess.AddContour(make2DSegment(vol, 0));

                    for (int h = 0; h < holes.Count; h++)
                    {
                        if (holes[h].Count < 3)
                        {
                            OutVMesh.SetData(null);
                            UIMessages.Add("Hole Cross has <3 Vertices: Can't create Caps!");
                            return;
                        }
                        tess.AddContour(make2DSegment(holes[h], 0));
                    }
                    tess.Tessellate(WindingRule.EvenOdd, ElementType.Polygons, 3);
                    vtStart = UnityLibTessUtility.FromContourVertex(tess.Vertices);
                    Bounds b;
                    vmesh.Vertex      = applyMat(vtStart, getMat(vol, 0, true), out b);
                    submesh.Material  = StartMaterial;
                    submesh.Triangles = tess.Elements;
                    if (ReverseTriOrder)
                    {
                        flipTris(ref submesh.Triangles, 0, submesh.Triangles.Length);
                    }
                    if (GenerateUV)
                    {
                        vmesh.UV = new Vector2[vtStart.Length];
                        applyUV(vtStart, ref vmesh.UV, 0, vtStart.Length, StartMaterialSettings, b);
                    }
                    #endregion
                }

                if (genEnd)
                {
                    #region --- End Cap ---

                    var tess = new Tess();
                    tess.UsePooling = true;
                    tess.AddContour(make2DSegment(vol, 0));

                    for (int h = 0; h < holes.Count; h++)
                    {
                        if (holes[h].Count < 3)
                        {
                            OutVMesh.SetData(null);
                            UIMessages.Add("Hole Cross has <3 Vertices: Can't create Caps!");
                            return;
                        }
                        tess.AddContour(make2DSegment(holes[h], 0));
                    }
                    tess.Tessellate(WindingRule.EvenOdd, ElementType.Polygons, 3);
                    vtEnd = UnityLibTessUtility.FromContourVertex(tess.Vertices);
                    Bounds b;
                    int    l = vmesh.Vertex.Length;
                    vmesh.Vertex = vmesh.Vertex.AddRange <Vector3>(applyMat(vtEnd, getMat(vol, vol.Count - 1, true), out b));
                    int[] tris = tess.Elements;
                    if (!ReverseTriOrder)
                    {
                        flipTris(ref tris, 0, tris.Length);
                    }
                    for (int i = 0; i < tris.Length; i++)
                    {
                        tris[i] += l;
                    }
                    if (!CloneStartCap && StartMaterial != EndMaterial)
                    {
                        vmesh.AddSubMesh(new CGVSubMesh(tris, EndMaterial));
                    }
                    else
                    {
                        submesh.Material  = StartMaterial;
                        submesh.Triangles = submesh.Triangles.AddRange <int>(tris);
                    }

                    if (GenerateUV)
                    {
                        System.Array.Resize <Vector2>(ref vmesh.UV, vmesh.UV.Length + vtEnd.Length);
                        applyUV(vtEnd, ref vmesh.UV, vtStart.Length, vtEnd.Length, (CloneStartCap) ? StartMaterialSettings : EndMaterialSettings, b);
                    }


                    #endregion
                }


                OutVMesh.SetData(vmesh);
            }
        }