void TriangulateWithRiver(HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e) { Vector3 centerL, centerR; if (cell.HasRiverThroughEdge(direction.Opposite())) { centerL = center + HexMetrics.GetFirstSolidCorner(direction.Previous()) * 0.25f; centerR = center + HexMetrics.GetSecondSolidCorner(direction.Next()) * 0.25f; } else if (cell.HasRiverThroughEdge(direction.Next())) { centerL = center; centerR = Vector3.Lerp(center, e.v5, 2f / 3f); } else if (cell.HasRiverThroughEdge(direction.Previous())) { centerL = Vector3.Lerp(center, e.v1, 2f / 3f); centerR = center; } else if (cell.HasRiverThroughEdge(direction.Next2())) { centerL = center; centerR = center + HexMetrics.GetSolidEdgeMiddle(direction.Next()) * (0.5f * HexMetrics.innerToOuter); } else { centerL = center + HexMetrics.GetSolidEdgeMiddle(direction.Previous()) * (0.5f * HexMetrics.innerToOuter); centerR = center; } center = Vector3.Lerp(centerL, centerR, 0.5f); EdgeVertices m = new EdgeVertices( Vector3.Lerp(centerL, e.v1, 0.5f), Vector3.Lerp(centerR, e.v5, 0.5f), 1f / 6f); m.v3.y = center.y = e.v3.y; TriangulateEdgeStrip(m, cell.Color, e, cell.Color); terrain.AddTriangle(centerL, m.v1, m.v2); terrain.AddTriangleColor(cell.Color); terrain.AddQuad(centerL, center, m.v2, m.v3); terrain.AddQuadColor(cell.Color); terrain.AddQuad(center, centerR, m.v3, m.v4); terrain.AddQuadColor(cell.Color); terrain.AddTriangle(centerR, m.v4, m.v5); terrain.AddTriangleColor(cell.Color); if (!cell.IsUnderwater) { bool reversed = cell.IncomingRiver == direction; TriangulateRiverQuad(centerL, centerR, m.v2, m.v4, cell.RiverSurfaceY, 0.4f, reversed); TriangulateRiverQuad(m.v2, m.v4, e.v2, e.v4, cell.RiverSurfaceY, 0.6f, reversed); } }
private void TriangulateWaterShore(HexDirection direction, HexCell cell, HexCell neighbor, Vector3 center) { EdgeVertices e1 = new EdgeVertices( center + HexMetrics.GetFirstWaterCorner(direction), center + HexMetrics.GetSecondWaterCorner(direction) ); water.AddTriangle(center, e1.v1, e1.v2); water.AddTriangle(center, e1.v2, e1.v3); water.AddTriangle(center, e1.v3, e1.v4); water.AddTriangle(center, e1.v4, e1.v5); Vector3 center2 = neighbor.Position; center2.y = center.y; EdgeVertices e2 = new EdgeVertices( center2 + HexMetrics.GetSecondSolidCorner(direction.Opposite()), center2 + HexMetrics.GetFirstSolidCorner(direction.Opposite()) ); if (cell.HasRiverThroughEdge(direction)) { TriangulateEstuary(e1, e2, cell.IncomingRiver == direction); } else { waterShore.AddQuad(e1.v1, e1.v2, e2.v1, e2.v2); waterShore.AddQuad(e1.v2, e1.v3, e2.v2, e2.v3); waterShore.AddQuad(e1.v3, e1.v4, e2.v3, e2.v4); waterShore.AddQuad(e1.v4, e1.v5, e2.v4, e2.v5); waterShore.AddQuadUV(0f, 0f, 0f, 1f); waterShore.AddQuadUV(0f, 0f, 0f, 1f); waterShore.AddQuadUV(0f, 0f, 0f, 1f); waterShore.AddQuadUV(0f, 0f, 0f, 1f); } HexCell nextNeighbor = cell.GetNeighbor(direction.Next()); if (nextNeighbor != null) { Vector3 v3 = nextNeighbor.Position + (nextNeighbor.IsUnderwater ? HexMetrics.GetFirstWaterCorner(direction.Previous()) : HexMetrics.GetFirstSolidCorner(direction.Previous())); v3.y = center.y; waterShore.AddTriangle(e1.v5, e2.v5, v3); waterShore.AddTriangleUV( new Vector2(0f, 0f), new Vector2(0f, 1f), new Vector2(0f, nextNeighbor.IsUnderwater ? 0f : 1f) ); } }
void TriangulateWithRiverBeginOrEnd(HexDirection direction, HexCell cell) { var center = cell.Center; var closerEdge = cell.Edges[(int)direction]; if (cell.HasRiverThroughEdge(direction.Next())) { if (cell.HasRiverThroughEdge(direction.Previous())) { center += HexMetrics.GetSolidEdgeMiddle(direction) * (HexMetrics.InnerToOuter * 0.5f); } else if (cell.HasRiverThroughEdge(direction.Previous2())) { center += HexMetrics.GetLeftSolidCorner(direction) * 0.25f; } } else if (cell.HasRiverThroughEdge(direction.Previous()) && cell.HasRiverThroughEdge(direction.Next2())) { center += HexMetrics.GetRightSolidCorner(direction) * 0.25f; } var m = new EdgeVertices(Vector3.Lerp(center, closerEdge.V1, 0.5f), Vector3.Lerp(center, closerEdge.V5, 0.5f)); m.V3.y = closerEdge.V3.y; // reassign middle verticle height as it is ommited in the calculation above TriangulateEdgeStrip(m, cell.Color, closerEdge, cell.Color); TriangulateEdgeFan(center, m, cell.Color); // river segments are added only if the current segment is not under water if (!cell.IsUnderwater) { bool reversed = cell.HasIncomingRiver; // outer circle of the hex TriangulateRiverQuadUnperturbed(m.V2, m.V4, closerEdge.V2, closerEdge.V4, cell.RiverSurfaceY, 0.6f, reversed); // end (or start) triangle center.y = m.V2.y = m.V4.y = cell.RiverSurfaceY; Rivers.AddTriangleUnperturbed(center, m.V2, m.V4); if (reversed) { Rivers.AddTriangleUV(new Vector2(0.5f, 0.4f), new Vector2(1f, 0.2f), new Vector2(0f, 0.2f)); } else { Rivers.AddTriangleUV(new Vector2(0.5f, 0.4f), new Vector2(0f, 0.6f), new Vector2(1f, 0.6f)); } } }
//河流三角划分 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 { centerL = 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; //fill the space between the middle and edge lines. 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); }
void TriangulateAdjacentToRiver( HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e ) { Terrain terrain = cell.Terrain; if (terrain.HasRoads) { TriangulateRoadAdjacentToRiver(direction, cell, center, e); } if (terrain.RiverTerrain.HasRiverThroughEdge(direction.Next())) { if (terrain.RiverTerrain.HasRiverThroughEdge(direction.Previous())) { center += HexMetrics.GetSolidEdgeMiddle(direction) * (HexMetrics.innerToOuter * 0.5f); } else if ( terrain.RiverTerrain.HasRiverThroughEdge(direction.Previous2()) ) { center += HexMetrics.GetFirstSolidCorner(direction) * 0.25f; } } else if ( terrain.RiverTerrain.HasRiverThroughEdge(direction.Previous()) && terrain.RiverTerrain.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 (!terrain.IsUnderwater && !terrain.HasRoadThroughEdge(direction)) { features.AddFeature(cell, (center + e.v1 + e.v5) * (1f / 3f)); } }
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 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)); }
private void Triangulate(HexDirection dir, HexCell cell) { Vector3 center = cell.transform.localPosition; Vector3 v1 = center + HexMertics.GetFirstSolidCornor(dir); Vector3 v2 = center + HexMertics.GetSecondSolidCornor(dir); ///第一个顶点的位置为cell正中心,其余为cell的顶点 AddTriangle(center, v1, v2); AddTriangleColor(cell.color); ///根据方向获取相邻的节点 HexCell neighbor = cell.GetNeighbor(dir) ?? cell; HexCell preNeighbor = cell.GetNeighbor(dir.Previous()) ?? cell; HexCell nextNeighbor = cell.GetNeighbor(dir.Next()) ?? cell; if (dir <= HexDirection.SE) { TriangulateConnection(dir, cell, v1, v2); } //AddTriangle(v1, center + HexMertics.GetFirstCornor(dir),v3); //AddTriangleColor(cell.color, (cell.color + preNeighbor.color + neighbor.color) / 3, bridgeColor); //AddTriangle(v2, v4, center + HexMertics.GetSecondCornor(dir)); //AddTriangleColor(cell.color, bridgeColor, (cell.color + neighbor.color + nextNeighbor.color) / 3); }
/// <summary> /// Only call this after checking CanChangeDir, this function will not return the current dir if it is the only one left /// </summary> /// <param name="currentNeighbors"></param> /// <param name="currentDirection"></param> /// <returns></returns> private int GetNewDir(List <HexCell> currentNeighbors, HexDirection currentDirection) { var viableNeighborsIndices = new List <int>(); for (int i = 0; i < currentNeighbors.Count; i++) { try { if (currentNeighbors[i].landType == LandType.Grass && i != (int)currentDirection) { viableNeighborsIndices.Add(i); } } catch (NullReferenceException) { } } var favoredDirections = new HexDirection[] { currentDirection.Next(), currentDirection.Previous() }; foreach (var hexDir in favoredDirections) { if (viableNeighborsIndices.Contains((int)hexDir)) { return((int)hexDir); } } return(viableNeighborsIndices[UnityEngine.Random.Range(0, viableNeighborsIndices.Count)]); }
void TriangulateWithRiver( HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e ) { Vector3 centerL = center + HexMetrics.GetFirstSolidCorner(direction.Previous()) * 0.25f; Vector3 centerR = center + HexMetrics.GetSecondSolidCorner(direction.Next()) * 0.25f; EdgeVertices m = new EdgeVertices( Vector3.Lerp(centerL, e.v1, 0.5f), Vector3.Lerp(centerR, e.v5, 0.5f), 1f / 6f ); m.v3.y = center.y = e.v3.y; TriangulateEdgeStrip(m, cell.Color, e, cell.Color); AddTriangle(centerL, m.v1, m.v2); AddTriangleColor(cell.Color); AddQuad(centerL, center, m.v2, m.v3); AddQuadColor(cell.Color); AddQuad(center, centerR, m.v3, m.v4); AddQuadColor(cell.Color); AddTriangle(centerR, m.v4, m.v5); AddTriangleColor(cell.Color); }
public RiverPath( IHexCell cell, HexDirection pathStart, HexDirection pathEnd, RiverFlow flow, IRiverCanon riverCanon, IHexGrid grid ) { Cell = cell; Path = new List <HexDirection>(); Flow = flow; if (flow == RiverFlow.Clockwise) { for (HexDirection i = pathStart; i != pathEnd; i = i.Next()) { Path.Add(i); } } else { for (HexDirection i = pathStart; i != pathEnd; i = i.Previous()) { Path.Add(i); } } Path.Add(pathEnd); RiverCanon = riverCanon; Grid = grid; }
//Since we're often triangulating water that goes up against land, //We need to be careful about how we assign colors. There are three //basic cases: center is water, either left or right (but not both) //is water, or all three cells are water. private void GetWaterColors( IHexCell center, HexDirection direction, out Color centerColor, out Color leftColor, out Color rightColor ) { centerColor = GetWaterColor(center); var left = Grid.GetNeighbor(center, direction.Previous()); var right = Grid.GetNeighbor(center, direction); bool isLeftWater = left != null && left.Terrain.IsWater(); bool isRightWater = right != null && right.Terrain.IsWater(); if (isLeftWater) { leftColor = GetWaterColor(left); rightColor = isRightWater ? rightColor = GetWaterColor(right) : Color.Lerp(centerColor, leftColor, 0.5f); } else if (isRightWater) { rightColor = GetWaterColor(right); leftColor = Color.Lerp(centerColor, rightColor, 0.5f); } else { leftColor = centerColor; rightColor = centerColor; } }
void Triangulate(HexDirection direction, HexCell cell) { Vector3 center = cell.transform.localPosition; Vector3 v1 = center + HexMetrics.GetFirstSolidCorner(direction); Vector3 v2 = center + HexMetrics.GetSecondSolidCorner(direction); Vector3 bridge = HexMetrics.GetBridge(direction); Vector3 v3 = v1 + bridge; Vector3 v4 = v2 + bridge; AddTriangle(center, v1, v2); AddTriangleColor(cell.color); AddQuad(v1, v2, v3, v4); HexCell prevNeighbor = cell.GetNeighbor(direction.Previous()) ?? cell; HexCell neighbor = cell.GetNeighbor(direction) ?? cell; HexCell nextNeighbor = cell.GetNeighbor(direction.Next()) ?? cell; Color bridgeColor = (cell.color + neighbor.color) * 0.5f; AddQuadColor(cell.color, bridgeColor); AddTriangle(v1, center + HexMetrics.GetFirstCorner(direction), v3); AddTriangleColor( cell.color, (cell.color + prevNeighbor.color + neighbor.color) / 3f, bridgeColor ); AddTriangle(v2, v4, center + HexMetrics.GetSecondCorner(direction)); AddTriangleColor( cell.color, bridgeColor, (cell.color + neighbor.color + nextNeighbor.color) / 3f ); }
private void Triangulate(HexDirection d, HexCell hexCell) { Vector3 center = hexCell.transform.localPosition; Vector3 v1 = center + HexMetrics.GetFirstSolidCorner(d); Vector3 v2 = center + HexMetrics.GetSecondSolidCorner(d); AddTriangle(center, v1, v2); AddTriangleColor(hexCell.color, hexCell.color, hexCell.color); HexCell neighborNext = hexCell.GetNeighbor(d.Next()) ?? hexCell; HexCell neighborPrev = hexCell.GetNeighbor(d.Previous()) ?? hexCell; //Color colorNext = (hexCell.color + neighbor.color + neighborNext.color) / 3f; //Color colorPrev = (hexCell.color + neighbor.color + neighborPrev.color) / 3f; //Color colorBridge = (hexCell.color + neighbor.color) * 0.5f; if (d <= HexDirection.SE) // NE , E, SE { TriangulateConnection(d, hexCell, v1, v2); } //// previous Corner //AddTriangle(v1, center + HexMetrics.GetFirstCorner(d), v3); //AddTriangleColor(hexCell.color, colorPrev, colorBridge); ////next corner //AddTriangle(v2, v4, center + HexMetrics.GetSecondCorner(d)); ; //AddTriangleColor(hexCell.color, colorBridge, colorNext); }
void Triangulate(HexDirection direction, HexCell cell) { Vector3 center = cell.transform.localPosition; Vector3 v1 = center + HexMatrics.GetFirstSolidCorner(direction); Vector3 v2 = center + HexMatrics.GetSecondSolidCorner(direction); AddTriangle(center, v1, v2); AddTriangleColor(cell.color); Vector3 v3 = center + HexMatrics.GetFirstCorner(direction); Vector3 v4 = center + HexMatrics.GetSecondCorner(direction); AddQuad(v1, v2, v3, v4); HexCell prevNeighbor = cell.GetNeighbor(direction.Previous()) ?? cell; HexCell neighbor = cell.GetNeighbor(direction) ?? cell; HexCell nextNeighbor = cell.GetNeighbor(direction.Next()) ?? cell; AddQuadColor( cell.color, cell.color, (cell.color + prevNeighbor.color + neighbor.color) / 3f, (cell.color + neighbor.color + nextNeighbor.color) / 3f ); }
private void TriangulateWaterShore(HexDirection direction, HexCell cell, HexCell neighbor, Vector3 center) { var edge = new EdgeVertices( center + HexMetrics.GetFirstWaterCorner(direction), center + HexMetrics.GetSecondWaterCorner(direction), HexMetrics.edgeOuterStep); _water.AddTriangle(center, edge.v1, edge.v2); _water.AddTriangle(center, edge.v2, edge.v3); _water.AddTriangle(center, edge.v3, edge.v4); _water.AddTriangle(center, edge.v4, edge.v5); var center2 = neighbor.Position; center2.y = center.y; var edge2 = new EdgeVertices( center2 + HexMetrics.GetSecondSolidCorner(direction.Opposite()), center2 + HexMetrics.GetFirstSolidCorner(direction.Opposite()), HexMetrics.edgeOuterStep); if (cell.HasRiverThroughEdge(direction)) { TriangulateEstuary(edge, edge2, cell.IncomingRiver == direction); } else { _waterShore.AddQuad(edge.v1, edge.v2, edge2.v1, edge2.v2); _waterShore.AddQuad(edge.v2, edge.v3, edge2.v2, edge2.v3); _waterShore.AddQuad(edge.v3, edge.v4, edge2.v3, edge2.v4); _waterShore.AddQuad(edge.v4, edge.v5, edge2.v4, edge2.v5); _waterShore.AddQuadUV(0, 0, 0, 1); _waterShore.AddQuadUV(0, 0, 0, 1); _waterShore.AddQuadUV(0, 0, 0, 1); _waterShore.AddQuadUV(0, 0, 0, 1); } var nextNeighbor = cell.GetNeighbor(direction.Next()); if (nextNeighbor != null) { var v3 = nextNeighbor.Position + (nextNeighbor.IsUnderWater ? HexMetrics.GetFirstWaterCorner(direction.Previous()) : HexMetrics.GetFirstSolidCorner(direction.Previous())); v3.y = center.y; _waterShore.AddTriangle(edge.v5, edge2.v5, v3); _waterShore.AddTriangleUV(Vector2.zero, Vector2.up, nextNeighbor.IsUnderWater ? Vector2.zero : Vector2.up); } }
void TriangulateConnection(HexDirection direction, HexCell cell, Vector3 v1, Vector3 v2) { Vector3 bridge = HexMetrics.GetBridge(direction); Vector3 v3 = v1 + bridge; Vector3 v4 = v2 + bridge; HexCell neighbor = cell.GetNeighbor(direction); if (neighbor != null) { v3.y = v4.y = neighbor.transform.localPosition.y; } if (direction <= HexDirection.SE) { AddQuad(v1, v2, v3, v4); AddQuadColor( room.region.regionColor, room.region.regionColor, room.region.regionColor, room.region.regionColor ); } /// if the neifhfbour is wall we create wall if (cell.edgeTypes[(int)direction] == EdgeType.WALL) { AddConnectionWall(v1, v2, v3, v4, cell); } /// if the neihgbour is door we create door if (cell.edgeTypes[(int)direction] == EdgeType.DOOR) { GenerateDoor(v1, v2, v3, v4); } HexCell nextNeighbor = cell.GetNeighbor(direction.Next()); HexCell previousNeighbour = cell.GetNeighbor(direction.Previous()); Vector3 v2Top = v2 + Vector3.up * HexMetrics.wallHeight; Vector3 v4Top = v4 + Vector3.up * HexMetrics.wallHeight; if (direction <= HexDirection.NW) { Vector3 v5 = v2 + HexMetrics.GetBridge(direction.Next()); if (nextNeighbor != null) { v5.y = nextNeighbor.transform.localPosition.y; } if (direction <= HexDirection.E) { AddTriangle(v2, v4, v5); AddTriangleColor(room.region.regionColor); } /// create a triangle wall adjacent to wall if (cell.edgeTypes[(int)direction] == EdgeType.WALL || cell.edgeTypes[(int)direction] == EdgeType.DOOR) { AddConnectionWallTriangle(v2, v4, v5, cell); } } }
public bool IsSmoothCorner(HexDirection direction) { if (HasBuilding(direction.Previous()) && !HasBuilding(direction) && HasBuilding(direction.Next())) { return(true); } return(false); }
//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); }
public bool IsDrawPreviousRoadMesh(HexDirection direction) { if (isThroughRoad[(int)direction] == true && isThroughRoad[(int)direction.Previous()] == false) { return(true); } return(false); }
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 void TryExpandCorridor(ref Stack <TileProperties> remainingTiles, TileProperties affectedTile, HexDirection previousDirection) { TileProperties nextTile = affectedTile.GetNeighbor(previousDirection); if (affectedTile.Tile && nextTile.Tile && !ExpandCorridor(ref remainingTiles, affectedTile, previousDirection)) { ExpandCorridor(ref remainingTiles, affectedTile, previousDirection.Previous()); ExpandCorridor(ref remainingTiles, affectedTile, previousDirection.Next()); } }
public void RationalizeRiverContoursInCorner(IHexCell center, HexDirection direction) { IHexCell left = Grid.GetNeighbor(center, direction.Previous()); //Contours will only fall short or overlap when we're at a river confluence, //so we can save ourselves time by checking for that if (left != null && RiverCanon.HasRiverAlongEdge(center, direction.Previous()) && RiverCanon.HasRiverAlongEdge(center, direction) && RiverCanon.HasRiverAlongEdge(left, direction.Next()) ) { IHexCell right = Grid.GetNeighbor(center, direction); RiverSection centerLeftSection = RiverSectionCanon.GetSectionBetweenCells(center, left); RiverSection centerRightSection = RiverSectionCanon.GetSectionBetweenCells(center, right); bool shouldCullContours = true; //Rationalizing contours also doesn't need to occur between segments //that are adjacent segments of the same river, which would put us on //the inside of a river curve. So we make some checks to exclude that //possibility, as well foreach (var river in RiverAssemblyCanon.Rivers) { int leftIndex = river.IndexOf(centerLeftSection); int rightIndex = river.IndexOf(centerRightSection); bool areAdjacentInRiver = ((leftIndex + 1) == rightIndex) || ((rightIndex + 1) == leftIndex); if (leftIndex != -1 && rightIndex != -1 && areAdjacentInRiver) { shouldCullContours = false; break; } } if (shouldCullContours) { ContourRationalizer.RationalizeCellContours(center, direction); } } }
/// <summary> /// 填充河道细胞中其他没有河道的顶面部分 /// 在此函数中处理河流和道路共存的情况 /// </summary> /// <param name="direction"></param> /// <param name="cell"></param> /// <param name="center"></param> /// <param name="e"></param> void TriangulateAdjacentToRiver(HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e) { if (cell.HasRoads) { TriangulateRoadAdjacentToRiver(direction, cell, center, e); } if (cell.HasRiverThroughEdge(direction.Next())) { if (cell.HasRiverThroughEdge(direction.Previous())) { //当前方向的前一个方向和后一个方向上都有河道 //就是河道的流入和流出之间相差一个方向单位 center += HexMetrics.GetSoliEdgeMiddle(direction) * (HexMetrics.innerToOuter * 0.5f); } else if (cell.HasRiverThroughEdge(direction.Previous2())) { //当前方向的前一个方向和后两个方向上都有河道 //就是笔直的河道,这是靠近前一个方向上的 center += HexMetrics.GetFirstSolidCorner(direction) * 0.25f; } } else if (cell.HasRiverThroughEdge(direction.Previous()) && cell.HasRiverThroughEdge(direction.Next2())) { //当前方向的后一个方向和前两个方向上都有河道 //就是笔直的河道,这是靠近后一个方向上的 center += HexMetrics.GetSecondSolidCorner(direction) * 0.25f; } EdgeVertices m = new EdgeVertices( Vector3.Lerp(center, e.v1, 0.5f), Vector3.Lerp(center, e.v5, 0.5f) ); TriangulateEdgeStrip(m, cell.Color, e, cell.Color); TriangulateEdgeFan(center, m, cell.Color); if (!cell.IsUnderwater && !cell.HasRoadThroughEdge(direction)) { features.AddFeature(cell, (center + e.v1 + e.v5) * (1f / 3f)); } }
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, color1, cell.TerrainTypeIndex, e, color1, cell.TerrainTypeIndex ); TriangulateEdgeFan(center, e, cell.TerrainTypeIndex); }
public void TriangulateAdjacentToRiver(HexDirection dir, HexCell cell, Vector3 center, EdgeVertices edges) { if (cell.HasRoads) { TriangulateRoadsAdjacentToRiver(dir, cell, center, edges); } if (cell.HasRiverThroughEdge(dir.Next())) { if (cell.HasRiverThroughEdge(dir.Previous())) { center += HexMetrics.GetSolidEdgeMiddle(dir) * (HexMetrics.InnerToOuter * 0.5f); } else if (cell.HasRiverThroughEdge(dir.Previous2())) { center += HexMetrics.GetFirstSolidCorner(dir) * 0.23f; } } else if (cell.HasRiverThroughEdge(dir.Previous()) && cell.HasRiverThroughEdge(dir.Next2())) { center += HexMetrics.GetSecondSolidCorner(dir) * 0.25f; } EdgeVertices modifiedEdges = new EdgeVertices(Vector3.Lerp(center, edges.v1, 0.5f), Vector3.Lerp(center, edges.v5, 0.5f)); Color color = Weights1; // cell.Color; TriangulateEdgeStrip(modifiedEdges, color, cell.TerrainTypeIndex, edges, color, cell.CellIndex); TriangulateEdgeFan(center, modifiedEdges, color, cell.CellIndex); if (!cell.IsUnderwater && !cell.HasRoadThroughEdge(dir)) { // centred in triangle Vector3 position = (center + edges.v1 + edges.v5) * (1f / 3f); FeatureManager.AddFeature(cell, position); } }
void TriangulateWaterShore( HexDirection direction, HexCell cell, HexCell neighbor, Vector3 center ) { EdgeVertices e1 = new EdgeVertices( center + HexMetrics.GetFirstWaterCorner(direction), center + HexMetrics.GetSecondWaterCorner(direction) ); water.AddTriangle(center, e1.v1, e1.v2); Vector3 center2 = neighbor.Position; center2.y = center.y; EdgeVertices e2 = new EdgeVertices( center2 + HexMetrics.GetSecondOuterCorner(direction.Opposite()), center2 + HexMetrics.GetFirstOuterCorner(direction.Opposite()) ); waterShore.AddQuad(e1.v1, e1.v2, e2.v1, e2.v2); waterShore.AddQuadUV(0f, 0f, 0f, 1f); HexCell nextNeighbor = cell.GetNeighbor(direction.Next()); if (nextNeighbor != null) { Vector3 v3 = nextNeighbor.Position + (nextNeighbor.IsUnderwater ? HexMetrics.GetFirstWaterCorner(direction.Previous()) : HexMetrics.GetFirstOuterCorner(direction.Previous())); v3.y = center.y; waterShore.AddTriangle( e1.v2, e2.v2, v3 ); waterShore.AddTriangleUV( new Vector2(0f, 0f), new Vector2(0f, 1f), new Vector2(0f, nextNeighbor.IsUnderwater ? 0f : 1f) ); } }
void TriangulateAdjacentToRiver(HexDirection dir, HexCell hexCell, Vector3 center, EdgeVertices e) { // // Road + River if (hexCell.HasRoads) { TriangulateRoadAdjacentToRiver(dir, hexCell, center, e); } // Overlapping if (hexCell.HasRiverThroughEdge(dir.Next())) { if (hexCell.HasRiverThroughEdge(dir.Previous())) { center += Hex.GetSolidEdgeMiddle(dir) * Hex.innerToOuter * 0.5f; } else if (hexCell.HasRiverThroughEdge(dir.Previous().Previous())) { center += Hex.GetFirstSolidPoint(dir) * 0.25f; } } else if (hexCell.HasRiverThroughEdge(dir.Previous()) && hexCell.HasRiverThroughEdge(dir.Next().Next())) { center += Hex.GetSecondSolidPoint(dir) * 0.25f; } EdgeVertices m = new EdgeVertices( Vector3.Lerp(center, e.v1, 0.5f), Vector3.Lerp(center, e.v5, 0.5f) ); TriangulateEdgeStrip(m, /*hexCell.Color*/ weights1, hexCell.Index, e, /*hexCell.Color*/ weights1, hexCell.Index); TriangulateEdgeFan(center, e, hexCell.Index); if (!hexCell.IsUnderwater && !hexCell.HasRoadThroughEdge(dir)) { features.AddFeature(hexCell, ((center + e.v1 + e.v5) * (1f / 3f))); } }
public void updateChunkWithWallsTest() { 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; cells[index].Walled = true; cells[index].SetOutgoingRiver(direction); HexCell cell1 = cells[index].GetNeighbor(direction) .GetNeighbor(direction); cell1.Walled = true; cell1.GetNeighbor(direction.Previous()).Elevation = 1; cell1.GetNeighbor(direction.Previous()).Walled = true; HexCell cell2 = cells[index].GetNeighbor(direction.Next()) .GetNeighbor(direction.Next()).GetNeighbor(direction); cell2.GetNeighbor(direction.Previous()).Walled = true; cell2.GetNeighbor(direction).Walled = true; // Update chunk foreach (HexGridChunk chunk in chunks) { chunk.Triangulate(); } Assert.IsTrue(cells[index].Walled); Assert.AreEqual(direction, cells[index].OutgoingRiver); GameObject.Destroy(obj); }