diff --git a/Runtime/TerrainBuilder.cs b/Runtime/TerrainBuilder.cs index 4c16d2737761ffbf1eb450d2923300add0681cc9..403e4a058c868397d62eb5cb829ec425b473c8b1 100644 --- a/Runtime/TerrainBuilder.cs +++ b/Runtime/TerrainBuilder.cs @@ -21,10 +21,10 @@ namespace Wander [ReadOnly] public int nTilesWide; [ReadOnly] public int nTilesHigh; [ReadOnly] public Dictionary<uint, byte> pixelToLayerIndex; - [ReadOnly] public List<TerrainTile> tiles = new List<TerrainTile>(); + public Vector2 originWGS84 = new Vector2(51.985365f, 5.664941f); // Copy directly from Google maps. This is Forum on Campus WUR. - public Vector2Int numTiles = new Vector2Int(1,1); + public int numRings = 1; public int controlResolution = 8192; public int heightMapResolution = 1024; public bool loadHeight = true; @@ -32,17 +32,26 @@ namespace Wander public int zoom = 11; public int numDLRetries = 5; public bool runOnStart = false; + public int maxDownloads = 32; + public string prefix = "Terrain"; public Material terrainMat = null; public List<TerrainLayer2> layers; + + + private List<TerrainTile> tiles = new List<TerrainTile>(); internal void CancelAndClean() { - tiles.ForEach( t => t.CancelAndClean() ); + tiles.ForEach( t => + { + if (t!=null) t.CancelAndClean(); + } ); tiles = new List<TerrainTile>(); } internal void Build() { + CancelAndClean(); CalcPreliminaries(); CreatePixelToLayerIndex(); CreateTerrain(); @@ -94,24 +103,50 @@ namespace Wander } } + Terrain GetNeighbour( string prefix, int x, int y ) + { + var neighbour = GameObject.Find( $"{prefix}_{x}_{y-1}" ); + if (neighbour != null) + return neighbour.GetComponent<Terrain>(); + return null; + } + + void BuildTile( double rdX, double rdY, int x, int y ) + { + GameObject go = new GameObject($"{prefix}_{x}_{y}"); + var tile = go.AddComponent<TerrainTile>(); + tiles.Add( tile ); + tile.builder = this; + tile.tileOrigin = RDUtils.RD2Tile( new Vector2( (float)rdX+adjustedSize.x * x, (float)rdY+adjustedSize.z * y ), zoom ); + tile.rdOrigin = RDUtils.Tile2RD( tile.tileOrigin, zoom ); + tile.terrainOffset = new Vector2Int( x, y ); + tile.Build(); + } + void CreateTerrain() { RDUtils.GPS2RD( originWGS84.x, originWGS84.y, out double rdX, out double rdY ); - for ( int y = -numTiles.y/2; y <= numTiles.y/2; y++ ) + BuildTile( rdX, rdY, 0, 0 ); + for (int c = 1;c <= numRings;c++) { - for (int x = -numTiles.y/2;x <= numTiles.x/2;x++) - { - - GameObject go = new GameObject($"GeneratedTerrain_{x}_{y}"); - var tile = go.AddComponent<TerrainTile>(); - tiles.Add( tile ); - tile.builder = this; - tile.tileOrigin = RDUtils.RD2Tile( new Vector2( (float)rdX+adjustedSize.x * x, (float)rdY+adjustedSize.z * y ), zoom ); - tile.rdOrigin = RDUtils.Tile2RD( tile.tileOrigin, zoom ); - tile.terrainOffset = new Vector2Int( x, y ); - tile.Build(); - } + for (int y2 = -c; y2 <= c; y2++) BuildTile( rdX, rdY, -c, y2 ); + for (int y2 = -c; y2 <= c; y2++) BuildTile( rdX, rdY, c, y2 ); + for (int x2 = -c+1; x2 <= c-1; x2++) BuildTile( rdX, rdY, x2, c ); + for (int x2 = -c+1; x2 <= c-1; x2++) BuildTile( rdX, rdY, x2, -c ); } + GameObject terrainRoot = new GameObject("TerrainRoot"); + tiles.ForEach( t => + { + var ofs = t.GetComponent<TerrainTile>().terrainOffset; + int x = ofs.x; + int y = ofs.y; + var top = GetNeighbour( prefix, x, y+1 ); + var bottom = GetNeighbour( prefix, x, y-1 ); + var left = GetNeighbour( prefix, x-1, y ); + var right = GetNeighbour( prefix, x+1, y ); + t.GetComponent<Terrain>().SetNeighbors( left, top, right, bottom ); + t.transform.SetParent( terrainRoot.transform, true ); + } ); } } @@ -124,7 +159,8 @@ namespace Wander { TerrainBuilder builder = (TerrainBuilder)target; - EditorGUILayout.HelpBox( "Look up a location in Google maps and copy GPS coordinates in Origin WGS84 X, Y.", MessageType.Info, true ); + EditorGUILayout.HelpBox( "Look up a location in Google maps and copy GPS coordinates in Origin WGS84 X, Y", MessageType.Info, true ); + EditorGUILayout.HelpBox( "Press CTRL-S when done, otherwise result appears wrong.", MessageType.Warning, true ); GUILayout.BeginHorizontal(); { diff --git a/Runtime/TerrainTile.cs b/Runtime/TerrainTile.cs index c35a9c99b8840bb3e903f5a56528eec8df59e285..ad097c3f77167543fee4ef6561888192505f6906 100644 --- a/Runtime/TerrainTile.cs +++ b/Runtime/TerrainTile.cs @@ -9,8 +9,9 @@ using UnityEngine.Networking; namespace Wander { - struct MapTile + class MapTile { + internal bool started; internal int numRetries; internal int deltaTileX; // Relative tile index with respect to origin up left corner. So, 0, -1, etc. internal int deltaTileY; @@ -33,7 +34,7 @@ namespace Wander [ReadOnly] public TerrainBuilder builder; [ReadOnly] public TerrainData terrainData; [ReadOnly] public Terrain terrain; - [ReadOnly] public Vector2Int terrainOffset = new Vector2Int(0, 0); + [ReadOnly] public Vector2Int terrainOffset; private List<MapTile> requests; private byte[] controlData; @@ -96,6 +97,7 @@ namespace Wander } } + // If want height and height is finished. if ( builder.loadHeight ) { if (normalizeHeightTask == null && asyncHeightHandle.IsFinished() && asyncHeightHandle.Valid ) @@ -143,6 +145,8 @@ namespace Wander gameObject.AddComponent<TerrainCollider>().terrainData = terrainData; gameObject.transform.position = new Vector3( terrainOffset.x*builder.adjustedSize.x, 0, terrainOffset.y*builder.adjustedSize.z ); + + } internal void SyncLayersToMaterial() @@ -244,7 +248,7 @@ namespace Wander int tileY = -y + tileOrigin.y; string url = GetMapUrl(tileX, tileY, builder.zoom); UnityWebRequest www = UnityWebRequestTexture.GetTexture(url); - www.SendWebRequest(); + //www.SendWebRequest(); MapTile td = new MapTile(); td.www = www; td.deltaTileX = x; @@ -267,10 +271,16 @@ namespace Wander if (requests==null) return; + int numActive = 0; for (int i = 0;i < requests.Count;i++) { var tile = requests[i]; var www = tile.www; + if (!tile.started) + { + tile.started = true; + www.SendWebRequest(); + } if (www.isDone) { if (www.result != UnityWebRequest.Result.Success) @@ -301,6 +311,8 @@ namespace Wander i--; } } + if (++numActive == builder.maxDownloads) + break; } } @@ -317,8 +329,8 @@ namespace Wander float[,] CreateHeightMap( HeightData heightData ) { - var heights = new float[builder.heightMapResolution, builder.heightMapResolution]; - int height = heightData.height; + var heights = new float[builder.heightMapResolution+1, builder.heightMapResolution+1]; + int height = heightData.height; for (int y = 0;y<height;y++) { if (state== State.None) @@ -332,6 +344,11 @@ namespace Wander heights[height-y-1, x] = absHeight; } } + for (int y = 0;y <height;y++) + heights[y, heightData.width] = heights[y, heightData.width-1]; + for (int x = 0;x <heightData.width;x++) + heights[height, x] = heights[height-1, x]; + heights[height, heightData.width] = heights[height, heightData.width-1]; return heights; } diff --git a/TerrainBuilder.prefab b/TerrainBuilder.prefab index 3cb4f2edc3c57539b720d322a9c4502b7e3c1c29..6f1f2464556d8f425e31ede0b5265f76f2b43e83 100644 --- a/TerrainBuilder.prefab +++ b/TerrainBuilder.prefab @@ -44,24 +44,21 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: cd43ca4104daaec4a9d3a76a67972b44, type: 3} m_Name: m_EditorClassIdentifier: - rdOrigin: {x: 170214.08, y: 440729.9} - tileOrigin: {x: 33900, y: 34424} adjustedSize: {x: 215.04, y: 200, z: 215.04} tileSize: 13.44 tilePixelSize: 256 nTilesWide: 16 nTilesHigh: 16 - terrainData: {fileID: 0} - terrain: {fileID: 0} originWGS84: {x: 51.954845, y: 5.608702} - terrainOffset: {x: 0, y: 0} + numRings: 1 controlResolution: 4096 heightMapResolution: 256 loadHeight: 1 terrainHeight: 200 zoom: 16 - numDLRetries: 5 + numDLRetries: 10 runOnStart: 0 + maxDownloads: 16 terrainMat: {fileID: 2100000, guid: 85a6a12772aee984dac2ab9fa88f3370, type: 2} layers: - layer: {fileID: 8574412962073106934, guid: f963e57374ac1ff44b017a60c3f8ad82, type: 2}