public Vector3 GetRiverMidpointOffset(VoronoiDirection direction)
    {
        VoronoiDirection prevRiver = direction;

        while (!HasRiverThroughEdge(prevRiver))
        {
            prevRiver = prevRiver.Previous(this);
        }

        int steps = 0;
        VoronoiDirection nextRiver = prevRiver;

        while (!HasRiverThroughEdge(nextRiver) || nextRiver == prevRiver)
        {
            nextRiver = nextRiver.Next(this);
            ++steps;
        }

        VoronoiDirection halfDirection = prevRiver;

        for (int i = 0; i < steps / 2; ++i)
        {
            halfDirection = halfDirection.Next(this);
        }

        if (steps % 2 == 0)
        {
            return(VoronoiMetrics.GetSolidEdgeMiddle(this, halfDirection) *
                   VoronoiMetrics.InnerToOuter(this, halfDirection));
        }
        return(VoronoiMetrics.GetSecondSolidCorner(this, halfDirection));
    }
Beispiel #2
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);
        }
    }
Beispiel #3
0
    private void TriangulateWater(VoronoiCell cell, VoronoiDirection direction, Vector3 center)
    {
        center = center.normalized * cell.WaterSurfaceElevation;
        Vector3 c1 = center + VoronoiMetrics.GetFirstSolidCorner(cell, direction);
        Vector3 c2 = center + VoronoiMetrics.GetSecondSolidCorner(cell, direction);

        Water.AddTriangle(center, c1, c2);

        if (cell.EdgeConnections.Contains(direction))
        {
            VoronoiCell neighbor = cell.GetNeighbor(direction);
            if (neighbor == null || !neighbor.IsUnderwater)
            {
                return;
            }

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

            Vector3 e1 = c1 + bridge;
            Vector3 e2 = c2 + bridge;

            Water.AddQuad(c1, c2, e1, e2);
        }

        if (cell.CornerConnections.Contains(direction))
        {
            VoronoiCell neighbor     = cell.GetNeighbor(direction);
            VoronoiCell nextNeighbor = cell.GetNeighbor(direction.Next(cell));

            if (neighbor == null || !neighbor.IsUnderwater || nextNeighbor == null || !nextNeighbor.IsUnderwater)
            {
                return;
            }

            Vector3 bridge = VoronoiMetrics.GetWaterBridge(cell, direction);
            Vector3 e2     = c2 + bridge;

            Water.AddTriangle(c2, e2, c2 + VoronoiMetrics.GetWaterBridge(cell, direction.Next(cell)));
        }
    }
Beispiel #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);
    }
Beispiel #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);
    }