Ejemplo n.º 1
0
    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);
        }
    }
Ejemplo n.º 2
0
    /// <summary>
    /// 三角化有河流的六边形内部的非河流扇形
    /// </summary>
    /// <param name="direction"></param>
    /// <param name="cell"></param>
    /// <param name="center"></param>
    /// <param name="e"></param>
    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);
    }
Ejemplo n.º 3
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, cell.Color, e, cell.Color);
        TriangulateEdgeFan(center, m, cell.Color);
    }
Ejemplo n.º 4
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);
        if (!cell.IsUnderWater && !cell.HasRoadThroughEdge(direction))
        {
            featureManager.AddFeature(cell, (center + e.v1 + e.v5) * (1f / 3f));
        }
    }
Ejemplo n.º 5
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);
        }
    }
Ejemplo n.º 6
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);
        }
    }
Ejemplo n.º 7
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);
    }
        public void solidEdgeMiddleTest()
        {
            Vector3      corner1   = new Vector3(0f, 0f, HexMetrics.outerRadius);
            Vector3      corner2   = new Vector3(HexMetrics.innerRadius, 0f, 0.5f * HexMetrics.outerRadius);
            Vector3      expected  = (corner1 + corner2) * (0.5f * HexMetrics.solidFactor);
            HexDirection direction = HexDirection.NE;
            Vector3      actual    = HexMetrics.GetSolidEdgeMiddle(direction);

            Assert.AreEqual(expected, actual);
        }
Ejemplo n.º 9
0
    void TriangulateWithRiverBeginOrEnd(HexDirection direction, HexCell cell)
    {
        var center     = cell.Center;
        var closerEdge = cell.Edges[(int)direction];

        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.GetLeftSolidCorner(direction) * 0.25f;
            }
        }
        else if (cell.HasRiverThroughEdge(direction.Previous()) && cell.HasRiverThroughEdge(direction.Next2()))
        {
            center += HexMetrics.GetRightSolidCorner(direction) * 0.25f;
        }

        var m = new EdgeVertices(Vector3.Lerp(center, closerEdge.V1, 0.5f), Vector3.Lerp(center, closerEdge.V5, 0.5f));

        m.V3.y = closerEdge.V3.y; // reassign middle verticle height as it is ommited in the calculation above

        TriangulateEdgeStrip(m, cell.Color, closerEdge, cell.Color);
        TriangulateEdgeFan(center, m, cell.Color);

        // river segments are added only if the current segment is not under water
        if (!cell.IsUnderwater)
        {
            bool reversed = cell.HasIncomingRiver;

            // outer circle of the hex
            TriangulateRiverQuadUnperturbed(m.V2, m.V4, closerEdge.V2, closerEdge.V4, cell.RiverSurfaceY, 0.6f, reversed);

            // end (or start) triangle
            center.y = m.V2.y = m.V4.y = cell.RiverSurfaceY;
            Rivers.AddTriangleUnperturbed(center, 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));
            }
        }
    }
Ejemplo n.º 10
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));
        }
    }
Ejemplo n.º 11
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));
        }
    }
Ejemplo n.º 12
0
    public void TriangulateAdjacentToRiver(HexDirection dir, HexCell cell, Vector3 center, EdgeVertices edges)
    {
        if (cell.HasRoads)
        {
            TriangulateRoadsAdjacentToRiver(dir, cell, center, edges);
        }


        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.23f;
            }
        }
        else if (cell.HasRiverThroughEdge(dir.Previous()) && cell.HasRiverThroughEdge(dir.Next2()))
        {
            center += HexMetrics.GetSecondSolidCorner(dir) * 0.25f;
        }


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

        Color color = Weights1; // cell.Color;

        TriangulateEdgeStrip(modifiedEdges, color, cell.TerrainTypeIndex, edges, color, cell.CellIndex);
        TriangulateEdgeFan(center, modifiedEdges, color, cell.CellIndex);


        if (!cell.IsUnderwater && !cell.HasRoadThroughEdge(dir))
        {
            // centred in triangle
            Vector3 position = (center + edges.v1 + edges.v5) * (1f / 3f);
            FeatureManager.AddFeature(cell, position);
        }
    }
    /// <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));
        }
    }
Ejemplo n.º 14
0
    /// <summary>
    /// Fill the cell triangle with a strip and a fan. We cannot suffice with a single fan,
    /// because we have to make sure that we match the middle edge of the parts that do contain a river.
    /// </summary>
    void TriangulateAdjacentToRiver(HexDirection direction, HexCell cell, EdgeVertices e)
    {
        if (cell.HasRoads)
        {
            TriangulateRoadAdjacentToRiver(direction, cell, e);
        }

        var center = cell.Center;

        if (cell.HasRiverThroughEdge(direction.Next()))
        {
            // we are inside a curve
            if (cell.HasRiverThroughEdge(direction.Previous()))
            {
                center += HexMetrics.GetSolidEdgeMiddle(direction) * (HexMetrics.InnerToOuter * 0.5f);
            }
            // we are inside a straight line
            else if (cell.HasRiverThroughEdge(direction.Previous2()))
            {
                center += HexMetrics.GetLeftSolidCorner(direction) * 0.25f;
            }
        }
        // The final case is when we have a river in the previous direction, and it is a straight one.
        // That requires moving the center towards the next solid corner.
        else if (cell.HasRiverThroughEdge(direction.Previous()) && cell.HasRiverThroughEdge(direction.Next2()))
        {
            center += HexMetrics.GetRightSolidCorner(direction) * 0.25f;
        }

        var m = new EdgeVertices(Vector3.Lerp(center, e.V1, 0.5f), Vector3.Lerp(center, e.V5, 0.5f));

        m.V3.y = e.V3.y;

        TriangulateEdgeStrip(m, cell.Color, e, cell.Color);
        TriangulateEdgeFan(center, m, cell.Color);
    }
Ejemplo n.º 15
0
        public void Execute(Entity entity, int index, [ReadOnly] ref Cell cellData, [ReadOnly] ref NewDataTag tag, [ReadOnly] ref Neighbors neighbors, [ReadOnly] ref NeighborsIndex neighborsIndex, [ReadOnly] ref River river)
        {
            //0.获取单元索引,Execute的index不可靠,添加动态缓存
            int cellIndex = cellData.Index;
            DynamicBuffer <ColorBuffer>  colorBuffer  = CommandBuffer.AddBuffer <ColorBuffer>(index, entity);
            DynamicBuffer <VertexBuffer> vertexBuffer = CommandBuffer.AddBuffer <VertexBuffer>(index, entity);
            //用于河流的动态缓存
            DynamicBuffer <UvBuffer>    uvBuffer     = CommandBuffer.AddBuffer <UvBuffer>(index, entity);
            DynamicBuffer <RiverBuffer> riverBuffers = CommandBuffer.AddBuffer <RiverBuffer>(index, entity);

            //1.获取当前单元的中心位置
            Vector3 currCellCenter = cellData.Position;
            //缓存当前单元的颜色
            Color currCellColor = cellData.Color;
            //当前单元的海拔
            int elevation = cellData.Elevation;

            ////保存需要混合的颜色,使用数组[]是为了方便循环
            Color[] blendColors = new Color[6];
            blendColors[0] = neighbors.NE;
            blendColors[1] = neighbors.E;
            blendColors[2] = neighbors.SE;
            blendColors[3] = neighbors.SW;
            blendColors[4] = neighbors.W;
            blendColors[5] = neighbors.NW;
            //前3个方向相邻单元的索引
            int[] directionIndex = new int[6];
            directionIndex[0] = neighborsIndex.NEIndex;
            directionIndex[1] = neighborsIndex.EIndex;
            directionIndex[2] = neighborsIndex.SEIndex;
            directionIndex[3] = neighborsIndex.SWIndex;
            directionIndex[4] = neighborsIndex.WIndex;
            directionIndex[5] = neighborsIndex.NWIndex;
            //前三个方向相邻单元的海拔
            int[] elevations = new int[6];
            elevations[0] = neighbors.NEElevation;
            elevations[1] = neighbors.EElevation;
            elevations[2] = neighbors.SEElevation;
            elevations[3] = neighbors.SWElevation;
            elevations[4] = neighbors.WElevation;
            elevations[5] = neighbors.NWElevation;
            //添加六边形单元六个方向的顶点、三角和颜色
            for (int j = 0; j < 6; j++)
            {
                //1.添加中心区域的3个顶点
                int          next = (j + 1) > 5 ? 0 : (j + 1);
                EdgeVertices e    = new EdgeVertices((currCellCenter + HexMetrics.SolidCorners[j]), (currCellCenter + HexMetrics.SolidCorners[next]));

                int prev  = (j - 1) < 0 ? 5 : (j - 1);
                int next2 = (j + 2) <= 5 ? (j + 2) : (j - 4);
                int prev2 = (j - 2) >= 0 ? (j - 2) : (j + 4);
                //是否有河流通过
                bool  hasRiverThroughEdge = HasRiverThroughEdge(river, directionIndex[j]);
                float RiverSurfaceY       = (elevation + HexMetrics.riverSurfaceElevationOffset) * HexMetrics.elevationStep;

                //如果有河流通过,则降低海拔来创造河道
                if (cellData.HasRiver)
                {
                    if (hasRiverThroughEdge)
                    {
                        e.v3.y = (elevation + HexMetrics.streamBedElevationOffset) * HexMetrics.elevationStep;
                        if (river.HasOutgoingRiver != river.HasIncomingRiver)
                        {
                            //TriangulateWithRiverBeginOrEnd(directions[j], directions[prev], directions[next], currCellColor, currCellCenter, e, ref colorBuffer, ref vertexBuffer);
                            EdgeVertices m = new EdgeVertices(Vector3.Lerp(currCellCenter, e.v1, 0.5f), Vector3.Lerp(currCellCenter, e.v5, 0.5f));
                            m.v3.y = e.v3.y;
                            TriangulateEdgeStrip(m, currCellColor, e, currCellColor, ref colorBuffer, ref vertexBuffer);
                            TriangulateEdgeFan(currCellCenter, m, currCellColor, ref colorBuffer, ref vertexBuffer);
                            TriangulateRiverQuad(m.v2, m.v4, e.v2, e.v4, RiverSurfaceY, RiverSurfaceY, 0.6f, ref uvBuffer, ref riverBuffers, river.HasIncomingRiver);
                            Vector3 center = currCellCenter;
                            center.y = m.v2.y = m.v4.y = RiverSurfaceY;
                            AddTriangle(center, m.v2, m.v4, ref riverBuffers);
                            if (river.HasIncomingRiver)
                            {
                                AddTriangleUV(new Vector2(0.5f, 0.4f), new Vector2(1f, 0.2f), new Vector2(0f, 0.2f), ref uvBuffer);
                            }
                            else
                            {
                                AddTriangleUV(new Vector2(0.5f, 0.4f), new Vector2(0f, 0.6f), new Vector2(1f, 0.6f), ref uvBuffer);
                            }
                        }
                        else
                        {
                            //TriangulateWithRiver(direction, directions[prev], directions[next], currCellColor, currCellCenter, e, ref colorBuffer, ref vertexBuffer, oppositeHasRiverThroughEdge);
                            Vector3 centerL, centerR;
                            //获取当前方向的相反方向,并判断是否有河流经过
                            if (HasRiverThroughEdge(river, directionIndex[OppositeDirection(j)]))
                            {
                                centerL = currCellCenter + HexMetrics.GetFirstSolidCorner(prev) * 0.25f;
                                centerR = currCellCenter + HexMetrics.GetSecondSolidCorner(next) * 0.25f;
                            }
                            else if (HasRiverThroughEdge(river, directionIndex[next]))
                            {
                                centerL = currCellCenter;
                                centerR = Vector3.Lerp(currCellCenter, e.v5, 2f / 3f);
                            }
                            else if (HasRiverThroughEdge(river, directionIndex[prev]))
                            {
                                centerL = Vector3.Lerp(currCellCenter, e.v1, 2f / 3f);
                                centerR = currCellCenter;
                            }
                            else if (HasRiverThroughEdge(river, directionIndex[next2]))
                            {
                                centerL = currCellCenter;
                                centerR = currCellCenter + HexMetrics.GetSolidEdgeMiddle(next) * (0.5f * HexMetrics.innerToOuter);
                            }
                            else
                            {
                                centerL = currCellCenter + HexMetrics.GetSolidEdgeMiddle(prev) * (0.5f * HexMetrics.innerToOuter);
                                centerR = currCellCenter;
                            }

                            Vector3      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, currCellColor, e, currCellColor, ref colorBuffer, ref vertexBuffer);
                            AddTriangle(centerL, currCellColor, m.v1, currCellColor, m.v2, currCellColor, ref colorBuffer, ref vertexBuffer);
                            AddQuad(centerL, currCellColor, center, currCellColor, m.v2, currCellColor, m.v3, currCellColor, ref colorBuffer, ref vertexBuffer);
                            AddQuad(center, currCellColor, centerR, currCellColor, m.v3, currCellColor, m.v4, currCellColor, ref colorBuffer, ref vertexBuffer);
                            AddTriangle(centerR, currCellColor, m.v4, currCellColor, m.v5, currCellColor, ref colorBuffer, ref vertexBuffer);
                            bool reversed = river.IncomingRiver == directionIndex[j];
                            TriangulateRiverQuad(centerL, centerR, m.v2, m.v4, RiverSurfaceY, RiverSurfaceY, 0.4f, ref uvBuffer, ref riverBuffers, reversed);
                            TriangulateRiverQuad(m.v2, m.v4, e.v2, e.v4, RiverSurfaceY, RiverSurfaceY, 0.6f, ref uvBuffer, ref riverBuffers, reversed);
                        }
                    }
                    else
                    {
                        Vector3 center = currCellCenter;
                        if (HasRiverThroughEdge(river, directionIndex[next]))
                        {
                            if (HasRiverThroughEdge(river, directionIndex[prev]))
                            {
                                center += HexMetrics.GetSolidEdgeMiddle(j) * (HexMetrics.innerToOuter * 0.5f);
                            }
                            else if (HasRiverThroughEdge(river, directionIndex[prev2]))
                            {
                                center += HexMetrics.GetFirstSolidCorner(j) * 0.25f;
                            }
                        }
                        else if (HasRiverThroughEdge(river, directionIndex[prev]) && HasRiverThroughEdge(river, directionIndex[next2]))
                        {
                            center += HexMetrics.GetSecondSolidCorner(j) * 0.25f;
                        }
                        EdgeVertices m = new EdgeVertices(
                            Vector3.Lerp(center, e.v1, 0.5f),
                            Vector3.Lerp(center, e.v5, 0.5f)
                            );

                        TriangulateEdgeStrip(m, currCellColor, e, currCellColor, ref colorBuffer, ref vertexBuffer);
                        TriangulateEdgeFan(center, m, currCellColor, ref colorBuffer, ref vertexBuffer);
                    }
                }
                else
                {
                    TriangulateEdgeFan(currCellCenter, e, currCellColor, ref colorBuffer, ref vertexBuffer);
                }
                //Connection Between 2 cells
                #region  Bridge=桥
                //桥只连接前三个方向相邻的单元,从而避免重复连接
                if (j <= 2)
                {
                    if (directionIndex[j] == int.MinValue)
                    {//如果没有相邻的单元,则跳过循环
                        continue;
                    }

                    //添加外围桥接区域的顶点
                    Vector3 bridge = (HexMetrics.GetBridge(j));

                    bridge.y = (elevations[j] - elevation) * HexMetrics.elevationStep;
                    EdgeVertices e2 = new EdgeVertices(e.v1 + bridge, e.v5 + bridge);
                    if (hasRiverThroughEdge)
                    {
                        float neighborRiverSurfaceY = (elevations[j] + HexMetrics.riverSurfaceElevationOffset) * HexMetrics.elevationStep;
                        e2.v3.y = (elevations[j] + HexMetrics.streamBedElevationOffset) * HexMetrics.elevationStep;
                        TriangulateRiverQuad(e.v2, e.v4, e2.v2, e2.v4, RiverSurfaceY, neighborRiverSurfaceY, 0.8f, ref uvBuffer, ref riverBuffers, river.HasIncomingRiver && river.IncomingRiver == directionIndex[j]);
                    }
                    #region 桥面
                    //判断当前单元与相邻单元的海拔高低差,如果是斜坡,则添加阶梯,平面和峭壁则无需阶梯
                    if (HexMetrics.GetEdgeType(elevation, elevations[j]) == HexMetrics.HexEdgeType.Slope)
                    {
                        TriangulateEdgeTerraces(e, e2, currCellColor, blendColors[j], ref colorBuffer, ref vertexBuffer);
                    }
                    else
                    {
                        Color bridgeColor = (currCellColor + blendColors[j]) * 0.5f;
                        TriangulateEdgeStrip(e, currCellColor, e2, blendColors[j], ref colorBuffer, ref vertexBuffer);
                    }

                    #endregion

                    #region 桥洞

                    //添加外圈区域三向颜色混合

                    if (j <= 1 && directionIndex[next] != int.MinValue)
                    {
                        //下一个相邻单元的海拔
                        int     nextElevation = elevations[next];
                        Vector3 vertex5       = e.v5 + HexMetrics.GetBridge(next);
                        vertex5.y = nextElevation * HexMetrics.elevationStep;
                        //判断相邻的三个六边形单元的高低关系,按照最低(Bottom),左(Left),右(Right)的顺序进行三角化处理
                        if (elevation <= elevations[j])
                        {
                            if (elevation <= nextElevation)
                            {
                                //当前单元海拔最低
                                TriangulateCorner(e.v5, currCellColor, e2.v5, blendColors[j], vertex5, blendColors[next], ref colorBuffer, ref vertexBuffer, elevation, elevations[j], nextElevation);
                            }
                            else
                            {
                                TriangulateCorner(vertex5, blendColors[next], e.v5, currCellColor, e2.v5, blendColors[j], ref colorBuffer, ref vertexBuffer, nextElevation, elevation, elevations[j]);
                            }
                        }
                        else if (elevations[j] <= nextElevation)
                        {
                            TriangulateCorner(e2.v5, blendColors[j], vertex5, blendColors[next], e.v5, currCellColor, ref colorBuffer, ref vertexBuffer, elevations[j], nextElevation, elevation);
                        }
                        else
                        {
                            TriangulateCorner(vertex5, blendColors[next], e.v5, currCellColor, e2.v5, blendColors[j], ref colorBuffer, ref vertexBuffer, nextElevation, elevation, elevations[j]);
                        }
                    }

                    #endregion
                }

                #endregion
            }
            //4.turn off cell system by remove NewDataTag
            CommandBuffer.RemoveComponent <NewDataTag>(index, entity);
        }
    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
            );
    }
Ejemplo n.º 17
0
    private 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;

        // Push the road center in the opposite direction of the river. This is
        // so that the road does not overlap with the river's begin or end.
        if (cell.HasRiverBeginOrEnd)
        {
            // Displace the center 1/3 of the distance to the edge middle point of the opposite direction.
            roadCenter += HexMetrics.GetSolidEdgeMiddle(cell.RiverBeginOrEndDirection.Opposite()) * (1f / 3f);

            // River crosses through the cell.
        }
        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;
            center     += corner * 0.25f;
            // Zig Zag cases
            // Move the road center by using one of the corners of the incoming river direction.
            // Push the road center away from that corner.
        }
        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;

            // Inside of Curved Rivers
            // River on both sides of the current direction, that means there is a curved river. In
            // this case pull the Road towards the current cell edge, shortening the road.
        }
        else if (previousHasRiver && nextHasRiver)
        {
            // Prune isolated road parts, that is, do not render a road through that edge.
            if (!hasRoadThroughEdge)
            {
                return;
            }

            Vector3 offset = HexMetrics.GetSolidEdgeMiddle(direction) * HexMetrics.innerToOuter;
            roadCenter += offset * 0.7f;
            center     += offset * 0.5f;
            // Outside of a curving river
            // There are three cell parts on the outside, we have to
            // find the middle direction.
        }
        else
        {
            HexDirection middle;
            if (previousHasRiver)
            {
                middle = direction.Next();
            }
            else if (nextHasRiver)
            {
                middle = direction.Previous();
            }
            else
            {
                middle = direction;
            }
            // Prune this side of the river if there is no road that continues through
            // this direction, the previous or the next one.
            if (!cell.HasRoadThroughEdge(middle) &&
                !cell.HasRoadThroughEdge(middle.Previous()) &&
                !cell.HasRoadThroughEdge(middle.Next()))
            {
                return;
            }
            roadCenter += HexMetrics.GetSolidEdgeMiddle(middle) * 0.25f;
        }

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

        TriangulateRoad(roadCenter, mL, mR, e, hasRoadThroughEdge);
        if (previousHasRiver)
        {
            TriangulateRoadEdge(roadCenter, center, mL);
        }
        if (nextHasRiver)
        {
            TriangulateRoadEdge(roadCenter, mR, center);
        }
    }
Ejemplo n.º 18
0
    void TriangulateRoadAdjacentToRiver(HexDirection direction, HexCell cell, EdgeVertices e)
    {
        var center = cell.Center;

        // produce partial roads in cells with rivers. The directions with rivers through them will cut gaps in the roads.
        bool    hasRoadThroughEdge = cell.HasRoadThroughEdge(direction);
        bool    previousHasRiver   = cell.HasRiverThroughEdge(direction.Previous());
        bool    nextHasRiver       = cell.HasRiverThroughEdge(direction.Next());
        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.GetRightSolidCorner(direction);
            }
            else
            {
                if (!hasRoadThroughEdge && !cell.HasRoadThroughEdge(direction.Previous()))
                {
                    return;
                }
                corner = HexMetrics.GetLeftSolidCorner(direction);
            }

            roadCenter += corner * 0.5f;

            // add bridges
            if (cell.IncomingRiver == direction.Next() &&
                (cell.HasRoadThroughEdge(direction.Next2()) || cell.HasRoadThroughEdge(direction.Opposite())))
            {
                Features.AddBridge(roadCenter, center - corner * 0.5f);
            }

            center += corner * 0.25f;
        }
        // in case of zigzags
        else if (cell.IncomingRiver == cell.OutgoingRiver.Previous())
        {
            roadCenter -= HexMetrics.GetRightCorner(cell.IncomingRiver) * 0.2f;
        }
        else if (cell.IncomingRiver == cell.OutgoingRiver.Next())
        {
            roadCenter -= HexMetrics.GetLeftCorner(cell.IncomingRiver) * 0.2f;
        }
        // in case of curved rivers
        else if (previousHasRiver && nextHasRiver)
        {
            if (!hasRoadThroughEdge)
            {
                return;
            }

            Vector3 offset = HexMetrics.GetSolidEdgeMiddle(direction) * HexMetrics.InnerToOuter;
            roadCenter += offset * 0.7f;
            center     += offset * 0.5f;
        }
        // outside of the curved river
        else
        {
            HexDirection middle;
            if (previousHasRiver)
            {
                middle = direction.Next();
            }
            else if (nextHasRiver)
            {
                middle = direction.Previous();
            }
            else
            {
                middle = direction;
            }

            // get rid off roads on the other side of the river
            if (!cell.HasRoadThroughEdge(middle) &&
                !cell.HasRoadThroughEdge(middle.Previous()) &&
                !cell.HasRoadThroughEdge(middle.Next()))
            {
                return;
            }

            Vector3 offset = HexMetrics.GetSolidEdgeMiddle(middle);
            roadCenter += offset * 0.25f;

            // prevent duplications
            if (direction == middle && cell.HasRoadThroughEdge(direction.Opposite()))
            {
                Features.AddBridge(roadCenter, center - offset * (HexMetrics.InnerToOuter * 0.7f));
            }
        }

        Vector2 interpolators = GetRoadInterpolators(direction, cell);
        Vector3 mL            = Vector3.Lerp(roadCenter, e.V1, interpolators.x);
        Vector3 mR            = Vector3.Lerp(roadCenter, e.V5, interpolators.y);

        TriangulateRoad(roadCenter, mL, mR, e, hasRoadThroughEdge);

        // close the gaps
        if (previousHasRiver)
        {
            TriangulateRoadEdge(roadCenter, center, mL);
        }
        if (nextHasRiver)
        {
            TriangulateRoadEdge(roadCenter, mR, center);
        }
    }
Ejemplo n.º 19
0
    void TriangulateWithRiver(HexDirection direction, HexCell cell)
    {
        var center     = cell.Center;
        var closerEdge = cell.Edges[(int)direction];

        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.GetLeftSolidCorner(direction) * 0.25f;
            }
        }
        else if (cell.HasRiverThroughEdge(direction.Previous()) && cell.HasRiverThroughEdge(direction.Next2()))
        {
            center += HexMetrics.GetRightSolidCorner(direction) * 0.25f;
        }

        Vector3 centerL, centerR;

        if (cell.HasRiverThroughEdge(direction.Opposite()))
        {
            centerL = center + HexMetrics.GetLeftSolidCorner(direction.Previous()) * 0.25f;
            centerR = center + HexMetrics.GetRightSolidCorner(direction.Next()) * 0.25f;
        }
        else if (cell.HasRiverThroughEdge(direction.Next()))
        {
            centerL = center;
            centerR = Vector3.Lerp(center, closerEdge.V5, 0.65f);
        }
        else if (cell.HasRiverThroughEdge(direction.Previous()))
        {
            centerL = Vector3.Lerp(center, closerEdge.V1, 0.65f);
            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;
        }

        // after deciding where the left and right points are, we can determine the final center by averaging them
        center = Vector3.Lerp(centerL, centerR, 0.5f);

        var m = new EdgeVertices(Vector3.Lerp(centerL, closerEdge.V1, 0.5f), Vector3.Lerp(centerR, closerEdge.V5, 0.5f), 1f / 12f);

        m.V3.y = closerEdge.V3.y;

        // external hex circle
        TriangulateEdgeStrip(m, cell.Color, closerEdge, cell.Color);

        // connection between hexes
        Terrain.AddTriangle(centerL, m.V1, m.V2);
        Terrain.AddTriangleColor(cell.Color);

        Terrain.AddQuad(centerL, new Vector3(center.x, cell.StreamBedY, center.z), m.V2, m.V3);
        Terrain.AddQuadColor(cell.Color);
        Terrain.AddQuad(new Vector3(center.x, cell.StreamBedY, center.z), centerR, m.V3, m.V4);
        Terrain.AddQuadColor(cell.Color);

        Terrain.AddTriangle(centerR, m.V4, m.V5);
        Terrain.AddTriangleColor(cell.Color);

        // create river quads
        if (!cell.IsUnderwater)
        {
            bool reversed = cell.IncomingRiver == direction;

            // inner fan of the hex
            TriangulateRiverQuadUnperturbed(centerL, centerR, m.V2, m.V4, cell.RiverSurfaceY, 0.4f, reversed);

            // external circle of the hex
            var neighbor = cell.GetNeighbor(direction);
            if (neighbor.IsUnderwater)
            {
                TriangulateRiverQuadUnperturbed(m.V2, m.V4, closerEdge.V2, closerEdge.V4,
                                                cell.RiverSurfaceY, HexMetrics.WaterSurfaceY, 0.6f, reversed);
            }
            // normal connection between two rivers
            else
            {
                TriangulateRiverQuadUnperturbed(m.V2, m.V4, closerEdge.V2, closerEdge.V4, cell.RiverSurfaceY, 0.6f, reversed);
            }
        }
    }
Ejemplo n.º 20
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;

        // Push road center away from river
        if (cell.HasRiverBeginOrEnd)
        {
            roadCenter += HexMetrics.GetSolidEdgeMiddle(cell.RiverBeginOrEndDirection.Opposite()) * (1f / 3f);
        }

        // Disconnect road on opposite side of river
        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;
            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;
            }
            roadCenter += HexMetrics.GetSolidEdgeMiddle(middle) * 0.25f;
        }
        Vector3 mL = Vector3.Lerp(roadCenter, e.v1, interpolators.x);
        Vector3 mR = Vector3.Lerp(roadCenter, e.v5, interpolators.y);

        TriangulateRoad(roadCenter, mL, mR, e, hasRoadThroughEdge);

        // Close gaps in road created by river
        if (previousHasRiver)
        {
            TriangulateRoadEdge(roadCenter, center, mL);
        }
        if (nextHasRiver)
        {
            TriangulateRoadEdge(roadCenter, mR, center);
        }
    }
Ejemplo n.º 21
0
    /// <summary>
    /// 生成有河流的三角网格
    /// </summary>
    /// <param name="direction">处理的对应方向</param>
    /// <param name="cell">六边形对象引用</param>
    /// <param name="center">中心点坐标</param>
    /// <param name="e">边界中值插值对象</param>
    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);

        // 根据计算进行网格拼接
        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
                );
        }
    }
Ejemplo n.º 22
0
    /// <summary>
    /// 道路临近河流时的网格处理
    /// </summary>
    /// <param name="direction"></param>
    /// <param name="cell"></param>
    /// <param name="center"></param>
    /// <param name="e"></param>
    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;
            center     += corner * 0.25f;
        }
        // 对于Z字形河流的道路填充判断
        else if (cell.IncomingRiver == cell.OutgoingRiver.Previous())
        {
            // 使道路中心远离河流流入方向向量的0.2
            roadCenter -= HexMetrics.GetSecondCorner(cell.IncomingRiver) * 0.2f;
        }
        else if (cell.IncomingRiver == cell.OutgoingRiver.Next())
        {
            // 使道路中心远离河流流入方向向量的0.2
            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;
            }
            // 将道路弧向中间方向的边界移动25%
            roadCenter += HexMetrics.GetSolidEdgeMiddle(middle) * 0.25f;
        }

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

        TriangulateRoad(roadCenter, mL, mR, e, hasRoadThroughEdge);
        // 平滑处理道路与河流相遇的网格,闭合网格空隙
        if (previousHasRiver)
        {
            TriangulateRoadEdge(roadCenter, center, mL);
        }
        if (nextHasRiver)
        {
            TriangulateRoadEdge(roadCenter, mR, center);
        }
    }
Ejemplo n.º 23
0
    /// <summary>
    /// 三角化有河流流过(有流出也有流入)的六边形内部的有河流的扇形
    /// </summary>
    /// <param name="direction"></param>
    /// <param name="cell"></param>
    /// <param name="center"></param>
    /// <param name="e"></param>
    void TriangulateWithRiver(HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e)
    {
        Vector3 centerL;    //六边形中心线的左边顶点
        Vector3 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, 2 / 3f);     // 把中心线右顶点往外部移动,让中心河道宽一点
        }
        // 如果流入方向和流出方向相邻
        else if (cell.HasRiverThroughEdge(direction.Previous()))
        {
            centerL = Vector3.Lerp(center, e.v1, 2 / 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 = centerR = center;
        }


        // 计算出中心线与外部边缘的中线
        // 梯形:
        //   外部边缘:   ————
        //   中线:        -——-
        //   六边形中心线: ——
        EdgeVertices m = new EdgeVertices(Vector3.Lerp(centerL, e.v1, 0.5f), Vector3.Lerp(centerR, e.v5, 0.5f), 1 / 6f);

        center = Vector3.Lerp(centerL, centerR, 0.5f);   // 中心点重新设置为中心线两顶点的中点
        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);

        // 顶点附近三个六边形格子的索引和splat贴图颜色
        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;    // 流入河水需要翻转UV
            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);
        }
    }
Ejemplo n.º 24
0
    /// <summary>
    /// 三角化有河流的六边形内的道路
    /// </summary>
    /// <param name="direction"></param>
    /// <param name="cell"></param>
    /// <param name="center">六边形的中心</param>
    /// <param name="e"></param>
    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; // 该参数与三角化河流那里一样用0.5,可以刚好移到河流边缘(TriangulateAdjacentToRiver方法内)
        }
        // 流出流入河流相隔一个扇形,且当前扇形位于河流弧度的外侧
        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);
        }
    }
    /// <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);
        }
    }
Ejemplo n.º 26
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
                );
        }
    }
    /// <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);
        }
    }
Ejemplo n.º 28
0
    //绘制河道贯穿的整个cell的情况
    void TriangulateWithRiver(
        HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e)
    {
        Vector3 centerL, centerR;

        if (cell.HasRiverThroughEdge(direction.Opposite()))
        {
            //河流中心的左右岸,*0.25是因为边界是4个矩形,河流占0.5
            centerL = center +
                      HexMetrics.GetFirstSolidCorner(direction.Previous()) * 0.25f;
            centerR = center +
                      HexMetrics.GetSecondSolidCorner(direction.Next()) * 0.25f;
        }
        //当cell河流存在转角的时候
        else if (cell.HasRiverThroughEdge(direction.Previous()))
        {
            centerR = center;
            centerL = Vector3.Lerp(center, e.v1, 2f / 3f);
        }
        else if (cell.HasRiverThroughEdge(direction.Next()))
        {
            centerL = center;
            centerR = Vector3.Lerp(center, e.v5, 2f / 3f);
        }
        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, 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);

        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);
        }
    }
Ejemplo n.º 29
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);
        }
    }
Ejemplo n.º 30
0
    private void TriangulateWithRiver(
        HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e)
    {
        Vector3 centerL, centerR;

        // Two cases:
        // If the cell has a river going through the opposite direction as well as the direction
        // that we are working with, the cell holds a straight river.
        if (cell.HasRiverThroughEdge(direction.Opposite()))
        {
            // Stretch the center into a line. Move 25% from the center to the first corner of the previous
            // direction, and 25% from the center to the second corner of the second direction.
            // One simple way of visualizing this is having a top-down view of the HexMesh and imagining
            // a triangulation in the eastern direction.
            centerL = center + HexMetrics.GetFirstSolidCorner(direction.Previous()) * 0.25f;
            centerR = center + HexMetrics.GetSecondSolidCorner(direction.Next()) * 0.25f;

            // Otherwise, the river does not flow in a straight line, check special cases:
            // Detect sharp turns by checking whether the cell has a rive going through the next
            // or previous cell part.
            // When there is a sharp turn, align the center line with the edge between this and the adjacent part.
        }
        else if (cell.HasRiverThroughEdge(direction.Next()))
        {
            centerL = center;
            centerR = Vector3.Lerp(center, e.v5, 2f / 3f /* Increased center line width from 1/2 to 2/3 */);
        }
        else if (cell.HasRiverThroughEdge(direction.Previous()))
        {
            centerL = Vector3.Lerp(center, e.v1, 2f / 3f /* Increased center line width from 1/2 to 2/3 */);
            centerR = center;

            // 2 step rotations, these produce gently curving rivers.
            // A river is going through two directions after this one.
            // Expand the center towards the center of the next direction's edge.
        }
        else if (cell.HasRiverThroughEdge(direction.Next2()))
        {
            centerL = center;
            // Note that the edge middle point is closer that the vertex itself (it's within the inner radius)
            // which is why extending the center towards that edge will end up with a pinched section.
            // We extend the center edge towards the middle edge times innerToOuter radius to keep
            // the channel width constant.
            centerR = center + HexMetrics.GetSolidEdgeMiddle(direction.Next())
                      * (0.5f * HexMetrics.innerToOuter);
            // 2 step rotation, a river is going through two directions before this one.
        }
        else
        {
            centerL = center + HexMetrics.GetSolidEdgeMiddle(direction.Previous())
                      * (0.5f * HexMetrics.innerToOuter);
            centerR = center;
        }

        // Determine the final center by averaging the Left and Right centers
        center = Vector3.Lerp(centerL, centerR, 0.5f);

        // We lerp the second and fourth vertices using 1/6 instead of the usual 1/4 as the
        // length from the edges is 1/8 instead of 1/4. This is because the channel has a
        // the same width along the river, so the relative edge length of the outer edges
        // will be 1/6 relative to the edge's middle length. (1/8 of 3/4)
        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);

        // Add the triangles and quads that reached the center.
        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);
        }
    }