public void TriangulateWithRiver(HexDirection dir, HexCell cell, Vector3 center, EdgeVertices edges)
    {
        Vector3 centerL;
        Vector3 centerR;

        float centerLinePinch = 2.0f / 3.0f;

        if (cell.HasRiverThroughEdge(dir.Opposite()))
        {
            centerL = center + HexMetrics.GetFirstSolidCorner(dir.Previous()) * HexMetrics.SubdivideFraction;
            centerR = center + HexMetrics.GetSecondSolidCorner(dir.Next()) * HexMetrics.SubdivideFraction;
            center  = (centerL + centerR) / 2.0f;
        }
        else if (cell.HasRiverThroughEdge(dir.Next()))
        {
            centerL = center;
            centerR = Vector3.Lerp(center, edges.v5, centerLinePinch);
        }
        else if (cell.HasRiverThroughEdge(dir.Previous()))
        {
            centerL = Vector3.Lerp(center, edges.v1, centerLinePinch);
            centerR = center;
        }
        else if (cell.HasRiverThroughEdge(dir.Next2()))
        {
            centerL = center;
            centerR = center + HexMetrics.GetSolidEdgeMiddle(dir.Next()) * (0.5f * HexMetrics.InnerToOuter);
        }
        else
        {
            centerL = center + HexMetrics.GetSolidEdgeMiddle(dir.Previous()) * (0.5f * HexMetrics.InnerToOuter);
            centerR = center;
        }

        EdgeVertices modifiedEdges = new EdgeVertices(Vector3.Lerp(centerL, edges.v1, 0.5f), Vector3.Lerp(centerR, edges.v5, 0.5f));

        modifiedEdges.v3.y = center.y = edges.v3.y;

        TriangulateEdgeStrip(modifiedEdges, Weights1, cell.TerrainTypeIndex, edges, Weights1, cell.CellIndex);

        Terrain.AddTriangle(centerL, modifiedEdges.v1, modifiedEdges.v2);
        Terrain.AddQuad(centerL, center, modifiedEdges.v2, modifiedEdges.v3);
        Terrain.AddQuad(center, centerR, modifiedEdges.v3, modifiedEdges.v4);
        Terrain.AddTriangle(centerR, modifiedEdges.v4, modifiedEdges.v5);

        Vector3 indices = new Vector3(cell.CellIndex, cell.CellIndex, cell.CellIndex);

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

        if (!cell.IsUnderwater)
        {
            bool reverse = cell.IncomingRiverDirection == dir;

            TriangulateRiverQuad(centerL, centerR, modifiedEdges.v2, modifiedEdges.v4, cell.RiverSurfaceY, 0.4f, reverse, indices);
            TriangulateRiverQuad(modifiedEdges.v2, modifiedEdges.v4, edges.v2, edges.v4, cell.RiverSurfaceY, 0.6f, reverse, indices);
        }
    }
    void TriangulateAdjacentToRiver(
        HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e
        )
    {
        if (cell.HasRiverThroughEdge(direction.Next()))
        {
            if (cell.HasRiverThroughEdge(direction.Previous()))
            {
                center += HexMetrics.GetSolidEdgeMiddle(direction) *
                          (HexMetrics.innerToOuter * 0.5f);
            }
            else if (cell.HasRiverThroughEdge(direction.Previous2()))
            {
                center += HexMetrics.GetFirstSolidCorner(direction) * 0.25f;
            }
        }
        else if (cell.HasRiverThroughEdge(direction.Previous()) &&
                 cell.HasRiverThroughEdge(direction.Next2())
                 )
        {
            center += HexMetrics.GetSecondSolidCorner(direction) * 0.25f;
        }

        EdgeVertices m = new EdgeVertices(
            Vector3.Lerp(center, e.v1, 0.5f),
            Vector3.Lerp(center, e.v5, 0.5f)
            );

        TriangulateEdgeStrip(m, color1, (int)cell.TerrainType, e, color1, (int)cell.TerrainType);
        TriangulateEdgeFan(center, m, (int)cell.TerrainType);
    }
Example #3
0
    // Rivers
    void TriangulateWithRiver(HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e)
    {
        Vector3 centerL, centerR;

        if (cell.HasRiverThroughEdge(direction.Opposite()))
        {
            // Left Vertex
            centerL = center + HexMetrics.GetFirstSolidCorner(direction.Previous()) * 0.25f;
            // Right Vertex
            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);

        // Middle Line
        EdgeVertices m = new EdgeVertices(
            Vector3.Lerp(centerL, e.v1, 0.5f),
            Vector3.Lerp(centerR, e.v5, 0.5f),
            1f / 6f);

        // Channel bottoms
        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);
        }
    }
Example #4
0
    void TriangulateAdjacentToRiver(HexDirection direction, HexCell_Script cell, Vector3 center, EdgeVertices e)
    {
        if (cell.HasRoads)
        {
            TriangulateRoadAdjacentToRiver(direction, cell, center, e);
        }

        if (cell.HasRiverThroughEdge(direction.Next()))
        {
            if (cell.HasRiverThroughEdge(direction.Previous()))
            {
                center += HexMetrics_Script.GetSolidEdgeMiddle(direction) * (HexMetrics_Script.innerToOuter * 0.5f);
            }
            else if (cell.HasRiverThroughEdge(direction.Previous2()))
            {
                center += HexMetrics_Script.GetFirstSolidCorner(direction) * 0.25f;
            }
        }
        else if (cell.HasRiverThroughEdge(direction.Previous()) &&
                 cell.HasRiverThroughEdge(direction.Next2()))
        {
            center += HexMetrics_Script.GetSecondSolidCorner(direction) * 0.25f;
        }

        EdgeVertices m = new EdgeVertices(Vector3.Lerp(center, e.v1, 0.5f),
                                          Vector3.Lerp(center, e.v5, 0.5f));

        TriangulateEdgeStrip(m, color1, cell.TerrainTypeIndex, e, color1, cell.TerrainTypeIndex);
        TriangulateEdgeFan(center, m, cell.TerrainTypeIndex);

        if (!cell.IsUnderwater && !cell.HasRoadThroughEdge(direction))
        {
            features.AddFeature(cell, (center + e.v1 + e.v5) * (1f / 3f));
        }
    }
Example #5
0
    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);

        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, weights1, cell.Index, e, weights1, cell.Index);

        terrain.AddTriangle(centerL, m.v1, m.v2);
        terrain.AddQuad(centerL, center, m.v2, m.v3);
        terrain.AddQuad(center, centerR, m.v3, m.v4);
        terrain.AddTriangle(centerR, m.v4, m.v5);

        Vector3 indices;

        indices.x = indices.y = indices.z = cell.Index;
        terrain.AddTriangleCellData(indices, weights1);
        terrain.AddQuadCellData(indices, weights1);
        terrain.AddQuadCellData(indices, weights1);
        terrain.AddTriangleCellData(indices, weights1);

        if (!cell.IsUnderWater)
        {
            bool reversed = cell.IncomingRiver == direction;
            TriangulateRiverQuad(centerL, centerR, 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);
        }
    }
Example #6
0
    /* Creates the 6 triangles that comprise a hex cell */
    void TriangulateCell(HexCell cell)
    {
        for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++)
        {
            if (cell.isHole)
            {
                TriangulateHoleWall(d, cell);
            }
            else
            {
                TriangulateWedge(d, cell);
            }

            if (CheckCellValid(cell.GetNeighbor(d)))
            {
                TriangulateEdge(d, cell);
            }

            /*** if corner cell, create the long walls of arena ***/
            // this check only passes for corner cells
            if (!CheckCellValid(cell.GetNeighbor(d)) &&
                !CheckCellValid(cell.GetNeighbor(d.Next())) &&
                !CheckCellValid(cell.GetNeighbor(d.Next2())))
            {
                TriangulateOuterWallPanel(d, cell);
                TriangulateOuterWallPanel(d.Next(), cell);
                TriangulateOuterWallPanel(d.Next2(), cell);

                TriangulateWallStrip(d, cell);
            }

            /**** Alt Method - creates honeycomb walls - pretty but makes for bad gameplay
             * HexCell n = cell.GetNeighbor(d);
             * if(CheckCellValid(n)){
             *      TriangulateEdge(d, cell);
             * }
             * else{
             *      TriangulateOuterWallPanel(d, cell);
             *      HexCell n2 = cell.GetNeighbor(d.Next());
             *      if(CheckCellValid(n2)){
             *              TriangulateOuterWallPanelCorner(d, cell, n2);
             *      }
             * }
             */
        }
    }
Example #7
0
 bool CanAddBridge(HexCell cell, HexDirection dir)
 {
     if (cell.incomingRiver != dir.Next())
     {
         return(false);
     }
     return(cell.HasRoadThroughEdge(dir.Next2()) || cell.HasRoadThroughEdge(dir.Opposite()));
 }
Example #8
0
    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);

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

        AddTriangle(centerL, m.v1, m.v2);
        AddTriangleColor(cell.Color);
        AddQuad(centerL, center, m.v2, m.v3);
        AddQuadColor(cell.Color);
        AddQuad(center, centerR, m.v3, m.v4);
        AddQuadColor(cell.Color);
        AddTriangle(centerR, m.v4, m.v5);
        AddTriangleColor(cell.Color);
    }
        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);
        }
Example #10
0
        public void TriangulateContoursBetween(
            IHexCell center, IHexCell right, HexDirection direction, Color centerWeights, Color rightWeights, IHexMesh mesh
            )
        {
            var centerRightContour = CellContourCanon.GetContourForCellEdge(center, direction);
            var rightCenterContour = CellContourCanon.GetContourForCellEdge(right, direction.Opposite());

            int centerRightIndex = 1, rightCenterIndex = rightCenterContour.Count - 1;

            while (centerRightIndex < centerRightContour.Count && rightCenterIndex > 0)
            {
                mesh.AddQuad(
                    centerRightContour[centerRightIndex - 1].ToXYZ(), centerRightContour[centerRightIndex].ToXYZ(),
                    rightCenterContour[rightCenterIndex].ToXYZ(), rightCenterContour[rightCenterIndex - 1].ToXYZ()
                    );

                mesh.AddQuadColor(centerWeights, rightWeights);

                centerRightIndex++;
                rightCenterIndex--;
            }

            for (; centerRightIndex < centerRightContour.Count; centerRightIndex++)
            {
                mesh.AddTriangle(
                    centerRightContour[centerRightIndex - 1].ToXYZ(), rightCenterContour[0].ToXYZ(), centerRightContour[centerRightIndex].ToXYZ()
                    );

                mesh.AddTriangleColor(centerWeights, rightWeights, centerWeights);
            }

            for (; rightCenterIndex > 0; rightCenterIndex--)
            {
                mesh.AddTriangle(
                    centerRightContour.Last().ToXYZ(), rightCenterContour[rightCenterIndex].ToXYZ(), rightCenterContour[rightCenterIndex - 1].ToXYZ()
                    );

                mesh.AddTriangleColor(centerWeights, rightWeights, rightWeights);
            }

            if (RiverCanon.HasRiverAlongEdge(right, direction.Next2()))
            {
                var nextRight = Grid.GetNeighbor(center, direction.Next());

                var rightNextRightContour = CellContourCanon.GetContourForCellEdge(right, direction.Next2());
                var nextRightRightContour = CellContourCanon.GetContourForCellEdge(nextRight, direction.Previous());

                mesh.AddTriangle(
                    centerRightContour.Last().ToXYZ(),
                    rightNextRightContour.Last().ToXYZ(),
                    nextRightRightContour.First().ToXYZ()
                    );

                mesh.AddTriangleColor(centerWeights, rightWeights, rightWeights);
            }
        }
 private HexDirection GetBestDirection(HexDirection startDirection, List <HexDirection> otherDirections, HexHash hash)
 {
     if (otherDirections.Contains(startDirection.Opposite()))
     {
         return(startDirection.Opposite());
     }
     else if (otherDirections.Contains(startDirection.Next2()))
     {
         return(startDirection.Next2());
     }
     else if (otherDirections.Contains(startDirection.Previous2()))
     {
         return(startDirection.Previous2());
     }
     else
     {
         return(otherDirections[Mathf.FloorToInt(hash.A * otherDirections.Count)]);
     }
 }
Example #12
0
        //The fact that we're building sections only from the NE, E, and SE
        //cell edges is very important. A lot of the code here is structured
        //as it is to deal with this reality.
        public void RefreshRiverSections()
        {
            sections.Clear();
            SectionBetweenCells.Clear();

            CellEdgeContourCanon.Clear();

            foreach (var cell in Grid.Cells)
            {
                for (HexDirection direction = HexDirection.NE; direction <= HexDirection.SE; direction++)
                {
                    if (RiverCanon.HasRiverAlongEdge(cell, direction))
                    {
                        var neighbor = Grid.GetNeighbor(cell, direction);

                        Vector3 start = cell.AbsolutePosition + RenderConfig.GetFirstCorner(direction);
                        Vector3 end   = cell.AbsolutePosition + RenderConfig.GetSecondCorner(direction);

                        RiverFlow flow = RiverCanon.GetFlowOfRiverAtEdge(cell, direction);

                        //Our control points need to operate differently if we're at endpoints,
                        //and both ControlOne and ControlTwo might have alternate behavior.
                        //We need to check both ends of the section for endpoints
                        bool previousCellRiver     = RiverCanon.HasRiverAlongEdge(cell, direction.Previous());
                        bool previousNeighborRiver = RiverCanon.HasRiverAlongEdge(neighbor, direction.Previous2());

                        bool hasPreviousEndpoint =
                            !previousCellRiver &&
                            !previousNeighborRiver;

                        bool hasNextEndpoint =
                            !RiverCanon.HasRiverAlongEdge(cell, direction.Next()) &&
                            !RiverCanon.HasRiverAlongEdge(neighbor, direction.Next2());

                        var newRiverSection = new RiverSection()
                        {
                            AdjacentCellOne  = cell,
                            AdjacentCellTwo  = neighbor,
                            DirectionFromOne = direction,
                            Start            = start,
                            End                 = end,
                            FlowFromOne         = flow,
                            HasPreviousEndpoint = hasPreviousEndpoint,
                            HasNextEndpoint     = hasNextEndpoint
                        };

                        SectionBetweenCells[new Tuple <IHexCell, IHexCell>(cell, neighbor)] = newRiverSection;

                        sections.Add(newRiverSection);
                    }
                }
            }
        }
Example #13
0
        private void TriangulateWaterCorner(
            IHexCell center, Vector3 localCenterPos, Color centerColor,
            IHexCell right, Vector3 localRightPos, Color rightColor,
            IHexCell left, Vector3 localLeftPos, Color leftColor,
            HexDirection direction, IHexMesh mesh
            )
        {
            mesh.AddTriangle(
                localCenterPos + RenderConfig.GetFirstSolidCorner(direction),
                localLeftPos + RenderConfig.GetFirstSolidCorner(direction.Next2()),
                localRightPos + RenderConfig.GetFirstSolidCorner(direction.Previous2())
                );

            mesh.AddTriangleColor(centerColor, leftColor, rightColor);
        }
Example #14
0
        //We need to draw a river from previousCell to nextCell by adding rivers
        //to the edges of currentCell. PreviousCell is in directionToNext.Next2(),
        //and should have some river pointing at currentCell
        private RiverPathResults CreateRiverAlongCell_GentleCWTurn(
            IHexCell previousCell, IHexCell currentCell, IHexCell nextCell,
            HexDirection directionToPrevious, HexDirection directionToNext,
            IEnumerable <IHexCell> oceanCells, HashSet <IHexCell> cellsAdjacentToRiver
            )
        {
            var leftLeftPath = new RiverPath(
                currentCell, directionToPrevious.Next(), directionToNext.Previous(),
                RiverFlow.Clockwise, RiverCanon, Grid
                );

            var leftRightPath = new RiverPath(
                currentCell, directionToPrevious, directionToNext.Next(),
                RiverFlow.Counterclockwise, RiverCanon, Grid
                );

            var rightRightPath = new RiverPath(
                currentCell, directionToNext.Next(),
                RiverFlow.Counterclockwise, RiverCanon, Grid
                );

            var rightleftPath = new RiverPath(
                currentCell, directionToPrevious, directionToNext.Previous(),
                RiverFlow.Clockwise, RiverCanon, Grid
                );

            var pathsToTry = new List <RiverPath>();

            //If directionToNext.Previous() is considered up,
            //this case triggers when previousCell has a river
            //along its upper-left edge.
            if (RiverCanon.HasRiverAlongEdge(previousCell, directionToPrevious.Next2()))
            {
                pathsToTry.Add(leftLeftPath);
                pathsToTry.Add(leftRightPath);
            }

            //If directionToNext.Previous() is considered up,
            //this case triggers when previousCell has a river
            //along its upper-right edge.
            if (RiverCanon.HasRiverAlongEdge(previousCell, directionToPrevious.Previous2()))
            {
                pathsToTry.Add(rightRightPath);
                pathsToTry.Add(rightleftPath);
            }

            return(TryFollowSomePath(pathsToTry, oceanCells, cellsAdjacentToRiver));
        }
Example #15
0
    void TriangulateAdjacentToRiver(
        HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e
        )
    {
        if (cell.HasRoads)
        {
            TriangulateRoadAdjacentToRiver(direction, cell, center, e);
        }

        if (cell.HasRiverThroughEdge(direction.Next()))
        {
            if (cell.HasRiverThroughEdge(direction.Previous()))
            {
                center += HexMetrics.GetSolidEdgeMiddle(direction) *
                          (HexMetrics.innerToOuter * 0.5f);
            }
            else if (
                cell.HasRiverThroughEdge(direction.Previous2())
                )
            {
                center += HexMetrics.GetFirstSolidCorner(direction) * 0.25f;
            }
        }
        else if (
            cell.HasRiverThroughEdge(direction.Previous()) &&
            cell.HasRiverThroughEdge(direction.Next2())
            )
        {
            center += HexMetrics.GetSecondSolidCorner(direction) * 0.25f;
        }

        EdgeVertices m = new EdgeVertices(
            Vector3.Lerp(center, e.v1, 0.5f),
            Vector3.Lerp(center, e.v5, 0.5f)
            );

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

        //спавн объектов игрового окружения в каждом из 6 треугольников если нет рек и дорог
        if (!cell.IsUnderwater && !cell.HasRoadThroughEdge(direction))
        {
            features.AddFeature(cell, (center + e.v1 + e.v5) * (1f / 3f));
        }
    }
Example #16
0
        //We need to draw a river from previousCell to nextCell by adding rivers
        //to the edges of currentCell. PreviousCell and nextCell are across from
        //each-other. Previous river should have some river pointing at currentCell
        private RiverPathResults CreateRiverAlongCell_StraightAcross(
            IHexCell previousCell, IHexCell currentCell, IHexCell nextCell,
            HexDirection directionToPrevious, HexDirection directionToNext,
            IEnumerable <IHexCell> oceanCells, HashSet <IHexCell> cellsAdjacentToRiver
            )
        {
            var leftToLeftPath = new RiverPath(
                currentCell, directionToNext.Previous2(), directionToNext.Previous(),
                RiverFlow.Clockwise, RiverCanon, Grid
                );

            var leftToRightPath = new RiverPath(
                currentCell, directionToPrevious, directionToNext.Next(),
                RiverFlow.Counterclockwise, RiverCanon, Grid
                );

            var rightToRightPath = new RiverPath(
                currentCell, directionToNext.Next2(), directionToNext.Next(),
                RiverFlow.Counterclockwise, RiverCanon, Grid
                );

            var rightToLeftPath = new RiverPath(
                currentCell, directionToPrevious, directionToNext.Previous(),
                RiverFlow.Clockwise, RiverCanon, Grid
                );

            var pathsToTry = new List <RiverPath>();

            //If nextCell is above us, this case happens when previousCell has a
            //river along its left edge
            if (RiverCanon.HasRiverAlongEdge(previousCell, directionToNext.Previous()))
            {
                pathsToTry.Add(leftToLeftPath);
                pathsToTry.Add(leftToRightPath);

                //If nextCell is above us, this case happens when previousCell has a
                //river along its right edge
            }
            else if (RiverCanon.HasRiverAlongEdge(previousCell, directionToNext.Next()))
            {
                pathsToTry.Add(rightToRightPath);
                pathsToTry.Add(rightToLeftPath);
            }

            return(TryFollowSomePath(pathsToTry, oceanCells, cellsAdjacentToRiver));
        }
Example #17
0
        public void updateChunkWithRiversAndRoads1Test()
        {
            GameObject obj  = MonoBehaviour.Instantiate(Resources.Load <GameObject>("Prefabs/Hex Grid"));
            HexGrid    grid = obj.GetComponent <HexGrid>();

            HexGridChunk[] chunks = grid.getHexGridChunks();

            HexCell[]    cells     = chunks[0].getCells();
            HexDirection direction = HexDirection.NE;
            int          index     = 7;

            // ....................................................
            // SET DIRECT RIVER
            // ....................................................
            // Find cell with next steps: go to NE, go to NE
            HexCell cell = cells[index].GetNeighbor(direction)
                           .GetNeighbor(direction);

            // Set river to NW direction
            cell.SetOutgoingRiver(direction.Previous());
            // Get neigbor from SE direction cell
            HexCell neighbor = cell.GetNeighbor(direction.Next2());

            // Set river to NW direction
            neighbor.SetOutgoingRiver(direction.Previous());

            // Set road to previous 2 direction
            cell.AddRoad(direction.Next());

            // Set road to opposite direction
            cell.AddRoad(direction.Next().Opposite());
            // ....................................................

            // Update chunk
            foreach (HexGridChunk chunk in chunks)
            {
                chunk.Triangulate();
            }

            Assert.IsTrue(cell.HasIncomingRiver);
            Assert.IsTrue(cell.HasOutgoingRiver);
            Assert.IsTrue(cell.HasRoads);

            GameObject.Destroy(obj);
        }
Example #18
0
    private void TriangulateAdjacentToRiver(
        HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e)
    {
        if (cell.HasRoads)
        {
            TriangulateRoadAdjacentToRiver(direction, cell, center, e);
        }

        if (cell.HasRiverThroughEdge(direction.Next()))
        {
            // Check whether we are on the inside of a curve.  This occurs when
            // both the previous and next direction contai a river. In this case teh center
            // will be moved towards the edge.
            if (cell.HasRiverThroughEdge(direction.Previous()))
            {
                center += HexMetrics.GetSolidEdgeMiddle(direction)
                          * (HexMetrics.innerToOuter * 0.5f);
                // Check whether this is a straight river, in that case move the center
                // towards the first corner.
            }
            else if (cell.HasRiverThroughEdge(direction.Previous2()))
            {
                center += HexMetrics.GetFirstSolidCorner(direction) * 0.25f;
            }
        }
        else if (
            cell.HasRiverThroughEdge(direction.Previous()) &&
            cell.HasRiverThroughEdge(direction.Next2()))
        {
            center += HexMetrics.GetSecondSolidCorner(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);

        if (!cell.IsUnderwater && !cell.HasRoadThroughEdge(direction))
        {
            features.AddFeature((center + e.v1 + e.v5) * (1f / 3f));
        }
    }
        public T GetMixForNextCornerAtPoint <T>(
            IHexCell center, IHexCell right, IHexCell nextRight, HexDirection direction, Vector3 point,
            DataSelectorCallback <T> dataSelector, Func <T, T, T> aggregator
            )
        {
            Vector2 centerCorner    = center.AbsolutePositionXZ + RenderConfig.GetSecondSolidCornerXZ(direction);
            Vector2 rightCorner     = right.AbsolutePositionXZ + RenderConfig.GetSecondSolidCornerXZ(direction.Next2());
            Vector2 nextRightCorner = nextRight.AbsolutePositionXZ + RenderConfig.GetSecondSolidCornerXZ(direction.Previous2());

            float percentCenter, percentRight, percentNextRight;

            Geometry2D.GetBarycentric2D(
                new Vector2(point.x, point.z), centerCorner, rightCorner, nextRightCorner,
                out percentCenter, out percentRight, out percentNextRight
                );

            T centerContribution    = dataSelector(point, center, direction, percentCenter);
            T rightContribution     = dataSelector(point, right, direction.Next2(), percentRight);
            T nextRightContribution = dataSelector(point, nextRight, direction.Previous2(), percentNextRight);

            return(aggregator(aggregator(centerContribution, rightContribution), nextRightContribution));
        }
Example #20
0
        void TriangulateAdjacentToRiver(HexDirection dir, HexCell cell, Vector3 center, EdgeVertices e)
        {
            if (cell.HasRoads)
            {
                TriangulateRoadAdjacentToRiver(dir, cell, center, e);
            }
            if (cell.HasRiverThroughEdge(dir.Next()))
            {
                if (cell.HasRiverThroughEdge(dir.Previous()))
                {
                    center += HexMetrics.GetSolidEdgeMiddle(dir)
                              * (HexMetrics.innerToOuter * 0.5f);
                }
                else if (cell.HasRiverThroughEdge(dir.Previous2()))
                {
                    center += HexMetrics.GetFirstSolidCorner(dir) * 0.25f;
                }
            }
            else if (cell.HasRiverThroughEdge(dir.Previous()) &&
                     cell.HasRiverThroughEdge(dir.Next2()))
            {
                center += HexMetrics.GetSecondSolidCorner(dir) * 0.25f;
            }
            var m = new EdgeVertices(
                Vector3.Lerp(center, e.v1, 0.5f),
                Vector3.Lerp(center, e.v5, 0.5f));

            TriangulateEdgeStrip(m, color1, cell.terrainTypeIndex, e, color1, cell.terrainTypeIndex);
            TriangulateEdgeFan(center, m, cell.terrainTypeIndex);

            if (CanAddFeature(cell, dir))
            {
                // offset the feature slightly from the center towards
                // the directional edge.
                var pos = (center + e.v1 + e.v5) * (1f / 3f);
                features.AddFeature(cell, pos);
            }
        }
Example #21
0
        //We need to draw a river from previousCell to nextCell by adding rivers
        //to the edges of currentCell. PreviousCell is in directionToNext.Next(),
        //and should have some river pointing at currentCell
        private RiverPathResults CreateRiverAlongCell_SharpCWTurn(
            IHexCell previousCell, IHexCell currentCell, IHexCell nextCell,
            HexDirection directionToPrevious, HexDirection directionToNext,
            IEnumerable <IHexCell> oceanCells, HashSet <IHexCell> cellsAdjacentToRiver
            )
        {
            var leftToLeftPath = new RiverPath(
                currentCell, directionToPrevious.Next(), directionToNext.Previous(),
                RiverFlow.Clockwise, RiverCanon, Grid
                );

            var leftToRightPath = new RiverPath(
                currentCell, directionToPrevious, RiverFlow.Counterclockwise,
                RiverCanon, Grid
                );

            var pathsToTry = new List <RiverPath>();

            //Assuming directionToPrevious.Opposite() is up,
            //this case triggers when previousCell has a
            //river along its upper left edge
            if (RiverCanon.HasRiverAlongEdge(previousCell, directionToPrevious.Next2()))
            {
                pathsToTry.Add(leftToLeftPath);
                pathsToTry.Add(leftToRightPath);
            }

            //Assuming directionToPrevious.Opposite() is up,
            //this case triggers when previousCell has a
            //river along its upper right edge
            if (RiverCanon.HasRiverAlongEdge(previousCell, directionToPrevious.Previous2()))
            {
                return(RiverPathResults.Success);
            }

            return(TryFollowSomePath(pathsToTry, oceanCells, cellsAdjacentToRiver));
        }
Example #22
0
    void TriangulateRoadAdjacentToRiver(
        HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e
        )
    {
        bool    hasRoadThroughEdge = cell.HasRoadThroughEdge(direction);
        bool    previousHasRiver   = cell.HasRiverThroughEdge(direction.Previous());
        bool    nextHasRiver       = cell.HasRiverThroughEdge(direction.Next());
        Vector2 interpolators      = GetRoadInterpolators(direction, cell);
        Vector3 roadCenter         = center;

        if (cell.HasRiverBeginOrEnd)
        {
            roadCenter += HexMetrics.GetSolidEdgeMiddle(
                cell.RiverBeginOrEndDirection.Opposite()
                ) * (1f / 3f);
        }
        else if (cell.IncomingRiver == cell.OutgoingRiver.Opposite())
        {
            Vector3 corner;
            if (previousHasRiver)
            {
                if (
                    !hasRoadThroughEdge &&
                    !cell.HasRoadThroughEdge(direction.Next())
                    )
                {
                    return;
                }
                corner = HexMetrics.GetSecondSolidCorner(direction);
            }
            else
            {
                if (
                    !hasRoadThroughEdge &&
                    !cell.HasRoadThroughEdge(direction.Previous())
                    )
                {
                    return;
                }
                corner = HexMetrics.GetFirstSolidCorner(direction);
            }
            roadCenter += corner * 0.5f;

            if (cell.IncomingRiver == direction.Next() && (
                    cell.HasRoadThroughEdge(direction.Next2()) ||
                    cell.HasRoadThroughEdge(direction.Opposite())
                    ))
            {
                features.AddBridge(roadCenter, center - corner * 0.5f);
            }
            center += corner * 0.25f;
        }
        else if (cell.IncomingRiver == cell.OutgoingRiver.Previous())
        {
            roadCenter -= HexMetrics.GetSecondCorner(cell.IncomingRiver) * 0.2f;
        }
        else if (cell.IncomingRiver == cell.OutgoingRiver.Next())
        {
            roadCenter -= HexMetrics.GetFirstCorner(cell.IncomingRiver) * 0.2f;
        }
        else if (previousHasRiver && nextHasRiver)
        {
            if (!hasRoadThroughEdge)
            {
                return;
            }
            Vector3 offset = HexMetrics.GetSolidEdgeMiddle(direction) *
                             HexMetrics.innerToOuter;
            roadCenter += offset * 0.7f;
            center     += offset * 0.5f;
        }
        else
        {
            HexDirection middle;
            if (previousHasRiver)
            {
                middle = direction.Next();
            }
            else if (nextHasRiver)
            {
                middle = direction.Previous();
            }
            else
            {
                middle = direction;
            }
            if (
                !cell.HasRoadThroughEdge(middle) &&
                !cell.HasRoadThroughEdge(middle.Previous()) &&
                !cell.HasRoadThroughEdge(middle.Next())
                )
            {
                return;
            }
            Vector3 offset = HexMetrics.GetSolidEdgeMiddle(middle);
            roadCenter += offset * 0.25f;
            if (
                direction == middle &&
                cell.HasRoadThroughEdge(direction.Opposite())
                )
            {
                features.AddBridge(
                    roadCenter,
                    center - offset * (HexMetrics.innerToOuter * 0.7f)
                    );
            }
        }

        Vector3 mL = Vector3.Lerp(roadCenter, e.v1, interpolators.x);
        Vector3 mR = Vector3.Lerp(roadCenter, e.v5, interpolators.y);

        TriangulateRoad(roadCenter, mL, mR, e, hasRoadThroughEdge, cell.Index);
        if (previousHasRiver)
        {
            TriangulateRoadEdge(roadCenter, center, mL, cell.Index);
        }
        if (nextHasRiver)
        {
            TriangulateRoadEdge(roadCenter, mR, center, cell.Index);
        }
    }
Example #23
0
    void TriangulateWithRiver(HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e)
    {
        //outer walls
        Vector3 centerL, centerR;

        if (cell.HasRiverThroughEdge(direction.Opposite()))
        {
            centerL = center +
                      HexMetric.GetFirstSolidCorner(direction.Previous()) * 0.25f;
            centerR = center +
                      HexMetric.GetSecondSolidCorner(direction.Next()) * 0.25f;
        }
        // sharp turns
        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;
        }
        // two way turns
        else if (cell.HasRiverThroughEdge(direction.Next2()))
        {
            centerL = center;
            centerR = center + HexMetric.GetSolidEdgeMiddle(direction.Next()) * (0.5f * HexMetric.innerToOuter);
        }
        else
        {
            centerL = center + HexMetric.GetSolidEdgeMiddle(direction.Previous()) * (0.5f * HexMetric.innerToOuter);
            centerR = center;
        }

        //mid point of channel
        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;
        //fill area
        TriangulateEdgeStrip(m, color1, cell.TerrainTypeIndex, e, color1, cell.TerrainTypeIndex);
        terrain.AddTriangle(centerL, m.v1, m.v2);
        terrain.AddQuad(centerL, center, m.v2, m.v3);
        terrain.AddQuad(center, centerR, m.v3, m.v4);
        terrain.AddTriangle(centerR, m.v4, m.v5);

        terrain.AddTriangleColor(color1);
        terrain.AddQuadColor(color1);
        terrain.AddQuadColor(color1);
        terrain.AddTriangleColor(color1);

        Vector3 types;

        types.x = types.y = types.z = cell.TerrainTypeIndex;
        terrain.AddTriangleTerrainTypes(types);
        terrain.AddQuadTerrainTypes(types);
        terrain.AddQuadTerrainTypes(types);
        terrain.AddTriangleTerrainTypes(types);

        //river water quads
        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);
        }
    }
Example #24
0
    int CreateRiver(HexCell origin)
    {
        int          length    = 1;
        HexCell      cell      = origin;
        HexDirection direction = HexDirection.NE;

        while (!cell.IsUnderwater)
        {
            int minNeighborElevation = int.MaxValue;
            flowDirections.Clear();
            for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++)
            {
                HexCell neighbor = cell.GetNeighbor(d);
                if (!neighbor)
                {
                    continue;
                }

                if (neighbor.Elevation < minNeighborElevation)
                {
                    minNeighborElevation = neighbor.Elevation;
                }

                if (neighbor == origin || neighbor.HasIncomingRiver)
                {
                    continue;
                }

                int delta = neighbor.Elevation - cell.Elevation;
                if (delta > 0)
                {
                    continue;
                }
                if (neighbor.HasOutgoingRiver)
                {
                    cell.SetOutgoingRiver(d);
                    return(length);
                }

                if (delta < 0)
                {
                    flowDirections.Add(d);
                    flowDirections.Add(d);
                    flowDirections.Add(d);
                }
                if (
                    length == 1 ||
                    (d != direction.Next2() && d != direction.Previous2())
                    )
                {
                    flowDirections.Add(d);
                }
                flowDirections.Add(d);
            }
            if (flowDirections.Count == 0)
            {
                if (length == 1)
                {
                    return(0);
                }

                if (minNeighborElevation >= cell.Elevation)
                {
                    cell.WaterLevel = minNeighborElevation;
                    if (minNeighborElevation == cell.Elevation)
                    {
                        cell.Elevation = minNeighborElevation - 1;
                    }
                }
                break;
            }

            direction = flowDirections[Random.Range(0, flowDirections.Count)];
            cell.SetOutgoingRiver(direction);
            length += 1;

            if (
                minNeighborElevation >= cell.Elevation &&
                Random.value < extraLakeProbability
                )
            {
                cell.WaterLevel = cell.Elevation;
                cell.Elevation -= 1;
            }

            cell = cell.GetNeighbor(direction);
        }

        return(length);
    }
    /// <summary>
    /// Creates road geometry when there is a river in the cell.
    /// </summary>
    void TriangulateRoadAdjacentToRiver(HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e)
    {
        bool    hasRoadThroughEdge = cell.HasRoadThroughEdge(direction);
        bool    previousHasRiver   = cell.HasRiverThroughEdge(direction.Previous());
        bool    nextHasRiver       = cell.HasRiverThroughEdge(direction.Next());
        Vector2 interpolators      = GetRoadInterpolators(direction, cell);
        Vector3 roadCenter         = center;

        // When there is a river start/end or a river zig-zag then we only need to offset road center
        // If there is a straight section of river cutting through or a smooth turn then those divide the road network

        if (cell.HasRiverBeginOrEnd)           // If this is river start or river end
        {
            roadCenter += HexMetrics.GetSolidEdgeMiddle(cell.RiverBeginOrEndDirection.Opposite()) * (1f / 3f);
        }
        else if (cell.IncomingRiver == cell.OutgoingRiver.Opposite())           // If this is a river section cutting cell in the middle
        {
            Vector3 corner;
            if (previousHasRiver)
            {
                if (!hasRoadThroughEdge && !cell.HasRoadThroughEdge(direction.Next()))
                {
                    return;                     // Dont draw on the other side of the river
                }
                corner = HexMetrics.GetSecondSolidCorner(direction);
            }
            else
            {
                if (!hasRoadThroughEdge && !cell.HasRoadThroughEdge(direction.Previous()))
                {
                    return;                     // Dont draw on the other side of the river
                }
                corner = HexMetrics.GetFirstSolidCorner(direction);
            }

            roadCenter += corner * 0.5f;

            // Prevent duplicate bridges and add a bridge if road on both sides
            if (cell.IncomingRiver == direction.Next() && (
                    cell.HasRoadThroughEdge(direction.Next2()) ||
                    cell.HasRoadThroughEdge(direction.Opposite())
                    ))
            {
                Features.AddBridge(roadCenter, center - corner * 0.5f);
            }

            center += corner * 0.25f;
        }
        else if (cell.IncomingRiver == cell.OutgoingRiver.Previous())           // Check if zig-zag and offset
        {
            roadCenter -= HexMetrics.GetSecondCorner(cell.IncomingRiver) * 0.2f;
        }
        else if (cell.IncomingRiver == cell.OutgoingRiver.Next())           // Check if zig-zag and offset
        {
            roadCenter -= HexMetrics.GetFirstCorner(cell.IncomingRiver) * 0.2f;
        }
        else if (previousHasRiver && nextHasRiver)           // Check smooth curve (inside of the curve)
        {
            if (!hasRoadThroughEdge)
            {
                return;                 // Dont draw on the other side of the river
            }
            Vector3 offset = HexMetrics.GetSolidEdgeMiddle(direction) * HexMetrics.InnerToOuter;
            roadCenter += offset * 0.7f;
            center     += offset * 0.5f;
        }
        else           // Smooth curve (outside of the curve)
        {
            HexDirection middle;
            if (previousHasRiver)
            {
                middle = direction.Next();
            }
            else if (nextHasRiver)
            {
                middle = direction.Previous();
            }
            else
            {
                middle = direction;
            }

            if (!cell.HasRoadThroughEdge(middle) && !cell.HasRoadThroughEdge(middle.Previous()) &&
                !cell.HasRoadThroughEdge(middle.Next()))
            {
                return;                 // Dont draw on the other side of the river
            }

            // Set center and add bridge
            Vector3 offset = HexMetrics.GetSolidEdgeMiddle(middle);
            roadCenter += offset * 0.25f;

            // Prevent duplicate bridges and road on both sides
            if (direction == middle && cell.HasRoadThroughEdge(direction.Opposite()))
            {
                Features.AddBridge(roadCenter, center - offset * (HexMetrics.InnerToOuter * 0.7f));
            }
        }

        Vector3 mL = Vector3.Lerp(roadCenter, e.v1, interpolators.x);
        Vector3 mR = Vector3.Lerp(roadCenter, e.v5, interpolators.y);

        TriangulateRoad(roadCenter, mL, mR, e, hasRoadThroughEdge, cell.Index);

        // Create auxiliary geometry
        if (previousHasRiver)
        {
            TriangulateRoadEdge(roadCenter, center, mL, cell.Index);
        }
        if (nextHasRiver)
        {
            TriangulateRoadEdge(roadCenter, mR, center, cell.Index);
        }
    }
    /// <summary>
    /// Creates the triangles for a side of the hexagon, when there is a river in the hex.
    /// </summary>
    void TriangulateAdjacentToRiver(HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e)
    {
        if (cell.HasRoads)
        {
            TriangulateRoadAdjacentToRiver(direction, cell, center, e);
        }

        // Determine center by finding river channel center edge
        if (cell.HasRiverThroughEdge(direction.Next()))
        {
            if (cell.HasRiverThroughEdge(direction.Previous()))
            {
                center += HexMetrics.GetSolidEdgeMiddle(direction) * (HexMetrics.InnerToOuter * 0.5f);
            }
            else if (cell.HasRiverThroughEdge(direction.Previous2()))
            {
                center += HexMetrics.GetFirstSolidCorner(direction) * 0.25f;
            }
        }
        else if (cell.HasRiverThroughEdge(direction.Previous()) && cell.HasRiverThroughEdge(direction.Next2()))
        {
            center += HexMetrics.GetSecondSolidCorner(direction) * 0.25f;
        }

        EdgeVertices m = new EdgeVertices(
            Vector3.Lerp(center, e.v1, 0.5f),
            Vector3.Lerp(center, e.v5, 0.5f)
            );

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

        // If possible add any features
        if (!cell.IsUnderwater && !cell.HasRoadThroughEdge(direction))
        {
            Features.AddFeature(cell, (center + e.v1 + e.v5) * (1f / 3f));
        }
    }
    /// <summary>
    /// Creates the triangles for a side of the hexagon, with river passing through (incoming and outgoing river) at this side.
    /// </summary>
    void TriangulateWithRiver(HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e)
    {
        Vector3 centerL, centerR;

        if (cell.HasRiverThroughEdge(direction.Opposite()))           // If river flows forward through the cell
        // Extend center into line
        {
            centerL = center + HexMetrics.GetFirstSolidCorner(direction.Previous()) * 0.25f;
            centerR = center + HexMetrics.GetSecondSolidCorner(direction.Next()) * 0.25f;
        }
        else if (cell.HasRiverThroughEdge(direction.Next()))           // If river bends sharply in next dir
        {
            centerL = center;
            centerR = Vector3.Lerp(center, e.v5, 2f / 3f);
        }
        else if (cell.HasRiverThroughEdge(direction.Previous()))           // If river bends sharply in prev dir
        {
            centerL = Vector3.Lerp(center, e.v1, 2f / 3f);
            centerR = center;
        }
        else if (cell.HasRiverThroughEdge(direction.Next2()))           //  River bends smoothly to next.next dir
        {
            centerL = center;
            centerR = center + HexMetrics.GetSolidEdgeMiddle(direction.Next()) * (0.5f * HexMetrics.InnerToOuter);
        }
        else           //  River bends smoothly to previous.previous dir
        {
            centerL = center + HexMetrics.GetSolidEdgeMiddle(direction.Previous()) * (0.5f * HexMetrics.InnerToOuter);
            centerR = center;
        }

        center = Vector3.Lerp(centerL, centerR, 0.5f);         // Average center to serve all cases

        // Edge 1/2 the way from edge and cell center
        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;         // Lower middle edge and center to river bed

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

        // Final gap between the middle edge and the center
        // Geo
        Terrain.AddTriangle(centerL, m.v1, m.v2);
        Terrain.AddQuad(centerL, center, m.v2, m.v3);
        Terrain.AddQuad(center, centerR, m.v3, m.v4);
        Terrain.AddTriangle(centerR, m.v4, m.v5);

        // Splat + Terrain Types
        Vector3 indices;

        indices.x = indices.y = indices.z = cell.Index;
        Terrain.AddTriangleCellData(indices, weights1);
        Terrain.AddQuadCellData(indices, weights1);
        Terrain.AddQuadCellData(indices, weights1);
        Terrain.AddTriangleCellData(indices, weights1);

        if (!cell.IsUnderwater)             // No river water surface when underwater, river bed allowed
        // River water surface
        {
            bool reversed = cell.IncomingRiver == direction;
            TriangulateRiverQuad(centerL, centerR, 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);
        }
    }
    /// <summary>
    /// Creates the segments of the river flowing through multiple cells. There are some specifications to creating a river:
    /// - The cell a river is joined onto must be level or a lower elevation
    /// - River cannot loop onto itself.
    /// - River will priorities cells that aren't directly next to itself (Harsh turns on the river)
    /// - If it runs into another river origin then it will join the two rivers together.
    /// - If the surrounding cells of the river end are higher than the current, it will create lake
    /// - There is a random chance of lakes being created along the river if the cell is of lower elevation
    /// </summary>
    /// <param name="origin"> Origin cell of river </param>
    /// <returns> Amount of cells used in river creation </returns>
    int CreateRiver(HexCell origin)
    {
        int          length    = 1;
        HexCell      cell      = origin;
        HexDirection direction = HexDirection.NE;

        while (!cell.isUnderwater)
        {
            int minNeighborElevation = int.MaxValue;
            flowDirections.Clear();
            for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++)
            {
                HexCell neighbor = cell.GetNeighbor(d);

                if (!neighbor)
                {
                    continue;
                }
                if (neighbor.Elevation < minNeighborElevation)
                {
                    minNeighborElevation = neighbor.Elevation;
                }

                if (neighbor == origin || neighbor.HasIncomingRiver)
                {
                    continue;
                }
                int delta = neighbor.Elevation - cell.Elevation;
                if (delta > 0)
                {
                    continue;
                }
                if (delta < 0)                  //Increases chance of river choosing a cell which goes downhill
                {
                    flowDirections.Add(d);
                    flowDirections.Add(d);
                    flowDirections.Add(d);
                }
                if (length == 1 || (d != direction.Next2() && d != direction.Previous2()))                  //Increases chance of river choosing cell that has a gentler turn
                {
                    flowDirections.Add(d);
                }
                if (neighbor.HasOutgoingRiver)                   // If river runs into another origin river, join the rivers together. Early Return
                {
                    cell.SetOutgoingRiver(d);
                    return(length);
                }


                flowDirections.Add(d);
            }
            if (flowDirections.Count == 0)
            {
                if (length == 1)
                {
                    return(0);
                }

                if (minNeighborElevation >= cell.Elevation)
                {
                    cell.WaterLevel = minNeighborElevation;
                    if (minNeighborElevation == cell.Elevation)
                    {
                        cell.Elevation = minNeighborElevation - 1;
                    }
                }
                break;
            }

            direction = flowDirections[Random.Range(0, flowDirections.Count)];
            cell.SetOutgoingRiver(direction);
            length += 1;

            if (minNeighborElevation >= cell.Elevation && Random.value < extraLakeProbabiliity)
            {
                cell.WaterLevel = cell.Elevation;
                cell.Elevation -= 1;
            }

            cell = cell.GetNeighbor(direction);
        }
        return(length);
    }
Example #29
0
        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);

            var 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, color1, cell.terrainTypeIndex, e, color1, cell.terrainTypeIndex);

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

            terrain.AddTriangleColor(color1);
            terrain.AddQuadColor(color1);
            terrain.AddQuadColor(color1);
            terrain.AddTriangleColor(color1);

            var types = Vector3.one * cell.terrainTypeIndex;

            terrain.AddTriangleTerrainTypes(types);
            terrain.AddQuadTerrainTypes(types);
            terrain.AddQuadTerrainTypes(types);
            terrain.AddTriangleTerrainTypes(types);

            if (!cell.isUnderWater)
            {
                var 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);
            }
        }
    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);


        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, color1, (int)cell.TerrainType, e, color1, (int)cell.TerrainType);

        terrain.AddTriangle(centerL, m.v1, m.v2);
        terrain.AddQuad(centerL, center, m.v2, m.v3);
        terrain.AddQuad(center, centerR, m.v3, m.v4);
        terrain.AddTriangle(centerR, m.v4, m.v5);

        terrain.AddTriangleColor(color1);
        terrain.AddQuadColor(color1);
        terrain.AddQuadColor(color1);
        terrain.AddTriangleColor(color1);

        Vector3 types;

        types.x = types.y = types.z = (float)cell.TerrainType;
        terrain.AddTriangleTerrainTypes(types);
        terrain.AddQuadTerrainTypes(types);
        terrain.AddQuadTerrainTypes(types);
        terrain.AddTriangleTerrainTypes(types);

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