Ejemplo n.º 1
0
        private void TriangulateRoadAdjacentToRiver(HexDirection direction, HexCell cell, Vector3 centre, EdgeVertices e)
        {
            var edgeRoad      = cell.HasRoadThroughEdge(direction);
            var previousRiver = cell.HasRiverThroughEdge(direction.Previous());
            var nextRiver     = cell.HasRiverThroughEdge(direction.Next());

            var interpolators = GetRoadInterpolators(direction, cell);
            var roadCentre    = centre;

            if (cell.HasRiverBeginOrEnd) // pointy end of rivers
            {
                roadCentre += HexMetrics.GetSolidEdgeMiddle(cell.RiverBeginOrEndDirection.Opposite()) * 1f / 3;
            }
            else if (cell.IncomingRiver == cell.OutgoingRiver.Opposite()) // straight rivers
            {
                Vector3 corner;
                if (previousRiver)
                {
                    if (!edgeRoad && !cell.HasRoadThroughEdge(direction.Next()))
                    {
                        return; // isolated on one side of the river
                    }
                    corner = HexMetrics.GetSecondSolidCorner(direction);
                }
                else
                {
                    if (!edgeRoad && !cell.HasRoadThroughEdge(direction.Previous()))
                    {
                        return; // isolated on one side of the river
                    }
                    corner = HexMetrics.GetFirstSolidCorner(direction);
                }

                roadCentre += corner / 2;
                if (cell.IncomingRiver == direction.Next() &&
                    (cell.HasRoadThroughEdge(direction.Next2()) ||
                     cell.HasRoadThroughEdge(direction.Opposite())))
                {
                    Features.AddBridge(roadCentre, centre - corner / 2);
                }
                centre += corner / 4;
            }
            else if (cell.IncomingRiver == cell.OutgoingRiver.Previous()) // zigzag river orientation 1
            {
                roadCentre -= HexMetrics.GetSecondSolidCorner(cell.IncomingRiver) * 0.2f;
            }
            else if (cell.IncomingRiver == cell.OutgoingRiver.Next()) // zigzag river orientation 2
            {
                roadCentre -= HexMetrics.GetFirstSolidCorner(cell.IncomingRiver) * 0.2f;
            }
            else if (previousRiver && nextRiver) // inside of curved river
            {
                if (!edgeRoad)
                {
                    return; // isolated road - i.e road didn't come from this edge, and doesn't connect out either.
                }
                var offset = HexMetrics.GetSolidEdgeMiddle(direction) * HexMetrics.InnerToOuter;
                roadCentre += offset * 0.7f;
                centre     += offset / 2;
            }
            else // outside of curved river
            {
                HexDirection middle;
                if (previousRiver)
                {
                    middle = direction.Next();
                }
                else if (nextRiver)
                {
                    middle = direction.Previous();
                }
                else
                {
                    middle = direction;
                }
                if (!cell.HasRoadThroughEdge(middle) && !cell.HasRoadThroughEdge(middle.Previous()) && !cell.HasRoadThroughEdge(middle.Next()))
                {
                    return; // prune orphaned rivers on the inside of a curve
                }
                var offset = HexMetrics.GetSolidEdgeMiddle(middle);
                roadCentre += offset / 4;
                if (direction == middle && cell.HasRoadThroughEdge(direction.Opposite()))
                {
                    Features.AddBridge(roadCentre, centre - offset * (HexMetrics.InnerToOuter * 0.7f));
                }
            }

            var ml = Vector3.Lerp(roadCentre, e.v1, interpolators.x);
            var mr = Vector3.Lerp(roadCentre, e.v5, interpolators.y);

            TriangulateRoad(roadCentre, ml, mr, e, edgeRoad, cell.Index);

            if (previousRiver)
            {
                TriangulateRoadEdge(roadCentre, centre, ml, cell.Index);
            }
            if (nextRiver)
            {
                TriangulateRoadEdge(roadCentre, mr, centre, cell.Index);
            }
        }
Ejemplo n.º 2
0
        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);
        }
Ejemplo n.º 3
0
        private void TriangulateConnection(HexDirection direction, HexCell cell, EdgeVertices e1)
        {
            var neighbour = cell.GetNeighbour(direction);

            if (neighbour == null)
            {
                return; // dont add for edge hexes
            }
            var bridge = HexMetrics.GetBridge(direction);

            bridge.y = neighbour.Position.y - cell.Position.y;
            var e2 = new EdgeVertices(
                e1.v1 + bridge,
                e1.v5 + bridge
                );

            var hasRiver = cell.HasRiverThroughEdge(direction);
            var hasRoad  = cell.HasRoadThroughEdge(direction);

            if (hasRiver)
            {
                var startV3 = e2.v3.y;
                e2.v3.y = neighbour.StreamBedY;
                var indices = new Vector3(cell.Index, neighbour.Index, cell.Index);

                // by definition, both cells have rivers through them
                // however, if both are underwater, then we want (i want) no river bed
                // if only one is, the river should merge with the stream
                // EXCEPT if there is an elevation difference, in which case we need the stream bed to make a waterfall

                // if im a river and the neighbour is a river
                if (!cell.IsUnderwater && !neighbour.IsUnderwater)
                {
                    TriangulateRiverQuad(
                        e1.v2, e1.v4, e2.v2, e2.v4, cell.RiverSurfaceY, neighbour.RiverSurfaceY, 0.8f,
                        cell.HasIncomingRiver && cell.IncomingRiver == direction, indices);
                }
                // if im a river and the neighbour is beneath me
                else if (!cell.IsUnderwater && cell.Elevation > neighbour.WaterLevel)
                {
                    TriangulateWaterfallInWater(
                        e1.v2, e1.v4, e2.v2, e2.v4,
                        cell.RiverSurfaceY, neighbour.RiverSurfaceY,
                        neighbour.WaterLevel, indices);
                }
                // im underwater but the neighbour is heigher than me
                else if (cell.IsUnderwater && !neighbour.IsUnderwater && neighbour.Elevation > cell.WaterLevel)
                {
                    TriangulateWaterfallInWater(
                        e2.v4, e2.v2, e1.v4, e1.v2,
                        neighbour.RiverSurfaceY, cell.RiverSurfaceY,
                        cell.WaterLevel, indices);
                }
                else if ((cell.IsUnderwater == neighbour.IsUnderwater == true) || // both underwater
                         !cell.IsUnderwater && neighbour.IsUnderwater) // river into water on same level
                {
                    e2.v3.y = startV3;                                 // if a river, this will smooth e1 (river side) into e2 (lake/sea bed, which is normal surface)
                }
                // if not a river, then e1 is already sea/lake bed, so e2 will now be approximate same level
            }

            if (HexMetrics.GetEdgeType(cell.Elevation, neighbour.Elevation) == HexEdgeType.Slope)
            {
                TriangulateEdgeTerrace(e1, cell, e2, neighbour, hasRoad);
            }
            else
            {
                TriangulateEdgeStrip(e1, weights1, cell.Index, e2, weights2, neighbour.Index, hasRoad);
            }

            Features.AddWall(e1, cell, e2, neighbour, hasRiver, hasRoad);

            if (direction > HexDirection.E)
            {
                return;
            }
            var nextDirection = direction.Next();
            var nextNeighbour = cell.GetNeighbour(nextDirection);

            if (nextNeighbour == null)
            {
                return;
            }

            var v5 = e1.v5 + HexMetrics.GetBridge(nextDirection);

            v5.y = nextNeighbour.Position.y;

            var minElevation = Mathf.Min(cell.Elevation, neighbour.Elevation, nextNeighbour.Elevation);

            if (minElevation == cell.Elevation)
            {
                TriangulateCorner(e1.v5, cell, e2.v5, neighbour, v5, nextNeighbour);
            }
            else if (minElevation == neighbour.Elevation)
            {
                TriangulateCorner(e2.v5, neighbour, v5, nextNeighbour, e1.v5, cell);
            }
            else
            {
                TriangulateCorner(v5, nextNeighbour, e1.v5, cell, e2.v5, neighbour);
            }
        }
Ejemplo n.º 4
0
        private void TriangulateWithRiver(HexDirection direction, HexCell cell, Vector3 centre, EdgeVertices e)
        {
            Vector3 centreL, centreR;

            if (cell.HasRiverThroughEdge(direction.Opposite()))
            {
                centreL = centre + HexMetrics.GetFirstSolidCorner(direction.Previous()) * 0.25f;
                centreR = centre + HexMetrics.GetSecondSolidCorner(direction.Next()) * 0.25f;
            }
            else if (cell.HasRiverThroughEdge(direction.Next()))
            {
                centreL = centre;
                centreR = Vector3.Lerp(centre, e.v5, 2f / 3);
            }
            else if (cell.HasRiverThroughEdge(direction.Previous()))
            {
                centreL = Vector3.Lerp(centre, e.v1, 2f / 3);
                centreR = centre;
            }
            else if (cell.HasRiverThroughEdge(direction.Next2()))
            {
                centreL = centre;
                centreR = centre + HexMetrics.GetSolidEdgeMiddle(direction.Next()) * 0.5f * HexMetrics.InnerToOuter;
            }
            else
            {
                centreL = centre + HexMetrics.GetSolidEdgeMiddle(direction.Previous()) * 0.5f * HexMetrics.InnerToOuter;
                centreR = centre;
            }

            centre = Vector3.Lerp(centreL, centreR, 0.5f); // aligns edges

            var m = new EdgeVertices(
                Vector3.Lerp(centreL, e.v1, 0.5f),
                Vector3.Lerp(centreR, e.v5, 0.5f),
                1f / 6);

            m.v3.y = centre.y = e.v3.y;

            TriangulateEdgeStrip(m, weights1, cell.Index, e, weights1, cell.Index);

            Terrain.AddTriangle(centreL, m.v1, m.v2);
            Terrain.AddQuad(centreL, centre, m.v2, m.v3);
            Terrain.AddQuad(centre, centreR, m.v3, m.v4);
            Terrain.AddTriangle(centreR, m.v4, m.v5);

            var indices = new Vector3(cell.Index, cell.Index, cell.Index);

            Terrain.AddTriangleCellData(indices, weights1);
            Terrain.AddQuadCellData(indices, weights1);
            Terrain.AddQuadCellData(indices, weights1);
            Terrain.AddTriangleCellData(indices, weights1);

            var reversed = cell.IncomingRiver == direction;

            TriangulateRiverQuad(centreL, centreR, m.v2, m.v4, cell.RiverSurfaceY, 0.4f, reversed, indices);
            TriangulateRiverQuad(m.v2, m.v4, e.v2, e.v4, cell.RiverSurfaceY, 0.6f, reversed, indices);
        }
Ejemplo n.º 5
0
        private void TriangulateWithRiverBeginOrEnd(HexDirection direction, HexCell cell, Vector3 centre, EdgeVertices e)
        {
            var m = new EdgeVertices(
                Vector3.Lerp(centre, e.v1, 0.5f),
                Vector3.Lerp(centre, e.v5, 0.5f));

            m.v3.y = e.v3.y;

            TriangulateEdgeStrip(m, weights1, cell.Index, e, weights1, cell.Index);
            TriangulateEdgeFan(centre, m, cell.Index);

            var reversed = cell.HasIncomingRiver;
            var indices  = new Vector3(cell.Index, cell.Index, cell.Index);

            TriangulateRiverQuad(m.v2, m.v4, e.v2, e.v4, cell.RiverSurfaceY, 0.6f, reversed, indices);

            centre.y = m.v2.y = m.v4.y = cell.RiverSurfaceY;
            Rivers.AddTriangle(centre, 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));
            }

            Rivers.AddTriangleCellData(indices, weights1);
        }
Ejemplo n.º 6
0
        private void TriangulateAdjacentToRiver(HexDirection direction, HexCell cell, Vector3 centre, EdgeVertices e)
        {
            if (cell.HasRoads)
            {
                TriangulateRoadAdjacentToRiver(direction, cell, centre, e);
            }

            if (cell.HasRiverThroughEdge(direction.Next()))
            {
                if (cell.HasRiverThroughEdge(direction.Previous())) // on a curve, so pull back the centre point
                {
                    centre += HexMetrics.GetSolidEdgeMiddle(direction) * HexMetrics.InnerToOuter * 0.5f;
                }
                else if (cell.HasRiverThroughEdge(direction.Previous2())) // straight connection - pull to one side
                {
                    centre += HexMetrics.GetFirstSolidCorner(direction) * 0.25f;
                }
            }
            else if (cell.HasRiverThroughEdge(direction.Previous()) && cell.HasRiverThroughEdge(direction.Next2()))
            {
                centre += HexMetrics.GetSecondSolidCorner(direction) * 0.25f; // other type of straight connection
            }
            var m = new EdgeVertices(
                Vector3.Lerp(centre, e.v1, 0.5f),
                Vector3.Lerp(centre, e.v5, 0.5f));

            TriangulateEdgeStrip(m, weights1, cell.Index, e, weights1, cell.Index);
            TriangulateEdgeFan(centre, m, cell.Index);

            if (!cell.IsUnderwater && !cell.HasRoadThroughEdge(direction))
            {
                Features.AddFeature(cell, (cell.Position + e.v1 + e.v5) * (1f / 3));
            }
        }
Ejemplo n.º 7
0
        private void TriangulateWithoutRiver(HexDirection direction, HexCell cell, Vector3 centre, EdgeVertices e)
        {
            TriangulateEdgeFan(cell.Position, e, cell.Index);

            if (cell.HasRoads)
            {
                var interpolators = GetRoadInterpolators(direction, cell);
                TriangulateRoad(centre,
                                Vector3.Lerp(centre, e.v1, interpolators.x), Vector3.Lerp(centre, e.v5, interpolators.y),
                                e, cell.HasRoadThroughEdge(direction), cell.Index);
            }
        }