예제 #1
0
    private TerrainParticles GenerateParticles(PSPolygon shape)
    {
        var     center = shape.Bounds.center;
        var     coords = new List <Vector2>();
        Vector2 coord;
        var     xMin = shape.Bounds.xMin;
        var     xMax = shape.Bounds.xMax;
        var     yMin = shape.Bounds.yMin;
        var     yMax = shape.Bounds.yMax;

        for (float x = xMin; x < xMax; x += 0.1f)
        {
            for (float y = yMin; y < yMax; y += 0.1f)
            {
                coord = new Vector2(x, y);
                if (shape.PointInPolygon(coord))
                {
                    coords.Add(coord);
                }
            }
        }
        if (coords.Count > maxParticles)
        {
            int everyNth = coords.Count / maxParticles + 1;
            coords = coords.Where((p, i) => i % everyNth == 0).ToList();
        }
        var mainTexUV    = coords.Select(c => terrainMesh.getMainTexUV(c, doNotWrapUV));
        var overlayTexUV = coords.Select(c => terrainMesh.getOverlayTexUV(c, doNotWrapUV, floorEdges));
        var colors       = coords.Select(c => terrainMesh.terrainTintColor(c, doNotWrapUV));

        return(new TerrainParticles(coords.ToArray(), mainTexUV.ToArray(), overlayTexUV.ToArray(), colors.ToArray(), center));
    }
    public static List <PSPolygon> ContourPolygons(List <Vector2> vertices, List <int> triangles)
    {
        Dictionary <string, Edge> edges = new Dictionary <string, Edge>();

        for (int i = 0; i < triangles.Count; i += 3)
        {
            for (int e = 0; e < 3; e++)
            {
                Edge edge = new Edge(triangles[i + e], triangles[i + e + 1 > i + 2 ? i : i + e + 1]);
                if (edges.ContainsKey(edge.key))
                {
                    edges.Remove(edge.key);
                }
                else
                {
                    edges.Add(edge.key, edge);
                }
            }
        }

        var lookup   = edges.Values.ToLookup(e => e.v0);
        var polygons = new List <PSPolygon>();

        if (edges.Count == 0)
        {
            return(polygons);
        }
        Edge       startEdge    = edges.Values.First();
        Edge       nextEdge     = startEdge;
        List <int> colliderPath = new List <int>();

        while (true)
        {
            colliderPath.Add(nextEdge.v0);
            var removed = edges.Remove(nextEdge.key);
            nextEdge = SelectEdge(vertices, nextEdge, lookup[nextEdge.v1]);

            if (nextEdge.key == startEdge.key)
            {
                var polygon = new PSPolygon(colliderPath.Select(index => vertices[index]));
                polygons.Add(polygon);

                colliderPath.Clear();
                if (edges.Count > 0)
                {
                    startEdge = edges.Values.First();
                    nextEdge  = startEdge;

                    continue;
                }

                break;
            }
        }

        return(polygons);
    }
예제 #3
0
    private void UpdateCaveBackground(Vector2[][] segments)
    {
        var outerSteps   = Mathf.FloorToInt(outerRadius * Mathf.PI * 2 / 4);
        var outerPolygon = Enumerable.Range(0, outerSteps).Select(i => {
            var angle = 2f * Mathf.PI * i / outerSteps;
            return(new Vector2(Mathf.Sin(angle), Mathf.Cos(angle)) * outerRadius);
        });
        var innerSteps   = Mathf.FloorToInt(innerRadius * Mathf.PI * 2 / 4);
        var innerPolygon = Enumerable.Range(0, innerSteps).Select(i => {
            var angle = -2f * Mathf.PI * i / innerSteps;
            return(new Vector2(Mathf.Sin(angle), Mathf.Cos(angle)) * innerRadius);
        });
        var area = new List <IEnumerable <Vector2> >(2);

        area.Add(outerPolygon);
        area.Add(innerPolygon);

        var constraint = new ConstraintOptions();

        constraint.ConformingDelaunay = true;
        var quality = new QualityOptions();

        quality.MaximumArea = 10;
        var data = segments.AsParallel().Select(segment => {
            var segmentPolygon = new PSPolygon(segment);
            var doNotWrapUV    = segmentPolygon.Bounds.center.x < 0 && segmentPolygon.Bounds.center.y < 0;
            var poly           = new Polygon();
            foreach (var polygon in PSClipperHelper.intersection(area, segment))
            {
                poly.Add(createContour(polygon));
            }
            var imesh     = poly.Triangulate(constraint, quality);
            var vertices  = new List <Vector2>();
            var triangles = new List <int>();
            getTriangles(imesh, ref vertices, ref triangles);
            var uv     = vertices.Select(v => getUV(v, doNotWrapUV)).ToList();
            var colors = vertices.Select(v => (Color32)backgroundTintColor(v, doNotWrapUV)).ToList();
            return(new { vertices, triangles, uv, colors });
        }).ToList();

        var currentIndex = 0;
        var tris         = new List <int>();

        foreach (var d in data)
        {
            tris.AddRange(d.triangles.Select(i => currentIndex + i));
            currentIndex += d.vertices.Count;
        }

        UpdateMesh(
            caveBackground,
            data.SelectMany(d => d.vertices).Select(v => (Vector3)v),
            data.SelectMany(d => d.uv),
            null,
            data.SelectMany(d => d.colors),
            tris);
    }
예제 #4
0
    private GameObject GenerateFragment(PSPolygon polygon)
    {
        TerrainPiece piece = Instantiate(terrainPieceTemplate, gameObject.transform.position, gameObject.transform.rotation);

        var poly = new Polygon();

        poly.Add(TerrainMesh.createContour(polygon.points));
        var quality = new QualityOptions();

        quality.MinimumAngle = 36;
        quality.MaximumAngle = 91;
        var imesh = poly.Triangulate(quality);

        List <Vector2> vertices  = new List <Vector2>();
        List <int>     triangles = new List <int>();

        getTriangles(imesh, ref vertices, ref triangles);

        var polygonBoundsCenter = polygon.Bounds.center;
        var doNotWrapUV         = polygonBoundsCenter.x < 0 && polygonBoundsCenter.y < 0;
        var floorEdges          = getFloorEdges(polygon);

        var uvs  = vertices.Select(v => getUV(v, doNotWrapUV)).ToArray();
        var uv2s = vertices.Select(v => getUV2(v, doNotWrapUV, floorEdges)).ToArray();

        UpdateMesh(
            piece.GetComponent <MeshFilter>(),
            vertices.Select(v => (Vector3)v),
            uvs,
            uv2s,
            vertices.Select(p => (Color32)terrainTintColor(p, doNotWrapUV)),
            triangles);
        UpdateMesh(
            piece.background,
            vertices.Select(v => (Vector3)v),
            uvs,
            uv2s,
            vertices.Select(p => (Color32)backgroundTintColor(p, doNotWrapUV)),
            triangles);

        PolygonCollider2D collider = piece.gameObject.AddComponent <PolygonCollider2D>();

        collider.SetPath(0, polygon.points);

        piece.terrainMesh = this;
        piece.doNotWrapUV = doNotWrapUV;
        piece.floorEdges  = floorEdges;

        piece.gameObject.SetActive(true);
        return(piece.gameObject);
    }
예제 #5
0
 private void DrawPolygon(PSPolygon polygon, Vector2 offset)
 {
     for (int i = 0; i < polygon.points.Length; i++)
     {
         if (i + 1 == polygon.points.Length)
         {
             Gizmos.DrawLine(polygon.points[i] + offset, polygon.points[0] + offset);
         }
         else
         {
             Gizmos.DrawLine(polygon.points[i] + offset, polygon.points[i + 1] + offset);
         }
     }
 }
예제 #6
0
    private static List <PSEdge> getCeilingEdges(PSPolygon polygon, float innerRadius)
    {
        var     ceilingEdges      = new List <PSEdge>();
        Vector2 previous          = polygon.points.Last();
        bool    previousIsCeiling = isCeilingPoint(previous, polygon, innerRadius);
        bool    currentIsCeiling;

        foreach (var p in polygon.points)
        {
            currentIsCeiling = isCeilingPoint(p, polygon, innerRadius);
            if ((currentIsCeiling || previousIsCeiling) && Vector3.Cross(previous, p).sqrMagnitude > 0)
            {
                ceilingEdges.Add(new PSEdge(previous, p));
            }
            previous          = p;
            previousIsCeiling = currentIsCeiling;
        }
        return(ceilingEdges);
    }
예제 #7
0
    private static List <PSEdge> getFloorEdges(PSPolygon polygon)
    {
        var     floorEdges      = new List <PSEdge>();
        Vector2 previous        = polygon.points.Last();
        bool    previousIsFloor = isFloorPoint(previous, polygon);
        bool    currentIsFloor;

        foreach (var p in polygon.points)
        {
            currentIsFloor = isFloorPoint(p, polygon);
            if ((currentIsFloor || previousIsFloor) && Vector3.Cross(previous, p).sqrMagnitude > 0)
            {
                floorEdges.Add(new PSEdge(previous, p));
            }
            previous        = p;
            previousIsFloor = currentIsFloor;
        }
        return(floorEdges);
    }
예제 #8
0
    private void GenerateTerrainTriangles(List <Vector2> points, out List <Vector2> vertices, out List <int> triangles)
    {
        var imesh     = new GenericMesher().Triangulate(points.Select(toVertex).ToList());
        var idToIndex = new Dictionary <int, int>();

        vertices  = new List <Vector2>();
        triangles = new List <int>();
        foreach (var triangle in imesh.Triangles)
        {
            if (!caveSystem.insideCave(PSPolygon.GetCenter(triangle.vertices.Select(toVector2).ToList())))
            {
                foreach (var v in triangle.vertices.Reverse())
                {
                    if (!idToIndex.ContainsKey(v.ID))
                    {
                        idToIndex.Add(v.ID, vertices.Count);
                        vertices.Add(toVector2(v));
                    }
                    triangles.Add(idToIndex[v.ID]);
                }
            }
        }
    }
예제 #9
0
 private static bool isCeilingPoint(Vector2 point, PSPolygon polygon, float innerRadius)
 {
     return(point.magnitude > innerRadius + 0.005f && polygon.PointInPolygon(point + (point.normalized * 0.005f)));
 }
예제 #10
0
 private static bool isFloorPoint(Vector2 point, PSPolygon polygon)
 {
     return(polygon.PointInPolygon(point + (point.normalized * -0.005f)));
 }
예제 #11
0
 public static List <PSPolygon> difference(PSPolygon subject, PSPolygon clip)
 {
     return(PSClipperHelper.difference(subject.points, clip.points).Select(p => new PSPolygon(p)).ToList());
 }