private void TriangulateEstuary(EdgeVertices e1, EdgeVertices e2, bool incomingRiver, Vector3 indices) { WaterShore.AddTriangle(e2.v1, e1.v2, e1.v1); WaterShore.AddTriangle(e2.v5, e1.v5, e1.v4); WaterShore.AddTriangleUV( new Vector2(0f, 1f), new Vector2(0f, 0f), new Vector2(0f, 0f) ); WaterShore.AddTriangleUV( new Vector2(0f, 1f), new Vector2(0f, 0f), new Vector2(0f, 0f) ); WaterShore.AddTriangleCellData(indices, weights2, weights1, weights1); WaterShore.AddTriangleCellData(indices, weights2, weights1, weights1); Estuaries.AddQuad(e2.v1, e1.v2, e2.v2, e1.v3); Estuaries.AddTriangle(e1.v3, e2.v2, e2.v4); Estuaries.AddQuad(e1.v3, e1.v4, e2.v4, e2.v5); Estuaries.AddQuadUV( new Vector2(0f, 1f), new Vector2(0f, 0f), new Vector2(1f, 1f), new Vector2(0f, 0f)); Estuaries.AddTriangleUV( new Vector2(0f, 0f), new Vector2(1f, 1f), new Vector2(1f, 1f)); Estuaries.AddQuadUV( new Vector2(0f, 0f), new Vector2(0f, 0f), new Vector2(1f, 1f), new Vector2(0f, 1f)); Estuaries.AddQuadCellData(indices, weights2, weights1, weights2, weights1); Estuaries.AddTriangleCellData(indices, weights1, weights2, weights2); Estuaries.AddQuadCellData(indices, weights1, weights2); if (incomingRiver) { Estuaries.AddQuadUV2( new Vector2(1.5f, 1f), new Vector2(0.7f, 1.15f), new Vector2(1f, 0.8f), new Vector2(0.5f, 1.1f)); Estuaries.AddTriangleUV2( new Vector2(0.5f, 1.1f), new Vector2(1f, 0.8f), new Vector2(0f, 0.8f)); Estuaries.AddQuadUV2( new Vector2(0.5f, 1.1f), new Vector2(0.3f, 1.15f), new Vector2(0f, 0.8f), new Vector2(-0.5f, 1f)); } else { Estuaries.AddQuadUV2( new Vector2(-0.5f, -0.2f), new Vector2(0.3f, -0.35f), new Vector2(0f, 0f), new Vector2(0.5f, -0.3f)); Estuaries.AddTriangleUV2( new Vector2(0.5f, -0.3f), new Vector2(0f, 0f), new Vector2(1f, 0f)); Estuaries.AddQuadUV2( new Vector2(0.5f, -0.3f), new Vector2(0.7f, -0.35f), new Vector2(1f, 0f), new Vector2(1.5f, -0.2f)); } }
/// <summary> /// Creates the estuary (when river meets shore) geometry. /// </summary> void TriangulateEstuary(EdgeVertices e1, EdgeVertices e2, bool incomingRiver, Vector3 indices) { // Some of the estuary is still water shore, namely one triangle on each side // that leaves the estuary itself with a trapezoid shape connecting the shore/river to water WaterShore.AddTriangle(e2.v1, e1.v2, e1.v1); WaterShore.AddTriangle(e2.v5, e1.v5, e1.v4); WaterShore.AddTriangleUV(new Vector2(0f, 1f), new Vector2(0f, 0f), new Vector2(0f, 0f)); WaterShore.AddTriangleUV(new Vector2(0f, 1f), new Vector2(0f, 0f), new Vector2(0f, 0f)); WaterShore.AddTriangleCellData(indices, weights2, weights1, weights1); WaterShore.AddTriangleCellData(indices, weights2, weights1, weights1); // Make the estuary trapezoid Estuaries.AddQuad(e2.v1, e1.v2, e2.v2, e1.v3); // Adding it rotated for symetric geometry Estuaries.AddTriangle(e1.v3, e2.v2, e2.v4); Estuaries.AddQuad(e1.v3, e1.v4, e2.v4, e2.v5); // For shore effect Estuaries.AddQuadUV( new Vector2(0f, 1f), new Vector2(0f, 0f), new Vector2(1f, 1f), new Vector2(0f, 0f) ); Estuaries.AddTriangleUV( new Vector2(0f, 0f), new Vector2(1f, 1f), new Vector2(1f, 1f) ); Estuaries.AddQuadUV( new Vector2(0f, 0f), new Vector2(0f, 0f), new Vector2(1f, 1f), new Vector2(0f, 1f) ); Estuaries.AddQuadCellData(indices, weights2, weights1, weights2, weights1); Estuaries.AddTriangleCellData(indices, weights1, weights2, weights2); Estuaries.AddQuadCellData(indices, weights1, weights2); // For river effect, depending on river flow direction UVs are different // That is if river flows into the water or out of the water (e.g. when a river starts from a lake) if (incomingRiver) { Estuaries.AddQuadUV2(new Vector2(1.5f, 1f), new Vector2(0.7f, 1.15f), new Vector2(1f, 0.8f), new Vector2(0.5f, 1.1f)); Estuaries.AddTriangleUV2(new Vector2(0.5f, 1.1f), new Vector2(1f, 0.8f), new Vector2(0f, 0.8f)); Estuaries.AddQuadUV2(new Vector2(0.5f, 1.1f), new Vector2(0.3f, 1.15f), new Vector2(0f, 0.8f), new Vector2(-0.5f, 1f)); } else { Estuaries.AddQuadUV2(new Vector2(-0.5f, -0.2f), new Vector2(0.3f, -0.35f), new Vector2(0f, 0f), new Vector2(0.5f, -0.3f)); Estuaries.AddTriangleUV2(new Vector2(0.5f, -0.3f), new Vector2(0f, 0f), new Vector2(1f, 0f)); Estuaries.AddQuadUV2(new Vector2(0.5f, -0.3f), new Vector2(0.7f, -0.35f), new Vector2(1f, 0f), new Vector2(1.5f, -0.2f)); } }
/// <summary> /// Creates geometry for water connection non water cell. /// </summary> void TriangulateWaterShore(HexDirection direction, HexCell cell, HexCell neighbor, Vector3 center) { // Careful to find the WATER corner not the solid corner // Careful to get the WATER bridge EdgeVertices e1 = new EdgeVertices( center + HexMetrics.GetFirstWaterCorner(direction), center + HexMetrics.GetSecondWaterCorner(direction) ); // Triangle fan still part of open water Water.AddTriangle(center, e1.v1, e1.v2); Water.AddTriangle(center, e1.v2, e1.v3); Water.AddTriangle(center, e1.v3, e1.v4); Water.AddTriangle(center, e1.v4, e1.v5); Vector3 indices; indices.x = indices.z = cell.Index; indices.y = neighbor.Index; Water.AddTriangleCellData(indices, weights1); Water.AddTriangleCellData(indices, weights1); Water.AddTriangleCellData(indices, weights1); Water.AddTriangleCellData(indices, weights1); // Bridge - We get the bridge by finding the land hex center and working from there Vector3 center2 = neighbor.Position; if (neighbor.ColumnIndex < cell.ColumnIndex - 1) { center2.x += HexMetrics.WrapSize * HexMetrics.InnerDiameter; } else if (neighbor.ColumnIndex > cell.ColumnIndex + 1) { center2.x -= HexMetrics.WrapSize * HexMetrics.InnerDiameter; } center2.y = center.y; EdgeVertices e2 = new EdgeVertices( center2 + HexMetrics.GetSecondSolidCorner(direction.Opposite()), center2 + HexMetrics.GetFirstSolidCorner(direction.Opposite()) ); if (cell.HasRiverThroughEdge(direction)) { TriangulateEstuary(e1, e2, cell.HasIncomingRiver && cell.IncomingRiver == direction, indices); // River and Shore meet -> Estuary -> different geometry } else // Else normal shore geometry { WaterShore.AddQuad(e1.v1, e1.v2, e2.v1, e2.v2); WaterShore.AddQuad(e1.v2, e1.v3, e2.v2, e2.v3); WaterShore.AddQuad(e1.v3, e1.v4, e2.v3, e2.v4); WaterShore.AddQuad(e1.v4, e1.v5, e2.v4, e2.v5); WaterShore.AddQuadUV(0f, 0f, 0f, 1f); // U null, V -> 0 water side, 1 shore side WaterShore.AddQuadUV(0f, 0f, 0f, 1f); WaterShore.AddQuadUV(0f, 0f, 0f, 1f); WaterShore.AddQuadUV(0f, 0f, 0f, 1f); WaterShore.AddQuadCellData(indices, weights1, weights2); WaterShore.AddQuadCellData(indices, weights1, weights2); WaterShore.AddQuadCellData(indices, weights1, weights2); WaterShore.AddQuadCellData(indices, weights1, weights2); } // Corner tripple connection triangle - shore water HexCell nextNeighbor = cell.GetNeighbor(direction.Next()); if (nextNeighbor != null) { Vector3 center3 = nextNeighbor.Position; if (nextNeighbor.ColumnIndex < cell.ColumnIndex - 1) { center3.x += HexMetrics.WrapSize * HexMetrics.InnerDiameter; } else if (nextNeighbor.ColumnIndex > cell.ColumnIndex + 1) { center3.x -= HexMetrics.WrapSize * HexMetrics.InnerDiameter; } // Since this is a tripple connection we need to check if neighbor is underwater or not // If he is underwater connect with WaterCorner if not with SolidCorner Vector3 v3 = center3 + (nextNeighbor.IsUnderwater ? HexMetrics.GetFirstWaterCorner(direction.Previous()) : HexMetrics.GetFirstSolidCorner(direction.Previous())); v3.y = center.y; WaterShore.AddTriangle(e1.v5, e2.v5, v3); WaterShore.AddTriangleUV( new Vector2(0f, 0f), new Vector2(0f, 1f), new Vector2(0f, nextNeighbor.IsUnderwater ? 0f : 1f) // U null, V -> 0 water side, 1 shore side ); indices.z = nextNeighbor.Index; WaterShore.AddTriangleCellData(indices, weights1, weights2, weights3); } }
private void TriangulateWaterShore(HexDirection direction, HexCell cell, HexCell neighbour, Vector3 centre) { var e1 = new EdgeVertices( centre + HexMetrics.GetFirstWaterCorner(direction), centre + HexMetrics.GetSecondWaterCorner(direction) ); Water.AddTriangle(centre, e1.v1, e1.v2); Water.AddTriangle(centre, e1.v2, e1.v3); Water.AddTriangle(centre, e1.v3, e1.v4); Water.AddTriangle(centre, e1.v4, e1.v5); var indices = new Vector3(cell.Index, neighbour.Index, cell.Index); Water.AddTriangleCellData(indices, weights1); Water.AddTriangleCellData(indices, weights1); Water.AddTriangleCellData(indices, weights1); Water.AddTriangleCellData(indices, weights1); var centre2 = neighbour.Position; if (neighbour.ColumnIndex < cell.ColumnIndex - 1) { centre2.x += HexMetrics.WrapSize * HexMetrics.InnerDiameter; } else if (neighbour.ColumnIndex > cell.ColumnIndex + 1) { centre2.x -= HexMetrics.WrapSize * HexMetrics.InnerDiameter; } centre2.y = centre.y; var e2 = new EdgeVertices( centre2 + HexMetrics.GetSecondSolidCorner(direction.Opposite()), centre2 + HexMetrics.GetFirstSolidCorner(direction.Opposite()) ); // rather than calculating from current centre, work backwards from neighbour centre to find edge if (cell.HasRiverThroughEdge(direction)) { TriangulateEstuary(e1, e2, cell.IncomingRiver == direction, indices); } else { WaterShore.AddQuad(e1.v1, e1.v2, e2.v1, e2.v2); WaterShore.AddQuad(e1.v2, e1.v3, e2.v2, e2.v3); WaterShore.AddQuad(e1.v3, e1.v4, e2.v3, e2.v4); WaterShore.AddQuad(e1.v4, e1.v5, e2.v4, e2.v5); WaterShore.AddQuadUV(0f, 0f, 0f, 1f); WaterShore.AddQuadUV(0f, 0f, 0f, 1f); WaterShore.AddQuadUV(0f, 0f, 0f, 1f); WaterShore.AddQuadUV(0f, 0f, 0f, 1f); WaterShore.AddQuadCellData(indices, weights1, weights2); WaterShore.AddQuadCellData(indices, weights1, weights2); WaterShore.AddQuadCellData(indices, weights1, weights2); WaterShore.AddQuadCellData(indices, weights1, weights2); } var nextNeighbour = cell.GetNeighbour(direction.Next()); if (nextNeighbour == null) { return; } var centre3 = nextNeighbour.Position; if (nextNeighbour.ColumnIndex < cell.ColumnIndex - 1) { centre3.x += HexMetrics.WrapSize * HexMetrics.InnerDiameter; } else if (nextNeighbour.ColumnIndex > cell.ColumnIndex + 1) { centre3.x -= HexMetrics.WrapSize * HexMetrics.InnerDiameter; } var v3 = centre3 + (nextNeighbour.IsUnderwater ? HexMetrics.GetFirstWaterCorner(direction.Previous()) : HexMetrics.GetFirstSolidCorner(direction.Previous())); v3.y = centre.y; WaterShore.AddTriangle(e1.v5, e2.v5, v3); WaterShore.AddTriangleUV( new Vector2(0f, 0f), new Vector2(0f, 1f), new Vector2(0f, nextNeighbour.IsUnderwater ? 0f : 1f)); indices.z = nextNeighbour.Index; WaterShore.AddTriangleCellData(indices, weights1, weights2, weights3); }