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