예제 #1
0
    public TerrainTriangulationData TriangulateHexTerrainEdge(
        Hex hex,
        Hex neighbor,
        TerrainTriangulationData triangulationData,
        Dictionary <HexDirections, Hex> neighbors,
        HexDirections direction,
        HexRiverData riverData,
        FeatureContainer features,
        Dictionary <HexDirections, bool> roadEdges,
        Dictionary <HexDirections, ElevationEdgeTypes> elevationEdgeTypes,
        float hexOuterRadius,
        int wrapSize
        )
    {
        triangulationData = TriangulateTerrainCenter(
            riverData,
            direction,
            hex,
            triangulationData,
            hexOuterRadius,
            wrapSize,
            this,
            features,
            roadEdges
            );

        if (direction <= HexDirections.Southeast)
        {
            triangulationData = TriangulateTerrainConnection(
                hex,
                neighbor,
                triangulationData,
                direction,
                riverData,
                roadEdges,
                elevationEdgeTypes,
                hexOuterRadius,
                wrapSize,
                this,
                features
                );

            // Adjust the other edge of the connection  if there is a river through
            // that edge.
            triangulationData = TryTriangulateNeighborTerrainCorner(
                hex,
                neighbor,
                triangulationData,
                direction,
                neighbors,
                hexOuterRadius,
                wrapSize,
                this,
                features
                );
        }

        return(triangulationData);
    }
    public WaterTriangulationData TriangulateHexOpenWaterEdge(
        Hex source,
        Hex neighbor,
        Dictionary <HexDirections, Hex> neighbors,
        HexDirections direction,
        WaterTriangulationData waterTriData,
        TerrainTriangulationData terrainTriData,
        float hexOuterRadius,
        int wrapSize
        )
    {
        if (source.IsUnderwater)
        {
            if (
                !neighbor.IsUnderwater
                )
            {
                waterTriData = TriangulateShoreOpenWater(
                    source,
                    neighbor,
                    waterTriData.waterSurfaceCenter,
                    waterTriData.sourceWaterEdge,
                    hexOuterRadius,
                    wrapSize,
                    this,
                    waterTriData
                    );
            }
            else
            {
                waterTriData = TriangulateOpenWaterCenter(
                    source,
                    waterTriData,
                    direction,
                    hexOuterRadius,
                    wrapSize,
                    this
                    );

                waterTriData = TriangulateOpenWaterConnection(
                    source,
                    neighbor,
                    direction,
                    waterTriData,
                    terrainTriData,
                    neighbors,
                    hexOuterRadius,
                    wrapSize,
                    this
                    );
            }
        }

        return(waterTriData);
    }
    private TerrainTriangulationData TriangulateTerrainConnectionRoads(
        Hex source,
        Hex neighbor,
        TerrainTriangulationData data,
        HexDirections direction,
        HexRiverData riverData,
        Dictionary <HexDirections, bool> roadEdges,
        Dictionary <HexDirections, ElevationEdgeTypes> elevationEdgeTypes,
        float hexOuterRadius,
        int wrapSize,
        MapMeshChunkLayer roads
        )
    {
        bool hasRoad = roadEdges[direction];

        if (
//            hex.GetEdgeType(direction) == ElevationEdgeTypes.Slope
            elevationEdgeTypes[direction] == ElevationEdgeTypes.Slope
            )
        {
            if (hasRoad)
            {
                TriangulateEdgeTerracesRoads(
                    data.centerEdgeVertices,
                    source,
                    data.connectionEdgeVertices,
                    neighbor,
                    hasRoad,
                    hexOuterRadius,
                    wrapSize,
                    roads
                    );
            }
        }
        else
        {
            if (hasRoad)
            {
                TriangulateEdgeStripRoads(
                    data.centerEdgeVertices,
                    _weights1,
                    source.Index,
                    data.connectionEdgeVertices,
                    _weights2,
                    neighbor.Index,
                    hexOuterRadius,
                    wrapSize,
                    roads
                    );
            }
        }

        return(data);
    }
예제 #4
0
    public TerrainTriangulationData TriangulateHexRiverEdge(
        Hex hex,
        Hex neighbor,
        HexDirections direction,
        Dictionary <HexDirections, bool> roadEdges,
        HexRiverData riverData,
        TerrainTriangulationData triangulationData,
        float hexOuterRadius,
        int wrapSize
        )
    {
        if (riverData.HasRiver)
        {
            triangulationData = TriangulateCenterRiverSurface(
                riverData,
                direction,
                hex,
                triangulationData,
                hexOuterRadius,
                wrapSize,
                this,
                roadEdges
                );

            if (direction <= HexDirections.Southeast)
            {
                /*triangulationData =
                 *  GetConnectionEdgeVertices(
                 *      hex,
                 *      neighbor,
                 *      direction,
                 *      triangulationData,
                 *      hexOuterRadius
                 *  );*/

                // Adjust the other edge of the connection  if there is a river through
                // that edge.
                triangulationData = TriangulateRiverConnection(
                    hex,
                    neighbor,
                    triangulationData,
                    direction,
                    riverData,
                    hexOuterRadius,
                    wrapSize,
                    this
                    );
            }
        }


        return(triangulationData);
    }
예제 #5
0
    private TerrainTriangulationData TriangulateCenterRiverQuads(
        Hex source,
        TerrainTriangulationData triangulationData,
        HexDirections direction,
        HexRiverData riverData,
        float hexOuterRadius,
        int wrapSize,
        MapMeshChunkLayer rivers
        )
    {
        bool reversed = riverData.HasIncomingRiverInDirection(
            direction
            );

        Vector3 centerHexIndices;

        centerHexIndices.x         =
            centerHexIndices.y     =
                centerHexIndices.z =
                    source.Index;

        TriangulateRiverQuad(
            triangulationData.riverCenterLeft,
            triangulationData.riverCenterRight,
            triangulationData.middleEdgeVertices.vertex2,
            triangulationData.middleEdgeVertices.vertex4,
            source.RiverSurfaceY,
            0.4f,
            reversed,
            centerHexIndices,
            hexOuterRadius,
            wrapSize,
            rivers
            );

        TriangulateRiverQuad(
            triangulationData.middleEdgeVertices.vertex2,
            triangulationData.middleEdgeVertices.vertex4,
            triangulationData.centerEdgeVertices.vertex2,
            triangulationData.centerEdgeVertices.vertex4,
            source.RiverSurfaceY,
            0.6f,
            reversed,
            centerHexIndices,
            hexOuterRadius,
            wrapSize,
            rivers
            );

        return(triangulationData);
    }
예제 #6
0
    private TerrainTriangulationData TriangulateCenterRiverSurface(
        HexRiverData riverData,
        HexDirections direction,
        Hex source,
        TerrainTriangulationData data,
        float hexOuterRadius,
        int wrapSize,
        MapMeshChunkLayer rivers,
        Dictionary <HexDirections, bool> roadEdges
        )
    {
        if (riverData.HasRiver)
        {
            if (riverData.HasRiverInDirection(direction))
            {
// If the triangle has a river through the edge, lower center edge vertex
// to simulate stream bed.
                if (riverData.HasRiverStartOrEnd)
                {
                    if (!source.IsUnderwater)
                    {
                        data = TriangulateRiverBeginOrEndRiver(
                            source,
                            data,
                            riverData,
                            hexOuterRadius,
                            wrapSize,
                            rivers
                            );
                    }
                }
                else if (!source.IsUnderwater)
                {
                    data = TriangulateCenterRiverQuads(
                        source,
                        data,
                        direction,
                        riverData,
                        hexOuterRadius,
                        wrapSize,
                        rivers
                        );
                }
            }
        }

        return(data);
    }
예제 #7
0
    private TerrainTriangulationData TriangulateRiverBeginOrEndTerrain(
        Hex source,
        TerrainTriangulationData data,
        float hexOuterRadius,
        int wrapSize,
        MapMeshChunkLayer terrain
        )
    {
        data.middleEdgeVertices = new EdgeVertices(
            Vector3.Lerp(
                data.terrainCenter,
                data.centerEdgeVertices.vertex1,
                0.5f
                ),
            Vector3.Lerp(
                data.terrainCenter,
                data.centerEdgeVertices.vertex5,
                0.5f
                )
            );

        data.middleEdgeVertices.vertex3.y = source.StreamBedY;

        TriangulateEdgeStripTerrain(
            data.middleEdgeVertices,
            _weights1,
            source.Index,
            data.centerEdgeVertices,
            _weights1,
            source.Index,
            hexOuterRadius,
            wrapSize,
            terrain
            );

        TriangulateEdgeFan(
            data.terrainCenter,
            data.middleEdgeVertices,
            source.Index,
            hexOuterRadius,
            wrapSize,
            terrain
            );

        return(data);
    }
    public TerrainTriangulationData TriangulateHexRoadEdge(
        Hex hex,
        Hex neighbor,
        TerrainTriangulationData triangulationData,
        HexDirections direction,
        HexRiverData riverData,
        FeatureContainer features,
        Dictionary <HexDirections, bool> roadEdges,
        Dictionary <HexDirections, ElevationEdgeTypes> elevationEdgeTypes,
        float hexOuterRadius,
        int wrapSize
        )
    {
        triangulationData = TriangulateCenterRiverRoad(
            riverData,
            direction,
            hex,
            triangulationData,
            hexOuterRadius,
            wrapSize,
            this,
            roadEdges,
            features
            );

        if (direction <= HexDirections.Southeast)
        {
            triangulationData = TriangulateTerrainConnectionRoads(
                hex,
                neighbor,
                triangulationData,
                direction,
                riverData,
                roadEdges,
                elevationEdgeTypes,
                hexOuterRadius,
                wrapSize,
                this
                );
        }

        return(triangulationData);
    }
예제 #9
0
    protected TerrainTriangulationData GetCenterEdgeVertices(
        HexDirections direction,
        TerrainTriangulationData data,
        float hexOuterRadius
        )
    {
        // Triangle edge.
        data.centerEdgeVertices = new EdgeVertices(
            data.terrainCenter + HexagonPoint.GetFirstSolidCorner(
                direction,
                hexOuterRadius
                ),
            data.terrainCenter +
            HexagonPoint.GetSecondSolidCorner(
                direction,
                hexOuterRadius
                )
            );

        return(data);
    }
예제 #10
0
    protected TerrainTriangulationData GetConnectionEdgeVertices(
        Hex source,
        Hex neighbor,
        HexDirections direction,
        TerrainTriangulationData data,
        float hexOuterRadius
        )
    {
        Vector3 bridge = HexagonPoint.GetBridge(
            direction,
            hexOuterRadius
            );

        bridge.y = neighbor.Position.y - source.Position.y;

        data.connectionEdgeVertices = new EdgeVertices(
            data.centerEdgeVertices.vertex1 + bridge,
            data.centerEdgeVertices.vertex5 + bridge
            );

        return(data);
    }
예제 #11
0
    private TerrainTriangulationData TryTriangulateNeighborTerrainCorner(
        Hex source,
        Hex neighbor,
        TerrainTriangulationData data,
        HexDirections direction,
        Dictionary <HexDirections, Hex> neighbors,
        float hexOuterRadius,
        int wrapSize,
        MapMeshChunkLayer terrain,
        FeatureContainer features
        )
    {
        Hex nextNeighbor;

        if (
            neighbors.TryGetValue(
                direction.NextClockwise(),
                out nextNeighbor
                ) &&
            direction <= HexDirections.East
            )
        {
            TriangulateNeighborTerrainCorner(
                source,
                neighbor,
                nextNeighbor,
                direction,
                data,
                hexOuterRadius,
                wrapSize,
                terrain,
                features
                );
        }

        return(data);
    }
예제 #12
0
    private TerrainTriangulationData TriangulateTerrainCenter(
        HexRiverData riverData,
        HexDirections direction,
        Hex source,
        TerrainTriangulationData data,
        float hexOuterRadius,
        int wrapSize,
        MapMeshChunkLayer terrain,
        FeatureContainer features,
        Dictionary <HexDirections, bool> roadEdges
        )
    {
        if (riverData.HasRiver)
        {
            if (riverData.HasRiverInDirection(direction))
            {
                data.centerEdgeVertices.vertex3.y = source.StreamBedY;

                if (riverData.HasRiverStartOrEnd)
                {
                    data = TriangulateRiverBeginOrEndTerrain(
                        source,
                        data,
                        hexOuterRadius,
                        wrapSize,
                        terrain
                        );
                }
                else
                {
                    data = TriangulateRiverBanks(
                        data,
                        riverData,
                        direction,
                        hexOuterRadius
                        );

                    data = TriangulateRiverTerrain(
                        source,
                        data,
                        hexOuterRadius,
                        wrapSize,
                        terrain
                        );
                }
            }
            else
            {
                data = TriangulateTerrainAdjacentToRiver(
                    source,
                    direction,
                    data,
                    roadEdges,
                    riverData,
                    hexOuterRadius,
                    wrapSize,
                    terrain,
                    features
                    );
            }
        }
        else
        {
            // Triangulate terrain center without river, basic edge fan.
            TriangulateEdgeFan(
                data.terrainCenter,
                data.centerEdgeVertices,
                source.Index,
                hexOuterRadius,
                wrapSize,
                terrain
                );

            if (
                !source.IsUnderwater &&
                !roadEdges[direction]
                )
            {
                features.AddFeature(
                    source,
                    (
                        data.terrainCenter +
                        data.centerEdgeVertices.vertex1 +
                        data.centerEdgeVertices.vertex5
                    ) * (1f / 3f),
                    hexOuterRadius,
                    wrapSize
                    );
            }
        }

        return(data);
    }
예제 #13
0
    private TerrainTriangulationData TriangulateNeighborTerrainCorner(
        Hex source,
        Hex neighbor,
        Hex nextNeighbor,
        HexDirections direction,
        TerrainTriangulationData data,
        float hexOuterRadius,
        int wrapSize,
        MapMeshChunkLayer terrain,
        FeatureContainer features
        )
    {
// Create a 5th vertex and assign it with the elevation of the neighbor
// under consideration. This will be used as the final vertex in the
// triangle which fills the gap between bridges.
        Vector3 vertex5 =
            data.centerEdgeVertices.vertex5 + HexagonPoint.GetBridge(
                direction.NextClockwise(),
                hexOuterRadius
                );

        vertex5.y = nextNeighbor.Position.y;

        if (source.elevation <= neighbor.elevation)
        {
            if (source.elevation <= nextNeighbor.elevation)
            {
// This hex has lowest elevation, no rotation.
                TriangulateTerrainCorner(
                    data.centerEdgeVertices.vertex5,
                    source,
                    data.connectionEdgeVertices.vertex5,
                    neighbor,
                    vertex5,
                    nextNeighbor,
                    hexOuterRadius,
                    wrapSize,
                    terrain,
                    features
                    );
            }
            else
            {
// Next neighbor has lowest elevation, rotate counter-clockwise.
                TriangulateTerrainCorner(
                    vertex5,
                    nextNeighbor,
                    data.centerEdgeVertices.vertex5,
                    source,
                    data.connectionEdgeVertices.vertex5,
                    neighbor,
                    hexOuterRadius,
                    wrapSize,
                    terrain,
                    features
                    );
            }
        }
        else if (neighbor.elevation <= nextNeighbor.elevation)
        {
// Neighbor is lowest hex, rotate triangle clockwise.
            TriangulateTerrainCorner(
                data.connectionEdgeVertices.vertex5,
                neighbor,
                vertex5,
                nextNeighbor,
                data.centerEdgeVertices.vertex5,
                source,
                hexOuterRadius,
                wrapSize,
                terrain,
                features
                );
        }
        else
        {
// Next neighbor has lowest elevation, rotate counter-clockwise.
            TriangulateTerrainCorner(
                vertex5,
                nextNeighbor,
                data.centerEdgeVertices.vertex5,
                source,
                data.connectionEdgeVertices.vertex5,
                neighbor,
                hexOuterRadius,
                wrapSize,
                terrain,
                features
                );
        }

        return(data);
    }
예제 #14
0
    private TerrainTriangulationData TriangulateTerrainAdjacentToRiver(
        Hex source,
        HexDirections direction,
        TerrainTriangulationData triangulationData,
        Dictionary <HexDirections, bool> roadEdges,
        HexRiverData riverData,
        float hexOuterRadius,
        int wrapSize,
        MapMeshChunkLayer terrain,
        FeatureContainer features
        )
    {
        if (riverData.HasRiverInDirection(direction.NextClockwise()))
        {
/* If the direction has a river on either side, it has a slight curve.
 * The center vertex of river-adjacent triangle needs to be moved toward
 * the edge so they don't overlap the river.
 */
//            if (hex.HasRiverThroughEdge(direction.Previous())) {
            if (
                riverData.HasRiverInDirection(direction.PreviousClockwise())
                )
            {
                triangulationData.terrainCenter += HexagonPoint.GetSolidEdgeMiddle(
                    direction,
                    hexOuterRadius
                    ) * (HexagonConstants.INNER_TO_OUTER_RATIO * 0.5f);
            }

/* If the hex has a river through the previous previous direction,
 * it has a river flowing through the hex. Move the center vertex
 * of the river-adjacent triangle so that it does not overlap the river.
 */
            else if (
                riverData.HasRiverInDirection(
                    direction.PreviousClockwise2()
                    )
                )
            {
                triangulationData.terrainCenter +=
                    HexagonPoint.GetFirstSolidCorner(
                        direction,
                        hexOuterRadius
                        ) * 0.25f;
            }
        }

/* Second case of straight-river-adjacent triangle. Need to move center
 * so it doesn't overlap the river.
 */
        else if (
            riverData.HasRiverInDirection(direction.PreviousClockwise()) &&
            riverData.HasRiverInDirection(direction.NextClockwise2())
            )
        {
            triangulationData.terrainCenter += HexagonPoint.GetSecondSolidCorner(
                direction,
                hexOuterRadius
                ) * 0.25f;
        }

        EdgeVertices middle = new EdgeVertices(
            Vector3.Lerp(
                triangulationData.terrainCenter,
                triangulationData.centerEdgeVertices.vertex1,
                0.5f
                ),
            Vector3.Lerp(
                triangulationData.terrainCenter,
                triangulationData.centerEdgeVertices.vertex5,
                0.5f
                )
            );

        TriangulateEdgeStripTerrain(
            middle,
            _weights1,
            source.Index,
            triangulationData.centerEdgeVertices,
            _weights1,
            source.Index,
            hexOuterRadius,
            wrapSize,
            terrain
            );

        TriangulateEdgeFan(
            triangulationData.terrainCenter,
            middle,
            source.Index,
            hexOuterRadius,
            wrapSize,
            terrain
            );

        if (!source.IsUnderwater && roadEdges[direction])
        {
            features.AddFeature(
                source,
                (
                    triangulationData.terrainCenter +
                    triangulationData.centerEdgeVertices.vertex1 +
                    triangulationData.centerEdgeVertices.vertex5
                ) * (1f / 3f),
                hexOuterRadius,
                wrapSize
                );
        }

        return(triangulationData);
    }
예제 #15
0
    private TerrainTriangulationData TriangulateRiverTerrain(
        Hex source,
        TerrainTriangulationData triangulationData,
        float hexOuterRadius,
        int wrapSize,
        MapMeshChunkLayer terrain
        )
    {
        TriangulateEdgeStripTerrain(
            triangulationData.middleEdgeVertices,
            _weights1,
            source.Index,
            triangulationData.centerEdgeVertices,
            _weights1,
            source.Index,
            hexOuterRadius,
            wrapSize,
            terrain
            );

        terrain.AddTrianglePerturbed(
            triangulationData.riverCenterLeft,
            triangulationData.middleEdgeVertices.vertex1,
            triangulationData.middleEdgeVertices.vertex2,
            hexOuterRadius,
            wrapSize
            );

        terrain.AddQuadPerturbed(
            triangulationData.riverCenterLeft,
            triangulationData.terrainCenter,
            triangulationData.middleEdgeVertices.vertex2,
            triangulationData.middleEdgeVertices.vertex3,
            hexOuterRadius,
            wrapSize
            );

        terrain.AddQuadPerturbed(
            triangulationData.terrainCenter,
            triangulationData.riverCenterRight,
            triangulationData.middleEdgeVertices.vertex3,
            triangulationData.middleEdgeVertices.vertex4,
            hexOuterRadius,
            wrapSize
            );

        terrain.AddTrianglePerturbed(
            triangulationData.riverCenterRight,
            triangulationData.middleEdgeVertices.vertex4,
            triangulationData.middleEdgeVertices.vertex5,
            hexOuterRadius,
            wrapSize
            );

        Vector3 centerHexIndices;

        centerHexIndices.x         =
            centerHexIndices.y     =
                centerHexIndices.z =
                    source.Index;

        terrain.AddTriangleHexData(
            centerHexIndices,
            _weights1
            );

        terrain.AddQuadHexData(
            centerHexIndices,
            _weights1
            );

        terrain.AddQuadHexData(
            centerHexIndices,
            _weights1
            );

        terrain.AddTriangleHexData(
            centerHexIndices,
            _weights1
            );

        return(triangulationData);
    }
    private TerrainTriangulationData TriangulateRoadAdjacentToRiver(
        Hex source,
        HexDirections direction,
        TerrainTriangulationData data,
        HexRiverData riverData,
        Dictionary <HexDirections, bool> roadEdges,
        float hexOuterRadius,
        int wrapSize,
        MapMeshChunkLayer roads,
        FeatureContainer features
        )
    {
//        bool hasRoadThroughEdge = hex.HasRoadThroughEdge(direction);
        bool hasRoadThroughEdge = roadEdges[direction];

//          bool previousHasRiver = hex.HasRiverThroughEdge(
//              direction.Previous()
//          );
        bool previousHasRiver = riverData.HasIncomingRiverInDirection(
            direction.PreviousClockwise()
            );

//        bool nextHasRiver = hex.HasRiverThroughEdge(direction.Next());
        bool nextHasRiver = riverData.HasIncomingRiverInDirection(
            direction.NextClockwise()
            );

        Vector2 interpolators = GetRoadInterpolators(
            source,
            direction,
            roadEdges
            );

        Vector3 roadCenter = data.terrainCenter;

//        if (hex.HasRiverBeginOrEnd) {
        if (riverData.HasRiverStartOrEnd)
        {
            roadCenter +=
                HexagonPoint.GetSolidEdgeMiddle(
//                    hex.RiverBeginOrEndDirection.Opposite(),
                    riverData.RiverStartOrEndDirection.Opposite(),
                    hexOuterRadius
                    ) *
                (1f / 3f);
        }
//        else if(hex.IncomingRiver == hex.OutgoingRiver.Opposite()) {
        else if (
            riverData.HasStraightRiver
            )
        {
            Vector3 corner;

//  If the previous hex has a river, the corner the center will be
//  moved toward is equal to the current direction + 1.
            if (previousHasRiver)
            {
                if (
                    !hasRoadThroughEdge &&
//                    !hex.HasRoadThroughEdge(direction.Next())
                    !roadEdges[direction.NextClockwise()]
                    )
                {
                    return(data);
                }
                corner = HexagonPoint.GetSecondSolidCorner(
                    direction,
                    hexOuterRadius
                    );
            }
// If the previous hex does not have a river, the corner the center will
// be moved toward is the same index as the current direction.
            else
            {
                if (
                    !hasRoadThroughEdge &&
//                    !hex.HasRoadThroughEdge(direction.Previous())
                    !roadEdges[direction.PreviousClockwise()]
                    )
                {
                    return(data);
                }

                corner = HexagonPoint.GetFirstSolidCorner(
                    direction,
                    hexOuterRadius
                    );
            }

/* Using the example of a river flowing from east to west or west to east, for all cases
 * this will result in the river being pushed either directly "up" north away from the
 * river or directly "down" south away from the river.
 */
            roadCenter += corner * 0.5f;

            if (
//                hex.IncomingRiver == direction.Next() &&
                riverData.IncomingRivers[direction.NextClockwise()] &&
//                hex.HasRoadThroughEdge(direction.Next2()) ||
                roadEdges[direction.NextClockwise2()] ||
//                hex.HasRoadThroughEdge(direction.Opposite())
                roadEdges[direction.Opposite()]
                )
            {
                features.AddBridge(
                    roadCenter,
                    data.terrainCenter - corner * 0.5f,
                    hexOuterRadius,
                    wrapSize
                    );
            }

            data.terrainCenter += corner * 0.25f;
        }

// If the river has a zigzag, then the incoming river will be the on the
// edge previous from the outgoing river or the incoming river will be on
// the next edge of the outoing river. In the case of the former, the
// index of the corner whose vector is pointing away from the river is the
// index of the incoming river + 1. Otherwise it is the index of the
// incoming river. In both cases, subtracting the road center by that
// vector times 0.2f is sufficent to push the road center away from the
// river.

//        else if (hex.IncomingRiver == hex.OutgoingRiver.Previous()) {
        else if (riverData.HasPreviousClockwiseCornerRiver)
        {
            roadCenter -= HexagonPoint.GetSecondCorner(
//                hex.IncomingRiver,
                riverData.AnyIncomingRiver,
                hexOuterRadius
                ) * 0.2f;
        }
//        else if (hex.IncomingRiver == hex.OutgoingRiver.Next()) {
        else if (riverData.HasNextClockwiseCornerRiver)
        {
            roadCenter -= HexagonPoint.GetFirstCorner(
//                hex.IncomingRiver,
                riverData.AnyIncomingRiver,
                hexOuterRadius
                ) * 0.2f;
        }

// If there is a river on the previous and next edges, the river has a
// slight bend. Need to pull the road center toward the current hex edge,
// which will shorten the road back away from the river.

        else if (previousHasRiver && nextHasRiver)
        {
            if (!hasRoadThroughEdge)
            {
                return(data);
            }

// Must account for difference in scale between corners and middles by
// using HexMetrics.innerToOuter.

            Vector3 offset =
                HexagonPoint.GetSolidEdgeMiddle(
                    direction,
                    hexOuterRadius
                    ) *
                HexagonConstants.INNER_TO_OUTER_RATIO;

            roadCenter         += offset * 0.7f;
            data.terrainCenter += offset * 0.5f;
        }

// The only remaining case is that the hex lies on the outside of a
// curving river. In this case, there are three edges pointing away from
// the river. The middle edge of these three edges must be obtained.
// Then, the center of the road is pushed toward the middle of this edge.
        else
        {
            HexDirections middle;
            if (previousHasRiver)
            {
//                middle = direction.Next();
                middle = direction.NextClockwise();
            }
            else if (nextHasRiver)
            {
//                middle = direction.Previous();
                middle = direction.PreviousClockwise();
            }
            else
            {
//                middle = direction;
                middle = direction;
            }

// If there is no road through any of the hexes on the outer side of the
// river bend, then the road center need not move and should instead be
// pruned.
            if (
//                !hex.HasRoadThroughEdge(middle) &&
                !roadEdges[middle] &&
//                !hex.HasRoadThroughEdge(middle.Previous()) &&
                !roadEdges[middle.PreviousClockwise()] &&
//                !hex.HasRoadThroughEdge(middle.Next())
                !roadEdges[middle.NextClockwise()]
                )
            {
                return(data);
            }

            Vector3 offset = HexagonPoint.GetSolidEdgeMiddle(
                middle,
                hexOuterRadius
                );

            roadCenter += offset * 0.25f;

            if (
                direction == middle &&
//                hex.HasRoadThroughEdge(direction.Opposite())
                roadEdges[direction.Opposite()]
                )
            {
                features.AddBridge(
                    roadCenter,
                    data.terrainCenter - offset * (
                        HexagonConstants.INNER_TO_OUTER_RATIO * 0.7f
                        ),
                    hexOuterRadius,
                    wrapSize
                    );
            }
        }

        Vector3 middleLeft =
            Vector3.Lerp(
                roadCenter,
                data.centerEdgeVertices.vertex1,
                interpolators.x
                );

        Vector3 middleRight =
            Vector3.Lerp(
                roadCenter,
                data.centerEdgeVertices.vertex5,
                interpolators.y
                );

        TriangulateRoad(
            roadCenter,
            middleLeft,
            middleRight,
            data.centerEdgeVertices,
            hasRoadThroughEdge,
            source.Index,
            hexOuterRadius,
            wrapSize,
            roads
            );

        if (previousHasRiver)
        {
            TriangulateRoadEdge(
                roadCenter,
                data.terrainCenter,
                middleLeft,
                source.Index,
                hexOuterRadius,
                wrapSize,
                roads
                );
        }

        if (nextHasRiver)
        {
            TriangulateRoadEdge(
                roadCenter,
                middleRight,
                data.terrainCenter,
                source.Index,
                hexOuterRadius,
                wrapSize,
                roads
                );
        }

        return(data);
    }
예제 #17
0
    private TerrainTriangulationData TriangulateRiverBanks(
        TerrainTriangulationData data,
        HexRiverData riverData,
        HexDirections direction,
        float hexOuterRadius
        )
    {
        if (riverData.HasRiverInDirection(direction.Opposite()))
        {
/* Create a vertex 1/4th of the way from the center of the hex
 * to first solid corner of the previous edge, which is pointing
 * straight "down" toward the bottom of the hexagon for a left facing
 * edge.
 */
            data.riverCenterLeft = data.terrainCenter +
                                   HexagonPoint.GetFirstSolidCorner(
                direction.PreviousClockwise(),
                hexOuterRadius
                ) * 0.25f;

/* Create a vertex 1/4th of the way from the center of the hex
 * to the second solid corner of the next edge, which is pointing
 * straight "up" toward the top of the hexagon for a left facing edge.
 */
            data.riverCenterRight = data.terrainCenter +
                                    HexagonPoint.GetSecondSolidCorner(
                direction.NextClockwise(),
                hexOuterRadius
                ) * 0.25f;
        }

/* If the next direction has a sharp turn, there will be a river through
 * direction.Next() or direction.Previous(). Must align center line with
 * center line with edge between this river and the adjacent river.
 * Interpolate with an increased step to account for the rotation
 * of the center line.
 */
        else if (
            riverData.HasRiverInDirection(direction.NextClockwise())
            )
        {
            data.riverCenterLeft  = data.terrainCenter;
            data.riverCenterRight =
                Vector3.Lerp(
                    data.terrainCenter,
                    data.centerEdgeVertices.vertex5,
                    2f / 3f
                    );
        }
        else if (
            riverData.HasRiverInDirection(direction.PreviousClockwise())
            )
        {
            data.riverCenterLeft =
                Vector3.Lerp(
                    data.terrainCenter,
                    data.centerEdgeVertices.vertex1,
                    2f / 3f
                    );

            data.riverCenterRight = data.terrainCenter;
        }

/* If the hex has a river two directions next, or two directions
 * previous, there is a slight bend in the river. Need to push
 * the center line to the inside of the bend. Using
 * HexMetrics.innerToOuter to adjust for the fact that
 * the midpoint of a solid edge is closer to the center
 * of a hex than a solid edge corner.
 */
        else if (
            riverData.HasRiverInDirection(direction.NextClockwise2())
            )
        {
            data.riverCenterLeft = data.terrainCenter;

            data.riverCenterRight =
                data.terrainCenter +
                HexagonPoint.GetSolidEdgeMiddle(
                    direction.NextClockwise(),
                    hexOuterRadius
                    ) * (0.5f * HexagonConstants.INNER_TO_OUTER_RATIO);
        }
// Previous 2
        else
        {
            data.riverCenterLeft =
                data.terrainCenter +
                HexagonPoint.GetSolidEdgeMiddle(
                    direction.PreviousClockwise(),
                    hexOuterRadius
                    ) * (0.5f * HexagonConstants.INNER_TO_OUTER_RATIO);

            data.riverCenterRight = data.terrainCenter;
        }

/* Get the final location of the center by averaging
 * centerLeft and centerRight. For a straight through
 * river this average is the same as the center
 * of the hex. For a bend this moves the center
 * appropriately. Otherwise, all points are the same
 * and the center also remains at the center of the hex.
 */
        data.terrainCenter = Vector3.Lerp(
            data.riverCenterLeft,
            data.riverCenterRight,
            0.5f
            );

/* Create the middle edge vertices using points halfway between
 * centerLeft/centerRight and the 1st and 5th vertices of the
 * hexagons edge vertices for the given direction. Must use an
 * alternate constructor for the middle edge vertices object
 * because the length of the edge is 3/4ths rather than 1. To
 * keep the 2nd and 4th vertex in line with the rivers edges,
 * must interpolate by 1/6th instead of 1/3rd.
 */
        EdgeVertices middleEdgeVertices = new EdgeVertices(
            Vector3.Lerp(
                data.riverCenterLeft,
                data.centerEdgeVertices.vertex1,
                0.5f
                ),
            Vector3.Lerp(
                data.riverCenterRight,
                data.centerEdgeVertices.vertex5,
                0.5f
                ),
            1f / 6f
            );

/* Adjust the height of middle of the middle edge,
 * as well as the height of the center of the hexagon, to
 * the height of the middle of the outer edge of the
 * hexagon. The given edge of the hexagon has already
 * been adjusted to the height of the river bed.
 */
        middleEdgeVertices.vertex3.y =
            data.terrainCenter.y     =
                data.centerEdgeVertices.vertex3.y;

        data.middleEdgeVertices = middleEdgeVertices;
        return(data);
    }
예제 #18
0
    private TerrainTriangulationData TriangulateTerrainConnection(
        Hex source,
        Hex neighbor,
        TerrainTriangulationData data,
        HexDirections direction,
        HexRiverData riverData,
        Dictionary <HexDirections, bool> roadEdges,
        Dictionary <HexDirections, ElevationEdgeTypes> elevationEdgeTypes,
        float hexOuterRadius,
        int wrapSize,
        MapMeshChunkLayer terrain,
        FeatureContainer features
        )
    {
        if (riverData.HasRiverInDirection(direction))
        {
            data.connectionEdgeVertices.vertex3.y = neighbor.StreamBedY;
        }

        bool hasRoad = roadEdges[direction];

        if (
//            hex.GetEdgeType(direction) == ElevationEdgeTypes.Slope
            elevationEdgeTypes[direction] == ElevationEdgeTypes.Slope
            )
        {
            TriangulateEdgeTerracesTerrain(
                data.centerEdgeVertices,
                source,
                data.connectionEdgeVertices,
                neighbor,
                hexOuterRadius,
                wrapSize,
                terrain
                );
        }
        else
        {
            TriangulateEdgeStripTerrain(
                data.centerEdgeVertices,
                _weights1,
                source.Index,
                data.connectionEdgeVertices,
                _weights2,
                neighbor.Index,
                hexOuterRadius,
                wrapSize,
                terrain
                );
        }

        features.AddWall(
            data.centerEdgeVertices,
            source,
            data.connectionEdgeVertices,
            neighbor,
            riverData.HasRiverInDirection(direction),
            hasRoad,
            hexOuterRadius,
            wrapSize
            );

        return(data);
    }
예제 #19
0
    private TerrainTriangulationData TriangulateRiverBeginOrEndRiver(
        Hex source,
        TerrainTriangulationData triangulationData,
        HexRiverData riverData,
        float hexOuterRadius,
        int wrapSize,
        MapMeshChunkLayer rivers
        )
    {
        Vector3 riverSurfaceCenter = triangulationData.terrainCenter;
//            bool reversed = hex.HasIncomingRiver;
        bool reversed = riverData.HasIncomingRiver;

        Vector3 indices = new Vector3(
            source.Index,
            source.Index,
            source.Index
            );

        TriangulateRiverQuad(
            triangulationData.middleEdgeVertices.vertex2,
            triangulationData.middleEdgeVertices.vertex4,
            triangulationData.centerEdgeVertices.vertex2,
            triangulationData.centerEdgeVertices.vertex4,
            source.RiverSurfaceY,
            0.6f,
            reversed,
            indices,
            hexOuterRadius,
            wrapSize,
            rivers
            );

        riverSurfaceCenter.y =
            triangulationData.middleEdgeVertices.vertex2.y     =
                triangulationData.middleEdgeVertices.vertex4.y =
                    source.RiverSurfaceY;

        rivers.AddTrianglePerturbed(
            riverSurfaceCenter,
            triangulationData.middleEdgeVertices.vertex2,
            triangulationData.middleEdgeVertices.vertex4,
            hexOuterRadius,
            wrapSize
            );

        if (reversed)
        {
            rivers.AddTriangleUV(
                new Vector2(0.5f, 0.4f),
                new Vector2(1f, 0.2f),
                new Vector2(0f, 0.2f)
                );
        }
        else
        {
            rivers.AddTriangleUV(
                new Vector2(0.5f, 0.4f),
                new Vector2(0f, 0.6f),
                new Vector2(1f, 0.6f)
                );
        }

        rivers.AddTriangleHexData(indices, _weights1);

        return(triangulationData);
    }
    private TerrainTriangulationData TriangulateCenterRiverRoad(
        HexRiverData riverData,
        HexDirections direction,
        Hex source,
        TerrainTriangulationData data,
        float hexOuterRadius,
        int wrapSize,
        MapMeshChunkLayer roads,
        Dictionary <HexDirections, bool> roadEdges,
        FeatureContainer features
        )
    {
        if (riverData.HasRiver)
        {
            bool hasRoad = false;

            foreach (
                KeyValuePair <HexDirections, bool> pair in roadEdges
                )
            {
                if (pair.Value)
                {
                    hasRoad = true;
                    break;
                }
            }

            if (hasRoad)
            {
                TriangulateRoadAdjacentToRiver(
                    source,
                    direction,
                    data,
                    riverData,
                    roadEdges,
                    hexOuterRadius,
                    wrapSize,
                    roads,
                    features
                    );
            }
        }
        else
        {
            bool anyRoad = false;

            foreach (
                KeyValuePair <HexDirections, bool> pair in roadEdges
                )
            {
                if (pair.Value)
                {
                    anyRoad = true;
                    break;
                }
            }

            if (anyRoad)
            {
                TriangulateRoadWithoutRiver(
                    source,
                    direction,
                    data.centerEdgeVertices,
                    roadEdges,
                    data.terrainCenter,
                    hexOuterRadius,
                    wrapSize,
                    roads
                    );
            }
        }

        return(data);
    }
    private WaterTriangulationData TriangulateOpenWaterConnection(
        Hex source,
        Hex target,
        HexDirections direction,
        WaterTriangulationData waterTriData,
        TerrainTriangulationData terrainTriData,
        Dictionary <HexDirections, Hex> neighbors,
        float hexOuterRadius,
        int wrapSize,
        MapMeshChunkLayer water
        )
    {
        if (
            direction <= HexDirections.Southeast
            )
        {
            Vector3 bridge = HexagonPoint.GetWaterBridge(
                direction,
                hexOuterRadius
                );

            Vector3 edge1 = waterTriData.waterSurfaceCornerLeft + bridge;
            Vector3 edge2 = waterTriData.waterSurfaceCornerRight + bridge;

            water.AddQuadPerturbed(
                waterTriData.waterSurfaceCornerLeft,
                waterTriData.waterSurfaceCornerRight,
                edge1,
                edge2,
                hexOuterRadius,
                wrapSize
                );

            Vector3 openWaterIndices;
            openWaterIndices.x     =
                openWaterIndices.z =
                    source.Index;

            openWaterIndices.y = target.Index;

            water.AddQuadHexData(
                openWaterIndices,
                _weights1,
                _weights2
                );

            if (direction <= HexDirections.East)
            {
                Hex nextNeighbor;

                if (
                    neighbors.TryGetValue(
                        direction.NextClockwise(),
                        out nextNeighbor
                        ) &&
                    nextNeighbor.IsUnderwater
                    )
                {
                    water.AddTrianglePerturbed(
                        waterTriData.waterSurfaceCornerRight,
                        edge2,
                        waterTriData.waterSurfaceCornerRight +
                        HexagonPoint.GetWaterBridge(
                            direction.NextClockwise(),
                            hexOuterRadius
                            ),
                        hexOuterRadius,
                        wrapSize
                        );

                    openWaterIndices.z =
                        nextNeighbor.Index;

                    water.AddTriangleHexData(
                        openWaterIndices,
                        _weights1,
                        _weights2,
                        _weights3
                        );
                }
            }
        }

        return(waterTriData);
    }
예제 #22
0
    /// <summary>
    /// Triangulate the mesh geometry of an individual hex.
    /// </summary>
    /// <param name="source">
    /// The hex to whose mesh geometry is to be triangluated.
    /// </param>
    /// <param name="hexOuterRadius">
    /// The outer radius of the hex to be triangulated.
    /// </param>
    /// <param name="adjacencyGraph">
    ///
    /// </param>
    /// <param name="riverDigraph"></param>
    /// <param name="roadUndirectedGraph"></param>
    /// <param name="elevationDigraph"></param>
    /// <param name="wrapSize"></param>
    private void TriangulateHex(
        Hex source,
        Dictionary <HexDirections, Hex> neighbors,
        List <HexDirections> borderDirections,
        float hexOuterRadius,
        HexRiverData riverData,
        Dictionary <HexDirections, bool> roadEdges,
        Dictionary <HexDirections, ElevationEdgeTypes> elevationEdgeTypes,
        int wrapSize,
        TerrainChunkLayer terrainLayer,
        RiversChunkLayer riversLayer,
        RoadsChunkLayer roadsLayer,
        OpenWaterChunkLayer openWaterLayer,
        WaterShoreChunkLayer waterShoreLayer,
        EstuariesChunkLayer estuariesLayer,
        FeatureContainer features
        )
    {
        foreach (
            KeyValuePair <HexDirections, Hex> pair in neighbors
            )
        {
            // Initialize triangulation data.
            HexDirections direction = pair.Key;
            Hex           neighbor  = pair.Value;

            TerrainTriangulationData terrainTriData =
                new TerrainTriangulationData();

            terrainTriData.terrainCenter =
                source.Position;

            terrainTriData = GetCenterEdgeVertices(
                direction,
                terrainTriData,
                hexOuterRadius
                );

            if (direction <= HexDirections.Southeast)
            {
                terrainTriData = GetConnectionEdgeVertices(
                    source,
                    neighbor,
                    direction,
                    terrainTriData,
                    hexOuterRadius
                    );
            }

            // Triangulate layers for non-border edge.
            terrainTriData =
                terrainLayer.TriangulateHexTerrainEdge(
                    source,
                    neighbor,
                    terrainTriData,
                    neighbors,
                    direction,
                    riverData,
                    features,
                    roadEdges,
                    elevationEdgeTypes,
                    hexOuterRadius,
                    wrapSize
                    );

            terrainTriData =
                roadsLayer.TriangulateHexRoadEdge(
                    source,
                    neighbor,
                    terrainTriData,
                    direction,
                    riverData,
                    features,
                    roadEdges,
                    elevationEdgeTypes,
                    hexOuterRadius,
                    wrapSize
                    );

            terrainTriData =
                riversLayer.TriangulateHexRiverEdge(
                    source,
                    neighbor,
                    direction,
                    roadEdges,
                    riverData,
                    terrainTriData,
                    hexOuterRadius,
                    wrapSize
                    );

            WaterTriangulationData waterTriData =
                new WaterTriangulationData();

            waterTriData = GetWaterData(
                source,
                neighbor,
                waterTriData,
                direction,
                hexOuterRadius,
                wrapSize
                );

            waterTriData =
                openWaterLayer.TriangulateHexOpenWaterEdge(
                    source,
                    neighbor,
                    neighbors,
                    direction,
                    waterTriData,
                    terrainTriData,
                    hexOuterRadius,
                    wrapSize
                    );

            waterTriData =
                waterShoreLayer.TriangulateHexWaterShoreEdge(
                    source,
                    neighbor,
                    neighbors,
                    direction,
                    riverData,
                    waterTriData,
                    hexOuterRadius,
                    wrapSize
                    );

            waterTriData =
                estuariesLayer.TriangulateHexEstuaryEdge(
                    source,
                    neighbor,
                    direction,
                    riverData,
                    waterTriData,
                    hexOuterRadius,
                    wrapSize
                    );
        }

        bool anyEdge = false;

        foreach (KeyValuePair <HexDirections, bool> pair in roadEdges)
        {
            if (pair.Value)
            {
                anyEdge = true;
                break;
            }
        }

        // Add feature or special to hex.
        if (!source.IsUnderwater)
        {
            if (
                !riverData.HasRiver &&
                !anyEdge
                )
            {
                features.AddFeature(
                    source,
                    source.Position,
                    hexOuterRadius,
                    wrapSize
                    );
            }

            if (source.IsSpecial)
            {
                features.AddSpecialFeature(
                    source,
                    source.Position,
                    hexOuterRadius,
                    wrapSize
                    );
            }
        }
    }
예제 #23
0
    private TerrainTriangulationData TriangulateRiverConnection(
        Hex source,
        Hex neighbor,
        TerrainTriangulationData data,
        HexDirections direction,
        HexRiverData riverData,
        float hexOuterRadius,
        int wrapSize,
        MapMeshChunkLayer rivers
        )
    {
        if (riverData.HasRiverInDirection(direction))
        {
            Vector3 indices;
            indices.x = indices.z = source.Index;
            indices.y = neighbor.Index;

            if (!source.IsUnderwater)
            {
                if (!neighbor.IsUnderwater)
                {
                    TriangulateRiverQuad(
                        data.centerEdgeVertices.vertex2,
                        data.centerEdgeVertices.vertex4,
                        data.connectionEdgeVertices.vertex2,
                        data.connectionEdgeVertices.vertex4,
                        source.RiverSurfaceY,
                        neighbor.RiverSurfaceY,
                        0.8f,
                        (
//                            hex.HasIncomingRiver &&
//                            hex.IncomingRiver == direction
                            riverData.HasIncomingRiverInDirection(
                                direction
                                )
                        ),
                        indices,
                        hexOuterRadius,
                        wrapSize,
                        rivers
                        );
                }
                else if (source.elevation > neighbor.WaterLevel)
                {
                    TriangulateWaterfallInWater(
                        data.centerEdgeVertices.vertex2,
                        data.centerEdgeVertices.vertex4,
                        data.connectionEdgeVertices.vertex2,
                        data.connectionEdgeVertices.vertex4,
                        source.RiverSurfaceY,
                        neighbor.RiverSurfaceY,
                        neighbor.WaterSurfaceY,
                        indices,
                        hexOuterRadius,
                        wrapSize,
                        rivers
                        );
                }
            }
            else if (
                !neighbor.IsUnderwater &&
                neighbor.elevation > source.WaterLevel
                )
            {
                TriangulateWaterfallInWater(
                    data.connectionEdgeVertices.vertex4,
                    data.connectionEdgeVertices.vertex2,
                    data.centerEdgeVertices.vertex4,
                    data.centerEdgeVertices.vertex2,
                    neighbor.RiverSurfaceY,
                    source.RiverSurfaceY,
                    source.WaterSurfaceY,
                    indices,
                    hexOuterRadius,
                    wrapSize,
                    rivers
                    );
            }
        }

        return(data);
    }