示例#1
0
    public void SetOutgoingRiver(VoronoiDirection direction)
    {
        if (_hasOutgoingRiver && _outgoingRiver == direction)
        {
            return;
        }

        VoronoiCell neighbor = GetNeighbor(direction);

        if (!neighbor || _elevation < neighbor._elevation)
        {
            return;
        }

        RemoveOutgoingRiver();
        if (_hasIncomingRiver && _incomingRiver == direction)
        {
            RemoveIncomingRiver();
        }

        _hasOutgoingRiver = true;
        _outgoingRiver    = direction;

        neighbor.RemoveIncomingRiver();
        neighbor._hasIncomingRiver = true;
        neighbor._incomingRiver    = direction.Opposite(this);

        SetRoad(direction, false);
    }
示例#2
0
 public void AddRoad(VoronoiDirection direction)
 {
     if (!Roads[direction] && !HasRiverThroughEdge(direction) && GetElevationDifference(direction) <= 1)
     {
         SetRoad(direction, true);
     }
 }
示例#3
0
    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));
    }
示例#4
0
 private void Triangulate(VoronoiCell cell)
 {
     for (VoronoiDirection d = 0; d < cell.Neighbors.Count; ++d)
     {
         Triangulate(cell, d);
     }
 }
示例#5
0
 private void SetRoad(VoronoiDirection direction, bool state)
 {
     Roads[direction] = state;
     Neighbors[direction].Roads[direction.Opposite(this)] = state;
     Neighbors[direction].RefreshSelfOnly();
     RefreshSelfOnly();
 }
示例#6
0
    private void TriangulateWithRiverBeginOrEnd(VoronoiCell cell, VoronoiDirection direction, Vector3 center, EdgeVertices e)
    {
        EdgeVertices m = new EdgeVertices(
            Vector3.Lerp(center, e.V1, 0.5f),
            Vector3.Lerp(center, e.V5, 0.5f)
            );

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

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

        bool reversed = cell.HasIncomingRiver;

        TriangulateRiverQuad(m.V2, m.V4, e.V2, e.V4, cell.RiverSurfaceElevation, 0.6f, reversed);

        center = Vector3.ClampMagnitude(center, cell.RiverSurfaceElevation);
        m.V2   = Vector3.ClampMagnitude(m.V2, cell.RiverSurfaceElevation);
        m.V4   = Vector3.ClampMagnitude(m.V4, cell.RiverSurfaceElevation);
        Rivers.AddTriangle(center, m.V2, m.V4);

        if (reversed)
        {
            Rivers.AddTriangleUV(new Vector2(0.5f, 0.4f), new Vector2(1f, 0.2f), new Vector2(0f, 0.2f));
        }
        else
        {
            Rivers.AddTriangleUV(new Vector2(0.5f, 0.4f), new Vector2(0f, 0.6f), new Vector2(1f, 0.6f));
        }
    }
示例#7
0
    public static Vector3 GetWaterBridge(VoronoiCell cell, VoronoiDirection direction)
    {
        Vector3     v1       = cell.transform.position.normalized * cell.WaterSurfaceElevation + GetFirstSolidCorner(cell, direction);
        VoronoiCell neighbor = cell.GetNeighbor(direction);
        Vector3     v2       = neighbor.transform.position.normalized * neighbor.WaterSurfaceElevation + GetSecondSolidCorner(neighbor, neighbor.Neighbors.IndexOf(cell));

        return(v2 - v1);
    }
示例#8
0
    public static Vector3 GetBridge(VoronoiCell cell, VoronoiDirection direction)
    {
        Vector3     v1       = cell.transform.localPosition + GetFirstSolidCorner(cell, direction);
        VoronoiCell neighbor = cell.GetNeighbor(direction);
        Vector3     v2       = neighbor.transform.localPosition + GetSecondSolidCorner(neighbor, neighbor.Neighbors.IndexOf(cell));

        return(v2 - v1);
    }
示例#9
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);
            }
        }
    }
示例#10
0
 public void RemoveRoads()
 {
     for (VoronoiDirection direction = 0; direction < Roads.Count; ++direction)
     {
         if (Roads[direction])
         {
             SetRoad(direction, false);
         }
     }
 }
示例#11
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);
        }
    }
示例#12
0
 private void ValidateDrag(VoronoiCell currentCell)
 {
     for (_dragDirection = 0; _dragDirection < currentCell.Neighbors.Count; ++_dragDirection)
     {
         if (_previousCell.GetNeighbor(_dragDirection) == currentCell)
         {
             _isDrag = true;
             return;
         }
     }
     _isDrag = false;
 }
示例#13
0
    private void TriangulateWithoutRiver(VoronoiCell cell, VoronoiDirection direction, Vector3 center, EdgeVertices e)
    {
        TriangulateEdgeFan(center, e, cell.Color);

        if (cell.HasRoads)
        {
            Vector2 interpolators = GetRoadInterpolators(cell, direction);
            TriangulateRoad(
                center,
                Vector3.Lerp(center, e.V1, interpolators.x),
                Vector3.Lerp(center, e.V5, interpolators.y),
                e, cell.HasRoadThroughEdge(direction)
                );
        }
    }
示例#14
0
    private Vector2 GetRoadInterpolators(VoronoiCell cell, VoronoiDirection direction)
    {
        Vector2 interpolators;

        if (cell.HasRoadThroughEdge(direction))
        {
            interpolators.x = interpolators.y = 0.5f;
        }
        else
        {
            interpolators.x = cell.HasRoadThroughEdge(direction.Previous(cell)) ? 0.5f : 0.25f;
            interpolators.y = cell.HasRoadThroughEdge(direction.Next(cell)) ? 0.5f : 0.25f;
        }

        return(interpolators);
    }
示例#15
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);
        }
    }
示例#16
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)));
        }
    }
示例#17
0
    public bool HasRoadOnThisSideOfRiver(VoronoiDirection direction)
    {
        VoronoiDirection dir = direction;

        while (!HasRiverThroughEdge(dir))
        {
            if (HasRoadThroughEdge(dir))
            {
                return(true);
            }
            dir = dir.Previous(this);
        }
        dir = direction;
        while (!HasRiverThroughEdge(dir))
        {
            if (HasRoadThroughEdge(dir))
            {
                return(true);
            }
            dir = dir.Next(this);
        }
        return(false);
    }
示例#18
0
 public VoronoiEdgeType GetEdgeType(VoronoiDirection direction)
 {
     return(VoronoiMetrics.GetEdgeType(_elevation, Neighbors[direction]._elevation));
 }
示例#19
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);
    }
示例#20
0
 public static VoronoiDirection Next4(this VoronoiDirection direction, VoronoiCell cell)
 {
     return((VoronoiDirection)Mathf.Repeat(direction + 4, cell.Neighbors.Count));
 }
示例#21
0
 public bool HasRoadThroughEdge(VoronoiDirection direction)
 {
     return(Roads[direction]);
 }
示例#22
0
 public static VoronoiDirection Previous5(this VoronoiDirection direction, VoronoiCell cell)
 {
     return((VoronoiDirection)Mathf.Repeat(direction - 5, cell.Neighbors.Count));
 }
示例#23
0
 /// <summary>
 /// Get the direction to this cell from neighbor at direction.
 /// </summary>
 /// <param name="direction"></param>
 /// <param name="cell"></param>
 /// <returns></returns>
 public static VoronoiDirection Opposite(this VoronoiDirection direction, VoronoiCell cell)
 {
     return(cell.GetNeighbor(direction).Neighbors.IndexOf(cell));
 }
示例#24
0
    // Required to avoid reference comparisons in lists
    public override bool Equals(object obj)
    {
        VoronoiDirection item = (VoronoiDirection)obj;

        return(item != null && _direction.Equals(item._direction));
    }
示例#25
0
 public static Vector3 GetSecondSolidCorner(VoronoiCell cell, VoronoiDirection direction)
 {
     return(cell.Corners[direction + 1] * SolidFactor);
 }
示例#26
0
 public bool HasRiverThroughEdge(VoronoiDirection direction)
 {
     return(_hasIncomingRiver && _incomingRiver == direction ||
            _hasOutgoingRiver && _outgoingRiver == direction);
 }
示例#27
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);
    }
示例#28
0
    public int GetElevationDifference(VoronoiDirection direction)
    {
        int difference = _elevation - GetNeighbor(direction)._elevation;

        return(difference >= 0 ? difference : -difference);
    }
示例#29
0
    /// <summary>
    /// Sorts and aligns neighbors and corners.
    /// Flattens cell centers and adjusts corner vectors accordingly.
    /// </summary>
    /// <returns></returns>
    private IEnumerator FinalizeCells()
    {
        List <VoronoiCell> processed = new List <VoronoiCell> ();

        foreach (VoronoiCell cell in _cells)
        {
            // Sort Corners
            cell.Corners = cell.Corners
                           .OrderByDescending(x => (cell.transform.localPosition + x).ClockwiseAngle(cell.transform.localPosition))
                           .ToList();

            // Sort Neighbors
            cell.Neighbors = cell.Neighbors
                             .OrderByDescending(x => x.transform.position.ClockwiseAngle(cell.transform.position))
                             .ToList();

            // Allign Corners and Neighbors
            if ((cell.transform.localPosition + cell.Corners[0]).ClockwiseAngle(cell.transform.localPosition) <
                cell.Neighbors[0].transform.localPosition.ClockwiseAngle(cell.transform.localPosition))
            {
                cell.Neighbors.Rotate(1);
            }

            for (VoronoiDirection d = 0; d < cell.Neighbors.Count; ++d)
            {
                if (!processed.Contains(cell.GetNeighbor(d)))
                {
                    cell.EdgeConnections.Add(d);

                    if (!processed.Contains(cell.GetNeighbor(d.Next(cell))))
                    {
                        cell.CornerConnections.Add(d);
                    }
                }
            }

            processed.Add(cell);

            // Flatten cell
            Vector3 originalPosition = cell.transform.localPosition;
            Vector3 center           = Vector3.zero;
            foreach (Vector3 c in cell.Corners)
            {
                center += cell.transform.localPosition + c;
            }
            cell.transform.localPosition = center / cell.Corners.Count;

            // Correct corners and corner connections
            for (int i = 0; i < cell.Corners.Count; ++i)
            {
                cell.Corners[i] = cell.Corners[i] + (originalPosition - cell.transform.localPosition);
            }
            cell.Corners.Add(cell.Corners[0]);

            cell.BaseElevation = Radius;
            //cell.BaseElevation = cell.transform.localPosition.magnitude;
            cell.Elevation = 0;

            cell.Roads = new bool[cell.Neighbors.Count].ToList();

            switch (cell.Neighbors.Count)
            {
            case 3:
                cell.Color = Color.yellow;
                break;

            case 4:
                cell.Color = Color.blue;
                break;

            case 5:
                cell.Color = Color.green;
                break;

            case 7:
                cell.Color = Color.red;
                break;

            case 8:
                cell.Color = Color.magenta;
                break;

            case 9:
                cell.Color = Color.black;
                break;

            default:
                cell.Color = Color.white;
                break;
            }
        }

        yield return(null);
    }
示例#30
0
 public static Vector3 GetFirstCorner(VoronoiCell cell, VoronoiDirection direction)
 {
     return(cell.Corners[direction]);
 }