public static GridElevations GetVertexHeightsFromHeightmap(Vector3 position, Texture2D heightmap) { int v0 = GetTerrainHeightFromMap(position + GridMetrics.GetEdge(GridDirection.SW), heightmap); int v1 = GetTerrainHeightFromMap(position + GridMetrics.GetEdge(GridDirection.NW), heightmap); int v2 = GetTerrainHeightFromMap(position + GridMetrics.GetEdge(GridDirection.NE), heightmap); int v3 = GetTerrainHeightFromMap(position + GridMetrics.GetEdge(GridDirection.SE), heightmap); return(new GridElevations(v0, v1, v2, v3)); }
public static GridElevations GetVertexHeights(Vector3 position, int seed) { int v0 = GetTerrainHeightFromPerlin(position + GridMetrics.GetEdge(GridDirection.SW), seed); int v1 = GetTerrainHeightFromPerlin(position + GridMetrics.GetEdge(GridDirection.NW), seed); int v2 = GetTerrainHeightFromPerlin(position + GridMetrics.GetEdge(GridDirection.NE), seed); int v3 = GetTerrainHeightFromPerlin(position + GridMetrics.GetEdge(GridDirection.SE), seed); return(new GridElevations(v0, v1, v2, v3)); }
void MoveEditorPointer(SquareCell cell, GridDirection vertex) { if (activeMode == EditMode.color || activeMode == EditMode.rivers || activeMode == EditMode.roads || activeMode == EditMode.water_level || activeMode == EditMode.building || activeMode == EditMode.trees || activeMode == EditMode.rocks || activeMode == EditMode.mast || activeMode == EditMode.lighthouse || activeMode == EditMode.industry || activeMode == EditMode.town) { pointerLocation = GridCoordinates.ToPosition(cell.coordinates) + Vector3.up * cell.CentreElevation * GridMetrics.elevationStep; } if (activeMode == EditMode.elevation) { pointerLocation = GridCoordinates.ToPosition(cell.coordinates) + GridMetrics.GetEdge(vertex) + Vector3.up * (int)cell.GridElevations[vertex] * GridMetrics.elevationStep; } }
void AddWaterForSquare(SquareCell cell, Vector3 centre) { centre.y = cell.WaterSurfaceY; Vector3 c0 = centre + GridMetrics.GetEdge(GridDirection.SW); Vector3 c1 = centre + GridMetrics.GetEdge(GridDirection.NW); Vector3 c2 = centre + GridMetrics.GetEdge(GridDirection.NE); Vector3 c3 = centre + GridMetrics.GetEdge(GridDirection.SE); if (cell.IsFullyUnderwater) { water.AddQuad(c0, c1, c2, c3); } else if (cell.IsPartUnderwater) { float v0 = 0f, v1 = 0f, v2 = 0f, v3 = 0f; if (cell.GetNeighbor(GridDirection.N) && !cell.GetNeighbor(GridDirection.N).IsUnderwater) { v1 = 1f; v2 = 1f; } if (cell.GetNeighbor(GridDirection.NE) && !cell.GetNeighbor(GridDirection.NE).IsUnderwater) { v2 = 1f; } if (cell.GetNeighbor(GridDirection.E) && !cell.GetNeighbor(GridDirection.E).IsUnderwater) { v2 = 1f; v3 = 1f; } if (cell.GetNeighbor(GridDirection.SE) && !cell.GetNeighbor(GridDirection.SE).IsUnderwater) { v3 = 1f; } if (cell.GetNeighbor(GridDirection.S) && !cell.GetNeighbor(GridDirection.S).IsUnderwater) { v3 = 1f; v0 = 1f; } if (cell.GetNeighbor(GridDirection.SW) && !cell.GetNeighbor(GridDirection.SW).IsUnderwater) { v0 = 1f; } if (cell.GetNeighbor(GridDirection.W) && !cell.GetNeighbor(GridDirection.W).IsUnderwater) { v0 = 1f; v1 = 1f; } if (cell.GetNeighbor(GridDirection.NW) && !cell.GetNeighbor(GridDirection.NW).IsUnderwater) { v1 = 1f; } waterShore.AddQuad(c0, c1, c2, c3); waterShore.AddQuadV(v0, v1, v2, v3); } }
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); } } }
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); } }
void AddMeshForSquare(SquareCell cell) { Vector3 centre = cell.transform.localPosition; Vector3 verticleCentre = centre + Vector3.up * cell.CentreElevation * GridMetrics.elevationStep; Vector3 vb0 = centre + GridMetrics.GetEdge(GridDirection.SW); Vector3 vb1 = centre + GridMetrics.GetEdge(GridDirection.NW); Vector3 vb2 = centre + GridMetrics.GetEdge(GridDirection.NE); Vector3 vb3 = centre + GridMetrics.GetEdge(GridDirection.SE); vb0 = vb0 + Vector3.up * (cell.GridElevations.Y0) * GridMetrics.elevationStep; vb1 = vb1 + Vector3.up * (cell.GridElevations.Y1) * GridMetrics.elevationStep; vb2 = vb2 + Vector3.up * (cell.GridElevations.Y2) * GridMetrics.elevationStep; vb3 = vb3 + Vector3.up * (cell.GridElevations.Y3) * GridMetrics.elevationStep; Vector3 vs0 = centre + GridMetrics.GetSolidEdge(GridDirection.SW); Vector3 vs1 = centre + GridMetrics.GetSolidEdge(GridDirection.NW); Vector3 vs2 = centre + GridMetrics.GetSolidEdge(GridDirection.NE); Vector3 vs3 = centre + GridMetrics.GetSolidEdge(GridDirection.SE); Vector3 bridgeW = GridMetrics.GetBridge(GridDirection.W); Vector3 bridgeN = GridMetrics.GetBridge(GridDirection.N); Vector3 bridgeE = GridMetrics.GetBridge(GridDirection.E); Vector3 bridgeS = GridMetrics.GetBridge(GridDirection.S); Vector3 vS0 = vs0 + bridgeS + GetVertexBlendElevation(cell.GridElevations, GridDirection.SW, GridDirection.S); Vector3 vW0 = vs0 + bridgeW + GetVertexBlendElevation(cell.GridElevations, GridDirection.SW, GridDirection.W); Vector3 vN1 = vs1 + bridgeN + GetVertexBlendElevation(cell.GridElevations, GridDirection.NW, GridDirection.N); Vector3 vW1 = vs1 + bridgeW + GetVertexBlendElevation(cell.GridElevations, GridDirection.NW, GridDirection.W); Vector3 vN2 = vs2 + bridgeN + GetVertexBlendElevation(cell.GridElevations, GridDirection.NE, GridDirection.N); Vector3 vE2 = vs2 + bridgeE + GetVertexBlendElevation(cell.GridElevations, GridDirection.NE, GridDirection.E); Vector3 vE3 = vs3 + bridgeE + GetVertexBlendElevation(cell.GridElevations, GridDirection.SE, GridDirection.E); Vector3 vS3 = vs3 + bridgeS + GetVertexBlendElevation(cell.GridElevations, GridDirection.SE, GridDirection.S); if (cell.GridElevations.Y0 == cell.GridElevations.Y2) // keep diagonals level { vs0 += Vector3.up * (cell.GridElevations.Y0) * GridMetrics.elevationStep; vs1 += GetDoubleVertexBlendElevation(cell.GridElevations, GridDirection.NW); vs2 += Vector3.up * (cell.GridElevations.Y2) * GridMetrics.elevationStep; vs3 += GetDoubleVertexBlendElevation(cell.GridElevations, GridDirection.SE); } else if (cell.GridElevations.Y1 == cell.GridElevations.Y3) { vs0 += GetDoubleVertexBlendElevation(cell.GridElevations, GridDirection.SW); vs1 += Vector3.up * (cell.GridElevations.Y1) * GridMetrics.elevationStep; vs2 += GetDoubleVertexBlendElevation(cell.GridElevations, GridDirection.NE); vs3 += Vector3.up * (cell.GridElevations.Y3) * GridMetrics.elevationStep; } else { vs0 += GetDoubleVertexBlendElevation(cell.GridElevations, GridDirection.SW); vs1 += GetDoubleVertexBlendElevation(cell.GridElevations, GridDirection.NW); vs2 += GetDoubleVertexBlendElevation(cell.GridElevations, GridDirection.NE); vs3 += GetDoubleVertexBlendElevation(cell.GridElevations, GridDirection.SE); } // Works out which diagonal to add if (cell.GridElevations.Y0 == cell.GridElevations.Y2 || Mathf.Abs(cell.GridElevations.Y0 - cell.GridElevations.Y2) < Mathf.Abs(cell.GridElevations.Y1 - cell.GridElevations.Y3)) // sets direction of the triangle pairs in the quad { AddHalfCell(cell, GridDirection.NW, centre, vs0, vs1, vs2, vN1, vN2, vW0, vW1, vb1, vb2, vE2); AddHalfCell(cell, GridDirection.SE, centre, vs2, vs3, vs0, vS3, vS0, vE2, vE3, vb3, vb0, vW0); } else { AddHalfCell(cell, GridDirection.SW, centre, vs3, vs0, vs1, vW0, vW1, vS3, vS0, vb0, vb1, vN1); AddHalfCell(cell, GridDirection.NE, centre, vs1, vs2, vs3, vE2, vE3, vN1, vN2, vb2, vb3, vS3); } if (cell.HasRoads) { TriangulateRoadCentre(cell, verticleCentre, vs0, vs1, vs2, vs3); } if (cell.HasRiver) { if (cell.HasRiverThroughEdge(GridDirection.N)) { TriangulateWithRiver(GridDirection.N, cell, centre, vs1, vb1, vb2, vs2, 0f); } else { TriangulateWithRiver(GridDirection.N, cell, centre, vs1, vb1, vb2, vs2, 0f); } if (cell.HasRiverThroughEdge(GridDirection.E)) { TriangulateWithRiver(GridDirection.E, cell, centre, vs2, vb2, vb3, vs3, 0.5f); } else { TriangulateWithRiver(GridDirection.E, cell, centre, vs2, vb2, vb3, vs3, 0.5f); } if (cell.HasRiverThroughEdge(GridDirection.S)) { TriangulateWithRiver(GridDirection.S, cell, centre, vs3, vb3, vb0, vs0, 1f); } else { TriangulateWithRiver(GridDirection.S, cell, centre, vs3, vb3, vb0, vs0, 1f); } if (cell.HasRiverThroughEdge(GridDirection.W)) { TriangulateWithRiver(GridDirection.W, cell, centre, vs0, vb0, vb1, vs1, 0.5f); } else { TriangulateWithRiver(GridDirection.W, cell, centre, vs0, vb0, vb1, vs1, 0.5f); } } if (cell.IsUnderwater) { AddWaterForSquare(cell, centre); } if (!cell.IsUnderwater && !cell.HasRoads) { features.AddFeature(cell, verticleCentre); } }