/// <summary> /// Creates a heightmap of resolution <see cref="HeightmapResolution"/> asynchronously. /// If a <see cref="Heightmap"/> of the same resolution or higher has already been /// created, this method does nothing. /// A heightmap is 2D array of floats that represents the Y values (or heights) /// of to-be created vertices in 3D space. /// </summary> /// <param name="onComplete">Called when the heightmap has been created</param> public void CreateHeightmapAsync(Action onComplete) { ThreadPool.QueueUserWorkItem(d => { //Worker thread CreateHeightmap(); MTDispatch.Instance().Enqueue(onComplete); }); }
/// <summary> /// Fully constructs this Tile. This includes creating a Mesh, painting /// the terrain, and adding details (grass, objects, etc.) /// /// By default, calculating heights is done off of the main thread but /// can be disabled. /// </summary> /// <param name="onComplete">Called after all calculations have completed. /// <see cref="onComplete"/>Can be null if the result is not needed.</param> /// <param name="remapMin">Optionally linear transform the heightmap from [min, max] to [0, 1]</param> /// <param name="remapMax">Optionally linear transform the heightmap from [min, max] to [0, 1]</param> public void Generate(Action onComplete, float remapMin = 0f, float remapMax = 1f) { //Ensure MTD is instantiated MTDispatch.Instance(); if (TerraConfig.IsInEditMode) { GenerateEditor(remapMin, remapMax); onComplete(); } else { StartCoroutine(GenerateCoroutine(onComplete, remapMin, remapMax)); } }
/// <summary> /// Creates a heightmap of resolution <see cref="HeightmapResolution"/> asynchronously. /// If a <see cref="Heightmap"/> of the same resolution or higher has already been /// created, this method does nothing. /// A heightmap is 2D array of floats that represents the Y values (or heights) /// of to-be created vertices in 3D space. /// </summary> /// <param name="remapMin">Optionally linear transform the heightmap from [min, max] to [0, 1]</param> /// <param name="remapMax">Optionally linear transform the heightmap from [min, max] to [0, 1]</param> /// <param name="onComplete">Called when the heightmap has been created</param> public void CalculateHeightmapAsync(float remapMin = 0f, float remapMax = 1f, Action onComplete = null) { _lastGeneratedLodLevel = _tile.GetLodLevel(); Lod = _lastGeneratedLodLevel; bool shouldProfile = TerraConfig.Instance.EditorState.ShowDebugMessages; Stopwatch wsw = null; if (shouldProfile) { wsw = new Stopwatch(); wsw.Start(); } TerraConfig.Instance.Worker.Enqueue(() => { Stopwatch sw = null; if (shouldProfile) { sw = new Stopwatch(); Profiler.BeginThreadProfiling("Heightmap Workers", "Tile " + _tile.GridPosition); sw.Start(); } CalculateHeightmap(null, remapMin, remapMax); if (shouldProfile) { sw.Stop(); TerraConfig.Log("Tile " + _tile.GridPosition + " heightmap time: " + sw.ElapsedMilliseconds); Profiler.EndThreadProfiling(); } }, () => { if (shouldProfile) { wsw.Stop(); MTDispatch.Instance().Enqueue(() => { TerraConfig.Log("CalculateHM worker time elapsed " + wsw.ElapsedMilliseconds); onComplete(); }); } }); }
/// <summary> /// Adds a tile at the passed position asynchronously /// </summary> /// <param name="pos">Position to add tile at</param> public IEnumerator AddTileAsync(Vector2 pos) { TerrainTile tile = new GameObject("Tile: " + pos).AddComponent <TerrainTile>(); queuedTiles++; if (Settings.UseMultithreading) { ThreadData data = new ThreadData(); data.tile = tile; data.gen = Settings.Graph.GetEndGenerator(); ThreadPool.QueueUserWorkItem(new WaitCallback((d) => { //GetValue is not thread safe and must be locked lock (pollLock) { if (d is ThreadData) { ThreadData tData = (ThreadData)d; TerrainTile.MeshData md = tData.tile.CreateRawMesh(pos, tData.gen); MTDispatch.Instance().Enqueue(() => { //Main Thread tData.tile.RenderRawMeshData(md); if (Settings.UseCustomMaterial) { tile.ApplyCustomMaterial(); } else { tile.Details.ApplySplatmap(); } tile.UpdatePosition(pos); Cache.AddActiveTile(tile); queuedTiles--; }); } } }), data); } else { yield return(new WaitForSecondsRealtime(ADD_TILE_DELAY)); tile.CreateMesh(pos, false); yield return(null); if (Settings.UseCustomMaterial) { tile.ApplyCustomMaterial(); } else { tile.Details.ApplySplatmap(); } tile.gameObject.GetComponent <MeshRenderer>().enabled = true; Cache.AddActiveTile(tile); queuedTiles--; } }