// test if cell is neighbour of previous cell private bool ValidateDrag(HexCell newCell) { for (dragDirection = HexDirection.NE; dragDirection <= HexDirection.NW; dragDirection++) { if (previousCell.GetNeighbour(dragDirection) == newCell) { return(true); } } return(false); }
private bool IsErodible(HexCell cell) { var erodibleElevation = cell.Elevation - 2; for (var d = HexDirection.NE; d <= HexDirection.NW; d++) { var neighbour = cell.GetNeighbour(d); if (neighbour && neighbour.Elevation <= erodibleElevation) { return(true); } } return(false); }
private void TriangulateWater(HexDirection direction, HexCell cell, Vector3 centre) { centre.y = cell.WaterSurfaceY; var neighbour = cell.GetNeighbour(direction); if (neighbour != null && !neighbour.IsUnderwater) { TriangulateWaterShore(direction, cell, neighbour, centre); } else { TriangulateOpenWater(direction, cell, neighbour, centre); } }
private HexCell GetErosionTarget(HexCell cell) { var candidates = ListPool <HexCell> .Get(); var erodibleElevation = cell.Elevation - 2; for (var d = HexDirection.NE; d <= HexDirection.NW; d++) { var neighbour = cell.GetNeighbour(d); if (neighbour && neighbour.Elevation <= erodibleElevation) { candidates.Add(neighbour); } } var candidate = candidates[Random.Range(0, candidates.Count)]; ListPool <HexCell> .Add(candidates); return(candidate); }
private void TriangulateOpenWater(HexDirection direction, HexCell cell, HexCell neighbour, Vector3 centre) { var c1 = centre + HexMetrics.GetFirstWaterCorner(direction); var c2 = centre + HexMetrics.GetSecondWaterCorner(direction); Water.AddTriangle(centre, c1, c2); var indices = new Vector3(cell.Index, cell.Index, cell.Index); Water.AddTriangleCellData(indices, weights1); if (neighbour == null || direction > HexDirection.SE) { return; } var bridge = HexMetrics.GetWaterBridge(direction); var e1 = c1 + bridge; var e2 = c2 + bridge; Water.AddQuad(c1, c2, e1, e2); indices.y = neighbour.Index; Water.AddQuadCellData(indices, weights1, weights2); if (direction > HexDirection.E) { return; } var nextNeighbour = cell.GetNeighbour(direction.Next()); if (nextNeighbour == null || !nextNeighbour.IsUnderwater) { return; } Water.AddTriangle(c2, e2, c2 + HexMetrics.GetWaterBridge(direction.Next())); indices.z = nextNeighbour.Index; Water.AddTriangleCellData(indices, weights1, weights2, weights3); }
private void TriangulateWaterShore(HexDirection direction, HexCell cell, HexCell neighbour, Vector3 centre) { var e1 = new EdgeVertices( centre + HexMetrics.GetFirstWaterCorner(direction), centre + HexMetrics.GetSecondWaterCorner(direction) ); Water.AddTriangle(centre, e1.v1, e1.v2); Water.AddTriangle(centre, e1.v2, e1.v3); Water.AddTriangle(centre, e1.v3, e1.v4); Water.AddTriangle(centre, e1.v4, e1.v5); var indices = new Vector3(cell.Index, neighbour.Index, cell.Index); Water.AddTriangleCellData(indices, weights1); Water.AddTriangleCellData(indices, weights1); Water.AddTriangleCellData(indices, weights1); Water.AddTriangleCellData(indices, weights1); var centre2 = neighbour.Position; if (neighbour.ColumnIndex < cell.ColumnIndex - 1) { centre2.x += HexMetrics.WrapSize * HexMetrics.InnerDiameter; } else if (neighbour.ColumnIndex > cell.ColumnIndex + 1) { centre2.x -= HexMetrics.WrapSize * HexMetrics.InnerDiameter; } centre2.y = centre.y; var e2 = new EdgeVertices( centre2 + HexMetrics.GetSecondSolidCorner(direction.Opposite()), centre2 + HexMetrics.GetFirstSolidCorner(direction.Opposite()) ); // rather than calculating from current centre, work backwards from neighbour centre to find edge if (cell.HasRiverThroughEdge(direction)) { TriangulateEstuary(e1, e2, cell.IncomingRiver == direction, indices); } 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); WaterShore.AddQuadCellData(indices, weights1, weights2); WaterShore.AddQuadCellData(indices, weights1, weights2); WaterShore.AddQuadCellData(indices, weights1, weights2); WaterShore.AddQuadCellData(indices, weights1, weights2); } var nextNeighbour = cell.GetNeighbour(direction.Next()); if (nextNeighbour == null) { return; } var centre3 = nextNeighbour.Position; if (nextNeighbour.ColumnIndex < cell.ColumnIndex - 1) { centre3.x += HexMetrics.WrapSize * HexMetrics.InnerDiameter; } else if (nextNeighbour.ColumnIndex > cell.ColumnIndex + 1) { centre3.x -= HexMetrics.WrapSize * HexMetrics.InnerDiameter; } var v3 = centre3 + (nextNeighbour.IsUnderwater ? HexMetrics.GetFirstWaterCorner(direction.Previous()) : HexMetrics.GetFirstSolidCorner(direction.Previous())); v3.y = centre.y; WaterShore.AddTriangle(e1.v5, e2.v5, v3); WaterShore.AddTriangleUV( new Vector2(0f, 0f), new Vector2(0f, 1f), new Vector2(0f, nextNeighbour.IsUnderwater ? 0f : 1f)); indices.z = nextNeighbour.Index; WaterShore.AddTriangleCellData(indices, weights1, weights2, weights3); }
private void TriangulateConnection(HexDirection direction, HexCell cell, EdgeVertices e1) { var neighbour = cell.GetNeighbour(direction); if (neighbour == null) { return; // dont add for edge hexes } var bridge = HexMetrics.GetBridge(direction); bridge.y = neighbour.Position.y - cell.Position.y; var e2 = new EdgeVertices( e1.v1 + bridge, e1.v5 + bridge ); var hasRiver = cell.HasRiverThroughEdge(direction); var hasRoad = cell.HasRoadThroughEdge(direction); if (hasRiver) { var startV3 = e2.v3.y; e2.v3.y = neighbour.StreamBedY; var indices = new Vector3(cell.Index, neighbour.Index, cell.Index); // by definition, both cells have rivers through them // however, if both are underwater, then we want (i want) no river bed // if only one is, the river should merge with the stream // EXCEPT if there is an elevation difference, in which case we need the stream bed to make a waterfall // if im a river and the neighbour is a river if (!cell.IsUnderwater && !neighbour.IsUnderwater) { TriangulateRiverQuad( e1.v2, e1.v4, e2.v2, e2.v4, cell.RiverSurfaceY, neighbour.RiverSurfaceY, 0.8f, cell.HasIncomingRiver && cell.IncomingRiver == direction, indices); } // if im a river and the neighbour is beneath me else if (!cell.IsUnderwater && cell.Elevation > neighbour.WaterLevel) { TriangulateWaterfallInWater( e1.v2, e1.v4, e2.v2, e2.v4, cell.RiverSurfaceY, neighbour.RiverSurfaceY, neighbour.WaterLevel, indices); } // im underwater but the neighbour is heigher than me else if (cell.IsUnderwater && !neighbour.IsUnderwater && neighbour.Elevation > cell.WaterLevel) { TriangulateWaterfallInWater( e2.v4, e2.v2, e1.v4, e1.v2, neighbour.RiverSurfaceY, cell.RiverSurfaceY, cell.WaterLevel, indices); } else if ((cell.IsUnderwater == neighbour.IsUnderwater == true) || // both underwater !cell.IsUnderwater && neighbour.IsUnderwater) // river into water on same level { e2.v3.y = startV3; // if a river, this will smooth e1 (river side) into e2 (lake/sea bed, which is normal surface) } // if not a river, then e1 is already sea/lake bed, so e2 will now be approximate same level } if (HexMetrics.GetEdgeType(cell.Elevation, neighbour.Elevation) == HexEdgeType.Slope) { TriangulateEdgeTerrace(e1, cell, e2, neighbour, hasRoad); } else { TriangulateEdgeStrip(e1, weights1, cell.Index, e2, weights2, neighbour.Index, hasRoad); } Features.AddWall(e1, cell, e2, neighbour, hasRiver, hasRoad); if (direction > HexDirection.E) { return; } var nextDirection = direction.Next(); var nextNeighbour = cell.GetNeighbour(nextDirection); if (nextNeighbour == null) { return; } var v5 = e1.v5 + HexMetrics.GetBridge(nextDirection); v5.y = nextNeighbour.Position.y; var minElevation = Mathf.Min(cell.Elevation, neighbour.Elevation, nextNeighbour.Elevation); if (minElevation == cell.Elevation) { TriangulateCorner(e1.v5, cell, e2.v5, neighbour, v5, nextNeighbour); } else if (minElevation == neighbour.Elevation) { TriangulateCorner(e2.v5, neighbour, v5, nextNeighbour, e1.v5, cell); } else { TriangulateCorner(v5, nextNeighbour, e1.v5, cell, e2.v5, neighbour); } }