void AddCliffEdge(SquareCell cell, GridDirection direction) { GridDirection prev = direction.Previous(); GridDirection next = direction.Next(); GridDirection prevN = prev.Previous2(); GridDirection nextN = next.Next2(); SquareCell neighbor = cell.GetNeighbor(direction); if (neighbor != null) { Vector3 c0 = new Vector3(cell.coordinates.X, 0, cell.coordinates.Z) + GridMetrics.GetEdge(prev) + Vector3.up * (int)cell.GridElevations[prev] * GridMetrics.elevationStep; Vector3 c1 = new Vector3(cell.coordinates.X, 0, cell.coordinates.Z) + GridMetrics.GetEdge(next) + Vector3.up * (int)cell.GridElevations[next] * GridMetrics.elevationStep; Vector3 n0 = new Vector3(neighbor.coordinates.X, 0, neighbor.coordinates.Z) + GridMetrics.GetEdge(prevN) + Vector3.up * (int)neighbor.GridElevations[prevN] * GridMetrics.elevationStep; Vector3 n1 = new Vector3(neighbor.coordinates.X, 0, neighbor.coordinates.Z) + GridMetrics.GetEdge(nextN) + Vector3.up * (int)neighbor.GridElevations[nextN] * GridMetrics.elevationStep; if (c0 != n0 && c1 != n1) { if (c0.y > n0.y && n1.y > c1.y) // if edges cross heights along edge X { Vector2 cross = CrossingPoint(c1.y - c0.y, n1.y - n0.y, c0.y, n0.y); Vector3 worldCross = new Vector3(cell.coordinates.X, 0, cell.coordinates.Z) + GridMetrics.GetEdge(direction.Previous()) + (cross.x * 2 * GridMetrics.GetEdge(direction.Next2())) + new Vector3(0, cross.y, 0); terrain.AddTriangle(worldCross, c0, n0); terrain.AddTriangleColor(Color.cyan); terrain.AddTriangle(worldCross, n1, c1); terrain.AddTriangleColor(Color.green); } else if (c0.y > n0.y && c1.y > n1.y) // if one edge is always above the other { terrain.AddQuad(c0, n0, n1, c1); terrain.AddQuadColor(retainingWallColor); } } else if (c0.y > n0.y) { terrain.AddTriangle(c0, n0, c1); terrain.AddTriangleColor(retainingWallColor); } else if (c1.y > n1.y) { terrain.AddTriangle(c0, n1, c1); terrain.AddTriangleColor(retainingWallColor); } } }
public int GetElevationDifference(GridDirection direction) { int differencePrev = (int)this[direction.Previous()] - (int)this[direction.Opposite().Next()]; int differenceNext = (int)this[direction.Next()] - (int)this[direction.Opposite().Previous()]; int result = Mathf.Max(differencePrev, differenceNext); return(result); }
void MakeCornerBridge(GridMesh mesh, Vector3 v0, GridDirection bridgeDirection) { Vector3 b0 = GridMetrics.GetBridge(bridgeDirection.Previous()); Vector3 b1 = GridMetrics.GetBridge(bridgeDirection.Next()); mesh.AddQuad(v0, v0 + b0, v0 + b0 + b1, v0 + b1); if (mesh.useUVCoordinates) { mesh.AddQuadUV(0f, 0f, 0f, 1f); } }
public void ChangeVertexElevation(GridDirection vertex, int value) { if (value == 0 && ((HasRoadThroughEdge(vertex.Next()) && (GetElevationDifference(vertex.Next()) > 3 || HasCliff(vertex.Next()))) || (HasRoadThroughEdge(vertex.Previous()) && (GetElevationDifference(vertex.Previous()) > 3 || HasCliff(vertex.Previous()))) )) { Debug.Log("Could not change elevation"); } else { vertexElevations[vertex] += value; GroundMaterial.SetToMud(this, ref tile); } }
public bool HasCliff(GridDirection direction) { SquareCell neighbor = GetNeighbor(direction); if (neighbor) { bool noCliff = (int)vertexElevations[direction.Previous()] == (int)neighbor.vertexElevations[direction.Opposite().Next()] && (int)vertexElevations[direction.Next()] == (int)neighbor.vertexElevations[direction.Opposite().Previous()]; return(!noCliff); } else { return(false); } }
void EditCell(SquareCell cell, Vector3 hitpoint) { if (activeMode == EditMode.color) { cell.Tile = activeTileMaterial.GetClone; } else if (activeMode == EditMode.elevation) { GridDirection vertex = squareGrid.GetVertex(hitpoint); if (Input.GetMouseButton(0) && (stopWatch.ElapsedMilliseconds > 500f || freshClick)) { cell.ChangeVertexElevation(vertex, 1); if (!allowCliffs) { if (cell.GetNeighbor(vertex)) { cell.GetNeighbor(vertex).ChangeVertexElevation(vertex.Opposite(), 1); } if (cell.GetNeighbor(vertex.Next())) { cell.GetNeighbor(vertex.Next()).ChangeVertexElevation(vertex.Previous2(), 1); } if (cell.GetNeighbor(vertex.Previous())) { cell.GetNeighbor(vertex.Previous()).ChangeVertexElevation(vertex.Next2(), 1); } } stopWatch.Reset(); stopWatch.Start(); } if (Input.GetMouseButton(1) && (stopWatch.ElapsedMilliseconds > 500f || freshClick)) { cell.ChangeVertexElevation(vertex, -1); if (!allowCliffs) { if (cell.GetNeighbor(vertex)) { cell.GetNeighbor(vertex).ChangeVertexElevation(vertex.Opposite(), -1); } if (cell.GetNeighbor(vertex.Next())) { cell.GetNeighbor(vertex.Next()).ChangeVertexElevation(vertex.Previous2(), -1); } if (cell.GetNeighbor(vertex.Previous())) { cell.GetNeighbor(vertex.Previous()).ChangeVertexElevation(vertex.Next2(), -1); } } stopWatch.Reset(); stopWatch.Start(); } } else if (activeMode == EditMode.rivers) { if (Input.GetMouseButton(1)) { cell.RemoveRivers(); Explosion(cell); } else if (isDrag) { SquareCell otherCell = cell.GetNeighbor(dragDirection.Opposite()); // work with brushes if (otherCell) { otherCell.SetOutgoingRiver(dragDirection); } } } else if (activeMode == EditMode.roads) { float fracX = hitpoint.x - Mathf.Floor(hitpoint.x); float fracZ = hitpoint.z - Mathf.Floor(hitpoint.z); if (fracX > 0.25f && fracX < 0.75f || fracZ > 0.25f && fracZ < 0.75f) { GridDirection edge = squareGrid.GetEdge(hitpoint); if (Input.GetMouseButton(1)) { cell.RemoveRoad(edge); Explosion(cell); } else { cell.AddRoad(edge); } } } else if (activeMode == EditMode.water_level) { if (Input.GetMouseButton(0) && freshClick) { cell.WaterLevel++; } else if (Input.GetMouseButton(1) && freshClick) { cell.WaterLevel--; } } else if (activeMode == EditMode.building) { if (Input.GetMouseButton(0) && freshClick) { cell.UrbanLevel++; } if (Input.GetMouseButton(1) && freshClick) { cell.UrbanLevel = 0; Explosion(cell); } } else if (activeMode == EditMode.trees) { if (Input.GetMouseButton(0) && freshClick) { cell.PlantLevel++; } if (Input.GetMouseButton(1) && freshClick) { cell.PlantLevel = 0; Explosion(cell); } } else if (activeMode == EditMode.rocks) { if (Input.GetMouseButton(0) && freshClick) { cell.ScenaryObject = 1; } if (Input.GetMouseButton(1) && freshClick) { cell.ScenaryObject = 0; Explosion(cell); } } else if (activeMode == EditMode.mast) { if (Input.GetMouseButton(0) && freshClick) { cell.ScenaryObject = 2; } if (Input.GetMouseButton(1) && freshClick) { cell.ScenaryObject = 0; Explosion(cell); } } else if (activeMode == EditMode.lighthouse) { if (Input.GetMouseButton(0) && freshClick) { cell.ScenaryObject = 3; } if (Input.GetMouseButton(1) && freshClick) { cell.ScenaryObject = 0; Explosion(cell); } } else if (activeMode == EditMode.industry) { if (Input.GetMouseButton(0) && freshClick) { cell.Industry = (int)activeIndustry + 1; } if (Input.GetMouseButton(1) && freshClick) { cell.Industry = 0; Explosion(cell); } } else if (activeMode == EditMode.town) { if (cell.Town == null) { GameObject town = Instantiate(townPrefab); TownManager manager = town.GetComponent <TownManager>(); town.transform.position = GridCoordinates.ToPosition(cell.coordinates) + new Vector3(0, cell.CentreElevation * GridMetrics.elevationStep, 0); manager.Init(cell); cell.Town = manager; } } }
void AddColors(SquareCell cell, GridDirection direction) { SquareCell prevNeighbor = cell.GetNeighbor(direction.Previous()) ?? cell; SquareCell neighbor = cell.GetNeighbor(direction) ?? cell; SquareCell nextNeighbor = cell.GetNeighbor(direction.Next()) ?? cell; SquareCell next2Neighbor = cell.GetNeighbor(direction.Next2()) ?? cell; SquareCell next3Neighbor = cell.GetNeighbor(direction.Next3()) ?? cell; Color previousMix = (GetColor(prevNeighbor, cell) + cell.Color) / 2f; Color neighborMix = (GetColor(neighbor, cell) + cell.Color + GetColor(prevNeighbor, cell) + GetColor(nextNeighbor, cell)) / 4f; Color nextMix = (GetColor(nextNeighbor, cell) + cell.Color) / 2f; Color nextNeighborMix = (GetColor(nextNeighbor, cell) + cell.Color + GetColor(next2Neighbor, cell) + GetColor(next3Neighbor, cell)) / 4f; Color next2Mix = (GetColor(next3Neighbor, cell) + cell.Color) / 2f; if (cell.HasRiver) { if (cell.HasRiverThroughEdge(direction.Previous())) { terrain.AddTriangleColor(cell.Color); } if (cell.HasRiverThroughEdge(direction.Next())) { terrain.AddTriangleColor(cell.Color); } terrain.AddTriangleColor(cell.Color); terrain.AddTriangleColor(cell.Color); } else { terrain.AddTriangleColor(cell.Color); } if (cell.HasRiverThroughEdge(direction.Next())) { terrain.AddQuadColor(cell.Color, nextMix, nextMix, cell.Color); terrain.AddQuadColor(cell.Color, nextMix, nextMix, cell.Color); } else { terrain.AddQuadColor(cell.Color, nextMix, nextMix, cell.Color); } // next Edge if (cell.HasRiverThroughEdge(direction.Previous())) { terrain.AddQuadColor(cell.Color, cell.Color, previousMix, previousMix); terrain.AddQuadColor(cell.Color, cell.Color, previousMix, previousMix); } else { terrain.AddQuadColor(cell.Color, cell.Color, previousMix, previousMix); } // previous Edge if (cell.HasRiverThroughEdge(direction)) { } else { terrain.AddQuadColor(cell.Color, previousMix, neighborMix, nextMix); } // direction Corner if (cell.HasRiverThroughEdge(direction.Next2())) { } else { terrain.AddQuadColor(cell.Color, nextMix, nextNeighborMix, next2Mix); } // next Corner }
void AddHalfCell(SquareCell cell, GridDirection direction, Vector3 centre, Vector3 v0, Vector3 v1, Vector3 v2, Vector3 va, Vector3 vb, Vector3 vc, Vector3 vd, Vector3 vx, Vector3 vy, Vector3 vz) { Vector3 riverbed = centre + Vector3.up * (cell.CentreElevation + GridMetrics.streamBedElevationOffset) * GridMetrics.elevationStep; Vector3 midSolidEdgePrev = centre + GridMetrics.GetSolidEdge(direction.Previous()) + Vector3.up * (cell.CentreElevation + GridMetrics.streamBedElevationOffset) * GridMetrics.elevationStep; Vector3 midSolidEdgeNext = centre + GridMetrics.GetSolidEdge(direction.Next()) + Vector3.up * (cell.CentreElevation + GridMetrics.streamBedElevationOffset) * GridMetrics.elevationStep; SquareCell neighborPrev = cell.GetNeighbor(direction.Previous()) ?? cell; SquareCell neighborNext = cell.GetNeighbor(direction.Next()) ?? cell; Vector3 midEdgePrev = centre + GridMetrics.GetEdge(direction.Previous()) + Vector3.up * ((cell.CentreElevation + neighborPrev.CentreElevation) / 2 + GridMetrics.streamBedElevationOffset) * GridMetrics.elevationStep; Vector3 midEdgeNext = centre + GridMetrics.GetEdge(direction.Next()) + Vector3.up * ((cell.CentreElevation + neighborNext.CentreElevation) / 2 + GridMetrics.streamBedElevationOffset) * GridMetrics.elevationStep; if (cell.HasRiver) { if (cell.HasRiverThroughEdge(direction.Previous())) { terrain.AddTriangle(v0, midSolidEdgePrev, riverbed); // split tri into two tris terrain.AddTriangle(midSolidEdgePrev, v1, riverbed); } else { terrain.AddTriangle(v0, v1, riverbed); } // edge with no river if (cell.HasRiverThroughEdge(direction.Next())) { terrain.AddTriangle(v1, midSolidEdgeNext, riverbed); // split tri into two tris terrain.AddTriangle(midSolidEdgeNext, v2, riverbed); } else { terrain.AddTriangle(v1, v2, riverbed); } // edge with no river } else { terrain.AddTriangle(v0, v1, v2); } if (cell.HasRiverThroughEdge(direction.Next())) { terrain.AddQuad(v1, va, midEdgeNext, midSolidEdgeNext); terrain.AddQuad(midSolidEdgeNext, midEdgeNext, vb, v2); } else { terrain.AddQuad(v1, va, vb, v2); } // top Edge if (cell.HasRiverThroughEdge(direction.Previous())) { terrain.AddQuad(v1, midSolidEdgePrev, midEdgePrev, vd); terrain.AddQuad(midSolidEdgePrev, v0, vc, midEdgePrev); } else { terrain.AddQuad(v1, v0, vc, vd); } // left Edge if (cell.HasRiverThroughEdge(direction)) { } else { terrain.AddQuad(v1, vd, vx, va); } // direction edge if (cell.HasRiverThroughEdge(direction.Next2())) { } else { terrain.AddQuad(v2, vb, vy, vz); } // clockwise edge AddColors(cell, direction); if (cell.HasRoadThroughEdge(direction.Next())) { midEdgeNext = centre + GridMetrics.GetEdge(direction.Next()) + Vector3.up * ((int)cell.GridElevations[direction] + (int)cell.GridElevations[direction.Next2()]) / 2 * GridMetrics.elevationStep; midSolidEdgeNext = centre + GridMetrics.GetSolidEdge(direction.Next()) + Vector3.up * ((int)cell.GridElevations[direction] + (int)cell.GridElevations[direction.Next2()]) / 2 * GridMetrics.elevationStep; TriangulateRoadSegment(v1, midSolidEdgeNext, v2, va, midEdgeNext, vb); } if (cell.HasRoadThroughEdge(direction.Previous())) { midEdgePrev = centre + GridMetrics.GetEdge(direction.Previous()) + Vector3.up * ((int)cell.GridElevations[direction] + (int)cell.GridElevations[direction.Previous2()]) / 2 * GridMetrics.elevationStep; midSolidEdgePrev = centre + GridMetrics.GetSolidEdge(direction.Previous()) + Vector3.up * ((int)cell.GridElevations[direction] + (int)cell.GridElevations[direction.Previous2()]) / 2 * GridMetrics.elevationStep; TriangulateRoadSegment(v0, midSolidEdgePrev, v1, vc, midEdgePrev, vd); } }
float GetStraightGrad(GridElevations el, GridDirection direction) { return((float)el[direction.Previous()] - (float)el[direction.Next()]); }
Vector3 GetDoubleVertexBlendElevation(GridElevations el, GridDirection direction) { float delta = (GetStraightGrad(el, direction.Previous()) - GetStraightGrad(el, direction.Next())) * GridMetrics.blendFactor / 2; return(Vector3.up * GridMetrics.elevationStep * ((float)el[direction] + delta)); }