public void TriangulateWithRiver(HexDirection dir, HexCell cell, Vector3 center, EdgeVertices edges) { Vector3 centerL; Vector3 centerR; float centerLinePinch = 2.0f / 3.0f; if (cell.HasRiverThroughEdge(dir.Opposite())) { centerL = center + HexMetrics.GetFirstSolidCorner(dir.Previous()) * HexMetrics.SubdivideFraction; centerR = center + HexMetrics.GetSecondSolidCorner(dir.Next()) * HexMetrics.SubdivideFraction; center = (centerL + centerR) / 2.0f; } else if (cell.HasRiverThroughEdge(dir.Next())) { centerL = center; centerR = Vector3.Lerp(center, edges.v5, centerLinePinch); } else if (cell.HasRiverThroughEdge(dir.Previous())) { centerL = Vector3.Lerp(center, edges.v1, centerLinePinch); centerR = center; } else if (cell.HasRiverThroughEdge(dir.Next2())) { centerL = center; centerR = center + HexMetrics.GetSolidEdgeMiddle(dir.Next()) * (0.5f * HexMetrics.InnerToOuter); } else { centerL = center + HexMetrics.GetSolidEdgeMiddle(dir.Previous()) * (0.5f * HexMetrics.InnerToOuter); centerR = center; } EdgeVertices modifiedEdges = new EdgeVertices(Vector3.Lerp(centerL, edges.v1, 0.5f), Vector3.Lerp(centerR, edges.v5, 0.5f)); modifiedEdges.v3.y = center.y = edges.v3.y; TriangulateEdgeStrip(modifiedEdges, Weights1, cell.TerrainTypeIndex, edges, Weights1, cell.CellIndex); Terrain.AddTriangle(centerL, modifiedEdges.v1, modifiedEdges.v2); Terrain.AddQuad(centerL, center, modifiedEdges.v2, modifiedEdges.v3); Terrain.AddQuad(center, centerR, modifiedEdges.v3, modifiedEdges.v4); Terrain.AddTriangle(centerR, modifiedEdges.v4, modifiedEdges.v5); Vector3 indices = new Vector3(cell.CellIndex, cell.CellIndex, cell.CellIndex); Terrain.AddTriangleCellData(indices, Weights1); Terrain.AddQuadCellData(indices, Weights1); Terrain.AddQuadCellData(indices, Weights1); Terrain.AddTriangleCellData(indices, Weights1); if (!cell.IsUnderwater) { bool reverse = cell.IncomingRiverDirection == dir; TriangulateRiverQuad(centerL, centerR, modifiedEdges.v2, modifiedEdges.v4, cell.RiverSurfaceY, 0.4f, reverse, indices); TriangulateRiverQuad(modifiedEdges.v2, modifiedEdges.v4, edges.v2, edges.v4, cell.RiverSurfaceY, 0.6f, reverse, indices); } }
void TriangulateAdjacentToRiver( HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e ) { if (cell.HasRiverThroughEdge(direction.Next())) { if (cell.HasRiverThroughEdge(direction.Previous())) { center += HexMetrics.GetSolidEdgeMiddle(direction) * (HexMetrics.innerToOuter * 0.5f); } else if (cell.HasRiverThroughEdge(direction.Previous2())) { center += HexMetrics.GetFirstSolidCorner(direction) * 0.25f; } } else if (cell.HasRiverThroughEdge(direction.Previous()) && cell.HasRiverThroughEdge(direction.Next2()) ) { center += HexMetrics.GetSecondSolidCorner(direction) * 0.25f; } EdgeVertices m = new EdgeVertices( Vector3.Lerp(center, e.v1, 0.5f), Vector3.Lerp(center, e.v5, 0.5f) ); TriangulateEdgeStrip(m, color1, (int)cell.TerrainType, e, color1, (int)cell.TerrainType); TriangulateEdgeFan(center, m, (int)cell.TerrainType); }
// Rivers void TriangulateWithRiver(HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e) { Vector3 centerL, centerR; if (cell.HasRiverThroughEdge(direction.Opposite())) { // Left Vertex centerL = center + HexMetrics.GetFirstSolidCorner(direction.Previous()) * 0.25f; // Right Vertex centerR = center + HexMetrics.GetSecondSolidCorner(direction.Next()) * 0.25f; } else if (cell.HasRiverThroughEdge(direction.Next())) { centerL = center; centerR = Vector3.Lerp(center, e.v5, 2f / 3f); } else if (cell.HasRiverThroughEdge(direction.Previous())) { centerL = Vector3.Lerp(center, e.v1, 2f / 3f); centerR = center; } else if (cell.HasRiverThroughEdge(direction.Next2())) { centerL = center; centerR = center + HexMetrics.GetSolidEdgeMiddle(direction.Next()) * (0.5f * HexMetrics.innerToOuter); } else { centerL = center + HexMetrics.GetSolidEdgeMiddle(direction.Previous()) * (0.5f * HexMetrics.innerToOuter); centerR = center; } center = Vector3.Lerp(centerL, centerR, 0.5f); // Middle Line EdgeVertices m = new EdgeVertices( Vector3.Lerp(centerL, e.v1, 0.5f), Vector3.Lerp(centerR, e.v5, 0.5f), 1f / 6f); // Channel bottoms m.v3.y = center.y = e.v3.y; TriangulateEdgeStrip(m, cell.Color, e, cell.Color); terrain.AddTriangle(centerL, m.v1, m.v2); terrain.AddTriangleColor(cell.Color); terrain.AddQuad(centerL, center, m.v2, m.v3); terrain.AddQuadColor(cell.Color); terrain.AddQuad(center, centerR, m.v3, m.v4); terrain.AddQuadColor(cell.Color); terrain.AddTriangle(centerR, m.v4, m.v5); terrain.AddTriangleColor(cell.Color); if (!cell.IsUnderwater) { bool reversed = cell.IncomingRiver == direction; TriangulateRiverQuad(centerL, centerR, m.v2, m.v4, cell.RiverSurfaceY, 0.4f, reversed); TriangulateRiverQuad(m.v2, m.v4, e.v2, e.v4, cell.RiverSurfaceY, 0.6f, reversed); } }
void TriangulateAdjacentToRiver(HexDirection direction, HexCell_Script cell, Vector3 center, EdgeVertices e) { if (cell.HasRoads) { TriangulateRoadAdjacentToRiver(direction, cell, center, e); } if (cell.HasRiverThroughEdge(direction.Next())) { if (cell.HasRiverThroughEdge(direction.Previous())) { center += HexMetrics_Script.GetSolidEdgeMiddle(direction) * (HexMetrics_Script.innerToOuter * 0.5f); } else if (cell.HasRiverThroughEdge(direction.Previous2())) { center += HexMetrics_Script.GetFirstSolidCorner(direction) * 0.25f; } } else if (cell.HasRiverThroughEdge(direction.Previous()) && cell.HasRiverThroughEdge(direction.Next2())) { center += HexMetrics_Script.GetSecondSolidCorner(direction) * 0.25f; } EdgeVertices m = new EdgeVertices(Vector3.Lerp(center, e.v1, 0.5f), Vector3.Lerp(center, e.v5, 0.5f)); TriangulateEdgeStrip(m, color1, cell.TerrainTypeIndex, e, color1, cell.TerrainTypeIndex); TriangulateEdgeFan(center, m, cell.TerrainTypeIndex); if (!cell.IsUnderwater && !cell.HasRoadThroughEdge(direction)) { features.AddFeature(cell, (center + e.v1 + e.v5) * (1f / 3f)); } }
void TriangulateWithRiver(HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e) { Vector3 centerL, centerR; if (cell.HasRiverThroughEdge(direction.Opposite())) { centerL = center + HexMetrics.GetFirstSolidCorner(direction.Previous()) * 0.25f; centerR = center + HexMetrics.GetSecondSolidCorner(direction.Next()) * 0.25f; } else if (cell.HasRiverThroughEdge(direction.Next())) { centerL = center; centerR = Vector3.Lerp(center, e.v5, 2f / 3f); } else if (cell.HasRiverThroughEdge(direction.Previous())) { centerL = Vector3.Lerp(center, e.v1, 2f / 3f); centerR = center; } else if (cell.HasRiverThroughEdge(direction.Next2())) { centerL = center; centerR = center + HexMetrics.GetSolidEdgeMiddle(direction.Next()) * (0.5f * HexMetrics.innerToOuter); } else { centerL = center + HexMetrics.GetSolidEdgeMiddle(direction.Previous()) * (0.5f * HexMetrics.innerToOuter); centerR = center; } center = Vector3.Lerp(centerL, centerR, 0.5f); EdgeVertices m = new EdgeVertices( Vector3.Lerp(centerL, e.v1, 0.5f), Vector3.Lerp(centerR, e.v5, 0.5f), 1f / 6f ); m.v3.y = center.y = e.v3.y; TriangulateEdgeStrip(m, weights1, cell.Index, e, weights1, cell.Index); terrain.AddTriangle(centerL, m.v1, m.v2); terrain.AddQuad(centerL, center, m.v2, m.v3); terrain.AddQuad(center, centerR, m.v3, m.v4); terrain.AddTriangle(centerR, m.v4, m.v5); Vector3 indices; indices.x = indices.y = indices.z = cell.Index; terrain.AddTriangleCellData(indices, weights1); terrain.AddQuadCellData(indices, weights1); terrain.AddQuadCellData(indices, weights1); terrain.AddTriangleCellData(indices, weights1); if (!cell.IsUnderWater) { bool reversed = cell.IncomingRiver == direction; TriangulateRiverQuad(centerL, centerR, m.v2, m.v4, cell.RiverSurfaceY, 0.4f, reversed, indices); TriangulateRiverQuad(m.v2, m.v4, e.v2, e.v4, cell.RiverSurfaceY, 0.6f, reversed, indices); } }
/* Creates the 6 triangles that comprise a hex cell */ void TriangulateCell(HexCell cell) { for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { if (cell.isHole) { TriangulateHoleWall(d, cell); } else { TriangulateWedge(d, cell); } if (CheckCellValid(cell.GetNeighbor(d))) { TriangulateEdge(d, cell); } /*** if corner cell, create the long walls of arena ***/ // this check only passes for corner cells if (!CheckCellValid(cell.GetNeighbor(d)) && !CheckCellValid(cell.GetNeighbor(d.Next())) && !CheckCellValid(cell.GetNeighbor(d.Next2()))) { TriangulateOuterWallPanel(d, cell); TriangulateOuterWallPanel(d.Next(), cell); TriangulateOuterWallPanel(d.Next2(), cell); TriangulateWallStrip(d, cell); } /**** Alt Method - creates honeycomb walls - pretty but makes for bad gameplay * HexCell n = cell.GetNeighbor(d); * if(CheckCellValid(n)){ * TriangulateEdge(d, cell); * } * else{ * TriangulateOuterWallPanel(d, cell); * HexCell n2 = cell.GetNeighbor(d.Next()); * if(CheckCellValid(n2)){ * TriangulateOuterWallPanelCorner(d, cell, n2); * } * } */ } }
bool CanAddBridge(HexCell cell, HexDirection dir) { if (cell.incomingRiver != dir.Next()) { return(false); } return(cell.HasRoadThroughEdge(dir.Next2()) || cell.HasRoadThroughEdge(dir.Opposite())); }
void TriangulateWithRiver( HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e ) { Vector3 centerL, centerR; if (cell.HasRiverThroughEdge(direction.Opposite())) { centerL = center + HexMetrics.GetFirstSolidCorner(direction.Previous()) * 0.25f; centerR = center + HexMetrics.GetSecondSolidCorner(direction.Next()) * 0.25f; } else if (cell.HasRiverThroughEdge(direction.Next())) { centerL = center; centerR = Vector3.Lerp(center, e.v5, 2f / 3f); } else if (cell.HasRiverThroughEdge(direction.Previous())) { centerL = Vector3.Lerp(center, e.v1, 2f / 3f); centerR = center; } else if (cell.HasRiverThroughEdge(direction.Next2())) { centerL = center; centerR = center + HexMetrics.GetSolidEdgeMiddle(direction.Next()) * (0.5f * HexMetrics.innerToOuter); } else { centerL = center + HexMetrics.GetSolidEdgeMiddle(direction.Previous()) * (0.5f * HexMetrics.innerToOuter); centerR = center; } center = Vector3.Lerp(centerL, centerR, 0.5f); EdgeVertices m = new EdgeVertices( Vector3.Lerp(centerL, e.v1, 0.5f), Vector3.Lerp(centerR, e.v5, 0.5f), 1f / 6f ); m.v3.y = center.y = e.v3.y; TriangulateEdgeStrip(m, cell.Color, e, cell.Color); AddTriangle(centerL, m.v1, m.v2); AddTriangleColor(cell.Color); AddQuad(centerL, center, m.v2, m.v3); AddQuadColor(cell.Color); AddQuad(center, centerR, m.v3, m.v4); AddQuadColor(cell.Color); AddTriangle(centerR, m.v4, m.v5); AddTriangleColor(cell.Color); }
private void TriangulateWithRiver(HexDirection direction, HexCell cell, Vector3 centre, EdgeVertices e) { Vector3 centreL, centreR; if (cell.HasRiverThroughEdge(direction.Opposite())) { centreL = centre + HexMetrics.GetFirstSolidCorner(direction.Previous()) * 0.25f; centreR = centre + HexMetrics.GetSecondSolidCorner(direction.Next()) * 0.25f; } else if (cell.HasRiverThroughEdge(direction.Next())) { centreL = centre; centreR = Vector3.Lerp(centre, e.v5, 2f / 3); } else if (cell.HasRiverThroughEdge(direction.Previous())) { centreL = Vector3.Lerp(centre, e.v1, 2f / 3); centreR = centre; } else if (cell.HasRiverThroughEdge(direction.Next2())) { centreL = centre; centreR = centre + HexMetrics.GetSolidEdgeMiddle(direction.Next()) * 0.5f * HexMetrics.InnerToOuter; } else { centreL = centre + HexMetrics.GetSolidEdgeMiddle(direction.Previous()) * 0.5f * HexMetrics.InnerToOuter; centreR = centre; } centre = Vector3.Lerp(centreL, centreR, 0.5f); // aligns edges var m = new EdgeVertices( Vector3.Lerp(centreL, e.v1, 0.5f), Vector3.Lerp(centreR, e.v5, 0.5f), 1f / 6); m.v3.y = centre.y = e.v3.y; TriangulateEdgeStrip(m, weights1, cell.Index, e, weights1, cell.Index); Terrain.AddTriangle(centreL, m.v1, m.v2); Terrain.AddQuad(centreL, centre, m.v2, m.v3); Terrain.AddQuad(centre, centreR, m.v3, m.v4); Terrain.AddTriangle(centreR, m.v4, m.v5); var indices = new Vector3(cell.Index, cell.Index, cell.Index); Terrain.AddTriangleCellData(indices, weights1); Terrain.AddQuadCellData(indices, weights1); Terrain.AddQuadCellData(indices, weights1); Terrain.AddTriangleCellData(indices, weights1); var reversed = cell.IncomingRiver == direction; TriangulateRiverQuad(centreL, centreR, m.v2, m.v4, cell.RiverSurfaceY, 0.4f, reversed, indices); TriangulateRiverQuad(m.v2, m.v4, e.v2, e.v4, cell.RiverSurfaceY, 0.6f, reversed, indices); }
public void TriangulateContoursBetween( IHexCell center, IHexCell right, HexDirection direction, Color centerWeights, Color rightWeights, IHexMesh mesh ) { var centerRightContour = CellContourCanon.GetContourForCellEdge(center, direction); var rightCenterContour = CellContourCanon.GetContourForCellEdge(right, direction.Opposite()); int centerRightIndex = 1, rightCenterIndex = rightCenterContour.Count - 1; while (centerRightIndex < centerRightContour.Count && rightCenterIndex > 0) { mesh.AddQuad( centerRightContour[centerRightIndex - 1].ToXYZ(), centerRightContour[centerRightIndex].ToXYZ(), rightCenterContour[rightCenterIndex].ToXYZ(), rightCenterContour[rightCenterIndex - 1].ToXYZ() ); mesh.AddQuadColor(centerWeights, rightWeights); centerRightIndex++; rightCenterIndex--; } for (; centerRightIndex < centerRightContour.Count; centerRightIndex++) { mesh.AddTriangle( centerRightContour[centerRightIndex - 1].ToXYZ(), rightCenterContour[0].ToXYZ(), centerRightContour[centerRightIndex].ToXYZ() ); mesh.AddTriangleColor(centerWeights, rightWeights, centerWeights); } for (; rightCenterIndex > 0; rightCenterIndex--) { mesh.AddTriangle( centerRightContour.Last().ToXYZ(), rightCenterContour[rightCenterIndex].ToXYZ(), rightCenterContour[rightCenterIndex - 1].ToXYZ() ); mesh.AddTriangleColor(centerWeights, rightWeights, rightWeights); } if (RiverCanon.HasRiverAlongEdge(right, direction.Next2())) { var nextRight = Grid.GetNeighbor(center, direction.Next()); var rightNextRightContour = CellContourCanon.GetContourForCellEdge(right, direction.Next2()); var nextRightRightContour = CellContourCanon.GetContourForCellEdge(nextRight, direction.Previous()); mesh.AddTriangle( centerRightContour.Last().ToXYZ(), rightNextRightContour.Last().ToXYZ(), nextRightRightContour.First().ToXYZ() ); mesh.AddTriangleColor(centerWeights, rightWeights, rightWeights); } }
private HexDirection GetBestDirection(HexDirection startDirection, List <HexDirection> otherDirections, HexHash hash) { if (otherDirections.Contains(startDirection.Opposite())) { return(startDirection.Opposite()); } else if (otherDirections.Contains(startDirection.Next2())) { return(startDirection.Next2()); } else if (otherDirections.Contains(startDirection.Previous2())) { return(startDirection.Previous2()); } else { return(otherDirections[Mathf.FloorToInt(hash.A * otherDirections.Count)]); } }
//The fact that we're building sections only from the NE, E, and SE //cell edges is very important. A lot of the code here is structured //as it is to deal with this reality. public void RefreshRiverSections() { sections.Clear(); SectionBetweenCells.Clear(); CellEdgeContourCanon.Clear(); foreach (var cell in Grid.Cells) { for (HexDirection direction = HexDirection.NE; direction <= HexDirection.SE; direction++) { if (RiverCanon.HasRiverAlongEdge(cell, direction)) { var neighbor = Grid.GetNeighbor(cell, direction); Vector3 start = cell.AbsolutePosition + RenderConfig.GetFirstCorner(direction); Vector3 end = cell.AbsolutePosition + RenderConfig.GetSecondCorner(direction); RiverFlow flow = RiverCanon.GetFlowOfRiverAtEdge(cell, direction); //Our control points need to operate differently if we're at endpoints, //and both ControlOne and ControlTwo might have alternate behavior. //We need to check both ends of the section for endpoints bool previousCellRiver = RiverCanon.HasRiverAlongEdge(cell, direction.Previous()); bool previousNeighborRiver = RiverCanon.HasRiverAlongEdge(neighbor, direction.Previous2()); bool hasPreviousEndpoint = !previousCellRiver && !previousNeighborRiver; bool hasNextEndpoint = !RiverCanon.HasRiverAlongEdge(cell, direction.Next()) && !RiverCanon.HasRiverAlongEdge(neighbor, direction.Next2()); var newRiverSection = new RiverSection() { AdjacentCellOne = cell, AdjacentCellTwo = neighbor, DirectionFromOne = direction, Start = start, End = end, FlowFromOne = flow, HasPreviousEndpoint = hasPreviousEndpoint, HasNextEndpoint = hasNextEndpoint }; SectionBetweenCells[new Tuple <IHexCell, IHexCell>(cell, neighbor)] = newRiverSection; sections.Add(newRiverSection); } } } }
private void TriangulateWaterCorner( IHexCell center, Vector3 localCenterPos, Color centerColor, IHexCell right, Vector3 localRightPos, Color rightColor, IHexCell left, Vector3 localLeftPos, Color leftColor, HexDirection direction, IHexMesh mesh ) { mesh.AddTriangle( localCenterPos + RenderConfig.GetFirstSolidCorner(direction), localLeftPos + RenderConfig.GetFirstSolidCorner(direction.Next2()), localRightPos + RenderConfig.GetFirstSolidCorner(direction.Previous2()) ); mesh.AddTriangleColor(centerColor, leftColor, rightColor); }
//We need to draw a river from previousCell to nextCell by adding rivers //to the edges of currentCell. PreviousCell is in directionToNext.Next2(), //and should have some river pointing at currentCell private RiverPathResults CreateRiverAlongCell_GentleCWTurn( IHexCell previousCell, IHexCell currentCell, IHexCell nextCell, HexDirection directionToPrevious, HexDirection directionToNext, IEnumerable <IHexCell> oceanCells, HashSet <IHexCell> cellsAdjacentToRiver ) { var leftLeftPath = new RiverPath( currentCell, directionToPrevious.Next(), directionToNext.Previous(), RiverFlow.Clockwise, RiverCanon, Grid ); var leftRightPath = new RiverPath( currentCell, directionToPrevious, directionToNext.Next(), RiverFlow.Counterclockwise, RiverCanon, Grid ); var rightRightPath = new RiverPath( currentCell, directionToNext.Next(), RiverFlow.Counterclockwise, RiverCanon, Grid ); var rightleftPath = new RiverPath( currentCell, directionToPrevious, directionToNext.Previous(), RiverFlow.Clockwise, RiverCanon, Grid ); var pathsToTry = new List <RiverPath>(); //If directionToNext.Previous() is considered up, //this case triggers when previousCell has a river //along its upper-left edge. if (RiverCanon.HasRiverAlongEdge(previousCell, directionToPrevious.Next2())) { pathsToTry.Add(leftLeftPath); pathsToTry.Add(leftRightPath); } //If directionToNext.Previous() is considered up, //this case triggers when previousCell has a river //along its upper-right edge. if (RiverCanon.HasRiverAlongEdge(previousCell, directionToPrevious.Previous2())) { pathsToTry.Add(rightRightPath); pathsToTry.Add(rightleftPath); } return(TryFollowSomePath(pathsToTry, oceanCells, cellsAdjacentToRiver)); }
void TriangulateAdjacentToRiver( HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e ) { if (cell.HasRoads) { TriangulateRoadAdjacentToRiver(direction, cell, center, e); } if (cell.HasRiverThroughEdge(direction.Next())) { if (cell.HasRiverThroughEdge(direction.Previous())) { center += HexMetrics.GetSolidEdgeMiddle(direction) * (HexMetrics.innerToOuter * 0.5f); } else if ( cell.HasRiverThroughEdge(direction.Previous2()) ) { center += HexMetrics.GetFirstSolidCorner(direction) * 0.25f; } } else if ( cell.HasRiverThroughEdge(direction.Previous()) && cell.HasRiverThroughEdge(direction.Next2()) ) { center += HexMetrics.GetSecondSolidCorner(direction) * 0.25f; } EdgeVertices m = new EdgeVertices( Vector3.Lerp(center, e.v1, 0.5f), Vector3.Lerp(center, e.v5, 0.5f) ); TriangulateEdgeStrip( m, weights1, cell.Index, e, weights1, cell.Index ); TriangulateEdgeFan(center, m, cell.Index); //спавн объектов игрового окружения в каждом из 6 треугольников если нет рек и дорог if (!cell.IsUnderwater && !cell.HasRoadThroughEdge(direction)) { features.AddFeature(cell, (center + e.v1 + e.v5) * (1f / 3f)); } }
//We need to draw a river from previousCell to nextCell by adding rivers //to the edges of currentCell. PreviousCell and nextCell are across from //each-other. Previous river should have some river pointing at currentCell private RiverPathResults CreateRiverAlongCell_StraightAcross( IHexCell previousCell, IHexCell currentCell, IHexCell nextCell, HexDirection directionToPrevious, HexDirection directionToNext, IEnumerable <IHexCell> oceanCells, HashSet <IHexCell> cellsAdjacentToRiver ) { var leftToLeftPath = new RiverPath( currentCell, directionToNext.Previous2(), directionToNext.Previous(), RiverFlow.Clockwise, RiverCanon, Grid ); var leftToRightPath = new RiverPath( currentCell, directionToPrevious, directionToNext.Next(), RiverFlow.Counterclockwise, RiverCanon, Grid ); var rightToRightPath = new RiverPath( currentCell, directionToNext.Next2(), directionToNext.Next(), RiverFlow.Counterclockwise, RiverCanon, Grid ); var rightToLeftPath = new RiverPath( currentCell, directionToPrevious, directionToNext.Previous(), RiverFlow.Clockwise, RiverCanon, Grid ); var pathsToTry = new List <RiverPath>(); //If nextCell is above us, this case happens when previousCell has a //river along its left edge if (RiverCanon.HasRiverAlongEdge(previousCell, directionToNext.Previous())) { pathsToTry.Add(leftToLeftPath); pathsToTry.Add(leftToRightPath); //If nextCell is above us, this case happens when previousCell has a //river along its right edge } else if (RiverCanon.HasRiverAlongEdge(previousCell, directionToNext.Next())) { pathsToTry.Add(rightToRightPath); pathsToTry.Add(rightToLeftPath); } return(TryFollowSomePath(pathsToTry, oceanCells, cellsAdjacentToRiver)); }
public void updateChunkWithRiversAndRoads1Test() { GameObject obj = MonoBehaviour.Instantiate(Resources.Load <GameObject>("Prefabs/Hex Grid")); HexGrid grid = obj.GetComponent <HexGrid>(); HexGridChunk[] chunks = grid.getHexGridChunks(); HexCell[] cells = chunks[0].getCells(); HexDirection direction = HexDirection.NE; int index = 7; // .................................................... // SET DIRECT RIVER // .................................................... // Find cell with next steps: go to NE, go to NE HexCell cell = cells[index].GetNeighbor(direction) .GetNeighbor(direction); // Set river to NW direction cell.SetOutgoingRiver(direction.Previous()); // Get neigbor from SE direction cell HexCell neighbor = cell.GetNeighbor(direction.Next2()); // Set river to NW direction neighbor.SetOutgoingRiver(direction.Previous()); // Set road to previous 2 direction cell.AddRoad(direction.Next()); // Set road to opposite direction cell.AddRoad(direction.Next().Opposite()); // .................................................... // Update chunk foreach (HexGridChunk chunk in chunks) { chunk.Triangulate(); } Assert.IsTrue(cell.HasIncomingRiver); Assert.IsTrue(cell.HasOutgoingRiver); Assert.IsTrue(cell.HasRoads); GameObject.Destroy(obj); }
private void TriangulateAdjacentToRiver( HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e) { if (cell.HasRoads) { TriangulateRoadAdjacentToRiver(direction, cell, center, e); } if (cell.HasRiverThroughEdge(direction.Next())) { // Check whether we are on the inside of a curve. This occurs when // both the previous and next direction contai a river. In this case teh center // will be moved towards the edge. if (cell.HasRiverThroughEdge(direction.Previous())) { center += HexMetrics.GetSolidEdgeMiddle(direction) * (HexMetrics.innerToOuter * 0.5f); // Check whether this is a straight river, in that case move the center // towards the first corner. } else if (cell.HasRiverThroughEdge(direction.Previous2())) { center += HexMetrics.GetFirstSolidCorner(direction) * 0.25f; } } else if ( cell.HasRiverThroughEdge(direction.Previous()) && cell.HasRiverThroughEdge(direction.Next2())) { center += HexMetrics.GetSecondSolidCorner(direction) * 0.25f; } EdgeVertices m = new EdgeVertices( Vector3.Lerp(center, e.v1, 0.5f), Vector3.Lerp(center, e.v5, 0.5f)); TriangulateEdgeStrip(m, cell.Color, e, cell.Color); TriangulateEdgeFan(center, m, cell.Color); if (!cell.IsUnderwater && !cell.HasRoadThroughEdge(direction)) { features.AddFeature((center + e.v1 + e.v5) * (1f / 3f)); } }
public T GetMixForNextCornerAtPoint <T>( IHexCell center, IHexCell right, IHexCell nextRight, HexDirection direction, Vector3 point, DataSelectorCallback <T> dataSelector, Func <T, T, T> aggregator ) { Vector2 centerCorner = center.AbsolutePositionXZ + RenderConfig.GetSecondSolidCornerXZ(direction); Vector2 rightCorner = right.AbsolutePositionXZ + RenderConfig.GetSecondSolidCornerXZ(direction.Next2()); Vector2 nextRightCorner = nextRight.AbsolutePositionXZ + RenderConfig.GetSecondSolidCornerXZ(direction.Previous2()); float percentCenter, percentRight, percentNextRight; Geometry2D.GetBarycentric2D( new Vector2(point.x, point.z), centerCorner, rightCorner, nextRightCorner, out percentCenter, out percentRight, out percentNextRight ); T centerContribution = dataSelector(point, center, direction, percentCenter); T rightContribution = dataSelector(point, right, direction.Next2(), percentRight); T nextRightContribution = dataSelector(point, nextRight, direction.Previous2(), percentNextRight); return(aggregator(aggregator(centerContribution, rightContribution), nextRightContribution)); }
void TriangulateAdjacentToRiver(HexDirection dir, HexCell cell, Vector3 center, EdgeVertices e) { if (cell.HasRoads) { TriangulateRoadAdjacentToRiver(dir, cell, center, e); } if (cell.HasRiverThroughEdge(dir.Next())) { if (cell.HasRiverThroughEdge(dir.Previous())) { center += HexMetrics.GetSolidEdgeMiddle(dir) * (HexMetrics.innerToOuter * 0.5f); } else if (cell.HasRiverThroughEdge(dir.Previous2())) { center += HexMetrics.GetFirstSolidCorner(dir) * 0.25f; } } else if (cell.HasRiverThroughEdge(dir.Previous()) && cell.HasRiverThroughEdge(dir.Next2())) { center += HexMetrics.GetSecondSolidCorner(dir) * 0.25f; } var m = new EdgeVertices( Vector3.Lerp(center, e.v1, 0.5f), Vector3.Lerp(center, e.v5, 0.5f)); TriangulateEdgeStrip(m, color1, cell.terrainTypeIndex, e, color1, cell.terrainTypeIndex); TriangulateEdgeFan(center, m, cell.terrainTypeIndex); if (CanAddFeature(cell, dir)) { // offset the feature slightly from the center towards // the directional edge. var pos = (center + e.v1 + e.v5) * (1f / 3f); features.AddFeature(cell, pos); } }
//We need to draw a river from previousCell to nextCell by adding rivers //to the edges of currentCell. PreviousCell is in directionToNext.Next(), //and should have some river pointing at currentCell private RiverPathResults CreateRiverAlongCell_SharpCWTurn( IHexCell previousCell, IHexCell currentCell, IHexCell nextCell, HexDirection directionToPrevious, HexDirection directionToNext, IEnumerable <IHexCell> oceanCells, HashSet <IHexCell> cellsAdjacentToRiver ) { var leftToLeftPath = new RiverPath( currentCell, directionToPrevious.Next(), directionToNext.Previous(), RiverFlow.Clockwise, RiverCanon, Grid ); var leftToRightPath = new RiverPath( currentCell, directionToPrevious, RiverFlow.Counterclockwise, RiverCanon, Grid ); var pathsToTry = new List <RiverPath>(); //Assuming directionToPrevious.Opposite() is up, //this case triggers when previousCell has a //river along its upper left edge if (RiverCanon.HasRiverAlongEdge(previousCell, directionToPrevious.Next2())) { pathsToTry.Add(leftToLeftPath); pathsToTry.Add(leftToRightPath); } //Assuming directionToPrevious.Opposite() is up, //this case triggers when previousCell has a //river along its upper right edge if (RiverCanon.HasRiverAlongEdge(previousCell, directionToPrevious.Previous2())) { return(RiverPathResults.Success); } return(TryFollowSomePath(pathsToTry, oceanCells, cellsAdjacentToRiver)); }
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); } }
void TriangulateWithRiver(HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e) { //outer walls Vector3 centerL, centerR; if (cell.HasRiverThroughEdge(direction.Opposite())) { centerL = center + HexMetric.GetFirstSolidCorner(direction.Previous()) * 0.25f; centerR = center + HexMetric.GetSecondSolidCorner(direction.Next()) * 0.25f; } // sharp turns else if (cell.HasRiverThroughEdge(direction.Next())) { centerL = center; centerR = Vector3.Lerp(center, e.v5, 2f / 3f); } else if (cell.HasRiverThroughEdge(direction.Previous())) { centerL = Vector3.Lerp(center, e.v1, 2f / 3f); centerR = center; } // two way turns else if (cell.HasRiverThroughEdge(direction.Next2())) { centerL = center; centerR = center + HexMetric.GetSolidEdgeMiddle(direction.Next()) * (0.5f * HexMetric.innerToOuter); } else { centerL = center + HexMetric.GetSolidEdgeMiddle(direction.Previous()) * (0.5f * HexMetric.innerToOuter); centerR = center; } //mid point of channel EdgeVertices m = new EdgeVertices(Vector3.Lerp(centerL, e.v1, 0.5f), Vector3.Lerp(centerR, e.v5, 0.5f), 1f / 6f); m.v3.y = center.y = e.v3.y; //fill area TriangulateEdgeStrip(m, color1, cell.TerrainTypeIndex, e, color1, cell.TerrainTypeIndex); terrain.AddTriangle(centerL, m.v1, m.v2); terrain.AddQuad(centerL, center, m.v2, m.v3); terrain.AddQuad(center, centerR, m.v3, m.v4); terrain.AddTriangle(centerR, m.v4, m.v5); terrain.AddTriangleColor(color1); terrain.AddQuadColor(color1); terrain.AddQuadColor(color1); terrain.AddTriangleColor(color1); Vector3 types; types.x = types.y = types.z = cell.TerrainTypeIndex; terrain.AddTriangleTerrainTypes(types); terrain.AddQuadTerrainTypes(types); terrain.AddQuadTerrainTypes(types); terrain.AddTriangleTerrainTypes(types); //river water quads if (!cell.IsUnderwater) { bool reversed = cell.IncomingRiver == direction; TriangulateRiverQuad(centerL, centerR, m.v2, m.v4, cell.RiverSurfaceY, 0.4f, reversed); TriangulateRiverQuad(m.v2, m.v4, e.v2, e.v4, cell.RiverSurfaceY, 0.6f, reversed); } }
int CreateRiver(HexCell origin) { int length = 1; HexCell cell = origin; HexDirection direction = HexDirection.NE; while (!cell.IsUnderwater) { int minNeighborElevation = int.MaxValue; flowDirections.Clear(); for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = cell.GetNeighbor(d); if (!neighbor) { continue; } if (neighbor.Elevation < minNeighborElevation) { minNeighborElevation = neighbor.Elevation; } if (neighbor == origin || neighbor.HasIncomingRiver) { continue; } int delta = neighbor.Elevation - cell.Elevation; if (delta > 0) { continue; } if (neighbor.HasOutgoingRiver) { cell.SetOutgoingRiver(d); return(length); } if (delta < 0) { flowDirections.Add(d); flowDirections.Add(d); flowDirections.Add(d); } if ( length == 1 || (d != direction.Next2() && d != direction.Previous2()) ) { flowDirections.Add(d); } flowDirections.Add(d); } if (flowDirections.Count == 0) { if (length == 1) { return(0); } if (minNeighborElevation >= cell.Elevation) { cell.WaterLevel = minNeighborElevation; if (minNeighborElevation == cell.Elevation) { cell.Elevation = minNeighborElevation - 1; } } break; } direction = flowDirections[Random.Range(0, flowDirections.Count)]; cell.SetOutgoingRiver(direction); length += 1; if ( minNeighborElevation >= cell.Elevation && Random.value < extraLakeProbability ) { cell.WaterLevel = cell.Elevation; cell.Elevation -= 1; } cell = cell.GetNeighbor(direction); } return(length); }
/// <summary> /// Creates road geometry when there is a river in the cell. /// </summary> void TriangulateRoadAdjacentToRiver(HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e) { bool hasRoadThroughEdge = cell.HasRoadThroughEdge(direction); bool previousHasRiver = cell.HasRiverThroughEdge(direction.Previous()); bool nextHasRiver = cell.HasRiverThroughEdge(direction.Next()); Vector2 interpolators = GetRoadInterpolators(direction, cell); Vector3 roadCenter = center; // When there is a river start/end or a river zig-zag then we only need to offset road center // If there is a straight section of river cutting through or a smooth turn then those divide the road network if (cell.HasRiverBeginOrEnd) // If this is river start or river end { roadCenter += HexMetrics.GetSolidEdgeMiddle(cell.RiverBeginOrEndDirection.Opposite()) * (1f / 3f); } else if (cell.IncomingRiver == cell.OutgoingRiver.Opposite()) // If this is a river section cutting cell in the middle { Vector3 corner; if (previousHasRiver) { if (!hasRoadThroughEdge && !cell.HasRoadThroughEdge(direction.Next())) { return; // Dont draw on the other side of the river } corner = HexMetrics.GetSecondSolidCorner(direction); } else { if (!hasRoadThroughEdge && !cell.HasRoadThroughEdge(direction.Previous())) { return; // Dont draw on the other side of the river } corner = HexMetrics.GetFirstSolidCorner(direction); } roadCenter += corner * 0.5f; // Prevent duplicate bridges and add a bridge if road on both sides if (cell.IncomingRiver == direction.Next() && ( cell.HasRoadThroughEdge(direction.Next2()) || cell.HasRoadThroughEdge(direction.Opposite()) )) { Features.AddBridge(roadCenter, center - corner * 0.5f); } center += corner * 0.25f; } else if (cell.IncomingRiver == cell.OutgoingRiver.Previous()) // Check if zig-zag and offset { roadCenter -= HexMetrics.GetSecondCorner(cell.IncomingRiver) * 0.2f; } else if (cell.IncomingRiver == cell.OutgoingRiver.Next()) // Check if zig-zag and offset { roadCenter -= HexMetrics.GetFirstCorner(cell.IncomingRiver) * 0.2f; } else if (previousHasRiver && nextHasRiver) // Check smooth curve (inside of the curve) { if (!hasRoadThroughEdge) { return; // Dont draw on the other side of the river } Vector3 offset = HexMetrics.GetSolidEdgeMiddle(direction) * HexMetrics.InnerToOuter; roadCenter += offset * 0.7f; center += offset * 0.5f; } else // Smooth curve (outside of the curve) { HexDirection middle; if (previousHasRiver) { middle = direction.Next(); } else if (nextHasRiver) { middle = direction.Previous(); } else { middle = direction; } if (!cell.HasRoadThroughEdge(middle) && !cell.HasRoadThroughEdge(middle.Previous()) && !cell.HasRoadThroughEdge(middle.Next())) { return; // Dont draw on the other side of the river } // Set center and add bridge Vector3 offset = HexMetrics.GetSolidEdgeMiddle(middle); roadCenter += offset * 0.25f; // Prevent duplicate bridges and road on both sides if (direction == middle && cell.HasRoadThroughEdge(direction.Opposite())) { Features.AddBridge(roadCenter, center - offset * (HexMetrics.InnerToOuter * 0.7f)); } } Vector3 mL = Vector3.Lerp(roadCenter, e.v1, interpolators.x); Vector3 mR = Vector3.Lerp(roadCenter, e.v5, interpolators.y); TriangulateRoad(roadCenter, mL, mR, e, hasRoadThroughEdge, cell.Index); // Create auxiliary geometry if (previousHasRiver) { TriangulateRoadEdge(roadCenter, center, mL, cell.Index); } if (nextHasRiver) { TriangulateRoadEdge(roadCenter, mR, center, cell.Index); } }
/// <summary> /// Creates the triangles for a side of the hexagon, when there is a river in the hex. /// </summary> void TriangulateAdjacentToRiver(HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e) { if (cell.HasRoads) { TriangulateRoadAdjacentToRiver(direction, cell, center, e); } // Determine center by finding river channel center edge if (cell.HasRiverThroughEdge(direction.Next())) { if (cell.HasRiverThroughEdge(direction.Previous())) { center += HexMetrics.GetSolidEdgeMiddle(direction) * (HexMetrics.InnerToOuter * 0.5f); } else if (cell.HasRiverThroughEdge(direction.Previous2())) { center += HexMetrics.GetFirstSolidCorner(direction) * 0.25f; } } else if (cell.HasRiverThroughEdge(direction.Previous()) && cell.HasRiverThroughEdge(direction.Next2())) { center += HexMetrics.GetSecondSolidCorner(direction) * 0.25f; } EdgeVertices m = new EdgeVertices( Vector3.Lerp(center, e.v1, 0.5f), Vector3.Lerp(center, e.v5, 0.5f) ); TriangulateEdgeStrip(m, weights1, cell.Index, e, weights1, cell.Index); TriangulateEdgeFan(center, m, cell.Index); // If possible add any features if (!cell.IsUnderwater && !cell.HasRoadThroughEdge(direction)) { Features.AddFeature(cell, (center + e.v1 + e.v5) * (1f / 3f)); } }
/// <summary> /// Creates the triangles for a side of the hexagon, with river passing through (incoming and outgoing river) at this side. /// </summary> void TriangulateWithRiver(HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e) { Vector3 centerL, centerR; if (cell.HasRiverThroughEdge(direction.Opposite())) // If river flows forward through the cell // Extend center into line { centerL = center + HexMetrics.GetFirstSolidCorner(direction.Previous()) * 0.25f; centerR = center + HexMetrics.GetSecondSolidCorner(direction.Next()) * 0.25f; } else if (cell.HasRiverThroughEdge(direction.Next())) // If river bends sharply in next dir { centerL = center; centerR = Vector3.Lerp(center, e.v5, 2f / 3f); } else if (cell.HasRiverThroughEdge(direction.Previous())) // If river bends sharply in prev dir { centerL = Vector3.Lerp(center, e.v1, 2f / 3f); centerR = center; } else if (cell.HasRiverThroughEdge(direction.Next2())) // River bends smoothly to next.next dir { centerL = center; centerR = center + HexMetrics.GetSolidEdgeMiddle(direction.Next()) * (0.5f * HexMetrics.InnerToOuter); } else // River bends smoothly to previous.previous dir { centerL = center + HexMetrics.GetSolidEdgeMiddle(direction.Previous()) * (0.5f * HexMetrics.InnerToOuter); centerR = center; } center = Vector3.Lerp(centerL, centerR, 0.5f); // Average center to serve all cases // Edge 1/2 the way from edge and cell center EdgeVertices m = new EdgeVertices( Vector3.Lerp(centerL, e.v1, 0.5f), Vector3.Lerp(centerR, e.v5, 0.5f), 1f / 6f ); m.v3.y = center.y = e.v3.y; // Lower middle edge and center to river bed TriangulateEdgeStrip(m, weights1, cell.Index, e, weights1, cell.Index); // Final gap between the middle edge and the center // Geo Terrain.AddTriangle(centerL, m.v1, m.v2); Terrain.AddQuad(centerL, center, m.v2, m.v3); Terrain.AddQuad(center, centerR, m.v3, m.v4); Terrain.AddTriangle(centerR, m.v4, m.v5); // Splat + Terrain Types Vector3 indices; indices.x = indices.y = indices.z = cell.Index; Terrain.AddTriangleCellData(indices, weights1); Terrain.AddQuadCellData(indices, weights1); Terrain.AddQuadCellData(indices, weights1); Terrain.AddTriangleCellData(indices, weights1); if (!cell.IsUnderwater) // No river water surface when underwater, river bed allowed // River water surface { bool reversed = cell.IncomingRiver == direction; TriangulateRiverQuad(centerL, centerR, m.v2, m.v4, cell.RiverSurfaceY, 0.4f, reversed, indices); TriangulateRiverQuad(m.v2, m.v4, e.v2, e.v4, cell.RiverSurfaceY, 0.6f, reversed, indices); } }
/// <summary> /// Creates the segments of the river flowing through multiple cells. There are some specifications to creating a river: /// - The cell a river is joined onto must be level or a lower elevation /// - River cannot loop onto itself. /// - River will priorities cells that aren't directly next to itself (Harsh turns on the river) /// - If it runs into another river origin then it will join the two rivers together. /// - If the surrounding cells of the river end are higher than the current, it will create lake /// - There is a random chance of lakes being created along the river if the cell is of lower elevation /// </summary> /// <param name="origin"> Origin cell of river </param> /// <returns> Amount of cells used in river creation </returns> int CreateRiver(HexCell origin) { int length = 1; HexCell cell = origin; HexDirection direction = HexDirection.NE; while (!cell.isUnderwater) { int minNeighborElevation = int.MaxValue; flowDirections.Clear(); for (HexDirection d = HexDirection.NE; d <= HexDirection.NW; d++) { HexCell neighbor = cell.GetNeighbor(d); if (!neighbor) { continue; } if (neighbor.Elevation < minNeighborElevation) { minNeighborElevation = neighbor.Elevation; } if (neighbor == origin || neighbor.HasIncomingRiver) { continue; } int delta = neighbor.Elevation - cell.Elevation; if (delta > 0) { continue; } if (delta < 0) //Increases chance of river choosing a cell which goes downhill { flowDirections.Add(d); flowDirections.Add(d); flowDirections.Add(d); } if (length == 1 || (d != direction.Next2() && d != direction.Previous2())) //Increases chance of river choosing cell that has a gentler turn { flowDirections.Add(d); } if (neighbor.HasOutgoingRiver) // If river runs into another origin river, join the rivers together. Early Return { cell.SetOutgoingRiver(d); return(length); } flowDirections.Add(d); } if (flowDirections.Count == 0) { if (length == 1) { return(0); } if (minNeighborElevation >= cell.Elevation) { cell.WaterLevel = minNeighborElevation; if (minNeighborElevation == cell.Elevation) { cell.Elevation = minNeighborElevation - 1; } } break; } direction = flowDirections[Random.Range(0, flowDirections.Count)]; cell.SetOutgoingRiver(direction); length += 1; if (minNeighborElevation >= cell.Elevation && Random.value < extraLakeProbabiliity) { cell.WaterLevel = cell.Elevation; cell.Elevation -= 1; } cell = cell.GetNeighbor(direction); } return(length); }
void TriangulateWithRiver( HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e ) { Vector3 centerL, centerR; if (cell.HasRiverThroughEdge(direction.Opposite())) { centerL = center + HexMetrics.GetFirstSolidCorner(direction.Previous()) * 0.25f; centerR = center + HexMetrics.GetSecondSolidCorner(direction.Next()) * 0.25f; } else if (cell.HasRiverThroughEdge(direction.Next())) { centerL = center; centerR = Vector3.Lerp(center, e.v5, 2f / 3f); } else if (cell.HasRiverThroughEdge(direction.Previous())) { centerL = Vector3.Lerp(center, e.v1, 2f / 3f); centerR = center; } else if (cell.HasRiverThroughEdge(direction.Next2())) { centerL = center; centerR = center + HexMetrics.GetSolidEdgeMiddle(direction.Next()) * (0.5f * HexMetrics.innerToOuter); } else { centerL = center + HexMetrics.GetSolidEdgeMiddle(direction.Previous()) * (0.5f * HexMetrics.innerToOuter); centerR = center; } center = Vector3.Lerp(centerL, centerR, 0.5f); var m = new EdgeVertices( Vector3.Lerp(centerL, e.v1, 0.5f), Vector3.Lerp(centerR, e.v5, 0.5f), 1f / 6f); m.v3.y = center.y = e.v3.y; TriangulateEdgeStrip(m, color1, cell.terrainTypeIndex, e, color1, cell.terrainTypeIndex); terrain.AddTriangle(centerL, m.v1, m.v2); //terrain.AddTriangleColor(cell.color); terrain.AddQuad(centerL, center, m.v2, m.v3); //terrain.AddQuadColor(cell.color); terrain.AddQuad(center, centerR, m.v3, m.v4); //terrain.AddQuadColor(cell.color); terrain.AddTriangle(centerR, m.v4, m.v5); //terrain.AddTriangleColor(cell.color); terrain.AddTriangleColor(color1); terrain.AddQuadColor(color1); terrain.AddQuadColor(color1); terrain.AddTriangleColor(color1); var types = Vector3.one * cell.terrainTypeIndex; terrain.AddTriangleTerrainTypes(types); terrain.AddQuadTerrainTypes(types); terrain.AddQuadTerrainTypes(types); terrain.AddTriangleTerrainTypes(types); if (!cell.isUnderWater) { var reversed = cell.incomingRiver == direction; TriangulateRiverQuad(centerL, centerR, m.v2, m.v4, cell.riverSurfaceY, 0.4f, reversed); TriangulateRiverQuad(m.v2, m.v4, e.v2, e.v4, cell.riverSurfaceY, 0.6f, reversed); } }
void TriangulateWithRiver( HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e ) { Vector3 centerL, centerR; if (cell.HasRiverThroughEdge(direction.Opposite())) { centerL = center + HexMetrics.GetFirstSolidCorner(direction.Previous()) * 0.25f; centerR = center + HexMetrics.GetSecondSolidCorner(direction.Next()) * 0.25f; } else if (cell.HasRiverThroughEdge(direction.Next())) { centerL = center; centerR = Vector3.Lerp(center, e.v5, 2f / 3f); } else if (cell.HasRiverThroughEdge(direction.Previous())) { centerL = Vector3.Lerp(center, e.v1, 2f / 3f); centerR = center; } else if (cell.HasRiverThroughEdge(direction.Next2())) { centerL = center; centerR = center + HexMetrics.GetSolidEdgeMiddle(direction.Next()) * (0.5f * HexMetrics.innerToOuter); } else { centerL = center + HexMetrics.GetSolidEdgeMiddle(direction.Previous()) * (0.5f * HexMetrics.innerToOuter); centerR = center; } center = Vector3.Lerp(centerL, centerR, 0.5f); EdgeVertices m = new EdgeVertices( Vector3.Lerp(centerL, e.v1, 0.5f), Vector3.Lerp(centerR, e.v5, 0.5f), 1f / 6f ); m.v3.y = center.y = e.v3.y; TriangulateEdgeStrip(m, color1, (int)cell.TerrainType, e, color1, (int)cell.TerrainType); terrain.AddTriangle(centerL, m.v1, m.v2); terrain.AddQuad(centerL, center, m.v2, m.v3); terrain.AddQuad(center, centerR, m.v3, m.v4); terrain.AddTriangle(centerR, m.v4, m.v5); terrain.AddTriangleColor(color1); terrain.AddQuadColor(color1); terrain.AddQuadColor(color1); terrain.AddTriangleColor(color1); Vector3 types; types.x = types.y = types.z = (float)cell.TerrainType; terrain.AddTriangleTerrainTypes(types); terrain.AddQuadTerrainTypes(types); terrain.AddQuadTerrainTypes(types); terrain.AddTriangleTerrainTypes(types); bool reversed = cell.IncomingRiver == direction; TriangulateRiverQuad( centerL, centerR, m.v2, m.v4, cell.RiverSurfaceY, 0.4f, reversed ); TriangulateRiverQuad( m.v2, m.v4, e.v2, e.v4, cell.RiverSurfaceY, 0.6f, reversed ); }