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); }
public void AddRoad(VoronoiDirection direction) { if (!Roads[direction] && !HasRiverThroughEdge(direction) && GetElevationDifference(direction) <= 1) { SetRoad(direction, true); } }
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)); }
private void Triangulate(VoronoiCell cell) { for (VoronoiDirection d = 0; d < cell.Neighbors.Count; ++d) { Triangulate(cell, d); } }
private void SetRoad(VoronoiDirection direction, bool state) { Roads[direction] = state; Neighbors[direction].Roads[direction.Opposite(this)] = state; Neighbors[direction].RefreshSelfOnly(); RefreshSelfOnly(); }
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)); } }
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); }
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); }
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); } } }
public void RemoveRoads() { for (VoronoiDirection direction = 0; direction < Roads.Count; ++direction) { if (Roads[direction]) { SetRoad(direction, false); } } }
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); } }
private void ValidateDrag(VoronoiCell currentCell) { for (_dragDirection = 0; _dragDirection < currentCell.Neighbors.Count; ++_dragDirection) { if (_previousCell.GetNeighbor(_dragDirection) == currentCell) { _isDrag = true; return; } } _isDrag = false; }
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) ); } }
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); }
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); } }
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))); } }
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); }
public VoronoiEdgeType GetEdgeType(VoronoiDirection direction) { return(VoronoiMetrics.GetEdgeType(_elevation, Neighbors[direction]._elevation)); }
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); }
public static VoronoiDirection Next4(this VoronoiDirection direction, VoronoiCell cell) { return((VoronoiDirection)Mathf.Repeat(direction + 4, cell.Neighbors.Count)); }
public bool HasRoadThroughEdge(VoronoiDirection direction) { return(Roads[direction]); }
public static VoronoiDirection Previous5(this VoronoiDirection direction, VoronoiCell cell) { return((VoronoiDirection)Mathf.Repeat(direction - 5, cell.Neighbors.Count)); }
/// <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)); }
// Required to avoid reference comparisons in lists public override bool Equals(object obj) { VoronoiDirection item = (VoronoiDirection)obj; return(item != null && _direction.Equals(item._direction)); }
public static Vector3 GetSecondSolidCorner(VoronoiCell cell, VoronoiDirection direction) { return(cell.Corners[direction + 1] * SolidFactor); }
public bool HasRiverThroughEdge(VoronoiDirection direction) { return(_hasIncomingRiver && _incomingRiver == direction || _hasOutgoingRiver && _outgoingRiver == direction); }
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); }
public int GetElevationDifference(VoronoiDirection direction) { int difference = _elevation - GetNeighbor(direction)._elevation; return(difference >= 0 ? difference : -difference); }
/// <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); }
public static Vector3 GetFirstCorner(VoronoiCell cell, VoronoiDirection direction) { return(cell.Corners[direction]); }