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, 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))); } }
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); }
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); }