예제 #1
0
    //e1 = solid edge vertices
    void TriangulatePoliticalBorder(HexDirection direction, HexCell cell, EdgeVertices e1)
    {
        if (cell.IsNeighborFriendly(direction))
        {
            return;
        }

        Vector3      center = cell.Position;
        EdgeVertices e3     = new EdgeVertices(
            center + HexMetrics.GetFirstCorner(direction),
            center + HexMetrics.GetSecondCorner(direction)
            );

        politicalBorders.AddQuad(e1.v1, e1.v2, e3.v1, e3.v2);
        politicalBorders.AddQuad(e1.v2, e1.v3, e3.v2, e3.v3);
        politicalBorders.AddQuad(e1.v3, e1.v4, e3.v3, e3.v4);
        politicalBorders.AddQuad(e1.v4, e1.v5, e3.v4, e3.v5);

        politicalBorders.AddQuadUV(0f, 0f, 1f, 0f);
        politicalBorders.AddQuadUV(0f, 0f, 1f, 0f);
        politicalBorders.AddQuadUV(0f, 0f, 1f, 0f);
        politicalBorders.AddQuadUV(0f, 0f, 1f, 0f);

        HexCell neighbor     = cell.GetNeighbor(direction);
        HexCell nextNeighbor = cell.GetNeighbor(direction.Next());

        if (cell.IsNeighborFriendly(direction.Next()))
        {
            Debug.Log("corner should be added");

            politicalBorders.AddTriangle(e3.v5, e1.v5 + HexMetrics.GetBridge(direction.Next()), e1.v5);
            politicalBorders.AddTriangleUV(new Vector2(0f, 0f), new Vector2(0f, 1f), new Vector2(0f, 1f));
        }
    }
예제 #2
0
    //仅处理无临边的情况
    private void NoNeighborConnection(HexDirectionEnum direction, HexCell cell, EdgeVertices edge)
    {
        Vector3 center = cell.Position;
        Vector3 bridge = HexMetrics.GetOneBridge(direction);
        Vector3 v3     = edge.v1 + bridge;
        Vector3 v4     = edge.v5 + bridge;
        Vector3 v5     = center + HexMetrics.GetFirstCorner(direction);
        Vector3 v6     = center + HexMetrics.GetSecondCorner(direction);

        HexCell prevNeighbor = cell.GetNeighbor(direction.Previous());
        HexCell nextNeighbor = cell.GetNeighbor(direction.Next());

        v6.y = v5.y = v4.y = v3.y = 0;

        EdgeVertices edge2 = new EdgeVertices(v5, v6);


        if (nextNeighbor == null && prevNeighbor != null)
        {
            edge2 = new EdgeVertices(v3, v6);

            HexCell noneCell = new GameObject().AddComponent <HexCell>();
            noneCell.Index = cell.Index;
            TriangulateCorner(edge.v1, cell, v5, prevNeighbor, v3, noneCell);
            DestroyObject(noneCell.gameObject);
        }
        if (cell.Elevation == HexMetrics.elevationDiffer)
        {
            TriangulateEdgeTerraces(edge, cell, edge2, cell, cell.HasRoadThroughEdge(direction));
        }
        else
        {
            TriangulateEdgeStrip(edge, weights1, cell.Index, edge2, weights1, cell.Index, cell.HasRoadThroughEdge(direction));
        }
    }
예제 #3
0
    void Triangulate(HexDirection direction, HexCell cell)
    {
        Vector3 center = cell.transform.localPosition;
        Vector3 v1     = center + HexMetrics.GetFirstSolidCorner(direction);
        Vector3 v2     = center + HexMetrics.GetSecondSolidCorner(direction);
        Vector3 bridge = HexMetrics.GetBridge(direction);
        Vector3 v3     = v1 + bridge;
        Vector3 v4     = v2 + bridge;

        AddTriangle(center, v1, v2);
        AddTriangleColor(cell.color);
        AddQuad(v1, v2, v3, v4);

        HexCell prevNeighbor = cell.GetNeighbor(direction.Previous()) ?? cell;
        HexCell neighbor     = cell.GetNeighbor(direction) ?? cell;
        HexCell nextNeighbor = cell.GetNeighbor(direction.Next()) ?? cell;

        Color bridgeColor = (cell.color + neighbor.color) * 0.5f;

        AddQuadColor(cell.color, bridgeColor);

        AddTriangle(v1, center + HexMetrics.GetFirstCorner(direction), v3);
        AddTriangleColor(
            cell.color,
            (cell.color + prevNeighbor.color + neighbor.color) / 3f,
            bridgeColor
            );
        AddTriangle(v2, v4, center + HexMetrics.GetSecondCorner(direction));
        AddTriangleColor(
            cell.color,
            bridgeColor,
            (cell.color + neighbor.color + nextNeighbor.color) / 3f
            );
    }
예제 #4
0
파일: HexCell.cs 프로젝트: rheehot/HexMap
 private void OnDrawGizmos()
 {
     Gizmos.color = Color.black;
     for (HexDirection direction = HexDirection.NE; direction <= HexDirection.NW; direction++)
     {
         Gizmos.DrawLine(transform.TransformPoint(HexMetrics.GetFirstCorner(direction))
                         , transform.TransformPoint(HexMetrics.GetSecondCorner(direction)));
     }
 }
예제 #5
0
    void Triangulate(HexDirection direction, HexCell cell)
    {
        Vector3 center = cell.transform.localPosition;

        map.AddTriangle(
            center,
            center + _hexMetrics.GetFirstCorner(direction),
            center + _hexMetrics.GetSecondCorner(direction)
            );
        map.AddTriangleColor(cell.Color);
    }
예제 #6
0
 //cellPos를 중심으로 육각 mesh를 생성
 void Triangulate(Vector3 cellPos)
 {
     for (HexDirection direction = HexDirection.NE; direction <= HexDirection.NW; direction++)
     {
         AddTriangle(
             cellPos,
             cellPos + HexMetrics.GetFirstCorner(direction),
             cellPos + HexMetrics.GetSecondCorner(direction)
             );
         AddTriangleColor(gridColor);
     }
 }
        public void secondCornerTest()
        {
            float innRad = HexMetrics.innerRadius;
            float outRad = HexMetrics.outerRadius;

            Vector3 expected = new Vector3(innRad, 0f, 0.5f * outRad);

            HexDirection direction = HexDirection.NE;
            Vector3      actual    = HexMetrics.GetSecondCorner(direction);

            Assert.AreEqual(expected, actual);
        }
예제 #8
0
    public void Outline(HexCell cell)
    {
        Vector3 center = cell.transform.localPosition;
        var     points = new Vector3[lengthOfLineRenderer];
        int     i      = 0;

        for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++)
        {
            points[i++] = center + HexMetrics.GetFirstCorner(d) + offset;
            points[i++] = center + HexMetrics.GetSecondCorner(d) + offset;
        }
        lineRenderer.SetPositions(points);
    }
예제 #9
0
파일: HexMap.cs 프로젝트: jc429/beelliards
    /* Creates a quad stretching from a cell's solid boundary to its true edge*/
    void TriangulateEdge(HexDirection direction, HexCell cell)
    {
        Vector3      center = cell.transform.localPosition;
        EdgeVertices e1     = new EdgeVertices(
            center + HexMetrics.GetFirstSolidCorner(direction),
            center + HexMetrics.GetSecondSolidCorner(direction)
            );
        EdgeVertices e2 = new EdgeVertices(
            center + HexMetrics.GetFirstCorner(direction),
            center + HexMetrics.GetSecondCorner(direction)
            );

        edgeMesh.AddQuad(e1, e2);
    }
예제 #10
0
    void Triangulate(HexDirection direction, HexCell cell)
    {
        Vector3 center = cell.transform.localPosition;

        terrain.AddTriangle(
            center,
            center + HexMetrics.GetFirstCorner(direction),
            center + HexMetrics.GetSecondCorner(direction)
            );
        HexCell prevNeighbor = cell.GetNeighbor(direction.Previous()) ?? cell;
        HexCell neighbor     = cell.GetNeighbor(direction) ?? cell;
        HexCell nextNeighbor = cell.GetNeighbor(direction.Next()) ?? cell;

        terrain.AddTriangleColor(cell.Color);
    }
예제 #11
0
    void Triangulate(HexDirection direction, HexCell cell)
    {
        Vector3 center = cell.transform.localPosition;
        Vector3 v1     = center + HexMetrics.GetFirstSolidCorner(direction);
        Vector3 v2     = center + HexMetrics.GetSecondSolidCorner(direction);

        Vector3 v5 = center + HexMetrics.GetFirstCorner(direction);
        Vector3 v6 = center + HexMetrics.GetSecondCorner(direction);

        AddTriangle(center, v1, v2);
        AddTriangleColor(cell.color);
        if (direction <= HexDirection.SE)
        {
            TriangulateConnection(direction, cell, v1, v2);
        }
    }
예제 #12
0
파일: HexMap.cs 프로젝트: jc429/beelliards
    void TriangulateWallStrip(HexDirection d, HexCell cell)
    {
        HexDirection castDir = d.Opposite();
        HexCell      n       = cell.GetNeighbor(castDir);

        if (CheckCellValid(n))
        {
            //limit to prevent infinite loops if something goes wrong
            for (int i = 0; i < 10; i++)
            {
                HexCell n2 = n.GetNeighbor(castDir);
                if (CheckCellValid(n2))
                {
                    n = n2;
                }
                else
                {
                    break;
                }
            }
            //n is final cell
            Vector3 offset = new Vector3(0, wallHeight, 0);

            EdgeVertices e1 = new EdgeVertices(
                cell.transform.localPosition + HexMetrics.GetFirstSolidCorner(castDir),
                n.transform.localPosition + HexMetrics.GetSecondSolidCorner(d)
                );

            EdgeVertices e2 = new EdgeVertices(
                e1.v1 + offset,
                e1.v2 + offset
                );
            wallMesh.AddQuad(e1, e2);

            EdgeVertices e3 = new EdgeVertices(
                offset + cell.transform.localPosition + HexMetrics.GetFirstCorner(castDir),
                offset + n.transform.localPosition + HexMetrics.GetSecondCorner(d)
                );
            wallMesh.AddQuad(e2, e3);

            EdgeVertices e4 = new EdgeVertices(
                offset + cell.transform.localPosition + HexMetrics.GetFirstCorner(castDir.Previous()),
                offset + n.transform.localPosition + HexMetrics.GetSecondCorner(d.Next())
                );
            wallMesh.AddQuad(e3, e4);
        }
    }
예제 #13
0
파일: HexMap.cs 프로젝트: jc429/beelliards
    /* creates the stage boundaries */
    void TriangulateOuterWallPanelCorner(HexDirection direction, HexCell cell, HexCell neighbor)
    {
        Vector3 offset   = new Vector3(0, wallHeight, 0);
        Vector3 endpoint = offset + cell.transform.localPosition + HexMetrics.GetSecondCorner(direction);

        EdgeVertices e1 = new EdgeVertices(
            cell.transform.localPosition + HexMetrics.GetSecondSolidCorner(direction),
            neighbor.transform.localPosition + HexMetrics.GetFirstSolidCorner(direction.Previous())
            );
        EdgeVertices e2 = new EdgeVertices(
            e1.v1 + offset,
            e1.v2 + offset
            );

        edgeMesh.AddQuad(e1, e2);
        edgeMesh.AddTriangle(e2.v1, endpoint, e2.v2);
    }
예제 #14
0
파일: HexMap.cs 프로젝트: jc429/beelliards
    /*** Unused? ***/

    /* creates the stage boundaries */
    void TriangulateOuterWallPanel(HexDirection direction, HexCell cell)
    {
        Vector3      center = cell.transform.localPosition;
        Vector3      offset = new Vector3(0, wallHeight, 0);
        EdgeVertices e1     = new EdgeVertices(
            center + HexMetrics.GetFirstSolidCorner(direction),
            center + HexMetrics.GetSecondSolidCorner(direction)
            );
        EdgeVertices e2 = new EdgeVertices(
            e1.v1 + offset,
            e1.v2 + offset
            );
        EdgeVertices e3 = new EdgeVertices(
            center + offset + HexMetrics.GetFirstCorner(direction),
            center + offset + HexMetrics.GetSecondCorner(direction)
            );

        wallMesh.AddQuad(e1, e2);
        wallMesh.AddQuad(e2, e3);
    }
예제 #15
0
    void Triangulate(HexDirection direction, HexCell cell)
    {
        //纯色区域三角化使用单一颜色
        Vector3 center = cell.transform.localPosition;
        Vector3 v1     = center + HexMetrics.GetFirstSolidCorner(direction);
        Vector3 v2     = center + HexMetrics.GetSecondSolidCorner(direction);

        AddTriangle(center, v1, v2);
        AddTriangleColor(cell.color);
        //梯形混色区域
        Vector3 bridge = HexMetrics.GetBridge(direction);
        Vector3 v3     = v1 + bridge;
        Vector3 v4     = v2 + bridge;

        AddQuad(v1, v2, v3, v4);
        HexCell prevNeighbor = cell.GetNeighbor(direction.Previous()) ?? cell;
        HexCell neighbor     = cell.GetNeighbor(direction) ?? cell;
        HexCell nextNeighbor = cell.GetNeighbor(direction.Next()) ?? cell;

        AddQuadColor(cell.color,
                     (cell.color + prevNeighbor.color + neighbor.color) * 0.5f);
        //补上被剔除的两个三角形(第一个三角形三个顶点的颜色分别是v1本色,2三个六边形混色,3桥色)
        Color bridgeColor = (cell.color + neighbor.color) * 0.5f;

//        AddQuadColor(cell.color, bridgeColor);
        AddTriangle(v1, center + HexMetrics.GetFirstCorner(direction), v3);
        AddExcludedTriangleColor(
            cell.color,
            (cell.color + prevNeighbor.color + neighbor.color) / 3f,
            bridgeColor);
        AddTriangle(v2, v4, center + HexMetrics.GetSecondCorner(direction));
        AddExcludedTriangleColor(
            cell.color,
            bridgeColor,
            (cell.color + neighbor.color + nextNeighbor.color) / 3f
            );
    }
예제 #16
0
    private void Triangulate(HexDirection direction, HexCell cell)
    {
        Vector3 center = cell.transform.localPosition;
        Vector3 v1     = center + HexMetrics.GetFirstSolidCorner(direction);
        Vector3 v2     = center + HexMetrics.GetSecondSolidCorner(direction);

        AddTriangle(center, v1, v2);
        AddTriangleColor(cell.CellColor);

        Vector3 v3 = center + HexMetrics.GetFirstCorner(direction);
        Vector3 v4 = center + HexMetrics.GetSecondCorner(direction);

        AddQuad(v1, v2, v3, v4);

        HexCell previousNeighbour = cell.GetNeighbour(direction.Previous()) ?? cell;
        HexCell neighbour         = cell.GetNeighbour(direction) ?? cell;
        HexCell nextNeighbour     = cell.GetNeighbour(direction.Next()) ?? cell;

        AddQuadColor(
            cell.CellColor,
            cell.CellColor,
            (cell.CellColor + previousNeighbour.CellColor + neighbour.CellColor) / 3f,
            (cell.CellColor + neighbour.CellColor + nextNeighbour.CellColor) / 3f);
    }
    /// <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);
        }
    }
예제 #18
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);
        }
    }
예제 #19
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);
        }
    }
예제 #20
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);
        }
    }
예제 #21
0
    void Triangulate(HexCell cell, List <HexCoordinates> neighbours)
    {
        Vector3 centre = cell.transform.localPosition;

        List <Vector3> linePoints = new List <Vector3>();

        if (cell.isHill)
        {
            Vector3 hillCentre = new Vector3(centre.x, centre.y + HexMetrics.hillHeight, centre.z);
            Color   shadedCol  = new Color(cell.colour.r * 0.8f, cell.colour.g * 0.8f, cell.colour.b * 0.8f);

            //Add 6 (smaller) triangles
            for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++)
            {
                Vector3 firstGroundCorner  = HexMetrics.GetFirstCorner(d);
                Vector3 secondGroundCorner = HexMetrics.GetSecondCorner(d);
                Vector3 firstHillCorner    = HexMetrics.GetFirstHillCorner(d);
                Vector3 secondHillCorner   = HexMetrics.GetSecondHillCorner(d);

                //Smaller Central Triangles
                AddTriangle(hillCentre, hillCentre + firstHillCorner, hillCentre + secondHillCorner);
                AddTriangleColour(cell.colour);
                linePoints.Add(hillCentre + HexMetrics.GetFirstHillCorner(d) + Vector3.up * 0.1f);

                //Side triangles
                AddTriangle(hillCentre + firstHillCorner, centre + firstGroundCorner, centre + secondGroundCorner);
                AddTriangle(centre + secondGroundCorner, hillCentre + secondHillCorner, hillCentre + firstHillCorner);

                if (d <= HexDirection.E)
                {
                    AddTriangleColour(shadedCol);
                    AddTriangleColour(shadedCol);
                }
                else
                {
                    AddTriangleColour(cell.colour);
                    AddTriangleColour(cell.colour);
                }


                //Lines up the hill
                LineRenderer connectorLine = Instantiate <LineRenderer>(linePrefab);
                connectorLine.transform.name   = cell.coordinates.ToString() + " " + System.Enum.GetName(typeof(HexDirection), d) + " Line";
                connectorLine.transform.parent = transform;
                connectorLine.positionCount    = 2;
                connectorLine.SetPositions(new Vector3[]
                {
                    hillCentre + HexMetrics.GetFirstHillCorner(d) + Vector3.up * 0.1f,
                    centre + HexMetrics.GetFirstCorner(d) + Vector3.up * 0.1f
                });
            }
        }
        else
        {
            //Add 6 triangles
            for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++)
            {
                AddTriangle(centre, centre + HexMetrics.GetFirstCorner(d), centre + HexMetrics.GetSecondCorner(d));
                AddTriangleColour(cell.colour);
                linePoints.Add(centre + HexMetrics.GetFirstCorner(d) + Vector3.up * 0.1f);
            }
        }

        LineRenderer outline = Instantiate <LineRenderer>(linePrefab);

        outline.transform.name   = cell.coordinates.ToString() + "Outline";
        outline.transform.parent = transform;
        outline.positionCount    = 6;
        outline.SetPositions(linePoints.ToArray());
    }
    void Triangulate(HexDirection direction, HexCell cell)
    {
        bool    isDeep = cell.Elevation == ElevationLevel.Deep ? true : false;
        Vector3 center = cell.transform.localPosition;
        Vector3 v1     = center + HexMetrics.GetFirstSolidCorner(direction, isDeep);
        Vector3 v2     = center + HexMetrics.GetSecondSolidCorner(direction, isDeep);

        //Center Tris
        terrain.AddTriangle(center, v1, v2);
        terrain.AddTriangleColor(cell.Color);

        Vector3 edge   = HexMetrics.GetEdge(direction, isDeep);
        Vector3 tempV3 = center + HexMetrics.GetFirstEdgeCorner(direction, isDeep);
        Vector3 tempV4 = center + HexMetrics.GetSecondEdgeCorner(direction, isDeep);
        Vector3 v3     = tempV3 + edge;
        Vector3 v4     = tempV4 + edge;

        HexCell prevNeighbor = cell.GetNeighbor(direction.Previous()) ?? cell;
        HexCell neighbor     = cell.GetNeighbor(direction) ?? cell;
        HexCell nextNeighbor = cell.GetNeighbor(direction.Next()) ?? cell;

        //Edge Elevation
        if (cell.Elevation < neighbor.Elevation)
        {
            v3.y = v4.y = neighbor.Position.y;
        }

        //Edge Terrace Quads & Quads
        if (isDeep && neighbor.Elevation == ElevationLevel.Flat)
        {
            TriangulateEdgeTerraces(v1, v2, cell, v3, v4, neighbor);
        }
        else if (isDeep && neighbor.Elevation != ElevationLevel.Flat &&
                 cell.Elevation < neighbor.Elevation)
        {
            terrain.AddQuad(v1, v2, v3, v4);
            terrain.AddQuadColor(neighbor.Color);
        }
        else
        {
            terrain.AddQuad(v1, v2, v3, v4);
            terrain.AddQuadColor(cell.Color);
        }

        Vector3 v5 = center + HexMetrics.GetFirstCorner(direction);
        Vector3 v6 = center + HexMetrics.GetSecondCorner(direction);

        //Vertice Elevation Change
        if (cell.Elevation < neighbor.Elevation)
        {
            v5.y = v6.y = neighbor.Position.y;
        }
        if (cell.Elevation < nextNeighbor.Elevation)
        {
            if (nextNeighbor.Elevation < neighbor.Elevation)
            {
                v6.y = neighbor.Position.y;
            }
            else
            {
                v6.y = nextNeighbor.Position.y;
            }
        }
        if (cell.Elevation < prevNeighbor.Elevation)
        {
            if (prevNeighbor.Elevation < neighbor.Elevation)
            {
                v5.y = neighbor.Position.y;
            }
            else
            {
                v5.y = prevNeighbor.Position.y;
            }
        }

        //Corner Tris & Corner Terrace Tris
        if (isDeep)
        {
            if (neighbor.Elevation == ElevationLevel.Flat)
            {
                TriangulateCornerTerraces(v1, cell, v5, v3, neighbor);
                TriangulateCornerTerraces(v2, cell, v4, v6, neighbor);
            }
            else if (cell.Elevation == neighbor.Elevation)
            {
                if (nextNeighbor.Elevation == ElevationLevel.Flat &&
                    prevNeighbor.Elevation == ElevationLevel.Flat)
                {
                    TriangulateOuterCornerTerraces(v5, cell, v3, v1, prevNeighbor);
                    TriangulateOuterCornerTerraces(v6, cell, v2, v4, nextNeighbor);
                }
                else if (nextNeighbor.Elevation == ElevationLevel.Flat)
                {
                    TriangulateOuterCornerTerraces(v6, cell, v2, v4, nextNeighbor);
                    terrain.AddTriangle(v1, v5, v3);
                    if (cell.Elevation < prevNeighbor.Elevation)
                    {
                        terrain.AddTriangleColor(prevNeighbor.Color);
                    }
                    else
                    {
                        terrain.AddTriangleColor(cell.Color);
                    }
                }
                else if (prevNeighbor.Elevation == ElevationLevel.Flat)
                {
                    TriangulateOuterCornerTerraces(v5, cell, v3, v1, prevNeighbor);
                    terrain.AddTriangle(v2, v4, v6);
                    if (cell.Elevation < nextNeighbor.Elevation)
                    {
                        terrain.AddTriangleColor(nextNeighbor.Color);
                    }
                    else
                    {
                        terrain.AddTriangleColor(cell.Color);
                    }
                }
                else if (cell.Elevation < nextNeighbor.Elevation &&
                         cell.Elevation < prevNeighbor.Elevation)
                {
                    terrain.AddTriangle(v1, v5, v3);
                    terrain.AddTriangleColor(prevNeighbor.Color);
                    terrain.AddTriangle(v2, v4, v6);
                    terrain.AddTriangleColor(nextNeighbor.Color);
                }
                else if (cell.Elevation < nextNeighbor.Elevation)
                {
                    terrain.AddTriangle(v1, v5, v3);
                    terrain.AddTriangleColor(cell.Color);
                    terrain.AddTriangle(v2, v4, v6);
                    terrain.AddTriangleColor(nextNeighbor.Color);
                }
                else if (cell.Elevation < prevNeighbor.Elevation)
                {
                    terrain.AddTriangle(v1, v5, v3);
                    terrain.AddTriangleColor(prevNeighbor.Color);
                    terrain.AddTriangle(v2, v4, v6);
                    terrain.AddTriangleColor(cell.Color);
                }
                else
                {
                    terrain.AddTriangle(v1, v5, v3);
                    terrain.AddTriangleColor(cell.Color);
                    terrain.AddTriangle(v2, v4, v6);
                    terrain.AddTriangleColor(cell.Color);
                }
            }
            else
            {
                if (nextNeighbor.Elevation == ElevationLevel.Flat &&
                    prevNeighbor.Elevation == ElevationLevel.Flat)
                {
                    TriangulateNextCornerTerracesCliff(v6, cell, v2, v4, neighbor, nextNeighbor);
                    TriangulatePrevCornerTerracesCliff(v5, cell, v3, v1, neighbor, prevNeighbor);
                }
                else if (nextNeighbor.Elevation == ElevationLevel.Flat)
                {
                    TriangulateNextCornerTerracesCliff(v6, cell, v2, v4, neighbor, nextNeighbor);
                    terrain.AddTriangle(v1, v5, v3);
                    terrain.AddTriangleColor(neighbor.Color);
                }
                else if (prevNeighbor.Elevation == ElevationLevel.Flat)
                {
                    TriangulatePrevCornerTerracesCliff(v5, cell, v3, v1, neighbor, prevNeighbor);
                    terrain.AddTriangle(v2, v4, v6);
                    terrain.AddTriangleColor(neighbor.Color);
                }
                else
                {
                    terrain.AddTriangle(v1, v5, v3);
                    terrain.AddTriangleColor(neighbor.Color);
                    terrain.AddTriangle(v2, v4, v6);
                    terrain.AddTriangleColor(neighbor.Color);
                }
            }
        }
        else
        {
            terrain.AddTriangle(v1, v5, v3);
            terrain.AddTriangleColor(cell.Color);
            terrain.AddTriangle(v2, v4, v6);
            terrain.AddTriangleColor(cell.Color);
        }

        //Features
        if (cell.Elevation == ElevationLevel.Flat)
        {
            features.AddFeature(cell, (center + v1 + v5) * (1f / 3f));
        }
    }
예제 #23
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)
        {
            //细胞中有河流的开始或结束
            //中心点道路往河流的相反方向偏移1/3位置
            roadCenter += HexMetrics.GetSoliEdgeMiddle(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;
        }
        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.GetSoliEdgeMiddle(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.GetSoliEdgeMiddle(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);
            //Debug.Log("Direction:" + direction);
        }
        if (nextHasRiver)
        {
            //当前方向的下一位方向存在河流时
            //道路中心,中间的右点,和单元格中心之间添加一个三角形
            TriangulateRoadEdge(roadCenter, mR, center);
        }
    }
예제 #24
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);
        }
    }
예제 #25
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);
        }
    }