private void TriangulateWithRiver(HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e) { Vector3 centerL, centerR; if (cell.HasRiverThroughEdge(direction.Opposite())) { centerL = center + HexMetrics.GetFirstSolidCorner(direction.Previous()) * 0.25f; centerR = center + HexMetrics.GetSecondSolidCorner(direction.Next()) * 0.25f; } else if (cell.HasRiverThroughEdge(direction.Next())) { centerL = center; centerR = Vector3.Lerp(center, e.v5, 2f / 3f); } else if (cell.HasRiverThroughEdge(direction.Previous())) { centerL = Vector3.Lerp(center, e.v1, 2f / 3f); centerR = center; } else if (cell.HasRiverThroughEdge(direction.Next2())) { centerL = center; centerR = center + HexMetrics.GetSolidEdgeMiddle(direction.Next()) * (0.5f * HexMetrics.innerToOuter); } else { centerL = center + HexMetrics.GetSolidEdgeMiddle(direction.Previous()) * (0.5f * HexMetrics.innerToOuter); centerR = center; } center = Vector3.Lerp(centerL, centerR, 0.5f); // Use alternative interpolation otherwise the river will appear pinched instead of straight EdgeVertices m = new EdgeVertices( Vector3.Lerp(centerL, e.v1, 0.5f), Vector3.Lerp(centerR, e.v5, 0.5f), 1f / 6f ); m.v3.y = center.y = e.v3.y; 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); if (!cell.IsUnderwater) { bool reversed = cell.IncomingRiver == direction; TriangulateRiverQuad(centerL, centerR, m.v2, m.v4, cell.RiverSurfaceY, 0.4f, reversed); TriangulateRiverQuad(m.v2, m.v4, e.v2, e.v4, cell.RiverSurfaceY, 0.6f, reversed); } }
/// <summary> /// Create the connection / bridge piece between cells /// </summary> /// <param name="direction">Direction of neighbor cell</param> /// <param name="cell">Current cell</param> /// <param name="v1">Cell first solid corner</param> /// <param name="v2">Cell second solid corner</param> private void TriangulateConnection(HexDirection direction, HexCell cell, EdgeVertices e1) { HexCell neighbor = cell.GetNeighbor(direction); //Ignore bridges for edges if (neighbor == null) { return; } Vector3 bridge = HexMetrics.GetBridge(direction); bridge.y = neighbor.Position.y - cell.Position.y; EdgeVertices e2 = new EdgeVertices( e1.v1 + bridge, e1.v5 + bridge ); if (cell.HasRiverThroughEdge(direction)) { e2.v3.y = neighbor.StreamBedY; if (!cell.IsUnderwater) { if (!neighbor.IsUnderwater) { TriangulateRiverQuad(e1.v2, e1.v4, e2.v2, e2.v4, cell.RiverSurfaceY, neighbor.RiverSurfaceY, 0.8f, cell.HasIncomingRiver && cell.IncomingRiver == direction); } else if (cell.Elevation > neighbor.WaterLevel) { TriangulateWaterfallInWater(e1.v2, e1.v4, e2.v2, e2.v4, cell.RiverSurfaceY, neighbor.RiverSurfaceY, neighbor.WaterSurfaceY); } else if (!neighbor.IsUnderwater && neighbor.Elevation > cell.WaterLevel) { TriangulateWaterfallInWater(e2.v4, e2.v2, e1.v4, e1.v2, neighbor.RiverSurfaceY, cell.RiverSurfaceY, cell.WaterSurfaceY); } } } if (cell.GetEdgeType(direction) == HexEdgeType.Slope) { TriangulateEdgeTerraces(e1, cell, e2, neighbor, cell.HasRoadThroughEdge(direction)); } else { TriangulateEdgeStrip(e1, cell.Color, e2, neighbor.Color, cell.HasRoadThroughEdge(direction)); } HexCell nextNeighbor = cell.GetNeighbor(direction.Next()); if (direction <= HexDirection.E && nextNeighbor != null) { Vector3 v5 = e1.v5 + HexMetrics.GetBridge(direction.Next()); v5.y = nextNeighbor.Position.y; 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); } } }