void TriangulateWithRiver( GridDirection direction, SquareCell cell, Vector3 centre, Vector3 v0, Vector3 v1, Vector3 v2, Vector3 v3, float v ) { GridDirection flowDirection; bool reversed = cell.HasIncomingRiver[(int)direction]; if (cell.HasOutgoingRiver[(int)direction]) { flowDirection = direction; } else if (reversed) { flowDirection = direction.Opposite(); } else { if (cell.HasIncomingRiver[(int)direction.Next2()] && cell.HasOutgoingRiver[(int)direction.Previous2()]) { flowDirection = direction.Previous2(); } else if (cell.HasOutgoingRiver[(int)direction.Next2()] && cell.HasIncomingRiver[(int)direction.Previous2()]) { flowDirection = direction.Next2(); } else { flowDirection = direction.Opposite(); } } TriangulateRiverTri(centre, v0, v3, cell.RiverSurfaceY, reversed, direction, flowDirection); SquareCell neighbor = cell.GetNeighbor(direction); if (neighbor && cell.HasRiverThroughEdge(direction)) { TriangulateRiverQuad(v3, v0, v1, v2, cell.RiverSurfaceY, neighbor.RiverSurfaceY, 0.8f, reversed); } }
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); } }
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); } }