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