Пример #1
0
        private void DrawFill(List <Vector> fillVertices)
        {
            if (m_mesh.Vertices.Count <= 2 || m_mesh.FillMode == FillMode.None || m_mesh.UvMapping.FillTexture == null)
            {
                return;
            }

            if (!m_mesh.IsClosed)
            {
                fillVertices.Add(m_mesh.FillMode != FillMode.Inverted ? m_mesh.Vertices.Last().Position : m_mesh.Vertices.First().Position);
            }


            var polygon = new Polygon(fillVertices.Select(v => new PolygonPoint(v.X, v.Y)));

            if (IsInverted)
            {
                var center = polygon.GetCentroid();
                var size   = new Size(polygon.BoundingBox.Width, polygon.BoundingBox.Height);

                var topLeft     = new Point(center.X - size.Width, center.Y + size.Height);
                var topRight    = new Point(center.X + size.Width, center.Y + size.Height);
                var bottomLeft  = new Point(center.X - size.Width, center.Y - size.Height);
                var bottomRight = new Point(center.X + size.Width, center.Y - size.Height);

                var invertedPolygon = new Polygon(
                    new PolygonPoint(bottomLeft.X, bottomLeft.Y),
                    new PolygonPoint(topLeft.X, topLeft.Y),
                    new PolygonPoint(topRight.X, topRight.Y),
                    new PolygonPoint(bottomRight.X, bottomRight.Y));

                invertedPolygon.AddHole(polygon);

                polygon = invertedPolygon;
            }

            try
            {
                P2T.Triangulate(polygon);
            }
            catch (Exception)
            {
                return;
            }

            var unitsPerFill = CalculateUnitsPerFillUv();

            foreach (var triangle in polygon.Triangles)
            {
                MeshFillData.AddTriangle(
                    new Point3D(triangle.Points._0.X, triangle.Points._0.Y, 0.0),
                    new Point3D(triangle.Points._1.X, triangle.Points._1.Y, 0.0),
                    new Point3D(triangle.Points._2.X, triangle.Points._2.Y, 0.0),
                    new Point(triangle.Points._0.X / unitsPerFill.X, triangle.Points._0.Y / unitsPerFill.Y),
                    new Point(triangle.Points._1.X / unitsPerFill.X, triangle.Points._1.Y / unitsPerFill.Y),
                    new Point(triangle.Points._2.X / unitsPerFill.X, triangle.Points._2.Y / unitsPerFill.Y));
            }
        }
Пример #2
0
 static Polygon CleanClone(Polygon polygon)
 {
     var n = new Polygon(polygon.Points.Select(p => new PolygonPoint(p.X, p.Y)));
     if (polygon.Holes != null)
     {
         foreach (var hole in polygon.Holes)
         {
             n.AddHole(CleanClone(hole));
         }
     }
     return n;
 }
Пример #3
0
		public void Triangulate() {
			var start = DateTime.Now;
			try {
				LastTriangulationException = null;
				var newpoly = CleanClone(Polygon);
				P2T.Triangulate(newpoly);
				Polygon = newpoly;
			} catch ( Exception e ) {
				LastTriangulationException = e;
			}
			var stop = DateTime.Now;
			LastTriangulationDuration = (stop-start);
		}
        /// <summary>
        /// Creates a <see cref="PrimitiveType.TriangleList"/> of vertices which cover the interior of the
        /// specified <paramref name="points"/>. The path must be closed and describe a simple polygon.
        /// </summary>
        /// <param name="points">Points describing the border of a simple polygon.</param>
        /// <param name="zCoord">Z coordinate of the created vertices.</param>
        /// <param name="verts">Returns a <see cref="PrimitiveType.TriangleList"/> of vertices.</param>
        public static void Triangulate(PointF[] points, float zCoord, out PositionColoredTextured[] verts)
        {
            PointF[] pathPoints = AdjustPoints(points);
            if (pathPoints.Length < 3)
            {
                verts = null;
                return;
            }
            if (pathPoints.Length == 3)
            {
                verts = new PositionColoredTextured[3];

                verts[0].Position = new Vector3(pathPoints[0].X, pathPoints[0].Y, zCoord);
                verts[1].Position = new Vector3(pathPoints[1].X, pathPoints[1].Y, zCoord);
                verts[2].Position = new Vector3(pathPoints[2].X, pathPoints[2].Y, zCoord);
                return;
            }

            IList <DelaunayTriangle> polygons;

            try
            {
                // Triangulation can fail (i.e. polygon is self-intersecting)
                var poly = new Poly2Tri.Polygon(pathPoints.Select(p => new PolygonPoint(p.X, p.Y)));
                P2T.Triangulate(poly);
                polygons = poly.Triangles;
            }
            catch (Exception)
            {
                verts = null;
                return;
            }

            verts = new PositionColoredTextured[polygons.Count * 3];
            int offset = 0;

            foreach (DelaunayTriangle triangle in polygons)
            {
                verts[offset++].Position = new Vector3((float)triangle.Points[0].X, (float)triangle.Points[0].Y, zCoord);
                verts[offset++].Position = new Vector3((float)triangle.Points[1].X, (float)triangle.Points[1].Y, zCoord);
                verts[offset++].Position = new Vector3((float)triangle.Points[2].X, (float)triangle.Points[2].Y, zCoord);
            }
        }
        protected override void Initialize()
        {
            // Define polygon
            _points = new List<PolygonPoint>();
            _points.Add(new PolygonPoint(-8.485714f, -1.914286f));
            _points.Add(new PolygonPoint(-6.514286f, -4.914286f));
            _points.Add(new PolygonPoint(-4.514286f, -3.914286f));
            _points.Add(new PolygonPoint(-1.514286f, -6.914286f));
            _points.Add(new PolygonPoint(1.485714f, -4.914286f));
            _points.Add(new PolygonPoint(2.485714f, -5.885714f));
            _points.Add(new PolygonPoint(7.457143f, -4.914286f));
            _points.Add(new PolygonPoint(8.457143f, -0.9428571f));
            _points.Add(new PolygonPoint(6.485714f, 1f));
            _points.Add(new PolygonPoint(4.457143f, 6.028572f));
            _points.Add(new PolygonPoint(0.4857143f, 7.057143f));
            _points.Add(new PolygonPoint(-1.485714f, 3.028571f));
            _points.Add(new PolygonPoint(-6.485714f, 1.028571f));
            _polygon = new Polygon(_points);

            // Decompose polygon
            P2T.Triangulate(_polygon);

            // Define bounding box
            _lowerBound = new Vector2((float)_polygon.MinX, (float)_polygon.MinY);
            _upperBound = new Vector2((float)_polygon.MaxX, (float)_polygon.MaxY);

            // Create vertices
            createVertices();

            // Create lines
            createLineVertices();

            // Load content
            base.Initialize();

            // Set window size
            _graphics.PreferredBackBufferWidth = _texture.Width + 64;
            _graphics.PreferredBackBufferHeight = _texture.Height + 64;
            _graphics.ApplyChanges();
        }
Пример #6
0
        public List<DelaunayTriangle> TriangulateComplex(
         PolyTree polyTree,
         bool ignoreFills = false, bool ignoreHoles = true)
        {
            PolyNode rootNode;
             if (polyTree.Total == 0) {
            Console.WriteLine(0);
            rootNode = new PolyNode();
             } else {
            rootNode = polyTree.GetFirst().Parent;
             }

             // Equivalent to rootNode.Contour = bounds;
             var contourField = rootNode.GetType().GetField("m_polygon", BindingFlags.Instance | BindingFlags.NonPublic);
             if (contourField == null) {
            throw new Exception("Could not find field contour backing field.");
             }
             contourField.SetValue(rootNode, kTriangulatorBounds);

             var result = new List<DelaunayTriangle>();
             int i = 0;
             for (var currentNode = rootNode; currentNode != null; currentNode = currentNode.GetNext()) {
            if ((ignoreHoles && currentNode.IsHole) || (ignoreFills && !currentNode.IsHole)) continue;
            var polyline = DownscalePolygon(currentNode.Contour);
            var finalPolygon = new Polygon(polyline);
            foreach (var child in currentNode.Childs) {
               var shrunkContour = EdgeShrink(child.Contour);
               var holePoints = DownscalePolygon(shrunkContour);
               var holePoly = new Polygon(holePoints);
               finalPolygon.AddHole(holePoly);
            }
            P2T.Triangulate(finalPolygon);
            result.AddRange(finalPolygon.Triangles);
             }
             return result;
        }
Пример #7
0
        protected override Polygon GetPolygon()
        {
            Polygon poly = new Polygon( GetPoints() );

            if( thickness > 0 )
            {
                List<PolygonPoint> holePoints = new List<PolygonPoint>();

                float x;
                float y;
                float radAngle;
                float degreeStep = 360f / sides;
                float r = radius - thickness;

                for( int i = 0; i < sides; i++ )
                {
                    radAngle = MathUtil.DegreesToRadians( degreeStep * i );
                    x = (float)( Math.Cos( radAngle ) * r );
                    y = (float)( Math.Sin( radAngle ) * r );

                    holePoints.Add( new PolygonPoint( x, y ) );
                }

                Polygon hole = new Polygon( holePoints );
                poly.AddHole( hole );
            }

            return poly;
        }
Пример #8
0
        public static Polygon LoadDat(string filename, bool xflip, bool yflip, bool displayFlipX, bool displayFlipY, float rotateAngleInDegrees)
        {
            var points = new List<PolygonPoint>();
            int lineNum = 0;
            double precision = TriangulationPoint.kVertexCodeDefaultPrecision;
            bool skipLine = false;
            foreach (var line_ in File.ReadAllLines(filename))
            {
                ++lineNum;
                string line = line_.Trim();
                if (string.IsNullOrEmpty(line) ||
                    line.StartsWith("//") ||
                    line.StartsWith("#") ||
                    line.StartsWith(";"))
                {
                    continue;
                }
                if (!skipLine && line.StartsWith("/*"))
                {
                    skipLine = true;
                    continue;
                }
                else if (skipLine)
                {
                    if (line.StartsWith("*/"))
                    {
                        skipLine = false;
                    }
                    continue;
                }
                if (line.StartsWith("Precision", StringComparison.InvariantCultureIgnoreCase))
                {
                    if( line.Length> 9)
                    {
                        string ps = line.Substring(9).Trim();
                        if (!double.TryParse(ps, NumberStyles.Float, CultureInfo.InvariantCulture, out precision))
                        {
                            Console.WriteLine("Invalid Precision '" + ps + "' in file " + filename + ", line " + lineNum.ToString() +".  Setting to " + TriangulationPoint.kVertexCodeDefaultPrecision.ToString());
                            precision = TriangulationPoint.kVertexCodeDefaultPrecision;
                        }
                    }
                }
                else
                {
                    var xy = line.Split(new[] { ' ', ',' }, StringSplitOptions.RemoveEmptyEntries);
                    double x, y;
                    if (xy != null &&
                        xy.Length >= 2 &&
                        double.TryParse(xy[0], NumberStyles.Float, CultureInfo.InvariantCulture, out x) &&
                        double.TryParse(xy[1], NumberStyles.Float, CultureInfo.InvariantCulture, out y))
                    {
                        points.Add(new PolygonPoint((xflip ? -1.0 : 1.0) * x, (yflip ? -1.0 : 1.0) * y));
                    }
                    else
                    {
                        Console.WriteLine("Invalid Input '" + line + "' in file " + filename + ", line " + lineNum.ToString());
                    }
                }
            }

            Polygon p = new Polygon(points);
            p.FileName = filename;
            p.DisplayFlipX = displayFlipX;
            p.DisplayFlipY = displayFlipY;
            p.DisplayRotate = rotateAngleInDegrees;
            p.Precision = precision;

            return p;
        }
Пример #9
0
        protected virtual Polygon GetPolygon()
        {
            Polygon poly = new Polygon(GetPoints());

            if (thickness > 0)
            {
                Polygon hole = new Polygon(GetPoints(thickness));
                poly.AddHole(hole);
            }

            return poly;
        }
Пример #10
0
		public void Add(Polygon p)
		{
			_polygons.Add(p);
		}
Пример #11
0
        /// <summary>
        /// triangulate polygon, algorithm from wiki is fast enough
        /// http://wiki.unity3d.com/index.php?title=Triangulator
        /// </summary>
        /// <returns></returns>
        public List <int> Triangulate()
        {
            // no holes supported
            if (holes.Count == 0)
            {
                var indices = new List <int>(Points.Length);

                int n = Points.Length;
                if (n < 3)
                {
                    return(indices);
                }

                var V = new int[n];
                if (Area > 0)
                {
                    for (int v = 0; v < n; v++)
                    {
                        V[v] = v;
                    }
                }
                else
                {
                    for (int v = 0; v < n; v++)
                    {
                        V[v] = (n - 1) - v;
                    }
                }

                int nv    = n;
                int count = 2 * nv;
                for (int m = 0, v = nv - 1; nv > 2;)
                {
                    if ((count--) <= 0)
                    {
                        return(indices);
                    }

                    int u = v;
                    if (nv <= u)
                    {
                        u = 0;
                    }
                    v = u + 1;
                    if (nv <= v)
                    {
                        v = 0;
                    }
                    int w = v + 1;
                    if (nv <= w)
                    {
                        w = 0;
                    }

                    if (Snip(u, v, w, nv, V))
                    {
                        int a, b, c, s, t;
                        a = V[u];
                        b = V[v];
                        c = V[w];
                        indices.Add(a);
                        indices.Add(b);
                        indices.Add(c);
                        m++;
                        for (s = v, t = v + 1; t < nv; s++, t++)
                        {
                            V[s] = V[t];
                        }
                        nv--;
                        count = 2 * nv;
                    }
                }

                indices.Reverse();
                return(indices);
            }
            else
            {
                // use poly2tri library to triangulate mesh with holes

                var p2tPoints = new List <Poly2Tri.PolygonPoint>(Points.Length);

                foreach (var point in Points)
                {
                    p2tPoints.Add(new Poly2Tri.PolygonPoint(point.x, point.y));
                }

                // create p2t polygon
                var p2tPolygon = new Poly2Tri.Polygon(p2tPoints);

                // add holes
                foreach (var polygonHole in holes)
                {
                    var p2tHolePoints = new List <Poly2Tri.PolygonPoint>(polygonHole.Points.Length);

                    foreach (var polygonPoint in polygonHole.Points)
                    {
                        p2tHolePoints.Add(new Poly2Tri.PolygonPoint(polygonPoint.x, polygonPoint.y));
                    }

                    p2tPolygon.AddHole(new Poly2Tri.Polygon(p2tHolePoints));
                }

                try
                {
                    Poly2Tri.P2T.Triangulate(p2tPolygon);
                }
                catch (Exception ex)
                {
                    ExploderUtils.Log("P2T Exception: " + ex);
                    return(null);
                }

                var triangles = p2tPolygon.Triangles.Count;

                var indices = new List <int>(triangles * 3);
                Points = new Vector2[triangles * 3];
                var j = 0;

                // recalc min max
                Min.x = float.MaxValue;
                Min.y = float.MaxValue;
                Max.x = float.MinValue;
                Max.y = float.MinValue;

                for (int i = 0; i < triangles; i++)
                {
                    indices.Add((j + 0));
                    indices.Add((j + 1));
                    indices.Add((j + 2));

                    Points[j + 2].x = (float)p2tPolygon.Triangles[i].Points._0.X;
                    Points[j + 2].y = (float)p2tPolygon.Triangles[i].Points._0.Y;

                    Points[j + 1].x = (float)p2tPolygon.Triangles[i].Points._1.X;
                    Points[j + 1].y = (float)p2tPolygon.Triangles[i].Points._1.Y;

                    Points[j + 0].x = (float)p2tPolygon.Triangles[i].Points._2.X;
                    Points[j + 0].y = (float)p2tPolygon.Triangles[i].Points._2.Y;

                    // recalc min max
                    for (int k = 0; k < 3; k++)
                    {
                        if (Points[j + k].x < Min.x)
                        {
                            Min.x = Points[j + k].x;
                        }
                        if (Points[j + k].y < Min.y)
                        {
                            Min.y = Points[j + k].y;
                        }
                        if (Points[j + k].x > Max.x)
                        {
                            Max.x = Points[j + k].x;
                        }
                        if (Points[j + k].y > Max.y)
                        {
                            Max.y = Points[j + k].y;
                        }
                    }

                    j += 3;
                }

                return(indices);
            }
        }
Пример #12
0
        public void UpdateNavigationMesh()
        {
            var visitedBlockedCells = new HashSet<NavigationGridletCell>();
             var blobs = new List<List<NavigationGridletCell>>();
             foreach (var cell in Cells) {
            if (!cell.Flags.HasFlag(CellFlags.Blocked)) {
               continue;
            }
            if (visitedBlockedCells.Contains(cell)) {
               continue;
            }

            var s = new Stack<NavigationGridletCell>();
            s.Push(cell);
            var blob = new List<NavigationGridletCell>();
            while (s.Any()) {
               var node = s.Pop();
               blob.Add(node);
               visitedBlockedCells.Add(node);
               var derps = new List<NavigationGridletCell>();
               if (node.X > 0) {
                  derps.Add(node.Gridlet.Cells[node.Index - 1]);
               }
               if (node.X < node.Gridlet.XLength - 1) {
                  derps.Add(node.Gridlet.Cells[node.Index + 1]);
               }
               if (node.Y > 0) {
                  derps.Add(node.Gridlet.Cells[node.Index - node.Gridlet.XLength]);
               }
               if (node.Y < node.Gridlet.YLength - 1) {
                  derps.Add(node.Gridlet.Cells[node.Index + node.Gridlet.XLength]);
               }
               var blockedNeighbors = derps.Where(n => n.Flags.HasFlag(CellFlags.Blocked)).ToArray();
               blockedNeighbors.Where(n => !visitedBlockedCells.Contains(n)).ForEach(s.Push);
            }
            blobs.Add(blob);
             }

             // derp
             var cps = new Polygon(new List<PolygonPoint> {
            new PolygonPoint(-XLength / 2.0f - 5, -YLength / 2.0f - 5),
            new PolygonPoint(XLength / 2.0f + 5, -YLength / 2.0f - 5),
            new PolygonPoint(XLength / 2.0f + 5, YLength / 2.0f + 5),
            new PolygonPoint(-XLength / 2.0f - 5, YLength / 2.0f + 5)
             });

             foreach (var blob in blobs) {
            var chull = GeometryUtilities.ConvexHull(blob.SelectMany(x => new[] { new ItzWarty.Geometry.Point2D(x.X, x.Y), new ItzWarty.Geometry.Point2D(x.X + 1, x.Y), new ItzWarty.Geometry.Point2D(x.X + 1, x.Y + 1), new ItzWarty.Geometry.Point2D(x.X, x.Y + 1) }).ToArray());
            cps.AddHole(
               new Polygon(
                  chull.Select(p => new PolygonPoint(p.X - XLength / 2.0f, p.Y - YLength / 2.0f)).ToArray()
               )
            );
             }

             var handledNeighborCells = new HashSet<NavigationGridletCell>();
             foreach (var edgeCell in EdgeCells.Where(x => x.Flags.HasFlag(CellFlags.Connector))) {
            var thisObb = this.OrientedBoundingBox;
            foreach (var neighbor in edgeCell.Neighbors) {
               if (handledNeighborCells.Contains(neighbor)) {
                  continue;
               } else {
                  handledNeighborCells.Add(neighbor);
               }

            //               var neighborObb = neighbor.OrientedBoundingBox;
            //               var neighborToLocal = OrientedBoundingBox.GetBoxToBoxMatrix(ref thisObb, ref neighborObb);
            //               Vector3 zero = new Vector3(0, 0, 0);
            //               Vector3 neighborRelativePosition;
            //               Vector3.Transform(ref zero, ref neighborToLocal, out neighborRelativePosition);
            //               var p = new PolygonPoint((neighborRelativePosition.X), (neighborRelativePosition.Y));
            //               var q = new PolygonPoint((neighborRelativePosition.X + 0.05), (neighborRelativePosition.Y + 0.05));
            //               cps.AddConstraint(new TriangulationConstraint(p, q));
            }
            //            var p = new PolygonPoint((edgeCell.X + 0.45) * 0.998f - XLength / 2.0f, (edgeCell.Y + 0.45f) * 0.98f - YLength / 2.0f);
            //            var q = new PolygonPoint((edgeCell.X + 0.55) * 0.999f - XLength / 2.0f, (edgeCell.Y + 0.55f) * 0.99f - YLength / 2.0f);
            //            cps.AddConstraint(new TriangulationConstraint(p, q));
             }
             //         cps.AddHole(
            //            new List<TriangulationPoint> {
            //               new TriangulationPoint(-XLength / 2 + 2, -YLength / 2 + 2),
            //               new TriangulationPoint(XLength / 2 - 2, -YLength / 2 + 2),
            //               new TriangulationPoint(XLength / 2 - 2, YLength / 2 - 2),
            //               new TriangulationPoint(-XLength / 2 + 2, YLength / 2 - 2)
            //            }, "hole");
             P2T.Triangulate(cps);
             Console.WriteLine(cps.Triangles.Count);
             Mesh = cps.Triangles;
            //         for (var x = 0; x < XLength; x++) {
            //            for (var y = 0; y < YLength; y++) {
            //               var cellIndex = x + y * XLength;
            //               if (Cells[cellIndex].Flags.HasFlag(CellFlags.Connector)) {
            //
            //               }
            //            }
            //         }
        }
Пример #13
0
        private void ConstructPolygon()
        {
            List<PolygonPoint> p2 = new List<PolygonPoint>();
            int i = 0, l = _points.Count;
            for (; i < l; i += 1)
            {
                p2.Add(new PolygonPoint(_points [i].x, _points [i].y));
            }

            _polygon = new Polygon(p2);
            _polygon.Simplify();
            P2T.Triangulate(_polygon);

            ContinueCreatingShape();
        }
Пример #14
0
    public static Mesh CreateXYMesh(Polygon polygon)
    {
        //AML Maybe pass this as arg and reduce coords to XY
        float z = polygon.outside[0].z;

        // Check for the easy case (a triangle)
        if (polygon.holes.Count == 0 && (polygon.outside.Count == 3 ||
                                         (polygon.outside.Count == 4 && polygon.outside[3] == polygon.outside[0])))
        {
            return(CreateTriangle(polygon));
        }
        // Convert the outside points (throwing out Z at this point)
        Poly2Tri.Polygon poly = new Poly2Tri.Polygon(ConvertPoints(polygon.outside));
        // Convert each of the holes
        foreach (List <Vector3> hole in polygon.holes)
        {
            poly.AddHole(new Poly2Tri.Polygon(ConvertPoints(hole)));
        }
        // Triangulate it!  Note that this may throw an exception if the data is bogus.
        try {
            DTSweepContext tcx = new DTSweepContext();
            tcx.PrepareTriangulation(poly);
            DTSweep.Triangulate(tcx);
            tcx = null;
        } catch (System.Exception e) {
            //Profiler.Exit(profileID);
            throw e;
        }
        // Create the indices array
        Dictionary <uint, int> codeToIndex = new Dictionary <uint, int>();
        List <Vector3>         vertexList  = new List <Vector3>();

        foreach (DelaunayTriangle t in poly.Triangles)
        {
            foreach (var p in t.Points)
            {
                if (codeToIndex.ContainsKey(p.VertexCode))
                {
                    continue;
                }
                codeToIndex[p.VertexCode] = vertexList.Count;
                vertexList.Add(new Vector3(p.Xf, p.Yf, z));
            }
        }
        int[] indices = new int[poly.Triangles.Count * 3];
        {
            int i = 0;
            foreach (DelaunayTriangle t in poly.Triangles)
            {
                indices[i++] = codeToIndex[t.Points[0].VertexCode];
                indices[i++] = codeToIndex[t.Points[1].VertexCode];
                indices[i++] = codeToIndex[t.Points[2].VertexCode];
            }
        }

        // Create the UV list, by looking up the closest point for each in our poly
        Vector2[] uv = null;
        if (polygon.outsideUVs != null)
        {
            uv = new Vector2[vertexList.Count];
            for (int i = 0; i < vertexList.Count; i++)
            {
                uv[i] = polygon.ClosestUV(vertexList[i]);
            }
        }

        // Create the mesh
        Mesh msh = new Mesh();

        msh.vertices  = vertexList.ToArray();
        msh.triangles = indices;
        msh.uv        = uv;
        msh.RecalculateNormals();
        msh.RecalculateBounds();
        return(msh);
    }
Пример #15
0
        private VertexPositionTexture[] createVerticesFromPoints(List<Vector2> points, out int primitiveCount)
        {
            List<PolygonPoint> p2tPoints = new List<PolygonPoint>();
            Polygon polygon;
            Vector2 topLeft = points[0];
            Vector2 bottomRight = points[0];
            VertexPositionTexture[] vertices;
            int index = 0;

            foreach (Vector2 v in points)
            {
                p2tPoints.Add(new PolygonPoint(v.X, v.Y));
                topLeft = Vector2.Min(v, topLeft);
                bottomRight = Vector2.Max(v, bottomRight);
            }

            polygon = new Polygon(p2tPoints);
            P2T.Triangulate(polygon);
            primitiveCount = polygon.Triangles.Count;
            vertices = new VertexPositionTexture[primitiveCount * 3];

            foreach (DelaunayTriangle triangle in polygon.Triangles)
            {
                Vector2 p1 = new Vector2(triangle.Points[0].Xf, triangle.Points[0].Yf);
                Vector2 p2 = new Vector2(triangle.Points[1].Xf, triangle.Points[1].Yf);
                Vector2 p3 = new Vector2(triangle.Points[2].Xf, triangle.Points[2].Yf);

                vertices[index++] = new VertexPositionTexture(
                    new Vector3(p1, 0),
                    (p1 - topLeft) / (bottomRight - topLeft));
                vertices[index++] = new VertexPositionTexture(
                    new Vector3(p2, 0),
                    (p2 - topLeft) / (bottomRight - topLeft));
                vertices[index++] = new VertexPositionTexture(
                    new Vector3(p3, 0),
                    (p3 - topLeft) / (bottomRight - topLeft));
            }

            return vertices;
        }
Пример #16
0
        private List<Polygon> TriangulatePolyTree(PolyTree tree)
        {
            List<Polygon> polygonsGenerated = new List<Polygon>();
            List<PolygonPoint> AllPoints = new List<PolygonPoint>();
            foreach (PolyNode islands in tree.Childs)
            {
                List<PolygonPoint> floorPoints = new List<PolygonPoint>();
                foreach (IntPoint point in SubdividePolygon(islands.Contour))
                {
                    floorPoints.Add(new PolygonPoint(point.X / GenerationInformation.CalculationScaleFactor, point.Y / GenerationInformation.CalculationScaleFactor));
                }

                AllPoints.AddRange(floorPoints);
                Polygon floorPolygon = new Polygon(floorPoints);

                foreach (PolyNode nextNode in islands.Childs)
                {
                    if (nextNode.IsHole)
                    {
                        List<PolygonPoint> holePoints = new List<PolygonPoint>();
                        foreach (IntPoint point in SubdividePolygon(nextNode.Contour))
                        {
                            holePoints.Add(new PolygonPoint(point.X / GenerationInformation.CalculationScaleFactor, point.Y / GenerationInformation.CalculationScaleFactor));
                        }
                        AllPoints.AddRange(holePoints);
                        floorPolygon.AddHole(new Polygon(holePoints));
                    }
                }
                if (GenerationInformation.UseGrid)
                {
                    List<TriangulationPoint> steinerPoints = new List<TriangulationPoint>();
                    for (float x = (float)floorPolygon.BoundingBox.MinX - ((float)floorPolygon.BoundingBox.MinX % GenerationInformation.GridSize.x); x < floorPolygon.BoundingBox.MaxX; x += GenerationInformation.GridSize.x)
                    {
                        for (float y = (float)floorPolygon.BoundingBox.MinY - ((float)floorPolygon.BoundingBox.MinY % GenerationInformation.GridSize.y); y < floorPolygon.BoundingBox.MaxY; y += GenerationInformation.GridSize.y)
                        {
                            TriangulationPoint p = new TriangulationPoint(x, y);
                            if (floorPolygon.IsPointInside(p))
                                steinerPoints.Add(p);
                        }
                    }

                    CullSteinerPoints(ref steinerPoints, AllPoints, 0.1f);

                    floorPolygon.AddSteinerPoints(steinerPoints);
                }

                floorPolygon.Prepare(P2T.CreateContext(TriangulationAlgorithm.DTSweep));
                P2T.Triangulate(floorPolygon);
                polygonsGenerated.Add(floorPolygon);

            }

            return polygonsGenerated;
        }
Пример #17
0
        private static void AddPathToBuffers(Path path, BufferGenerator vertexBufferGenerator, BufferGenerator indexBufferGenerator, ref int indexCount)
        {
            List<PolygonPoint> points = new List<PolygonPoint>();

            float r;
            float g;
            float b;
            if (path.CompositMode == CompositMode.Subtract)
            {
                r = 1f;
                g = 0f;
                b = 0f;
            }
            else
            {
                r = 1f;
                g = 1f;
                b = 1f;
            }

            foreach (var segment in path.Segments)
            {
                if (segment is QuadraticCurveSegment)
                {
                    var quadraticCurveSegment = segment as QuadraticCurveSegment;
                    AddQuadraticCurveSegment(quadraticCurveSegment, points, vertexBufferGenerator, indexBufferGenerator, ref indexCount, r, g, b);
                }
                else if(segment is LineSegment)
                {
                    var lineSegment = segment as LineSegment;
                    points.Add(new PolygonPoint(lineSegment.End.X, lineSegment.End.Y));

                    var ext = 0.01;
                    var normal = path.CompositMode == CompositMode.Subtract ? lineSegment.RightNormal : lineSegment.LeftNormal;
                    var p1 = (normal * ext) + lineSegment.Start;
                    var p2 = (normal * ext) + lineSegment.End;

                    AddVertex(vertexBufferGenerator, (float)lineSegment.Start.X, (float)lineSegment.Start.Y, 0f, 1f, r, g, b, 1f);
                    AddVertex(vertexBufferGenerator, (float)lineSegment.End.X, (float)lineSegment.End.Y, 0f, 1f, r, g, b, 1f);
                    AddVertex(vertexBufferGenerator, (float)p1.X, (float)p1.Y, 1f, 1f, r, g, b, 1f);
                    indexBufferGenerator.WriteUInt((uint)indexCount++, (uint)indexCount++, (uint)indexCount++);

                    AddVertex(vertexBufferGenerator, (float)lineSegment.Start.X, (float)lineSegment.Start.Y, 0f, 1f, r, g, b, 1f);
                    AddVertex(vertexBufferGenerator, (float)p1.X, (float)p1.Y, 0f, 0f, r, g, b, 1f);
                    AddVertex(vertexBufferGenerator, (float)p2.X, (float)p2.Y, 1f, 1f, r, g, b, 1f);
                    indexBufferGenerator.WriteUInt((uint)indexCount++, (uint)indexCount++, (uint)indexCount++);
                }
                else
                {
                    throw new NotImplementedException();
                }
            }

            Polygon polygon;

            try
            {
                polygon = new Polygon(points);
                P2T.Triangulate(polygon);
            }
            catch(Exception e)
            {
                System.Diagnostics.Debug.WriteLine(e.Message);
                return;
            }

            foreach (var triangle in polygon.Triangles)
            {
                AddVertex(vertexBufferGenerator, (float)triangle.Points[0].X, (float)triangle.Points[0].Y, 0f, 1f, r, g, b, 1f);
                AddVertex(vertexBufferGenerator, (float)triangle.Points[1].X, (float)triangle.Points[1].Y, 0f, 1f, r, g, b, 1f);
                AddVertex(vertexBufferGenerator, (float)triangle.Points[2].X, (float)triangle.Points[2].Y, 0f, 1f, r, g, b, 1f);
                indexBufferGenerator.WriteUInt((uint)indexCount++, (uint)indexCount++, (uint)indexCount++);
            }
        }
Пример #18
0
 public void Remove(Polygon p)
 {
     _polygons.Remove(p);
 }
Пример #19
0
    public static MeshProperties[] CreateMesh(List <BoundaryPoint> genPoly, Transform objTrans, float spriteSquareSize)
    {
        const int   _FRONTOFFSET     = 3;
        const float _BACKFACE_OFFSET = 0.5f;
        const float _SCALE_FACTOR    = 1.1f;

        MeshProperties _generatedMesh;
        MeshProperties _frontFaceMesh;

        Vector2[] _genPolyArrFront = new Vector2[genPoly.Count];

        List <VertexProperties> _verts = new List <VertexProperties>();
        List <VertexProperties> _frontFaceVerticies = new List <VertexProperties>();

        List <int> _indicies          = new List <int>();
        List <int> _frontFaceIndicies = new List <int>();

        //ConvertingToArray
        for (int i = 0; i < genPoly.Count; i++)
        {
            _genPolyArrFront[i] = objTrans.TransformPoint(genPoly[i].Pos);
        }

        Vector3 vecSum = Vector3.zero;

        //VerticiesFront
        for (int i = 0; i < genPoly.Count; i++)
        {
            Vector3 _position = new Vector3(_genPolyArrFront[i].x, _genPolyArrFront[i].y, 0.0f);

            vecSum += _position;

            _verts.Add(new VertexProperties {
                position = _position
            });
            _verts.Add(new VertexProperties {
                position = _position
            });
            _verts.Add(new VertexProperties {
                position = _position
            });

            _frontFaceVerticies.Add(new VertexProperties {
                position = _position
            });
        }

        //Calculating the center of the unscaled polygon
        Vector3 polygonCenter = vecSum / genPoly.Count;

        polygonCenter.z = objTrans.position.z;

        Matrix4x4 scaleMatrix = BlastProof.Mathematics.ScaleMatrix(_SCALE_FACTOR);

        Vector3 vecSum2 = Vector3.zero;

        //VerticiesBack
        for (int i = 0; i < genPoly.Count; i++)
        {
            Vector3 _position = scaleMatrix.MultiplyPoint(new Vector3(_genPolyArrFront[i].x, _genPolyArrFront[i].y, _BACKFACE_OFFSET));
            vecSum2 += _position;

            _verts.Add(new VertexProperties {
                position = _position
            });
            _verts.Add(new VertexProperties {
                position = _position
            });
            _verts.Add(new VertexProperties {
                position = _position
            });
        }

        Vector3 scaledPolyCenter = vecSum2 / genPoly.Count;

        scaledPolyCenter.z = objTrans.position.z;

        //Caching how much should the polygon move on axis so it matches the original scale polygon
        Vector3 translVec = polygonCenter - scaledPolyCenter;

        Matrix4x4 transMatrix = BlastProof.Mathematics.TranslateMatrix(translVec);

        //Multiplying each backface polygon position with the translation matrix so the center of backface polygon and frontface polygon matches
        for (int i = _verts.Count / 2; i < _verts.Count; i++)
        {
            _verts[i].position = transMatrix.MultiplyPoint(_verts[i].position);
        }

        var newGenPolyArrFront = new List <Poly2Tri.PolygonPoint>();

        for (int i = 0; i < _genPolyArrFront.Length; i++)
        {
            var point = new Poly2Tri.PolygonPoint(_genPolyArrFront[i].x, _genPolyArrFront[i].y);
            point.index = i;
            newGenPolyArrFront.Add(point);
        }

        Poly2Tri.Polygon poly = new Poly2Tri.Polygon(newGenPolyArrFront);

        DTSweepContext tcx = new DTSweepContext();

        tcx.PrepareTriangulation(poly);
        DTSweep.Triangulate(tcx);

        List <int> indiciesFromTriangulator = new List <int>();

        foreach (var triangle in poly.Triangles)
        {
            foreach (var point in triangle.Points)
            {
                indiciesFromTriangulator.Add(point.index);
            }
        }

        indiciesFromTriangulator.Reverse();

        Triangulator tri = new Triangulator(_genPolyArrFront);

        int[] triangledPoly = indiciesFromTriangulator.ToArray();

        //FrontFaceIndicies
        for (int i = 0; i < triangledPoly.Length; i++)
        {
            _indicies.Add(triangledPoly[i] * _FRONTOFFSET);
            _frontFaceIndicies.Add(triangledPoly[i]);
        }

        //BackFaceIndicies
        for (int i = triangledPoly.Length - 1; i >= 0; i--)
        {
            _indicies.Add(triangledPoly[i] * _FRONTOFFSET + (_verts.Count / 2));
        }

        //Front-Back Faces normals
        for (int i = 0; i < _indicies.Count / 2; i += 3)
        {
            int[] v1 = { _indicies[i], _indicies[(i + 1) % (_indicies.Count / 2)], _indicies[(i + 2) % (_indicies.Count / 2)] };
            int[] v2 = { _indicies[i + (_indicies.Count / 2)], _indicies[(i + 1) % (_indicies.Count / 2) + (_indicies.Count / 2)], _indicies[(i + 2) % (_indicies.Count / 2) + (_indicies.Count / 2)] };

            GetNormalsForVerts(_verts, v1);
            GetNormalsForVerts(_verts, v2);
            GetUVsWithSize(_verts, v1, Faces.forward, spriteSquareSize);
            GetUVsWithSize(_verts, v2, Faces.forward, spriteSquareSize);
        }

        //Generating Side Triangles
        for (int i = 1; i < _verts.Count / 2; i += 6)
        {
            int[] frontFaceVerts = { i, (i + 3) % (_verts.Count / 2) };
            int[] backFaceVerts  = { (i + (_verts.Count / 2)), (i + 3) % (_verts.Count / 2) + (_verts.Count / 2) };

            //verts pos are used as uvs
            int[] uvCoord = { i, (i + 3) % (_verts.Count / 2), (i + (_verts.Count / 2)), (i + 3) % (_verts.Count / 2) + (_verts.Count / 2) };

            GetQuadIndicies(frontFaceVerts, backFaceVerts, _indicies, _verts);

            GetUVsWithSize(_verts, uvCoord, Faces.left, spriteSquareSize);
        }

        //Generate Up-Down Verts
        for (int i = 5; i < _verts.Count / 2; i += 6)
        {
            int[] frontFaceVerts = { i % (_verts.Count / 2), (i + 3) % (_verts.Count / 2) };
            int[] backFaceVerts  = { (i % (_verts.Count / 2) + (_verts.Count / 2)),
                                     (i + 3) % (_verts.Count / 2) + (_verts.Count / 2) };

            //verts pos are used as uvs
            int[] uvCoord = { i % (_verts.Count / 2), (i + 3) % (_verts.Count / 2), (i % (_verts.Count / 2) + (_verts.Count / 2)), (i + 3) % (_verts.Count / 2) + (_verts.Count / 2) };

            GetQuadIndicies(frontFaceVerts, backFaceVerts, _indicies, _verts);
            GetUVsWithSize(_verts, uvCoord, Faces.up, spriteSquareSize);
        }

        _generatedMesh             = new MeshProperties(_verts);
        _generatedMesh.mesh_center = polygonCenter;
        _generatedMesh.SetIndicies(_indicies.ToArray());

        _frontFaceMesh             = new MeshProperties(_frontFaceVerticies);
        _frontFaceMesh.mesh_center = polygonCenter;
        _frontFaceMesh.SetIndicies(_frontFaceIndicies.ToArray());

        return(new MeshProperties[] { _generatedMesh, _frontFaceMesh });
    }
        GameObject GenerateCellRegionSurface(int cellIndex, Material material)
        {
            if (cellIndex<0 || cellIndex>=cells.Count) return null;
            Region region = cells [cellIndex].region;

            // Calculate region's surface points
            int numSegments = region.segments.Count;
            Connector connector = new Connector();
            if (_terrain==null) {
                connector.AddRange(region.segments);
            } else {
                for (int i = 0; i<numSegments; i++) {
                    Segment s = region.segments[i];
                    SurfaceSegmentForSurface(s, connector);
                }
            }
            Geom.Polygon surfacedPolygon = connector.ToPolygonFromLargestLineStrip();
            List<Point> surfacedPoints = surfacedPolygon.contours[0].points;

            List<PolygonPoint> ppoints = new List<PolygonPoint>(surfacedPoints.Count);
            for (int k=0;k<surfacedPoints.Count;k++) {
                double x = surfacedPoints[k].x+2;
                double y = surfacedPoints[k].y+2;
                if (!IsTooNearPolygon(x, y, ppoints)) {
                    float h = _terrain!=null ? _terrain.SampleHeight(transform.TransformPoint((float)x-2, (float)y-2,0)): 0;
                    ppoints.Add (new PolygonPoint(x, y, h));
                }
            }
            Poly2Tri.Polygon poly = new Poly2Tri.Polygon(ppoints);

            if (_terrain!=null) {
                if (steinerPoints==null) {
                    steinerPoints = new List<TriangulationPoint>(6000);
                } else {
                    steinerPoints.Clear();
                }

                float stepX = 1.0f / heightMapWidth;
                float smallStep = 1.0f / heightMapWidth;
                float y = region.rect2D.yMin + smallStep;
                float ymax = region.rect2D.yMax - smallStep;
                float[] acumY = new float[terrainRoughnessMapWidth];
                while(y<ymax) {
                    int j = (int)((y + 0.5f) * terrainRoughnessMapHeight); // * heightMapHeight)) / TERRAIN_CHUNK_SIZE;
                    if (j>=0) {
                    if (j>=terrainRoughnessMapHeight) j=terrainRoughnessMapHeight-1;
                    float sy = y + 2;
                    float xin = GetFirstPointInRow(sy, ppoints) + smallStep;
                    float xout = GetLastPointInRow(sy, ppoints) - smallStep;
                    int k0 = -1;
                    for (float x = xin; x<xout; x+=stepX) {
                        int k = (int)((x + 0.5f) * terrainRoughnessMapWidth); //)) / TERRAIN_CHUNK_SIZE;
                        if (k>=terrainRoughnessMapWidth) k=terrainRoughnessMapWidth-1;
                        if (k0!=k) {
                            k0=k;
                            stepX = terrainRoughnessMap[j,k];
                            if (acumY[k] >= stepX) acumY[k] = 0;
                            acumY[k] += smallStep;
                        }
                        if (acumY[k] >= stepX) {
                            // Gather precision height
                            float h = _terrain.SampleHeight (transform.TransformPoint(x,y,0));
                            float htl = _terrain.SampleHeight (transform.TransformPoint (x-smallStep, y+smallStep, 0));
                            if (htl>h) h = htl;
                            float htr = _terrain.SampleHeight (transform.TransformPoint (x+smallStep, y+smallStep, 0));
                            if (htr>h) h = htr;
                            float hbr = _terrain.SampleHeight (transform.TransformPoint (x+smallStep, y-smallStep, 0));
                            if (hbr>h) h = hbr;
                            float hbl = _terrain.SampleHeight (transform.TransformPoint (x-smallStep, y-smallStep, 0));
                            if (hbl>h) h = hbl;
                            steinerPoints.Add (new PolygonPoint (x+2, sy, h));
                        }
                    }
                    }
                    y += smallStep;
                    if (steinerPoints.Count>80000) {
                        break;
                    }
                }
                poly.AddSteinerPoints(steinerPoints);
            }

            P2T.Triangulate(poly);

            // Calculate & optimize mesh data
            int pointCount = poly.Triangles.Count*3;
            List<Vector3> meshPoints = new List<Vector3> (pointCount);
            int[] triNew = new int[pointCount];
            if (surfaceMeshHit == null)
                surfaceMeshHit = new Dictionary<TriangulationPoint, int> (2000);
            else
                surfaceMeshHit.Clear ();

            int triNewIndex =-1;
            int newPointsCount = -1;

            if (_gridNormalOffset>0) {
                for (int k=0;k<poly.Triangles.Count;k++) {
                    DelaunayTriangle dt = poly.Triangles[k];
                    TriangulationPoint p = dt.Points [0];
                    if (surfaceMeshHit.ContainsKey (p)) {
                        triNew [++triNewIndex] = surfaceMeshHit [p];
                    } else {
                        Vector3 np = new Vector3(p.Xf-2, p.Yf-2, -p.Zf);
                        np += transform.InverseTransformVector(_terrain.terrainData.GetInterpolatedNormal(np.x+0.5f,np.y+0.5f)) * _gridNormalOffset;
                        meshPoints.Add (np);
                        surfaceMeshHit.Add (p, ++newPointsCount);
                        triNew [++triNewIndex] = newPointsCount;
                    }
                    p = dt.Points [2];
                    if (surfaceMeshHit.ContainsKey (p)) {
                        triNew [++triNewIndex] = surfaceMeshHit [p];
                    } else {
                        Vector3 np = new Vector3(p.Xf-2, p.Yf-2, -p.Zf);
                        np += transform.InverseTransformVector(_terrain.terrainData.GetInterpolatedNormal(np.x+0.5f,np.y+0.5f)) * _gridNormalOffset;
                        meshPoints.Add (np);
                        surfaceMeshHit.Add (p, ++newPointsCount);
                        triNew [++triNewIndex] = newPointsCount;
                    }
                    p = dt.Points [1];
                    if (surfaceMeshHit.ContainsKey (p)) {
                        triNew [++triNewIndex] = surfaceMeshHit [p];
                    } else {
                        Vector3 np = new Vector3(p.Xf-2, p.Yf-2, -p.Zf);
                        np += transform.InverseTransformVector(_terrain.terrainData.GetInterpolatedNormal(np.x+0.5f,np.y+0.5f)) * _gridNormalOffset;
                        meshPoints.Add (np);
                        surfaceMeshHit.Add (p, ++newPointsCount);
                        triNew [++triNewIndex] = newPointsCount;
                    }
                }
            } else {
                for (int k=0;k<poly.Triangles.Count;k++) {
                    DelaunayTriangle dt = poly.Triangles[k];
                    TriangulationPoint p = dt.Points [0];
                    if (surfaceMeshHit.ContainsKey (p)) {
                        triNew [++triNewIndex] = surfaceMeshHit [p];
                    } else {
                        Vector3 np = new Vector3(p.Xf-2, p.Yf-2, -p.Zf);
                        meshPoints.Add (np);
                        surfaceMeshHit.Add (p, ++newPointsCount);
                        triNew [++triNewIndex] = newPointsCount;
                    }
                    p = dt.Points [2];
                    if (surfaceMeshHit.ContainsKey (p)) {
                        triNew [++triNewIndex] = surfaceMeshHit [p];
                    } else {
                        Vector3 np = new Vector3(p.Xf-2, p.Yf-2, -p.Zf);
                        meshPoints.Add (np);
                        surfaceMeshHit.Add (p, ++newPointsCount);
                        triNew [++triNewIndex] = newPointsCount;
                    }
                    p = dt.Points [1];
                    if (surfaceMeshHit.ContainsKey (p)) {
                        triNew [++triNewIndex] = surfaceMeshHit [p];
                    } else {
                        Vector3 np = new Vector3(p.Xf-2, p.Yf-2, -p.Zf);
                        meshPoints.Add (np);
                        surfaceMeshHit.Add (p, ++newPointsCount);
                        triNew [++triNewIndex] = newPointsCount;
                    }
                }
            }

            int cacheIndex = GetCacheIndexForCellRegion (cellIndex);
            string cacheIndexSTR = cacheIndex.ToString();
            // Deletes potential residual surface
            Transform t = surfacesLayer.transform.FindChild(cacheIndexSTR);
            if (t!=null) DestroyImmediate(t.gameObject);
            GameObject surf = Drawing.CreateSurface (cacheIndexSTR, meshPoints.ToArray(), triNew, material);
            _lastVertexCount += surf.GetComponent<MeshFilter>().sharedMesh.vertexCount;
            surf.transform.SetParent (surfacesLayer.transform, false);
            surf.transform.localPosition = Vector3.zero;
            surf.layer = gameObject.layer;
            if (surfaces.ContainsKey(cacheIndex)) surfaces.Remove(cacheIndex);
            surfaces.Add (cacheIndex, surf);
            return surf;
        }
Пример #21
0
 public PolygonInfo(string name, Polygon polygon)
 {
     Name    = name;
     Polygon = polygon;
     Triangulate();
 }
Пример #22
0
        // createFluidBody
        public void createFluidBody(List<Vector2> polygonPoints)
        {
            List<PolygonPoint> P2TPoints = new List<PolygonPoint>();
            Polygon polygon;
            Vector2 topLeft = polygonPoints[0];
            Vector2 bottomRight = polygonPoints[0];
            float spacing = RADIUS / 3.7f;
            Random random = new Random();

            foreach (Vector2 point in polygonPoints)
            {
                topLeft = Vector2.Min(topLeft, point);
                bottomRight = Vector2.Max(bottomRight, point);
                P2TPoints.Add(new PolygonPoint(point.X, point.Y));
            }
            polygon = new Polygon(P2TPoints);

            for (float i = topLeft.X; i < bottomRight.X; i += spacing)
            {
                for (float j = topLeft.Y; j < bottomRight.Y; j += spacing)
                {
                    Vector2 jitter = new Vector2(-1 + (float)random.NextDouble() * 2, -1 + (float)random.NextDouble() * 2) * (spacing * 0.2f);
                    Vector2 point = new Vector2(i, j) + jitter;
                    if (polygon.IsPointInside(new PolygonPoint(point.X, point.Y)))
                        createParticle(point, Vector2.Zero);
                }
            }
        }
Пример #23
0
        /// <summary>
        /// triangulate polygon, algorithm from wiki is fast enough
        /// http://wiki.unity3d.com/index.php?title=Triangulator
        /// </summary>
        /// <returns></returns>
        public List<int> Triangulate()
        {
            // no holes supported
            if (holes.Count == 0)
            {
                var indices = new List<int>(Points.Length);

                int n = Points.Length;
                if (n < 3)
                    return indices;

                var V = new int[n];
                if (Area > 0)
                {
                    for (int v = 0; v < n; v++)
                        V[v] = v;
                }
                else
                {
                    for (int v = 0; v < n; v++)
                        V[v] = (n - 1) - v;
                }

                int nv = n;
                int count = 2*nv;
                for (int m = 0, v = nv - 1; nv > 2;)
                {
                    if ((count--) <= 0)
                        return indices;

                    int u = v;
                    if (nv <= u)
                        u = 0;
                    v = u + 1;
                    if (nv <= v)
                        v = 0;
                    int w = v + 1;
                    if (nv <= w)
                        w = 0;

                    if (Snip(u, v, w, nv, V))
                    {
                        int a, b, c, s, t;
                        a = V[u];
                        b = V[v];
                        c = V[w];
                        indices.Add(a);
                        indices.Add(b);
                        indices.Add(c);
                        m++;
                        for (s = v, t = v + 1; t < nv; s++, t++)
                            V[s] = V[t];
                        nv--;
                        count = 2*nv;
                    }
                }

                indices.Reverse();
                return indices;
            }
            else
            {
                // use poly2tri library to triangulate mesh with holes

                var p2tPoints = new List<Poly2Tri.PolygonPoint>(Points.Length);

                foreach (var point in Points)
                {
                    p2tPoints.Add(new Poly2Tri.PolygonPoint(point.x, point.y));
                }

                // create p2t polygon
                var p2tPolygon = new Poly2Tri.Polygon(p2tPoints);

                // add holes
                foreach (var polygonHole in holes)
                {
                    var p2tHolePoints = new List<Poly2Tri.PolygonPoint>(polygonHole.Points.Length);

                    foreach (var polygonPoint in polygonHole.Points)
                    {
                        p2tHolePoints.Add(new Poly2Tri.PolygonPoint(polygonPoint.x, polygonPoint.y));
                    }

                    p2tPolygon.AddHole(new Poly2Tri.Polygon(p2tHolePoints));
                }

                try
                {
                    Poly2Tri.P2T.Triangulate(p2tPolygon);
                }
                catch (Exception ex)
                {
                    ExploderUtils.Log("P2T Exception: " + ex);
                    return null;
                }

                var triangles = p2tPolygon.Triangles.Count;

                var indices = new List<int>(triangles*3);
                Points = new Vector2[triangles*3];
                var j = 0;

                // recalc min max
                Min.x = float.MaxValue;
                Min.y = float.MaxValue;
                Max.x = float.MinValue;
                Max.y = float.MinValue;

                for (int i = 0; i < triangles; i++)
                {
                    indices.Add((j + 0));
                    indices.Add((j + 1));
                    indices.Add((j + 2));

                    Points[j + 2].x = (float)p2tPolygon.Triangles[i].Points._0.X;
                    Points[j + 2].y = (float)p2tPolygon.Triangles[i].Points._0.Y;

                    Points[j + 1].x = (float)p2tPolygon.Triangles[i].Points._1.X;
                    Points[j + 1].y = (float)p2tPolygon.Triangles[i].Points._1.Y;

                    Points[j + 0].x = (float)p2tPolygon.Triangles[i].Points._2.X;
                    Points[j + 0].y = (float)p2tPolygon.Triangles[i].Points._2.Y;

                    // recalc min max
                    for (int k = 0; k < 3; k++)
                    {
                        if (Points[j + k].x < Min.x)
                        {
                            Min.x = Points[j + k].x;
                        }
                        if (Points[j + k].y < Min.y)
                        {
                            Min.y = Points[j + k].y;
                        }
                        if (Points[j + k].x > Max.x)
                        {
                            Max.x = Points[j + k].x;
                        }
                        if (Points[j + k].y > Max.y)
                        {
                            Max.y = Points[j + k].y;
                        }
                    }

                    j += 3;
                }

                return indices;
            }
        }
Пример #24
0
 public static void Triangulate(Polygon p)
 {
     Triangulate(_defaultAlgorithm, p);
 }
Пример #25
0
    /// <summary>
    /// Create a Mesh from a given Polygon.
    /// </summary>
    /// <returns>The freshly minted mesh.</returns>
    /// <param name="polygon">Polygon you want to triangulate.</param>
    public static Mesh CreateMesh(Polygon polygon)
    {
        // Ensure we have the rotation properly calculated
        if (polygon.rotation == Quaternion.identity) polygon.CalcRotation();

        // Rotate 1 point and note where it ends up in Z
        float z = (polygon.rotation * polygon.outside[0]).z;

        // Convert the outside points (throwing out Z at this point)
        Poly2Tri.Polygon poly = new Poly2Tri.Polygon(ConvertPoints(polygon.outside, polygon.rotation));

        // Convert each of the holes
        foreach (List<Vector3> hole in polygon.holes) {
            poly.AddHole(new Poly2Tri.Polygon(ConvertPoints(hole, polygon.rotation)));
        }

        // Triangulate it!  Note that this may throw an exception if the data is bogus.
        DTSweepContext tcx = new DTSweepContext();
        tcx.PrepareTriangulation(poly);
        DTSweep.Triangulate(tcx);
        tcx = null;

        // Create the Vector3 vertices (undoing the rotation),
        // and also build a map of vertex codes to indices
        Quaternion invRot = Quaternion.Inverse(polygon.rotation);
        Dictionary<uint, int> codeToIndex = new Dictionary<uint, int>();
        List<Vector3> vertexList = new List<Vector3>();
        foreach (DelaunayTriangle t in poly.Triangles) {
            foreach (var p in t.Points) {
                if (codeToIndex.ContainsKey(p.VertexCode)) continue;
                codeToIndex[p.VertexCode] = vertexList.Count;
                Vector3 pos = new Vector3(p.Xf, p.Yf, z);	// (restore the Z we saved earlier)
                vertexList.Add(invRot * pos);
            }
        }

        // Create the indices array
        int[] indices = new int[poly.Triangles.Count * 3];
        {
            int i = 0;
            foreach (DelaunayTriangle t in poly.Triangles) {
                indices[i++] = codeToIndex[t.Points[0].VertexCode];
                indices[i++] = codeToIndex[t.Points[1].VertexCode];
                indices[i++] = codeToIndex[t.Points[2].VertexCode];
            }
        }

        // Create the UV list, by looking up the closest point for each in our poly
        Mesh msh = new Mesh();
        msh.vertices = vertexList.ToArray();
        Vector2[] uvs = new Vector2[msh.vertices.Length];
        for (int i=0; i < uvs.Length; i++) {
            uvs[i] = new Vector2(msh.vertices[i].x, msh.vertices[i].y);
        }
        msh.uv = uvs;
        /*if (polygon.OutsideUVs != null) {
            uv = new Vector2[vertexList.Count];
            for (int i=0; i<vertexList.Count; i++) {
                uv[i] = polygon.ClosestUV(vertexList[i]);
            }
        }*/

        // Create the mesh

        msh.triangles = indices;
        msh.RecalculateNormals();
        msh.RecalculateBounds();
        return msh;
    }
Пример #26
0
		public PolygonSet(Polygon poly)
		{
			_polygons.Add(poly);
		}
Пример #27
0
    /// <summary>
    /// Create a Mesh from a given Polygon.
    /// </summary>
    /// <returns>The freshly minted mesh.</returns>
    /// <param name="polygon">Polygon you want to triangulate.</param>
    public static Mesh CreateMesh(Polygon polygon)
    {
        // Ensure we have the rotation properly calculated
        if (polygon.rotation == Quaternion.identity)
        {
            polygon.CalcRotation();
        }

        // Rotate 1 point and note where it ends up in Z
        float z = (polygon.rotation * polygon.outside[0]).z;

        // Convert the outside points (throwing out Z at this point)
        Poly2Tri.Polygon poly = new Poly2Tri.Polygon(ConvertPoints(polygon.outside, polygon.rotation));

        // Convert each of the holes
        foreach (List <Vector3> hole in polygon.holes)
        {
            poly.AddHole(new Poly2Tri.Polygon(ConvertPoints(hole, polygon.rotation)));
        }

        // Triangulate it!  Note that this may throw an exception if the data is bogus.
        DTSweepContext tcx = new DTSweepContext();

        tcx.PrepareTriangulation(poly);
        DTSweep.Triangulate(tcx);
        tcx = null;

        // Create the Vector3 vertices (undoing the rotation),
        // and also build a map of vertex codes to indices
        Quaternion             invRot      = Quaternion.Inverse(polygon.rotation);
        Dictionary <uint, int> codeToIndex = new Dictionary <uint, int>();
        List <Vector3>         vertexList  = new List <Vector3>();

        foreach (DelaunayTriangle t in poly.Triangles)
        {
            foreach (var p in t.Points)
            {
                if (codeToIndex.ContainsKey(p.VertexCode))
                {
                    continue;
                }
                codeToIndex[p.VertexCode] = vertexList.Count;
                Vector3 pos = new Vector3(p.Xf, p.Yf, z);                       // (restore the Z we saved earlier)
                vertexList.Add(invRot * pos);
            }
        }

        // Create the indices array
        int[] indices = new int[poly.Triangles.Count * 3];
        {
            int i = 0;
            foreach (DelaunayTriangle t in poly.Triangles)
            {
                indices[i++] = codeToIndex[t.Points[0].VertexCode];
                indices[i++] = codeToIndex[t.Points[1].VertexCode];
                indices[i++] = codeToIndex[t.Points[2].VertexCode];
            }
        }

        // Create the UV list, by looking up the closest point for each in our poly
        Vector2[] uv = null;
//		if (polygon.outsideUVs != null) {
//			uv = new Vector2[vertexList.Count];
//			for (int i=0; i<vertexList.Count; i++) {
//				uv[i] = polygon.ClosestUV(vertexList[i]);
//			}
//		}

        // Create the mesh
        Mesh msh = new Mesh();

        msh.vertices  = vertexList.ToArray();
        msh.triangles = indices;
        msh.uv        = uv;
        msh.RecalculateNormals();
        msh.RecalculateBounds();
        return(msh);
    }
Пример #28
0
		/// <summary>
		/// Add a hole to the polygon.
		/// </summary>
		/// <param name="poly">A subtraction polygon fully contained inside this polygon.</param>
		public void AddHole(Polygon poly)
		{
			if (_holes == null) _holes = new List<Polygon>();
			_holes.Add(poly);
			// XXX: tests could be made here to be sure it is fully inside
			//        addSubtraction( poly.getPoints() );
		}
Пример #29
0
    /// <summary>
    /// Create a Mesh from a given Polygon.
    /// </summary>
    /// <returns>The freshly minted mesh.</returns>
    /// <param name="polygon">Polygon you want to triangulate.</param>
    public static bool CreateMesh(List <Poly2Mesh.Polygon> polygons, ref Mesh dstMesh)
    {
        // TODO: use vertex indices instead of actual vertices to find original vertices

        var poly2TriPolygons = new List <Poly2Tri.Polygon>();
        var codeToPositions  = new List <Dictionary <uint, Vector3> >();
        var zs = new List <float>();

        // Ensure we have the rotation properly calculated, and have a valid normal
        for (int p = 0; p < polygons.Count; p++)
        {
            if (polygons[p].rotation == Quaternion.identity)
            {
                polygons[p].CalcRotation();
            }
            if (polygons[p].planeNormal == Vector3.zero)
            {
                Debug.Log("polygons[p].planeNormal == Vector3.zero");
                return(false);       // bad data
            }

            // Rotate 1 point and note where it ends up in Z
            float z = (polygons[p].rotation * polygons[p].outside[0]).z;

            // Prepare a map from vertex codes to 3D positions.
            Dictionary <uint, Vector3> codeToPosition = new Dictionary <uint, Vector3>();

            // Convert the outside points (throwing out Z at this point)
            Poly2Tri.Polygon poly = new Poly2Tri.Polygon(ConvertPoints(polygons[p].outside, polygons[p].rotation, codeToPosition));


            // Convert each of the holes
            if (polygons[p].holes != null)
            {
                foreach (List <Vector3> hole in polygons[p].holes)
                {
                    poly.AddHole(new Poly2Tri.Polygon(ConvertPoints(hole, polygons[p].rotation, codeToPosition)));
                }
            }

            codeToPositions.Add(codeToPosition);
            poly2TriPolygons.Add(poly);
            zs.Add(z);
        }

        // Triangulate it!  Note that this may throw an exception if the data is bogus.
        for (int p = 0; p < poly2TriPolygons.Count; p++)
        {
            try
            {
                DTSweepContext tcx = new DTSweepContext();
                tcx.PrepareTriangulation(poly2TriPolygons[p]);
                DTSweep.Triangulate(tcx);
                tcx = null;
            } catch (System.Exception e) {
                //Profiler.Exit(profileID);
                Debug.LogException(e);
                //throw e;
            }
        }

        // Now, to get back to our original positions, use our code-to-position map.  We do
        // this instead of un-rotating to be a little more robust about noncoplanar polygons.

        // Create the Vector3 vertices (undoing the rotation),
        // and also build a map of vertex codes to indices
        Quaternion?            invRot      = null;
        Dictionary <uint, int> codeToIndex = new Dictionary <uint, int>();
        List <Vector3>         vertexList  = new List <Vector3>();
        List <int>             indexList   = new List <int>();
        int triangleCount = 0;

        for (int p = 0; p < polygons.Count; p++)
        {
            var poly           = poly2TriPolygons[p];
            var polygon        = polygons[p];
            var z              = zs[p];
            var codeToPosition = codeToPositions[p];
            triangleCount += poly.Triangles.Count;
            codeToIndex.Clear();
            foreach (DelaunayTriangle t in poly.Triangles)
            {
                foreach (var point in t.Points)
                {
                    if (codeToIndex.ContainsKey(point.VertexCode))
                    {
                        continue;
                    }
                    codeToIndex[point.VertexCode] = vertexList.Count;
                    Vector3 pos;
                    if (!codeToPosition.TryGetValue(point.VertexCode, out pos))
                    {
                        // This can happen in rare cases when we're hitting limits of floating-point precision.
                        // Rather than fail, let's just do the inverse rotation.
                        Debug.LogWarning("Vertex code lookup failed; using inverse rotation.");
                        if (!invRot.HasValue)
                        {
                            invRot = Quaternion.Inverse(polygon.rotation);
                        }
                        pos = invRot.Value * new Vector3(point.Xf, point.Yf, z);
                    }
                    vertexList.Add(pos);
                }
            }
            if (polygon.inverse)
            {
                foreach (DelaunayTriangle t in poly.Triangles)
                {
                    indexList.Add(codeToIndex[t.Points[2].VertexCode]);
                    indexList.Add(codeToIndex[t.Points[1].VertexCode]);
                    indexList.Add(codeToIndex[t.Points[0].VertexCode]);
                }
            }
            else
            {
                foreach (DelaunayTriangle t in poly.Triangles)
                {
                    indexList.Add(codeToIndex[t.Points[0].VertexCode]);
                    indexList.Add(codeToIndex[t.Points[1].VertexCode]);
                    indexList.Add(codeToIndex[t.Points[2].VertexCode]);
                }
            }
        }

        // Create the indices array
        var indices = indexList.ToArray();

        // Create the mesh
        dstMesh.vertices  = vertexList.ToArray();
        dstMesh.triangles = indices;
        dstMesh.RecalculateNormals();
        return(true);
    }
Пример #30
0
        protected override Polygon GetPolygon()
        {
            Polygon poly = new Polygon(GetPoints());

            if (thickness > 1)
            {
                List<PolygonPoint> points = GetPoints();
                Vector2 center = GetCentroid(points);
                float[] angles = { AngleA(a, b, c), AngleB(a, b, c), AngleC(a, b, c) };
                int count = points.Count;

                for (int i = count; --i >= 0;)
                {
                    PolygonPoint point = points[i];

                    double vecX = center.X - point.X;
                    double vecY = center.Y - point.Y;
                    double invLen = 1d / Math.Sqrt((vecX * vecX) + (vecY * vecY));
                    vecX = vecX * invLen;
                    vecY = vecY * invLen;

                    float ratio = 1 - (angles[i] / 180);
                    float angleThickness = ratio * thickness;
                    point.X += vecX * angleThickness;
                    point.Y += vecY * angleThickness;
                }

                Polygon hole = new Polygon(points);
                poly.AddHole(hole);
            }

            return poly;
        }
Пример #31
0
 public PolygonInfo(string name, Polygon polygon)
 {
     Name = name;
     Polygon = polygon;
     Triangulate();
 }
Пример #32
0
    /// <summary>
    /// Creates a <see cref="PrimitiveType.TriangleList"/> of vertices which cover the interior of the
    /// specified <paramref name="points"/>. The path must be closed and describe a simple polygon.
    /// </summary>
    /// <param name="points">Points describing the border of a simple polygon.</param>
    /// <param name="zCoord">Z coordinate of the created vertices.</param>
    /// <param name="verts">Returns a <see cref="PrimitiveType.TriangleList"/> of vertices.</param>
    public static void Triangulate(PointF[] points, float zCoord, out PositionColoredTextured[] verts)
    {
      PointF[] pathPoints = AdjustPoints(points);
      if (pathPoints.Length < 3)
      {
        verts = null;
        return;
      }
      if (pathPoints.Length == 3)
      {
        verts = new PositionColoredTextured[3];

        verts[0].Position = new Vector3(pathPoints[0].X, pathPoints[0].Y, zCoord);
        verts[1].Position = new Vector3(pathPoints[1].X, pathPoints[1].Y, zCoord);
        verts[2].Position = new Vector3(pathPoints[2].X, pathPoints[2].Y, zCoord);
        return;
      }

      IList<DelaunayTriangle> polygons;
      try
      {
        // Triangulation can fail (i.e. polygon is self-intersecting)
        var poly = new Poly2Tri.Polygon(pathPoints.Select(p => new PolygonPoint(p.X, p.Y)));
        P2T.Triangulate(poly);
        polygons = poly.Triangles;
      }
      catch (Exception)
      {
        verts = null;
        return;
      }

      verts = new PositionColoredTextured[polygons.Count * 3];
      int offset = 0;
      foreach (DelaunayTriangle triangle in polygons)
      {
        verts[offset++].Position = new Vector3((float)triangle.Points[0].X, (float)triangle.Points[0].Y, zCoord);
        verts[offset++].Position = new Vector3((float)triangle.Points[1].X, (float)triangle.Points[1].Y, zCoord);
        verts[offset++].Position = new Vector3((float)triangle.Points[2].X, (float)triangle.Points[2].Y, zCoord);
      }
    }
 public PolygonSet(Polygon poly)
 {
     _polygons.Add(poly);
 }
Пример #34
0
        public IEnumerable <MapObject> Create(IDGenerator generator, Box box, ITexture texture, int roundDecimals)
        {
            var width   = box.Width;
            var length  = Math.Max(1, Math.Abs((int)box.Length));
            var height  = box.Height;
            var flatten = (float)_flattenFactor.Value;
            var text    = _text.GetValue();

            var family = _fontChooser.GetFontFamily();
            var style  = Enum.GetValues(typeof(FontStyle)).OfType <FontStyle>().FirstOrDefault(fs => family.IsStyleAvailable(fs));

            if (!family.IsStyleAvailable(style))
            {
                family = FontFamily.GenericSansSerif;
            }

            var set = new PolygonSet();

            var sizes = new List <RectangleF>();

            using (var bmp = new Bitmap(1, 1))
            {
                using (var g = System.Drawing.Graphics.FromImage(bmp))
                {
                    using (var font = new Font(family, length, style, GraphicsUnit.Pixel))
                    {
                        for (var i = 0; i < text.Length; i += 32)
                        {
                            using (var sf = new StringFormat(StringFormat.GenericTypographic))
                            {
                                var rem   = Math.Min(text.Length, i + 32) - i;
                                var range = Enumerable.Range(0, rem).Select(x => new CharacterRange(x, 1)).ToArray();
                                sf.SetMeasurableCharacterRanges(range);
                                var reg = g.MeasureCharacterRanges(text.Substring(i, rem), font, new RectangleF(0, 0, float.MaxValue, float.MaxValue), sf);
                                sizes.AddRange(reg.Select(x => x.GetBounds(g)));
                            }
                        }
                    }
                }
            }

            var xOffset = box.Start.DX;
            var yOffset = box.End.DY;

            for (var ci = 0; ci < text.Length; ci++)
            {
                var c    = text[ci];
                var size = sizes[ci];

                var gp = new GraphicsPath();
                gp.AddString(c.ToString(CultureInfo.InvariantCulture), family, (int)style, length, new PointF(0, 0), StringFormat.GenericTypographic);
                gp.Flatten(new System.Drawing.Drawing2D.Matrix(), flatten);

                var polygons = new List <Polygon>();
                var poly     = new List <PolygonPoint>();

                for (var i = 0; i < gp.PointCount; i++)
                {
                    var type  = gp.PathTypes[i];
                    var point = gp.PathPoints[i];

                    poly.Add(new PolygonPoint(point.X + xOffset, -point.Y + yOffset));

                    if ((type & 0x80) == 0x80)
                    {
                        polygons.Add(new Polygon(poly));
                        poly.Clear();
                    }
                }

                var     tri     = new List <Polygon>();
                Polygon polygon = null;
                foreach (var p in polygons)
                {
                    if (polygon == null)
                    {
                        polygon = p;
                        tri.Add(p);
                    }
                    else if (p.CalculateWindingOrder() != polygon.CalculateWindingOrder())
                    {
                        polygon.AddHole(p);
                    }
                    else
                    {
                        polygon = null;
                        tri.Add(p);
                    }
                }

                foreach (var pp in tri)
                {
                    try
                    {
                        P2T.Triangulate(pp);
                        set.Add(pp);
                    }
                    catch
                    {
                        // Ignore
                    }
                }

                xOffset += size.Width;
            }

            var zOffset = box.Start.Z;

            foreach (var polygon in set.Polygons)
            {
                foreach (var t in polygon.Triangles)
                {
                    var points = t.Points.Select(x => new Coordinate((decimal)x.X, (decimal)x.Y, zOffset).Round(roundDecimals)).ToList();

                    var faces = new List <Coordinate[]>();

                    // Add the vertical faces
                    var z = new Coordinate(0, 0, height).Round(roundDecimals);
                    for (var j = 0; j < points.Count; j++)
                    {
                        var next = (j + 1) % points.Count;
                        faces.Add(new[] { points[j], points[j] + z, points[next] + z, points[next] });
                    }
                    // Add the top and bottom faces
                    faces.Add(points.ToArray());
                    faces.Add(points.Select(x => x + z).Reverse().ToArray());

                    // Nothing new here, move along
                    var solid = new Solid(generator.GetNextObjectID())
                    {
                        Colour = Colour.GetRandomBrushColour()
                    };
                    foreach (var arr in faces)
                    {
                        var face = new Face(generator.GetNextFaceID())
                        {
                            Parent  = solid,
                            Plane   = new Plane(arr[0], arr[1], arr[2]),
                            Colour  = solid.Colour,
                            Texture = { Texture = texture }
                        };
                        face.Vertices.AddRange(arr.Select(x => new Vertex(x, face)));
                        face.UpdateBoundingBox();
                        face.AlignTextureToFace();
                        solid.Faces.Add(face);
                    }
                    solid.UpdateBoundingBox();
                    yield return(solid);
                }
            }
        }
 public void Add(Polygon p)
 {
     _polygons.Add(p);
 }
Пример #36
0
 public static void Triangulate(Polygon p)
 {
     Triangulate(_defaultAlgorithm, p);
 }
        GameObject GenerateTerritoryRegionSurface(int territoryIndex, Material material, Vector2 textureScale, Vector2 textureOffset, float textureRotation)
        {
            if (territoryIndex<0 || territoryIndex>=territories.Count) return null;
            Region region = territories [territoryIndex].region;

            // Calculate region's surface points
            int numSegments = region.segments.Count;
            Connector connector = new Connector();
            if (_terrain==null) {
                connector.AddRange(region.segments);
            } else {
                for (int i = 0; i<numSegments; i++) {
                    Segment s = region.segments[i];
                    SurfaceSegmentForSurface(s, connector);
                }
            }
            Geom.Polygon surfacedPolygon = connector.ToPolygonFromLargestLineStrip();
            List<Point> surfacedPoints = surfacedPolygon.contours[0].points;

            List<PolygonPoint> ppoints = new List<PolygonPoint>(surfacedPoints.Count);
            for (int k=0;k<surfacedPoints.Count;k++) {
                double x = surfacedPoints[k].x+2;
                double y = surfacedPoints[k].y+2;
                if (!IsTooNearPolygon(x, y, ppoints)) {
                    float h = _terrain!=null ? _terrain.SampleHeight(transform.TransformPoint((float)x-2, (float)y-2,0)): 0;
                    ppoints.Add (new PolygonPoint(x, y, h));
                }
            }
            Poly2Tri.Polygon poly = new Poly2Tri.Polygon(ppoints);

            if (_terrain!=null) {

                if (steinerPoints==null) {
                    steinerPoints = new List<TriangulationPoint>(6000);
                } else {
                    steinerPoints.Clear();
                }

                float stepX = 1.0f / heightMapWidth;
                float smallStep = 1.0f / heightMapWidth;
                float y = region.rect2D.yMin + smallStep;
                float ymax = region.rect2D.yMax - smallStep;
                float[] acumY = new float[terrainRoughnessMapWidth];
                while(y<ymax) {
                    int j = (int)((y + 0.5f) * terrainRoughnessMapHeight); // * heightMapHeight)) / TERRAIN_CHUNK_SIZE;
                    if (j>=terrainRoughnessMapHeight) j=terrainRoughnessMapHeight-1;
                    float sy = y + 2;
                    float xin = GetFirstPointInRow(sy, ppoints) + smallStep;
                    float xout = GetLastPointInRow(sy, ppoints) - smallStep;
                    int k0 = -1;
                    for (float x = xin; x<xout; x+=stepX) {
                        int k = (int)((x + 0.5f) * terrainRoughnessMapWidth); //)) / TERRAIN_CHUNK_SIZE;
                        if (k>=terrainRoughnessMapWidth) k=terrainRoughnessMapWidth-1;
                        if (k0!=k) {
                            k0=k;
                            stepX = terrainRoughnessMap[j,k];
                            if (acumY[k] >= stepX) acumY[k] = 0;
                            acumY[k] += smallStep;
                        }
                        if (acumY[k] >= stepX) {
                            // Gather precision height
                            float h = _terrain.SampleHeight (transform.TransformPoint(x,y,0));
                            float htl = _terrain.SampleHeight (transform.TransformPoint (x-smallStep, y+smallStep, 0));
                            if (htl>h) h = htl;
                            float htr = _terrain.SampleHeight (transform.TransformPoint (x+smallStep, y+smallStep, 0));
                            if (htr>h) h = htr;
                            float hbr = _terrain.SampleHeight (transform.TransformPoint (x+smallStep, y-smallStep, 0));
                            if (hbr>h) h = hbr;
                            float hbl = _terrain.SampleHeight (transform.TransformPoint (x-smallStep, y-smallStep, 0));
                            if (hbl>h) h = hbl;
                            steinerPoints.Add (new PolygonPoint (x+2, sy, h));
                        }
                    }
                    y += smallStep;
                    if (steinerPoints.Count>80000) {
                        break;
                    }
                }
                poly.AddSteinerPoints(steinerPoints);
            }

            P2T.Triangulate(poly);

            Vector3[] revisedSurfPoints = new Vector3[poly.Triangles.Count*3];

            if (_gridNormalOffset>0) {
                for (int k=0;k<poly.Triangles.Count;k++) {
                    DelaunayTriangle dt = poly.Triangles[k];
                    float x = dt.Points[0].Xf-2;
                    float y = dt.Points[0].Yf-2;
                    float z = -dt.Points[0].Zf;
                    Vector3 nd = transform.InverseTransformVector(_terrain.terrainData.GetInterpolatedNormal(x+0.5f,y+0.5f)) * _gridNormalOffset;
                    revisedSurfPoints[k*3].x = x + nd.x;
                    revisedSurfPoints[k*3].y = y + nd.y;
                    revisedSurfPoints[k*3].z = z + nd.z;

                    x = dt.Points[2].Xf-2;
                    y = dt.Points[2].Yf-2;
                    z = -dt.Points[2].Zf;
                    nd = transform.InverseTransformVector(_terrain.terrainData.GetInterpolatedNormal(x+0.5f,y+0.5f)) * _gridNormalOffset;
                    revisedSurfPoints[k*3+1].x = x + nd.x;
                    revisedSurfPoints[k*3+1].y = y + nd.y;
                    revisedSurfPoints[k*3+1].z = z + nd.z;

                    x = dt.Points[1].Xf-2;
                    y = dt.Points[1].Yf-2;
                    z = -dt.Points[1].Zf;
                    nd = transform.InverseTransformVector(_terrain.terrainData.GetInterpolatedNormal(x+0.5f,y+0.5f)) * _gridNormalOffset;
                    revisedSurfPoints[k*3+2].x = x + nd.x;
                    revisedSurfPoints[k*3+2].y = y + nd.y;
                    revisedSurfPoints[k*3+2].z = z + nd.z;
                }
            } else {
                for (int k=0;k<poly.Triangles.Count;k++) {
                    DelaunayTriangle dt = poly.Triangles[k];
                    revisedSurfPoints[k*3].x = dt.Points[0].Xf-2;
                    revisedSurfPoints[k*3].y = dt.Points[0].Yf-2;
                    revisedSurfPoints[k*3].z = -dt.Points[0].Zf;
                    revisedSurfPoints[k*3+1].x = dt.Points[2].Xf-2;
                    revisedSurfPoints[k*3+1].y = dt.Points[2].Yf-2;
                    revisedSurfPoints[k*3+1].z = -dt.Points[2].Zf;
                    revisedSurfPoints[k*3+2].x = dt.Points[1].Xf-2;
                    revisedSurfPoints[k*3+2].y = dt.Points[1].Yf-2;
                    revisedSurfPoints[k*3+2].z = -dt.Points[1].Zf;
                }
            }
            int cacheIndex = GetCacheIndexForTerritoryRegion (territoryIndex);
            string cacheIndexSTR = cacheIndex.ToString();
            // Deletes potential residual surface
            Transform t = surfacesLayer.transform.FindChild(cacheIndexSTR);
            if (t!=null) DestroyImmediate(t.gameObject);
            GameObject surf = Drawing.CreateSurface (cacheIndexSTR, revisedSurfPoints, material);
            surf.transform.SetParent (surfacesLayer.transform, false);
            surf.transform.localPosition = Vector3.zero;
            surf.layer = gameObject.layer;
            if (surfaces.ContainsKey(cacheIndex)) surfaces.Remove(cacheIndex);
            surfaces.Add (cacheIndex, surf);

            return surf;
        }
Пример #38
0
    /// <summary>
    /// Create a Mesh from a given Polygon.
    /// </summary>
    /// <returns>The freshly minted mesh.</returns>
    /// <param name="polygon">Polygon you want to triangulate.</param>
    public static Mesh CreateMesh(Polygon polygon)
    {
        // Check for the easy case (a triangle)
        if (polygon.holes.Count == 0 && (polygon.outside.Count == 3 ||
                                         (polygon.outside.Count == 4 && polygon.outside[3] == polygon.outside[0])))
        {
            return(CreateTriangle(polygon));
        }

        // Ensure we have the rotation properly calculated, and have a valid normal
        if (polygon.rotation == Quaternion.identity)
        {
            polygon.CalcRotation();
        }
        if (polygon.planeNormal == Vector3.zero)
        {
            return(null);                                                       // bad data
        }
        // Rotate 1 point and note where it ends up in Z
        float z = (polygon.rotation * polygon.outside[0]).z;

        // Prepare a map from vertex codes to 3D positions.
        Dictionary <uint, Vector3> codeToPosition = new Dictionary <uint, Vector3>();

        // Convert the outside points (throwing out Z at this point)
        Poly2Tri.Polygon poly = new Poly2Tri.Polygon(ConvertPoints(polygon.outside, polygon.rotation, codeToPosition));

        // Convert each of the holes
        foreach (List <Vector3> hole in polygon.holes)
        {
            poly.AddHole(new Poly2Tri.Polygon(ConvertPoints(hole, polygon.rotation, codeToPosition)));
        }

        // Triangulate it!  Note that this may throw an exception if the data is bogus.
        try {
            DTSweepContext tcx = new DTSweepContext();
            tcx.PrepareTriangulation(poly);
            DTSweep.Triangulate(tcx);
            tcx = null;
        } catch (System.Exception e) {
            throw e;
        }

        // Now, to get back to our original positions, use our code-to-position map.  We do
        // this instead of un-rotating to be a little more robust about noncoplanar polygons.

        // Create the Vector3 vertices (undoing the rotation),
        // and also build a map of vertex codes to indices
        Quaternion?            invRot      = null;
        Dictionary <uint, int> codeToIndex = new Dictionary <uint, int>();
        List <Vector3>         vertexList  = new List <Vector3>();

        foreach (DelaunayTriangle t in poly.Triangles)
        {
            foreach (var p in t.Points)
            {
                if (codeToIndex.ContainsKey(p.VertexCode))
                {
                    continue;
                }
                codeToIndex[p.VertexCode] = vertexList.Count;
                Vector3 pos;
                if (!codeToPosition.TryGetValue(p.VertexCode, out pos))
                {
                    // This can happen in rare cases when we're hitting limits of floating-point precision.
                    // Rather than fail, let's just do the inverse rotation.
                    if (!invRot.HasValue)
                    {
                        invRot = Quaternion.Inverse(polygon.rotation);
                    }
                    pos = invRot.Value * new Vector3(p.Xf, p.Yf, z);
                }
                vertexList.Add(pos);
            }
        }

        // Create the indices array
        int[] indices = new int[poly.Triangles.Count * 3];
        {
            int i = 0;
            foreach (DelaunayTriangle t in poly.Triangles)
            {
                indices[i++] = codeToIndex[t.Points[0].VertexCode];
                indices[i++] = codeToIndex[t.Points[1].VertexCode];
                indices[i++] = codeToIndex[t.Points[2].VertexCode];
            }
        }

        // Create the UV list, by looking up the closest point for each in our poly
        Vector2[] uv = null;
        if (polygon.outsideUVs != null)
        {
            uv = new Vector2[vertexList.Count];
            for (int i = 0; i < vertexList.Count; i++)
            {
                uv[i] = polygon.ClosestUV(vertexList[i]);
            }
        }

        // Create the mesh
        Mesh msh = new Mesh();

        msh.vertices  = vertexList.ToArray();
        msh.triangles = indices;
        msh.uv        = uv;
        msh.RecalculateNormals();
        msh.RecalculateBounds();
        return(msh);
    }
Пример #39
0
 /// <summary>Triangulate a polygon and return whether it was successful.</summary>
 private static bool Triangulate(Polygon polygon)
 {
     TextWriter console = Console.Out;
     Console.SetOut(Controller.TrashLog);
     try
     {
         P2T.Triangulate(polygon);
         Console.SetOut(console);
         return true;
     }
     catch (Exception ex)
     {
         if (ex.Message != "Error marking neighbors -- t doesn't contain edge p1-p2!")
         {
             Console.SetOut(console);
             Trace.TraceWarning("Polygon failed to triangulate.");
         }
         return false;
     }
 }