Exemplo n.º 1
0
        // From https://github.com/speps/LibTessDotNet/issues/1
        public void Tesselate_WithNoEmptyPolygonsTrue_RemovesEmptyPolygons()
        {
            string data            = "2,0,4\n2,0,2\n4,0,2\n4,0,0\n0,0,0\n0,0,4";
            var    indices         = new List <int>();
            var    expectedIndices = new int[] { 0, 1, 2, 2, 3, 4, 3, 1, 5 };

            using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(data)))
            {
                var pset = DataLoader.LoadDat(stream);
                var tess = new Tess();
                PolyConvert.ToTess(pset, tess);
                tess.NoEmptyPolygons = true;
                tess.Tessellate(WindingRule.EvenOdd, ElementType.Polygons, 3);
                indices.Clear();
                for (int i = 0; i < tess.ElementCount; i++)
                {
                    for (int j = 0; j < 3; j++)
                    {
                        int index = tess.Elements[i * 3 + j];
                        indices.Add(index);
                    }
                }
                Assert.AreEqual(expectedIndices, indices.ToArray());
            }
        }
Exemplo n.º 2
0
        private static void AddToMesh(this Csg.Polygon p, ref Mesh mesh)
        {
            // Polygons coming back from Csg can have an arbitrary number
            // of vertices. We need to retessellate the returned polygon.
            var tess = new Tess();

            tess.NoEmptyPolygons = true;

            tess.AddContour(p.Vertices.ToContourVertices());

            tess.Tessellate(WindingRule.Positive, LibTessDotNet.Double.ElementType.Polygons, 3);
            for (var i = 0; i < tess.ElementCount; i++)
            {
                var a = tess.Vertices[tess.Elements[i * 3]].Position.ToVector3();
                var b = tess.Vertices[tess.Elements[i * 3 + 1]].Position.ToVector3();
                var c = tess.Vertices[tess.Elements[i * 3 + 2]].Position.ToVector3();

                var uva = (Csg.Vector2D)tess.Vertices[tess.Elements[i * 3]].Data;
                var uvb = (Csg.Vector2D)tess.Vertices[tess.Elements[i * 3 + 1]].Data;
                var uvc = (Csg.Vector2D)tess.Vertices[tess.Elements[i * 3 + 2]].Data;

                var v1 = mesh.AddVertex(a, uva.ToUV());
                var v2 = mesh.AddVertex(b, uvb.ToUV());
                var v3 = mesh.AddVertex(c, uvc.ToUV());
                mesh.AddTriangle(v1, v2, v3);
            }
        }
Exemplo n.º 3
0
        public void Tesselate_WithSingleTriangle_ProducesSameTriangle()
        {
            string data            = "0,0,0\n0,1,0\n1,1,0";
            var    indices         = new List <int>();
            var    expectedIndices = new int[] { 0, 1, 2 };

            using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(data)))
            {
                var pset = DataLoader.LoadDat(stream);
                var tess = new Tess();

                PolyConvert.ToTess(pset, tess);
                tess.Tessellate(WindingRule.EvenOdd, ElementType.Polygons, 3);

                indices.Clear();
                for (int i = 0; i < tess.ElementCount; i++)
                {
                    for (int j = 0; j < 3; j++)
                    {
                        int index = tess.Elements[i * 3 + j];
                        indices.Add(index);
                    }
                }

                Assert.AreEqual(expectedIndices, indices.ToArray());
            }
        }
Exemplo n.º 4
0
        public static void GenerateTestData()
        {
            foreach (var name in _loader.AssetNames)
            {
                var pset = _loader.GetAsset(name).Polygons;

                var lines   = new List <string>();
                var indices = new List <int>();

                foreach (WindingRule winding in Enum.GetValues(typeof(WindingRule)))
                {
                    var tess = new Tess();
                    PolyConvert.ToTess(pset, tess);
                    tess.Tessellate(winding, ElementType.Polygons, 3);

                    lines.Add(string.Format("{0} {1}", winding, 3));
                    for (int i = 0; i < tess.ElementCount; i++)
                    {
                        indices.Clear();
                        for (int j = 0; j < 3; j++)
                        {
                            int index = tess.Elements[i * 3 + j];
                            indices.Add(index);
                        }
                        lines.Add(string.Join(" ", indices));
                    }
                    lines.Add("");
                }

                File.WriteAllLines(Path.Combine(TestDataPath, name + ".testdat"), lines);
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Tessellates a polygon with libtess.
        /// </summary>
        /// <param name="contour"></param>
        /// <returns></returns>
        public static (List <Vector3> Vertices, List <Vector3> Triangles) TessellatePolygon(List <Vector3> contour)
        {
            var tess        = new Tess();
            var tessContour = contour.Select(v => new ContourVertex()
            {
                Position = new Vec3()
                {
                    X = v.X, Y = v.Z
                }
            }).ToArray();

            tess.AddContour(tessContour, ContourOrientation.CounterClockwise);
            tess.Tessellate(WindingRule.EvenOdd, ElementType.Polygons, 3);

            // convert verts to Vector3
            var verts = new List <Vector3>();

            foreach (var vert in tess.Vertices)
            {
                verts.Add(new Vector3(
                              vert.Position.X, 0, vert.Position.Y));
            }

            // convert triangles to Vector3
            var tris     = new List <Vector3>();
            var tessTris = tess.Elements;

            for (int i = 0; i < tess.ElementCount * 3; i += 3)
            {
                tris.Add(new Vector3(
                             tessTris[i], tessTris[i + 1], tessTris[i + 2]));
            }

            return(verts, tris);
        }
        public static void Triangulate(Vector2[][] paths, float edgeSmoothing, bool nonzero, out Vector2[] vertices, out ushort[] triangles)
        {
            Tess tess = new Tess();

            foreach (Vector2[] path in paths)
            {
                List <ContourVertex> contour = new List <ContourVertex>();

                for (var i = 0; i < path.Length; i++)
                {
                    Vector2 oldPos     = path[(path.Length + i - 1) % path.Length];
                    Vector2 currentPos = path[i];
                    Vector2 nextPos    = path[(i + 1) % path.Length];

                    //edge smoothing
                    if (Vector2.Dot((currentPos - oldPos).normalized, (nextPos - oldPos).normalized) >= 0.99f + Mathf.Pow(edgeSmoothing, 3) * 0.01)
                    {
                        continue;
                    }

                    contour.Add(new ContourVertex(new Vec3(currentPos.x, currentPos.y, 0)));
                }

                tess.AddContour(contour, ContourOrientation.CounterClockwise);
            }

            WindingRule windingRule = nonzero ? WindingRule.NonZero : WindingRule.EvenOdd;

            tess.Tessellate(windingRule);
            vertices  = (tess.Vertices ?? Array.Empty <ContourVertex>()).Select(v => new Vector2(v.Position.X, v.Position.Y)).ToArray();
            triangles = (tess.Elements ?? Array.Empty <int>()).Select(t => (ushort)t).ToArray();
        }
Exemplo n.º 7
0
 private void Reset()
 {
     tesselationAlgorithm = new Tess();
     triangleMapping.Clear();
     AllTriangle.Clear();
     searchCache.Clear();
 }
Exemplo n.º 8
0
        protected virtual int[] GetTriangleIndices()
        {
            if (tess == null)
            {
                tess = new Tess();
            }

            var contour = new ContourVertex[Vertices.Count];

            for (var i = 0; i < contour.Length; i++)
            {
                var vertex = Vertices[i];
                contour[i].Position = new Vec3 {
                    X = vertex.X, Y = vertex.Y
                };
            }

            tess.AddContour(contour, ContourOrientation.Clockwise);
            tess.Tessellate(WindingRule.EvenOdd, ElementType.Polygons, 3);

            var indices = new int[tess.Elements.Length];

            for (var i = 0; i < indices.Length; i++)
            {
                var position = tess.Vertices[tess.Elements[i]].Position;
                indices[i] = Vertices.IndexOf(new Vector2(position.X, position.Y));
            }

            return(indices);
        }
Exemplo n.º 9
0
        /// <summary>
        /// Triangulate this solid.
        /// </summary>
        /// <param name="mesh">The mesh to which the solid's tessellated data will be added.</param>
        public virtual void Tessellate(ref Mesh mesh)
        {
            foreach (var f in this.Faces.Values)
            {
                var tess = new Tess();
                tess.NoEmptyPolygons = true;

                tess.AddContour(f.Outer.ToContourVertexArray(f));

                if (f.Inner != null)
                {
                    foreach (var loop in f.Inner)
                    {
                        tess.AddContour(loop.ToContourVertexArray(f));
                    }
                }

                tess.Tessellate(WindingRule.Positive, LibTessDotNet.Double.ElementType.Polygons, 3);

                for (var i = 0; i < tess.ElementCount; i++)
                {
                    var a = tess.Vertices[tess.Elements[i * 3]].Position.ToVector3();
                    var b = tess.Vertices[tess.Elements[i * 3 + 1]].Position.ToVector3();
                    var c = tess.Vertices[tess.Elements[i * 3 + 2]].Position.ToVector3();

                    mesh.AddTriangle(a, b, c);
                }
            }
        }
Exemplo n.º 10
0
        /// <summary>
        /// Gets a triangulation, where the Indices are related to the Points
        /// </summary>
        /// <param name="Indices">Indices</param>
        /// <param name="Points">List ofPoints</param>
        public void TriAngulation(List <IndexType> Indices, List <xyf> Points)
        {
            Tess Tess = new Tess();

            Tess.UsePooling = true;

            for (int i = 0; i < Count; i++)
            {
                ContourVertex[] CV = new ContourVertex[this[i].Count];
                for (int j = 0; j < this[i].Count; j++)
                {
                    CV[j] = new ContourVertex();

                    CV[j].Position.X = (float)this[i][j].X;
                    CV[j].Position.Y = (float)this[i][j].Y;
                }
                Tess.AddContour(CV);
            }
            Tess.Tessellate(WindingRule.EvenOdd, ElementType.Polygons, 3);
            Indices.Clear();
            for (int i = 0; i < Tess.Elements.Length; i++)
            {
                Indices.Add((IndexType)(Tess.Elements[i]));
            }

            for (int i = 0; i < Tess.Vertices.Length; i++)
            {
                Points.Add(new xyf(Tess.Vertices[i].Position.X, Tess.Vertices[i].Position.Y));
            }
        }
Exemplo n.º 11
0
        void tessPoly(PointF[] source, Color polyColor, float alpha)
        {
            // Now we need to check for polyfill, and triangulate the polygon if needed.
            //if (enableFilledPolys)
            {
                var tess = new Tess();

                ContourVertex[] contour = new ContourVertex[source.Length];
                for (int pt = 0; pt < contour.Length; pt++)
                {
                    contour[pt].Position = new Vec3 {
                        X = source[pt].X, Y = source[pt].Y, Z = 0
                    };
                }
                tess.AddContour(contour, ContourOrientation.Clockwise);                 // keep our orientation to allow holes to be handled.

                // Triangulate.
                tess.Tessellate(WindingRule.NonZero, ElementType.Polygons, 3);                 // We don't have any hole polygons here.

                // Iterate triangles and create output geometry
                for (int i = 0; i < tess.ElementCount; i++)
                {
                    PointF[] tempPoly = new PointF[3];                     // 3 points.
                    tempPoly[0] = new PointF((float)tess.Vertices[tess.Elements[i * 3]].Position.X, (float)tess.Vertices[tess.Elements[i * 3]].Position.Y);
                    tempPoly[1] = new PointF((float)tess.Vertices[tess.Elements[(i * 3) + 1]].Position.X, (float)tess.Vertices[tess.Elements[(i * 3) + 1]].Position.Y);
                    tempPoly[2] = new PointF((float)tess.Vertices[tess.Elements[(i * 3) + 2]].Position.X, (float)tess.Vertices[tess.Elements[(i * 3) + 2]].Position.Y);

                    tessPolyList.Add(new ovp_Poly(clockwiseOrder(tempPoly).ToArray(), polyColor, alpha));
                }
            }
        }
        public List <Vector2[]> TriangulateClipperSolution(ClipperLib.PolyTree solution)
        {
            var tess = new Tess();

            tess.NoEmptyPolygons = true;

            // Add a contour for each part of the solution tree
            ClipperLib.PolyNode node = solution.GetFirst();
            while (node != null)
            {
                // Only interested in closed paths
                if (!node.IsOpen)
                {
                    // Add a new countor. Holes are automatically generated.
                    var vertices = node.Contour.Select(pt => new ContourVertex {
                        Position = new Vec3 {
                            X = pt.X, Y = pt.Y, Z = 0
                        }
                    }).ToArray();
                    tess.AddContour(vertices);
                }
                node = node.GetNext();
            }

            return(TrianglesFromTessellator(tess));
        }
        private List <Vector2[]> TrianglesFromTessellator(Tess tess)
        {
            var triangles = new List <Vector2[]>();

            // Do the tessellation
            tess.Tessellate(WindingRule.EvenOdd, ElementType.Polygons, 3);

            // Extract the triangles
            int numTriangles = tess.ElementCount;

            for (int i = 0; i < numTriangles; i++)
            {
                var v0 = tess.Vertices[tess.Elements[i * 3 + 0]].Position;
                var v1 = tess.Vertices[tess.Elements[i * 3 + 1]].Position;
                var v2 = tess.Vertices[tess.Elements[i * 3 + 2]].Position;

                var triangle = new List <Vector2>()
                {
                    new Vector2(v0.X, v0.Y),
                    new Vector2(v1.X, v1.Y),
                    new Vector2(v2.X, v2.Y),
                };

                // Assume each triangle needs to be CCW
                float cross = GeoMath.Cross(triangle[0], triangle[1], triangle[2]);
                if (cross > 0)
                {
                    triangle.Reverse();
                }

                triangles.Add(triangle.ToArray());
            }

            return(triangles);
        }
Exemplo n.º 14
0
        public static PolygonSet FromTess(Tess tess)
        {
            var output = new PolygonSet();

            for (int i = 0; i < tess.ElementCount; i++)
            {
                var poly = new Polygon();
                for (int j = 0; j < 3; j++)
                {
                    int index = tess.Elements[i * 3 + j];
                    if (index == -1)
                    {
                        continue;
                    }
                    var v = new PolygonPoint
                    {
                        X = tess.Vertices[index].Position.X,
                        Y = tess.Vertices[index].Position.Y
                    };
                    poly.Add(v);
                }
                output.Add(poly);
            }
            return(output);
        }
Exemplo n.º 15
0
        public void Tessellate_WithAsset_ReturnsExpectedTriangulation(TestCaseData data)
        {
            var pset = _loader.GetAsset(data.AssetName).Polygons;
            var tess = new Tess();

            PolyConvert.ToTess(pset, tess);
            tess.Tessellate(data.Winding, ElementType.Polygons, data.ElementSize);

            var resourceName = Assembly.GetExecutingAssembly().GetName().Name + ".TestData." + data.AssetName + ".testdat";
            var testData     = ParseTestData(data.Winding, data.ElementSize, Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName));

            Assert.IsNotNull(testData);
            Assert.AreEqual(testData.ElementSize, data.ElementSize);

            var indices = new List <int>();

            for (int i = 0; i < tess.ElementCount; i++)
            {
                for (int j = 0; j < data.ElementSize; j++)
                {
                    int index = tess.Elements[i * data.ElementSize + j];
                    indices.Add(index);
                }
            }

            Assert.AreEqual(testData.Indices, indices.ToArray());
        }
Exemplo n.º 16
0
        /// <summary>
        /// Triangulate this solid and pack the triangulated data into buffers
        /// appropriate for use with gltf.
        /// </summary>
        public GraphicsBuffers Tessellate()
        {
            var tessellations = new Tess[this.Faces.Count];

            var fi = 0;

            foreach (var f in this.Faces.Values)
            {
                var tess = new Tess();
                tess.NoEmptyPolygons = true;
                tess.AddContour(f.Outer.ToContourVertexArray(f));

                if (f.Inner != null)
                {
                    foreach (var loop in f.Inner)
                    {
                        tess.AddContour(loop.ToContourVertexArray(f));
                    }
                }

                tess.Tessellate(WindingRule.Positive, LibTessDotNet.Double.ElementType.Polygons, 3);

                tessellations[fi] = tess;
                fi++;
            }

            var buffers = new GraphicsBuffers();

            var iCursor = 0;
            var imax    = int.MinValue;

            for (var i = 0; i < tessellations.Length; i++)
            {
                var tess = tessellations[i];

                var a = tess.Vertices[tess.Elements[0]].Position.ToVector3();
                var b = tess.Vertices[tess.Elements[1]].Position.ToVector3();
                var c = tess.Vertices[tess.Elements[2]].Position.ToVector3();
                var n = (b - a).Cross(c - a).Unitized();

                for (var j = 0; j < tess.Vertices.Length; j++)
                {
                    var v = tess.Vertices[j];
                    buffers.AddVertex(v.Position.ToVector3(), n, new UV());
                }

                for (var k = 0; k < tess.Elements.Length; k++)
                {
                    var t     = tess.Elements[k];
                    var index = (ushort)(t + iCursor);
                    buffers.AddIndex(index);
                    imax = Math.Max(imax, index);
                }

                iCursor = imax + 1;
            }

            return(buffers);
        }
        public static void GenerateFillMesh(ShapeData shape, MeshBuilder meshBuilder)
        {
            Profiler.BeginSample("GenerateFillMesh");
            if (shape.GetVertexInfoList().Count < 3)
            {
                return;
            }

            Matrix4x4 m = Matrix4x4.TRS(Vector3.zero, Quaternion.LookRotation(shape.FillNormal), Vector3.one).inverse;

            // tesselation
            ContourVertex[] contour = new ContourVertex[shape.GetVertexInfoList().Count - 2 - (shape.IsStrokeClosed ? 1 : 0)];             // ignore first and last point

            for (int i = 0; i < contour.Length; i++)
            {
                Vector3 p = m.MultiplyPoint(shape.GetVertexInfoList()[i + 1].position);

                var pos = new Vec3();
                pos.X = p.x;
                pos.Y = p.y;
                pos.Z = 0;

                var v = new ContourVertex();
                v.Position = pos;
                v.Data     = shape.GetVertexInfoList()[i + 1].position;
                contour[i] = v;
            }

            if (tesselator == null)
            {
                tesselator = new Tess();
                //tesselator.UsePooling = true;
            }
            tesselator.AddContour(contour, ContourOrientation.CounterClockwise);
            tesselator.Tessellate(WindingRule.EvenOdd, ElementType.Polygons, 3, delegate(Vec3 position, object[] data, float[] weights)
            {
                return((Vector3)data[0] * weights[0] + (Vector3)data[1] * weights[1] + (Vector3)data[2] * weights[2] + (Vector3)data[3] * weights[3]);
            });


            meshBuilder.currentSubmesh = 0;
            for (int i = 0; i < tesselator.ElementCount; i++)
            {
                meshBuilder.AddTriangle(
                    meshBuilder.currentVertCount + tesselator.Elements[i * 3 + 0],
                    meshBuilder.currentVertCount + tesselator.Elements[i * 3 + 1],
                    meshBuilder.currentVertCount + tesselator.Elements[i * 3 + 2]);
            }

            for (int i = 0; i < tesselator.Vertices.Length; i++)
            {
                meshBuilder.AddVert();
                meshBuilder.SetCurrentPosition((Vector3)tesselator.Vertices[i].Data);
                meshBuilder.SetCurrentColor(shape.FillColor);
                meshBuilder.SetCurrentUV0((Vector2)(Vector3)tesselator.Vertices[i].Data);
            }

            Profiler.EndSample();
        }
Exemplo n.º 18
0
 public ActiveRegionDict(Tess tess)
 {
     _tess       = tess;
     _head       = Node.Create();
     _head._key  = null;
     _head._prev = _head;
     _head._next = _head;
 }
Exemplo n.º 19
0
        private static void TessellateShapeLibTess(Shape vectorShape, Color color, List <Geometry> geoms, TessellationOptions tessellationOptions)
        {
            UnityEngine.Profiling.Profiler.BeginSample("LibTess");

            var tess = new Tess();

            var angle  = 45.0f * Mathf.Deg2Rad;
            var mat    = Matrix2D.RotateLH(angle);
            var invMat = Matrix2D.RotateLH(-angle);

            var pats = new List <Vector2[]>();

            foreach (var c in vectorShape.Contours)
            {
                var contour     = new List <Vector2>(100);
                var tracedshape = ShapeUtils.TraceShape(c, vectorShape.PathProps.Stroke, tessellationOptions);
                foreach (var v in tracedshape)
                {
                    contour.Add(mat.MultiplyPoint(v));
                }
                pats.Add(tracedshape);

                tess.AddContour(contour.Select(v => new ContourVertex()
                {
                    Position = new Vec3()
                    {
                        X = v.x, Y = v.y
                    }
                }).ToArray(), ContourOrientation.Original);
            }

            var windingRule = (vectorShape.Fill.Mode == FillMode.OddEven) ? WindingRule.EvenOdd : WindingRule.NonZero;

            try
            {
                tess.Tessellate(windingRule, ElementType.Polygons, 3);
            }
            catch (System.Exception)
            {
                Debug.LogWarning("Shape tessellation failed, skipping...");
                UnityEngine.Profiling.Profiler.EndSample();
                return;
            }

            var indices  = tess.Elements.Select(i => (UInt16)i);
            var vertices = tess.Vertices.Select(v => invMat.MultiplyPoint(new Vector2(v.Position.X, v.Position.Y)));
            var paths    = pats.ToArray();

            if (indices.Count() > 0)
            {
                geoms.Add(new Geometry()
                {
                    Vertices = vertices.ToArray(), Indices = indices.ToArray(), Paths = paths, Color = color, Fill = vectorShape.Fill, FillTransform = vectorShape.FillTransform
                });
            }

            UnityEngine.Profiling.Profiler.EndSample();
        }
Exemplo n.º 20
0
        /// <summary>
        /// Triangulate this solid.
        /// </summary>
        /// <param name="mesh">The mesh to which the solid's tessellated data will be added.</param>
        /// <param name="transform">An optional transform used to transform the generated vertex coordinates.</param>
        /// <param name="color">An optional color to apply to the vertex.</param>
        public void Tessellate(ref Mesh mesh, Transform transform = null, Color color = default(Color))
        {
            foreach (var f in this.Faces.Values)
            {
                var tess = new Tess();
                tess.NoEmptyPolygons = true;

                tess.AddContour(f.Outer.ToContourVertexArray(f));

                if (f.Inner != null)
                {
                    foreach (var loop in f.Inner)
                    {
                        tess.AddContour(loop.ToContourVertexArray(f));
                    }
                }

                tess.Tessellate(WindingRule.Positive, LibTessDotNet.Double.ElementType.Polygons, 3);

                var faceMesh = new Mesh();
                (Vector3 U, Vector3 V)basis = (default(Vector3), default(Vector3));

                for (var i = 0; i < tess.ElementCount; i++)
                {
                    var a = tess.Vertices[tess.Elements[i * 3]].Position.ToVector3();
                    var b = tess.Vertices[tess.Elements[i * 3 + 1]].Position.ToVector3();
                    var c = tess.Vertices[tess.Elements[i * 3 + 2]].Position.ToVector3();

                    if (transform != null)
                    {
                        a = transform.OfPoint(a);
                        b = transform.OfPoint(b);
                        c = transform.OfPoint(c);
                    }

                    if (i == 0)
                    {
                        // Calculate the texture space basis vectors
                        // from the first triangle. This is acceptable
                        // for planar faces.
                        // TODO: Update this when we support non-planar faces.
                        // https://gamedev.stackexchange.com/questions/172352/finding-texture-coordinates-for-plane
                        var n = f.Plane().Normal;
                        basis = n.ComputeDefaultBasisVectors();
                    }

                    var v1 = faceMesh.AddVertex(a, new UV(basis.U.Dot(a), basis.V.Dot(a)), color: color);
                    var v2 = faceMesh.AddVertex(b, new UV(basis.U.Dot(b), basis.V.Dot(b)), color: color);
                    var v3 = faceMesh.AddVertex(c, new UV(basis.U.Dot(c), basis.V.Dot(c)), color: color);

                    faceMesh.AddTriangle(v1, v2, v3);
                }
                mesh.AddMesh(faceMesh);
            }
        }
Exemplo n.º 21
0
        /// <summary>
        /// Get the tessellation.
        /// </summary>
        public Tess GetTess()
        {
            var tess = new Tess
            {
                NoEmptyPolygons = true
            };

            tess.AddContour(polygon.Vertices.ToContourVertices());

            tess.Tessellate(WindingRule.Positive, ElementType.Polygons, 3);
            return(tess);
        }
Exemplo n.º 22
0
        // From https://github.com/memononen/libtess2/issues/14
        public void Tesselate_WithThinQuad_DoesNotCrash()
        {
            string data = "9.5,7.5,-0.5\n9.5,2,-0.5\n9.5,2,-0.4999999701976776123\n9.5,7.5,-0.4999999701976776123";

            using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(data)))
            {
                var pset = DataLoader.LoadDat(stream);
                var tess = new Tess();
                PolyConvert.ToTess(pset, tess);
                tess.Tessellate(WindingRule.EvenOdd, ElementType.Polygons, 3);
            }
        }
Exemplo n.º 23
0
        List <PointF[]> checkPoly(PointF[] poly)
        {
            List <PointF[]> output = new List <PointF[]>();

            PointF[] source = poly.ToArray();

            if ((poly[0].X != poly[poly.Length - 1].X) && (poly[0].Y != poly[poly.Length - 1].Y))
            {
                PointF[] tempPoly = new PointF[poly.Length + 1];
                for (int pt = 0; pt < poly.Length; pt++)
                {
                    tempPoly[pt] = new PointF(poly[pt].X, poly[pt].Y);
                }
                tempPoly[tempPoly.Length - 1] = new PointF(tempPoly[0].X, tempPoly[0].Y);
                source = tempPoly.ToArray();
            }

            // Now we need to check for polyfill, and triangulate the polygon if needed.
            if (enableFilledPolys)
            {
                var tess = new Tess();

                ContourVertex[] contour = new ContourVertex[source.Length];
                for (int pt = 0; pt < contour.Length; pt++)
                {
                    contour[pt].Position = new Vec3 {
                        X = source[pt].X, Y = source[pt].Y, Z = 0
                    };
                }
                tess.AddContour(contour, ContourOrientation.Clockwise);                 // keep our orientation to allow holes to be handled.

                // Triangulate.
                tess.Tessellate(WindingRule.Positive, ElementType.Polygons, 3);                 // We don't have any hole polygons here.

                // Iterate triangles and create output geometry
                for (int i = 0; i < tess.ElementCount; i++)
                {
                    PointF[] tempPoly = new PointF[3];                     // 3 points.
                    tempPoly[0] = new PointF((float)tess.Vertices[tess.Elements[i * 3]].Position.X, (float)tess.Vertices[tess.Elements[i * 3]].Position.Y);
                    tempPoly[1] = new PointF((float)tess.Vertices[tess.Elements[(i * 3) + 1]].Position.X, (float)tess.Vertices[tess.Elements[(i * 3) + 1]].Position.Y);
                    tempPoly[2] = new PointF((float)tess.Vertices[tess.Elements[(i * 3) + 2]].Position.X, (float)tess.Vertices[tess.Elements[(i * 3) + 2]].Position.Y);

                    output.Add(clockwiseOrder(tempPoly).ToArray());
                }
            }
            else
            {
                output.Add(source.ToArray());
            }

            return(output);
        }
        public static void GenerateShadowMesh(Mesh mesh, Vector3[] shapePath)
        {
            Color          meshInteriorColor = new Color(0, 0, 0, 1);
            List <Vector3> vertices          = new List <Vector3>();
            List <int>     triangles         = new List <int>();
            List <Vector4> tangents          = new List <Vector4>();

            // Create interior geometry
            int pointCount = shapePath.Length;
            var inputs     = new ContourVertex[pointCount];

            for (int i = 0; i < pointCount; ++i)
            {
                inputs[i] = new ContourVertex()
                {
                    Position = new Vec3()
                    {
                        X = shapePath[i].x, Y = shapePath[i].y
                    }, Data = meshInteriorColor
                }
            }
            ;

            Tess tessI = new Tess();

            tessI.AddContour(inputs, ContourOrientation.Original);
            tessI.Tessellate(WindingRule.EvenOdd, ElementType.Polygons, 3, InterpCustomVertexData);

            var indicesI  = tessI.Elements.Select(i => i).ToArray();
            var verticesI = tessI.Vertices.Select(v => new Vector3(v.Position.X, v.Position.Y, 0)).ToArray();

            vertices.AddRange(verticesI);
            triangles.AddRange(indicesI);

            InitializeTangents(vertices.Count, tangents);

            List <Edge> edges = new List <Edge>();

            PopulateEdgeArray(vertices, triangles, edges);
            SortEdges(edges);
            CreateShadowTriangles(vertices, triangles, tangents, edges);

            Vector3[] finalVertices  = vertices.ToArray();
            int[]     finalTriangles = triangles.ToArray();
            Vector4[] finalTangents  = tangents.ToArray();

            mesh.Clear();
            mesh.vertices  = finalVertices;
            mesh.triangles = finalTriangles;
            mesh.tangents  = finalTangents;
        }
    }
Exemplo n.º 25
0
 public static void ToTess(PolygonSet pset, Tess tess)
 {
     foreach (var poly in pset)
     {
         var v = new ContourVertex[poly.Count];
         for (int i = 0; i < poly.Count; i++)
         {
             v[i].Position = new Vec3(poly[i].X, poly[i].Y, poly[i].Z);
             v[i].Data     = poly[i].Color;
         }
         tess.AddContour(v, poly.Orientation);
     }
 }
Exemplo n.º 26
0
        internal static Tess TessFromPolygons(Polygon[] polygons)
        {
            var tess = new Tess();

            tess.NoEmptyPolygons = true;

            foreach (var p in polygons)
            {
                AddContour(tess, p);
            }

            return(tess);
        }
Exemplo n.º 27
0
        private static void BuildGeometryFromClipPaths(VectorUtils.Geometry geom, List <List <IntPoint> > paths, List <Vector2> outVerts, List <UInt16> outInds, ref UInt16 maxIndex)
        {
            var vertices    = new List <Vector2>(100);
            var indices     = new List <UInt16>(vertices.Capacity * 3);
            var vertexIndex = new Dictionary <IntPoint, UInt16>();

            foreach (var path in paths)
            {
                if (path.Count == 3)
                {
                    // Triangle case, no need to tessellate
                    foreach (var pt in path)
                    {
                        StoreClipVertex(vertexIndex, vertices, indices, pt, ref maxIndex);
                    }
                }
                else if (path.Count > 3)
                {
                    // Generic polygon case, we need to tessellate first
                    var tess    = new Tess();
                    var contour = new ContourVertex[path.Count];
                    for (int i = 0; i < path.Count; ++i)
                    {
                        contour[i] = new ContourVertex()
                        {
                            Position = new Vec3()
                            {
                                X = path[i].X, Y = path[i].Y, Z = 0.0f
                            }
                        }
                    }
                    ;
                    tess.AddContour(contour, ContourOrientation.Original);

                    var windingRule = WindingRule.NonZero;
                    tess.Tessellate(windingRule, ElementType.Polygons, 3);

                    foreach (var e in tess.Elements)
                    {
                        var v  = tess.Vertices[e];
                        var pt = new IntPoint(v.Position.X, v.Position.Y);
                        StoreClipVertex(vertexIndex, vertices, indices, pt, ref maxIndex);
                    }
                }
            }

            var invMatrix = geom.WorldTransform.Inverse();

            outVerts.AddRange(vertices.Select(v => invMatrix * v));
            outInds.AddRange(indices);
        }
Exemplo n.º 28
0
        private void AddContour(Tess tess, Polygon p, bool reversed = false)
        {
            var numPoints = p.Vertices.Count;
            var contour   = new ContourVertex[numPoints];

            for (var i = 0; i < numPoints; i++)
            {
                var v = p.Vertices[i];
                contour[i].Position = new Vec3 {
                    X = v.X, Y = v.Y, Z = v.Z
                };
            }
            tess.AddContour(contour, reversed ? ContourOrientation.Clockwise : ContourOrientation.CounterClockwise);
        }
Exemplo n.º 29
0
        public static UnityEngine.Mesh BuildMesh(List <Vector2[]> contours)
        {
            Tess tesselation = new Tess();

            foreach (Vector2[] contour in contours)
            {
                if (contour == null)
                {
                    continue;
                }

                int             pathLength = contour.Length;
                ContourVertex[] path       = new ContourVertex[pathLength];
                for (int j = 0; j < pathLength; j++)
                {
                    Vector2 position = contour[j];
                    path[j].Position = new Vec3 {
                        X = position.x, Y = position.y, Z = 0f
                    };
                }
                tesselation.AddContour(path);
            }

            tesselation.Tessellate(WindingRule.EvenOdd, ElementType.Polygons, 3);

            UnityEngine.Mesh mesh = new UnityEngine.Mesh();
            int meshVertexCount   = tesselation.Vertices.Length;

            Vector3[] vertices = new Vector3[meshVertexCount];

            for (int i = 0; i < meshVertexCount; i++)
            {
                vertices[i] = new Vector3(tesselation.Vertices[i].Position.X, tesselation.Vertices[i].Position.Y, 0f);
            }

            int numTriangles = tesselation.ElementCount;

            int[] triangles = new int[numTriangles * 3];
            for (int i = 0; i < numTriangles; i++)
            {
                triangles[i * 3]     = tesselation.Elements[i * 3];
                triangles[i * 3 + 1] = tesselation.Elements[i * 3 + 1];
                triangles[i * 3 + 2] = tesselation.Elements[i * 3 + 2];
            }

            mesh.vertices  = vertices;
            mesh.triangles = triangles;

            return(mesh);
        }
 /// <summary>
 /// Gets the tessellator available.
 /// </summary>
 /// <returns></returns>
 public Tess GetTessellatorAvailable()
 {
     if (!AvailableTessellators.TryDequeue(out var tess))
     {
         tess = new Tess
         {
             NoEmptyPolygons = true
         };
         if (Interlocked.Increment(ref TessellatorCount) > Environment.ProcessorCount)
         {
             Console.WriteLine($"WARNING: Greater number of Tessellators than Processors' count has been Created! Number has reached {TessellatorCount}!");
         }
     }
     return(tess);
 }