예제 #1
0
    private void TriangulateRoadAdjacentToRiver(VoronoiCell cell, VoronoiDirection direction, Vector3 center, EdgeVertices e)
    {
        bool hasRoadThroughEdge = cell.HasRoadThroughEdge(direction);
        bool previousHasRiver   = cell.HasRiverThroughEdge(direction.Previous(cell));
        bool nextHasRiver       = cell.HasRiverThroughEdge(direction.Next(cell));

        Vector2 interpolators = GetRoadInterpolators(cell, direction);
        Vector3 roadCenter    = center;

        if (cell.HasRiverBeginOrEnd)
        {
            roadCenter -= VoronoiMetrics.GetSolidEdgeMiddle(cell, cell.RiverBeginOrEndDirection) * (1 / 3f);
        }
        else if (cell.IncomingRiver == cell.OutgoingRiver.Previous(cell))
        {
            roadCenter -= VoronoiMetrics.GetSecondCorner(cell, cell.IncomingRiver) * 0.2f;
        }
        else if (cell.IncomingRiver == cell.OutgoingRiver.Next(cell))
        {
            roadCenter -= VoronoiMetrics.GetFirstCorner(cell, cell.IncomingRiver) * 0.2f;
        }
        else if (cell.HasRoadOnThisSideOfRiver(direction))
        {
            Vector3 offset = cell.GetRiverMidpointOffset(direction);

            if (previousHasRiver && nextHasRiver)
            {
                roadCenter += offset * 0.7f;
                center     += offset * 0.5f;
            }
            else
            {
                roadCenter += offset * 0.5f;
                center     += offset * 0.2f;
            }
        }
        else
        {
            return;
        }

        Vector3 mL = Vector3.Lerp(roadCenter, e.V1, interpolators.x);
        Vector3 mR = Vector3.Lerp(roadCenter, e.V5, interpolators.y);

        TriangulateRoad(roadCenter, mL, mR, e, hasRoadThroughEdge);

        if (previousHasRiver)
        {
            TriangulateRoadEdge(roadCenter, center, mL);
        }
        if (nextHasRiver)
        {
            TriangulateRoadEdge(roadCenter, mR, center);
        }
    }
예제 #2
0
    private void TriangulateConnection(VoronoiCell cell, VoronoiDirection direction, EdgeVertices e1)
    {
        VoronoiCell neighbor = cell.GetNeighbor(direction);

        Vector3 bridge = VoronoiMetrics.GetBridge(cell, direction);

        EdgeVertices e2 = new EdgeVertices(
            e1.V1 + bridge,
            e1.V5 + bridge
            );

        if (cell.HasRiverThroughEdge(direction))
        {
            e2.V3 = Vector3.ClampMagnitude(e2.V3, neighbor.StreamBedElevation);
            TriangulateRiverQuad(e1.V2, e1.V4, e2.V2, e2.V4,
                                 cell.RiverSurfaceElevation, neighbor.RiverSurfaceElevation, 0.8f,
                                 cell.HasIncomingRiver && cell.IncomingRiver == direction
                                 );
        }

        if (cell.GetEdgeType(direction) == VoronoiEdgeType.Slope)
        {
            TriangulateEdgeTerraces(e1, cell, e2, neighbor, cell.HasRoadThroughEdge(direction));
        }
        else
        {
            TriangulateEdgeStrip(e1, cell.Color, e2, neighbor.Color, cell.HasRoadThroughEdge(direction));
        }

        VoronoiCell nextNeighbor = cell.GetNeighbor(direction.Next(cell));

        if (cell.CornerConnections.Contains(direction))
        {
            Vector3 v5 = e1.V5 + VoronoiMetrics.GetBridge(cell, direction.Next(cell));

            if (cell.Elevation <= neighbor.Elevation)
            {
                if (cell.Elevation <= nextNeighbor.Elevation)
                {
                    TriangulateCorner(e1.V5, cell, e2.V5, neighbor, v5, nextNeighbor);
                }
                else
                {
                    TriangulateCorner(v5, nextNeighbor, e1.V5, cell, e2.V5, neighbor);
                }
            }
            else if (neighbor.Elevation <= nextNeighbor.Elevation)
            {
                TriangulateCorner(e2.V5, neighbor, v5, nextNeighbor, e1.V5, cell);
            }
            else
            {
                TriangulateCorner(v5, nextNeighbor, e1.V5, cell, e2.V5, neighbor);
            }
        }
    }
예제 #3
0
    private void Triangulate(VoronoiCell cell, VoronoiDirection direction)
    {
        Vector3 center = cell.transform.localPosition;

        EdgeVertices e = new EdgeVertices(
            center + VoronoiMetrics.GetFirstSolidCorner(cell, direction),
            center + VoronoiMetrics.GetSecondSolidCorner(cell, direction)
            );

        if (cell.HasRiver)
        {
            if (cell.HasRiverThroughEdge(direction))
            {
                e.V3 = Vector3.ClampMagnitude(e.V3, cell.StreamBedElevation);
                if (cell.HasRiverBeginOrEnd)
                {
                    TriangulateWithRiverBeginOrEnd(cell, direction, center, e);
                }
                else
                {
                    TriangulateWithRiver(cell, direction, center, e);
                }
            }
            else
            {
                TriangulateAdjacentToRiver(cell, direction, center, e);
            }
        }
        else
        {
            TriangulateWithoutRiver(cell, direction, center, e);
        }

        if (cell.EdgeConnections.Contains(direction))
        {
            TriangulateConnection(cell, direction, e);
        }

        if (cell.IsUnderwater)
        {
            TriangulateWater(cell, direction, center);
        }
    }
예제 #4
0
    private void TriangulateWithRiver(VoronoiCell cell, VoronoiDirection direction, Vector3 center, EdgeVertices e)
    {
        Vector3 centerR;
        Vector3 centerL = centerR = center;

        // 4 sided straight
        if (cell.HasRiverThroughEdge(direction.Next2(cell)) && cell.HasRiverThroughEdge(direction.Previous2(cell)))
        {
            centerL = center + VoronoiMetrics.GetSolidEdgeMiddle(cell, direction.Previous(cell)) *
                      (0.25f * VoronoiMetrics.InnerToOuter(cell, direction.Previous(cell)));
            centerR = center + VoronoiMetrics.GetSolidEdgeMiddle(cell, direction.Next(cell)) *
                      (0.25f * VoronoiMetrics.InnerToOuter(cell, direction.Next(cell)));

            // 1 step turn
        }
        else if (cell.HasRiverThroughEdge(direction.Next(cell)))
        {
            centerL = center;
            centerR = Vector3.Lerp(center, e.V5, 2 / 3f);

            // 1 step turn
        }
        else if (cell.HasRiverThroughEdge(direction.Previous(cell)))
        {
            centerL = Vector3.Lerp(center, e.V1, 2 / 3f);
            centerR = center;

            // 2 step turn
        }
        else if (cell.HasRiverThroughEdge(direction.Next2(cell)))
        {
            centerL = center;
            centerR = center + VoronoiMetrics.GetSolidEdgeMiddle(cell, direction.Next(cell)) *
                      (0.5f * VoronoiMetrics.InnerToOuter(cell, direction.Next(cell)));

            // 2 step turn
        }
        else if (cell.HasRiverThroughEdge(direction.Previous2(cell)))
        {
            centerL = center + VoronoiMetrics.GetSolidEdgeMiddle(cell, direction.Previous(cell)) *
                      (0.5f * VoronoiMetrics.InnerToOuter(cell, direction.Previous(cell)));
            centerR = center;

            // 6 sided straight
        }
        else if (cell.HasRiverThroughEdge(direction.Next3(cell)) &&
                 cell.HasRiverThroughEdge(direction.Previous3(cell)))
        {
            centerL = center + VoronoiMetrics.GetFirstSolidCorner(cell, direction.Previous(cell)) * 0.25f;
            centerR = center + VoronoiMetrics.GetSecondSolidCorner(cell, direction.Next(cell)) * 0.25f;

            // 7 sided straight
        }
        else if (cell.HasRiverThroughEdge(direction.Previous3(cell)) &&
                 cell.HasRiverThroughEdge(direction.Next4(cell)) &&
                 cell.Neighbors.Count > 4)
        {
            centerL = center + VoronoiMetrics.GetFirstSolidCorner(cell, direction.Previous(cell)) * 0.25f;
            centerR = center + VoronoiMetrics.GetSolidEdgeMiddle(cell, direction.Next2(cell)) * 0.25f;

            // 7 sided straight
        }
        else if (cell.HasRiverThroughEdge(direction.Previous4(cell)) &&
                 cell.HasRiverThroughEdge(direction.Next3(cell)) &&
                 cell.Neighbors.Count > 4)
        {
            centerL = center + VoronoiMetrics.GetSolidEdgeMiddle(cell, direction.Previous2(cell)) * 0.25f;
            centerR = center + VoronoiMetrics.GetSecondSolidCorner(cell, direction.Next(cell)) * 0.25f;

            // 8 sided straight
        }
        else if (cell.HasRiverThroughEdge(direction.Previous4(cell)) &&
                 cell.HasRiverThroughEdge(direction.Next4(cell)) &&
                 cell.Neighbors.Count > 4)
        {
            centerL = center + VoronoiMetrics.GetSolidEdgeMiddle(cell, direction.Previous2(cell)) * 0.25f;
            centerR = center + VoronoiMetrics.GetSolidEdgeMiddle(cell, direction.Next2(cell)) * 0.25f;

            // 3 step turn
        }
        else if (cell.HasRiverThroughEdge(direction.Previous3(cell)) &&
                 cell.HasRiverThroughEdge(direction.Next5(cell)) &&
                 cell.Neighbors.Count > 5)
        {
            centerR = center + VoronoiMetrics.GetSecondSolidCorner(cell, direction.Next2(cell)) * 0.25f;
            centerL = center + VoronoiMetrics.GetFirstSolidCorner(cell, direction.Previous(cell)) * 0.25f;

            // 3 step turn
        }
        else if (cell.HasRiverThroughEdge(direction.Previous5(cell)) &&
                 cell.HasRiverThroughEdge(direction.Next3(cell)) &&
                 cell.Neighbors.Count > 5)
        {
            centerL = center + VoronoiMetrics.GetFirstSolidCorner(cell, direction.Previous2(cell)) * 0.25f;
            centerR = center + VoronoiMetrics.GetSecondSolidCorner(cell, direction.Next(cell)) * 0.25f;
        }

        center = Vector3.Lerp(centerL, centerR, 0.5f);


        EdgeVertices m = new EdgeVertices(
            Vector3.Lerp(centerL, e.V1, 0.5f),
            Vector3.Lerp(centerR, e.V5, 0.5f),
            1 / 6f
            );

        m.V3   = Vector3.ClampMagnitude(m.V3, cell.StreamBedElevation);
        center = Vector3.ClampMagnitude(center, cell.StreamBedElevation);

        TriangulateEdgeStrip(m, cell.Color, e, cell.Color);
        Terrain.AddTriangle(centerL, m.V1, m.V2);
        Terrain.AddTriangleColor(cell.Color);
        Terrain.AddQuad(centerL, center, m.V2, m.V3);
        Terrain.AddQuadColor(cell.Color);
        Terrain.AddQuad(center, centerR, m.V3, m.V4);
        Terrain.AddQuadColor(cell.Color);
        Terrain.AddTriangle(centerR, m.V4, m.V5);
        Terrain.AddTriangleColor(cell.Color);

        bool reversed = cell.IncomingRiver == direction;

        TriangulateRiverQuad(centerL, centerR, m.V2, m.V4, cell.RiverSurfaceElevation, 0.4f, reversed);
        TriangulateRiverQuad(m.V2, m.V4, e.V2, e.V4, cell.RiverSurfaceElevation, 0.6f, reversed);
    }
예제 #5
0
    private void TriangulateAdjacentToRiver(VoronoiCell cell, VoronoiDirection direction, Vector3 center, EdgeVertices e)
    {
        if (cell.HasRoads)
        {
            TriangulateRoadAdjacentToRiver(cell, direction, center, e);
        }

        // Inside two step turn
        if (cell.HasRiverThroughEdge(direction.Next(cell)) &&
            cell.HasRiverThroughEdge(direction.Previous(cell)))
        {
            if (cell.Neighbors.Count == 4)
            {
                center += VoronoiMetrics.GetSolidEdgeMiddle(cell, direction) *
                          (0.25f * VoronoiMetrics.InnerToOuter(cell, direction));
            }
            else
            {
                center += VoronoiMetrics.GetSolidEdgeMiddle(cell, direction) *
                          (0.5f * VoronoiMetrics.InnerToOuter(cell, direction));
            }

            // 6 sided adjacencies
        }
        else if (cell.Neighbors.Count == 6)
        {
            if (cell.HasRiverThroughEdge(direction.Next(cell)) &&
                cell.HasRiverThroughEdge(direction.Previous2(cell)))
            {
                center += VoronoiMetrics.GetFirstSolidCorner(cell, direction) * 0.25f;
            }
            else if (cell.HasRiverThroughEdge(direction.Previous(cell)) &&
                     cell.HasRiverThroughEdge(direction.Next2(cell)))
            {
                center += VoronoiMetrics.GetSecondSolidCorner(cell, direction) * 0.25f;
            }

            // 7 sided adjacencies
        }
        else if (cell.Neighbors.Count == 7)
        {
            if (cell.HasRiverThroughEdge(direction.Next(cell)) &&
                cell.HasRiverThroughEdge(direction.Previous2(cell)))
            {
                center += VoronoiMetrics.GetFirstSolidCorner(cell, direction) * 0.25f;
            }
            else if (cell.HasRiverThroughEdge(direction.Previous(cell)) &&
                     cell.HasRiverThroughEdge(direction.Next2(cell)))
            {
                center += VoronoiMetrics.GetSecondSolidCorner(cell, direction) * 0.25f;
            }
            else if (cell.HasRiverThroughEdge(direction.Next2(cell)) &&
                     cell.HasRiverThroughEdge(direction.Previous2(cell)))
            {
                center += VoronoiMetrics.GetSolidEdgeMiddle(cell, direction) * 0.25f;
            }
            else if (cell.HasRiverThroughEdge(direction.Next(cell)) &&
                     cell.HasRiverThroughEdge(direction.Previous3(cell)))
            {
                center += VoronoiMetrics.GetSolidEdgeMiddle(cell, direction.Previous(cell)) * 0.25f;
            }
            else if (cell.HasRiverThroughEdge(direction.Next3(cell)) &&
                     cell.HasRiverThroughEdge(direction.Previous(cell)))
            {
                center += VoronoiMetrics.GetSolidEdgeMiddle(cell, direction.Next(cell)) * 0.25f;
            }
        }
        else if (cell.Neighbors.Count == 8)
        {
            if (cell.HasRiverThroughEdge(direction.Next(cell)) &&
                cell.HasRiverThroughEdge(direction.Previous3(cell)))
            {
                center += VoronoiMetrics.GetSolidEdgeMiddle(cell, direction.Previous(cell)) * 0.25f;
            }
            else if (cell.HasRiverThroughEdge(direction.Next2(cell)) &&
                     cell.HasRiverThroughEdge(direction.Previous2(cell)))
            {
                center += VoronoiMetrics.GetSolidEdgeMiddle(cell, direction) * 0.25f;
            }
            else if (cell.HasRiverThroughEdge(direction.Next3(cell)) &&
                     cell.HasRiverThroughEdge(direction.Previous(cell)))
            {
                center += VoronoiMetrics.GetSolidEdgeMiddle(cell, direction.Next(cell)) * 0.25f;
            }
            else if (cell.HasRiverThroughEdge(direction.Previous(cell)) &&
                     cell.HasRiverThroughEdge(direction.Next4(cell)))
            {
                center += VoronoiMetrics.GetSecondSolidCorner(cell, direction.Next(cell)) * 0.25f;
            }
            else if (cell.HasRiverThroughEdge(direction.Previous2(cell)) &&
                     cell.HasRiverThroughEdge(direction.Next3(cell)))
            {
                center += VoronoiMetrics.GetSecondSolidCorner(cell, direction) * 0.25f;
            }
            else if (cell.HasRiverThroughEdge(direction.Previous3(cell)) &&
                     cell.HasRiverThroughEdge(direction.Next2(cell)))
            {
                center += VoronoiMetrics.GetFirstSolidCorner(cell, direction) * 0.25f;
            }
            else if (cell.HasRiverThroughEdge(direction.Previous4(cell)) &&
                     cell.HasRiverThroughEdge(direction.Next(cell)))
            {
                center += VoronoiMetrics.GetFirstSolidCorner(cell, direction.Previous(cell)) * 0.25f;
            }
            else if (cell.HasRiverThroughEdge(direction.Previous(cell)) &&
                     cell.HasRiverThroughEdge(direction.Next2(cell)))
            {
                center += VoronoiMetrics.GetSecondSolidCorner(cell, direction) * 0.25f;
            }
            else if (cell.HasRiverThroughEdge(direction.Previous2(cell)) &&
                     cell.HasRiverThroughEdge(direction.Next(cell)))
            {
                center += VoronoiMetrics.GetFirstSolidCorner(cell, direction) * 0.25f;
            }
        }

        EdgeVertices m = new EdgeVertices(
            Vector3.Lerp(center, e.V1, 0.5f),
            Vector3.Lerp(center, e.V5, 0.5f)
            );

        TriangulateEdgeStrip(m, cell.Color, e, cell.Color);
        TriangulateEdgeFan(center, m, cell.Color);
    }