| using System; |
| using System; |
| using System.Collections.Generic; |
| using System.Collections.Generic; |
| using System.Diagnostics; |
| using System.Diagnostics; |
| using System.Threading; |
| using System.Threading; |
| using UnityEngine; |
| using UnityEngine; |
| |
| |
| public class HeightmapBuilder |
| public class HeightmapBuilder |
| { |
| { |
| public static HeightmapBuilder instance |
| public static HeightmapBuilder instance |
| { |
| { |
| get |
| get |
| { |
| { |
| if (HeightmapBuilder.hasBeenDisposed) |
| if (HeightmapBuilder.hasBeenDisposed) |
| { |
| { |
| ZLog.LogWarning("Tried to get instance of heightmap builder after heightmap builder has been disposed!"); |
| ZLog.LogWarning("Tried to get instance of heightmap builder after heightmap builder has been disposed!"); |
| return null; |
| return null; |
| } |
| } |
| if (HeightmapBuilder.m_instance == null) |
| if (HeightmapBuilder.m_instance == null) |
| { |
| { |
| HeightmapBuilder.m_instance = new HeightmapBuilder(); |
| HeightmapBuilder.m_instance = new HeightmapBuilder(); |
| } |
| } |
| return HeightmapBuilder.m_instance; |
| return HeightmapBuilder.m_instance; |
| } |
| } |
| } |
| } |
| |
| |
| private HeightmapBuilder() |
| private HeightmapBuilder() |
| { |
| { |
| HeightmapBuilder.m_instance = this; |
| HeightmapBuilder.m_instance = this; |
| this.m_builder = new Thread(new ThreadStart(this.BuildThread)); |
| this.m_builder = new Thread(new ThreadStart(this.BuildThread)); |
| this.m_builder.Start(); |
| this.m_builder.Start(); |
| } |
| } |
| |
| |
| public void Dispose() |
| public void Dispose() |
| { |
| { |
| if (HeightmapBuilder.hasBeenDisposed) |
| if (HeightmapBuilder.hasBeenDisposed) |
| { |
| { |
| return; |
| return; |
| } |
| } |
| HeightmapBuilder.hasBeenDisposed = true; |
| HeightmapBuilder.hasBeenDisposed = true; |
| if (this.m_builder != null) |
| if (this.m_builder != null) |
| { |
| { |
| ZLog.Log("Stopping build thread"); |
| ZLog.Log("Stopping build thread"); |
| this.m_lock.WaitOne(); |
| this.m_lock.WaitOne(); |
| this.m_stop = true; |
| this.m_stop = true; |
| this.m_lock.ReleaseMutex(); |
| this.m_lock.ReleaseMutex(); |
| this.m_builder.Join(); |
| this.m_builder.Join(); |
| this.m_builder = null; |
| this.m_builder = null; |
| } |
| } |
| if (this.m_lock != null) |
| if (this.m_lock != null) |
| { |
| { |
| this.m_lock.Close(); |
| this.m_lock.Close(); |
| this.m_lock = null; |
| this.m_lock = null; |
| } |
| } |
| } |
| } |
| |
| |
| private void BuildThread() |
| private void BuildThread() |
| { |
| { |
| ZLog.Log("Builder started"); |
| ZLog.Log("Builder started"); |
| bool flag = false; |
| bool flag = false; |
| while (!flag) |
| while (!flag) |
| { |
| { |
| this.m_lock.WaitOne(); |
| this.m_lock.WaitOne(); |
| bool flag2 = this.m_toBuild.Count > 0; |
| bool flag2 = this.m_toBuild.Count > 0; |
| this.m_lock.ReleaseMutex(); |
| this.m_lock.ReleaseMutex(); |
| if (flag2) |
| if (flag2) |
| { |
| { |
| this.m_lock.WaitOne(); |
| this.m_lock.WaitOne(); |
| HeightmapBuilder.HMBuildData hmbuildData = this.m_toBuild[0]; |
| HeightmapBuilder.HMBuildData hmbuildData = this.m_toBuild[0]; |
| this.m_lock.ReleaseMutex(); |
| this.m_lock.ReleaseMutex(); |
| new Stopwatch().Start(); |
| new Stopwatch().Start(); |
| this.Build(hmbuildData); |
| this.Build(hmbuildData); |
| this.m_lock.WaitOne(); |
| this.m_lock.WaitOne(); |
| this.m_toBuild.Remove(hmbuildData); |
| this.m_toBuild.Remove(hmbuildData); |
| this.m_ready.Add(hmbuildData); |
| this.m_ready.Add(hmbuildData); |
| while (this.m_ready.Count > 16) |
| while (this.m_ready.Count > 16) |
| { |
| { |
| this.m_ready.RemoveAt(0); |
| this.m_ready.RemoveAt(0); |
| } |
| } |
| this.m_lock.ReleaseMutex(); |
| this.m_lock.ReleaseMutex(); |
| } |
| } |
| Thread.Sleep(10); |
| Thread.Sleep(10); |
| this.m_lock.WaitOne(); |
| this.m_lock.WaitOne(); |
| flag = this.m_stop; |
| flag = this.m_stop; |
| this.m_lock.ReleaseMutex(); |
| this.m_lock.ReleaseMutex(); |
| } |
| } |
| } |
| } |
| |
| |
| private void Build(HeightmapBuilder.HMBuildData data) |
| private void Build(HeightmapBuilder.HMBuildData data) |
| { |
| { |
| int num = data.m_width + 1; |
| int num = data.m_width + 1; |
| int num2 = num * num; |
| int num2 = num * num; |
| Vector3 vector = data.m_center + new Vector3((float)data.m_width * data.m_scale * -0.5f, 0f, (float)data.m_width * data.m_scale * -0.5f); |
| Vector3 vector = data.m_center + new Vector3((float)data.m_width * data.m_scale * -0.5f, 0f, (float)data.m_width * data.m_scale * -0.5f); |
| WorldGenerator worldGen = data.m_worldGen; |
| WorldGenerator worldGen = data.m_worldGen; |
| data.m_cornerBiomes = new Heightmap.Biome[4]; |
| data.m_cornerBiomes = new Heightmap.Biome[4]; |
| . | data.m_cornerBiomes[0] = worldGen.GetBiome(vector.x, vector.z); |
| data.m_cornerBiomes[0] = worldGen.GetBiome(vector.x, vector.z, 0.02f, false); |
| data.m_cornerBiomes[1] = worldGen.GetBiome((float)((double)vector.x + (double)data.m_width * (double)data.m_scale), vector.z); |
| data.m_cornerBiomes[1] = worldGen.GetBiome((float)((double)vector.x + (double)data.m_width * (double)data.m_scale), vector.z, 0.02f, false); |
| data.m_cornerBiomes[2] = worldGen.GetBiome(vector.x, (float)((double)vector.z + (double)data.m_width * (double)data.m_scale)); |
| data.m_cornerBiomes[2] = worldGen.GetBiome(vector.x, (float)((double)vector.z + (double)data.m_width * (double)data.m_scale), 0.02f, false); |
| data.m_cornerBiomes[3] = worldGen.GetBiome((float)((double)vector.x + (double)data.m_width * (double)data.m_scale), (float)((double)vector.z + (double)data.m_width * (double)data.m_scale)); |
| data.m_cornerBiomes[3] = worldGen.GetBiome((float)((double)vector.x + (double)data.m_width * (double)data.m_scale), (float)((double)vector.z + (double)data.m_width * (double)data.m_scale), 0.02f, false); |
| Heightmap.Biome biome = data.m_cornerBiomes[0]; |
| Heightmap.Biome biome = data.m_cornerBiomes[0]; |
| Heightmap.Biome biome2 = data.m_cornerBiomes[1]; |
| Heightmap.Biome biome2 = data.m_cornerBiomes[1]; |
| Heightmap.Biome biome3 = data.m_cornerBiomes[2]; |
| Heightmap.Biome biome3 = data.m_cornerBiomes[2]; |
| Heightmap.Biome biome4 = data.m_cornerBiomes[3]; |
| Heightmap.Biome biome4 = data.m_cornerBiomes[3]; |
| data.m_baseHeights = new List<float>(num * num); |
| data.m_baseHeights = new List<float>(num * num); |
| for (int i = 0; i < num2; i++) |
| for (int i = 0; i < num2; i++) |
| { |
| { |
| data.m_baseHeights.Add(0f); |
| data.m_baseHeights.Add(0f); |
| } |
| } |
| . | int num3 = data.m_width * data.m_width; |
| int num3 = num * num; |
| data.m_baseMask = new Color[num3]; |
| data.m_baseMask = new Color[num3]; |
| for (int j = 0; j < num3; j++) |
| for (int j = 0; j < num3; j++) |
| { |
| { |
| data.m_baseMask[j] = new Color(0f, 0f, 0f, 0f); |
| data.m_baseMask[j] = new Color(0f, 0f, 0f, 0f); |
| } |
| } |
| for (int k = 0; k < num; k++) |
| for (int k = 0; k < num; k++) |
| { |
| { |
| float num4 = (float)((double)vector.z + (double)k * (double)data.m_scale); |
| float num4 = (float)((double)vector.z + (double)k * (double)data.m_scale); |
| float num5 = DUtils.SmoothStep(0f, 1f, (float)((double)k / (double)data.m_width)); |
| float num5 = DUtils.SmoothStep(0f, 1f, (float)((double)k / (double)data.m_width)); |
| for (int l = 0; l < num; l++) |
| for (int l = 0; l < num; l++) |
| { |
| { |
| float num6 = (float)((double)vector.x + (double)l * (double)data.m_scale); |
| float num6 = (float)((double)vector.x + (double)l * (double)data.m_scale); |
| float num7 = DUtils.SmoothStep(0f, 1f, (float)((double)l / (double)data.m_width)); |
| float num7 = DUtils.SmoothStep(0f, 1f, (float)((double)l / (double)data.m_width)); |
| Color color = Color.black; |
| Color color = Color.black; |
| float num8; |
| float num8; |
| if (data.m_distantLod) |
| if (data.m_distantLod) |
| { |
| { |
| . | Heightmap.Biome biome5 = worldGen.GetBiome(num6, num4); |
| Heightmap.Biome biome5 = worldGen.GetBiome(num6, num4, 0.02f, false); |
| num8 = worldGen.GetBiomeHeight(biome5, num6, num4, out color, false); |
| num8 = worldGen.GetBiomeHeight(biome5, num6, num4, out color, false); |
| } |
| } |
| else if (biome3 == biome && biome2 == biome && biome4 == biome) |
| else if (biome3 == biome && biome2 == biome && biome4 == biome) |
| { |
| { |
| num8 = worldGen.GetBiomeHeight(biome, num6, num4, out color, false); |
| num8 = worldGen.GetBiomeHeight(biome, num6, num4, out color, false); |
| } |
| } |
| else |
| else |
| { |
| { |
| Color[] array = new Color[4]; |
| Color[] array = new Color[4]; |
| float biomeHeight = worldGen.GetBiomeHeight(biome, num6, num4, out array[0], false); |
| float biomeHeight = worldGen.GetBiomeHeight(biome, num6, num4, out array[0], false); |
| float biomeHeight2 = worldGen.GetBiomeHeight(biome2, num6, num4, out array[1], false); |
| float biomeHeight2 = worldGen.GetBiomeHeight(biome2, num6, num4, out array[1], false); |
| float biomeHeight3 = worldGen.GetBiomeHeight(biome3, num6, num4, out array[2], false); |
| float biomeHeight3 = worldGen.GetBiomeHeight(biome3, num6, num4, out array[2], false); |
| float biomeHeight4 = worldGen.GetBiomeHeight(biome4, num6, num4, out array[3], false); |
| float biomeHeight4 = worldGen.GetBiomeHeight(biome4, num6, num4, out array[3], false); |
| float num9 = DUtils.Lerp(biomeHeight, biomeHeight2, num7); |
| float num9 = DUtils.Lerp(biomeHeight, biomeHeight2, num7); |
| float num10 = DUtils.Lerp(biomeHeight3, biomeHeight4, num7); |
| float num10 = DUtils.Lerp(biomeHeight3, biomeHeight4, num7); |
| num8 = DUtils.Lerp(num9, num10, num5); |
| num8 = DUtils.Lerp(num9, num10, num5); |
| Color color2 = Color.Lerp(array[0], array[1], num7); |
| Color color2 = Color.Lerp(array[0], array[1], num7); |
| Color color3 = Color.Lerp(array[2], array[3], num7); |
| Color color3 = Color.Lerp(array[2], array[3], num7); |
| color = Color.Lerp(color2, color3, num5); |
| color = Color.Lerp(color2, color3, num5); |
| } |
| } |
| data.m_baseHeights[k * num + l] = num8; |
| data.m_baseHeights[k * num + l] = num8; |
| . | if (l < data.m_width && k < data.m_width) |
| data.m_baseMask[k * num + l] = color; |
| { |
| |
| data.m_baseMask[k * data.m_width + l] = color; |
| |
| } |
| |
| } |
| } |
| } |
| } |
| if (data.m_distantLod) |
| if (data.m_distantLod) |
| { |
| { |
| for (int m = 0; m < 4; m++) |
| for (int m = 0; m < 4; m++) |
| { |
| { |
| List<float> list = new List<float>(data.m_baseHeights); |
| List<float> list = new List<float>(data.m_baseHeights); |
| for (int n = 1; n < num - 1; n++) |
| for (int n = 1; n < num - 1; n++) |
| { |
| { |
| for (int num11 = 1; num11 < num - 1; num11++) |
| for (int num11 = 1; num11 < num - 1; num11++) |
| { |
| { |
| float num12 = list[n * num + num11]; |
| float num12 = list[n * num + num11]; |
| float num13 = list[(n - 1) * num + num11]; |
| float num13 = list[(n - 1) * num + num11]; |
| float num14 = list[(n + 1) * num + num11]; |
| float num14 = list[(n + 1) * num + num11]; |
| float num15 = list[n * num + num11 - 1]; |
| float num15 = list[n * num + num11 - 1]; |
| float num16 = list[n * num + num11 + 1]; |
| float num16 = list[n * num + num11 + 1]; |
| if (Mathf.Abs(num12 - num13) > 10f) |
| if (Mathf.Abs(num12 - num13) > 10f) |
| { |
| { |
| num12 = (num12 + num13) * 0.5f; |
| num12 = (num12 + num13) * 0.5f; |
| } |
| } |
| if (Mathf.Abs(num12 - num14) > 10f) |
| if (Mathf.Abs(num12 - num14) > 10f) |
| { |
| { |
| num12 = (num12 + num14) * 0.5f; |
| num12 = (num12 + num14) * 0.5f; |
| } |
| } |
| if (Mathf.Abs(num12 - num15) > 10f) |
| if (Mathf.Abs(num12 - num15) > 10f) |
| { |
| { |
| num12 = (num12 + num15) * 0.5f; |
| num12 = (num12 + num15) * 0.5f; |
| } |
| } |
| if (Mathf.Abs(num12 - num16) > 10f) |
| if (Mathf.Abs(num12 - num16) > 10f) |
| { |
| { |
| num12 = (num12 + num16) * 0.5f; |
| num12 = (num12 + num16) * 0.5f; |
| } |
| } |
| data.m_baseHeights[n * num + num11] = num12; |
| data.m_baseHeights[n * num + num11] = num12; |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| public HeightmapBuilder.HMBuildData RequestTerrainSync(Vector3 center, int width, float scale, bool distantLod, WorldGenerator worldGen) |
| public HeightmapBuilder.HMBuildData RequestTerrainSync(Vector3 center, int width, float scale, bool distantLod, WorldGenerator worldGen) |
| { |
| { |
| HeightmapBuilder.HMBuildData hmbuildData; |
| HeightmapBuilder.HMBuildData hmbuildData; |
| do |
| do |
| { |
| { |
| hmbuildData = this.RequestTerrain(center, width, scale, distantLod, worldGen); |
| hmbuildData = this.RequestTerrain(center, width, scale, distantLod, worldGen); |
| } |
| } |
| while (hmbuildData == null); |
| while (hmbuildData == null); |
| return hmbuildData; |
| return hmbuildData; |
| } |
| } |
| |
| |
| private HeightmapBuilder.HMBuildData RequestTerrain(Vector3 center, int width, float scale, bool distantLod, WorldGenerator worldGen) |
| private HeightmapBuilder.HMBuildData RequestTerrain(Vector3 center, int width, float scale, bool distantLod, WorldGenerator worldGen) |
| { |
| { |
| this.m_lock.WaitOne(); |
| this.m_lock.WaitOne(); |
| for (int i = 0; i < this.m_ready.Count; i++) |
| for (int i = 0; i < this.m_ready.Count; i++) |
| { |
| { |
| HeightmapBuilder.HMBuildData hmbuildData = this.m_ready[i]; |
| HeightmapBuilder.HMBuildData hmbuildData = this.m_ready[i]; |
| if (hmbuildData.IsEqual(center, width, scale, distantLod, worldGen)) |
| if (hmbuildData.IsEqual(center, width, scale, distantLod, worldGen)) |
| { |
| { |
| this.m_ready.RemoveAt(i); |
| this.m_ready.RemoveAt(i); |
| this.m_lock.ReleaseMutex(); |
| this.m_lock.ReleaseMutex(); |
| return hmbuildData; |
| return hmbuildData; |
| } |
| } |
| } |
| } |
| for (int j = 0; j < this.m_toBuild.Count; j++) |
| for (int j = 0; j < this.m_toBuild.Count; j++) |
| { |
| { |
| if (this.m_toBuild[j].IsEqual(center, width, scale, distantLod, worldGen)) |
| if (this.m_toBuild[j].IsEqual(center, width, scale, distantLod, worldGen)) |
| { |
| { |
| this.m_lock.ReleaseMutex(); |
| this.m_lock.ReleaseMutex(); |
| return null; |
| return null; |
| } |
| } |
| } |
| } |
| this.m_toBuild.Add(new HeightmapBuilder.HMBuildData(center, width, scale, distantLod, worldGen)); |
| this.m_toBuild.Add(new HeightmapBuilder.HMBuildData(center, width, scale, distantLod, worldGen)); |
| this.m_lock.ReleaseMutex(); |
| this.m_lock.ReleaseMutex(); |
| return null; |
| return null; |
| } |
| } |
| |
| |
| public bool IsTerrainReady(Vector3 center, int width, float scale, bool distantLod, WorldGenerator worldGen) |
| public bool IsTerrainReady(Vector3 center, int width, float scale, bool distantLod, WorldGenerator worldGen) |
| { |
| { |
| this.m_lock.WaitOne(); |
| this.m_lock.WaitOne(); |
| for (int i = 0; i < this.m_ready.Count; i++) |
| for (int i = 0; i < this.m_ready.Count; i++) |
| { |
| { |
| if (this.m_ready[i].IsEqual(center, width, scale, distantLod, worldGen)) |
| if (this.m_ready[i].IsEqual(center, width, scale, distantLod, worldGen)) |
| { |
| { |
| this.m_lock.ReleaseMutex(); |
| this.m_lock.ReleaseMutex(); |
| return true; |
| return true; |
| } |
| } |
| } |
| } |
| for (int j = 0; j < this.m_toBuild.Count; j++) |
| for (int j = 0; j < this.m_toBuild.Count; j++) |
| { |
| { |
| if (this.m_toBuild[j].IsEqual(center, width, scale, distantLod, worldGen)) |
| if (this.m_toBuild[j].IsEqual(center, width, scale, distantLod, worldGen)) |
| { |
| { |
| this.m_lock.ReleaseMutex(); |
| this.m_lock.ReleaseMutex(); |
| return false; |
| return false; |
| } |
| } |
| } |
| } |
| this.m_toBuild.Add(new HeightmapBuilder.HMBuildData(center, width, scale, distantLod, worldGen)); |
| this.m_toBuild.Add(new HeightmapBuilder.HMBuildData(center, width, scale, distantLod, worldGen)); |
| this.m_lock.ReleaseMutex(); |
| this.m_lock.ReleaseMutex(); |
| return false; |
| return false; |
| } |
| } |
| |
| |
| private static bool hasBeenDisposed; |
| private static bool hasBeenDisposed; |
| |
| |
| private static HeightmapBuilder m_instance; |
| private static HeightmapBuilder m_instance; |
| |
| |
| private const int m_maxReadyQueue = 16; |
| private const int m_maxReadyQueue = 16; |
| |
| |
| private List<HeightmapBuilder.HMBuildData> m_toBuild = new List<HeightmapBuilder.HMBuildData>(); |
| private List<HeightmapBuilder.HMBuildData> m_toBuild = new List<HeightmapBuilder.HMBuildData>(); |
| |
| |
| private List<HeightmapBuilder.HMBuildData> m_ready = new List<HeightmapBuilder.HMBuildData>(); |
| private List<HeightmapBuilder.HMBuildData> m_ready = new List<HeightmapBuilder.HMBuildData>(); |
| |
| |
| private Thread m_builder; |
| private Thread m_builder; |
| |
| |
| private Mutex m_lock = new Mutex(); |
| private Mutex m_lock = new Mutex(); |
| |
| |
| private bool m_stop; |
| private bool m_stop; |
| |
| |
| public class HMBuildData |
| public class HMBuildData |
| { |
| { |
| public HMBuildData(Vector3 center, int width, float scale, bool distantLod, WorldGenerator worldGen) |
| public HMBuildData(Vector3 center, int width, float scale, bool distantLod, WorldGenerator worldGen) |
| { |
| { |
| this.m_center = center; |
| this.m_center = center; |
| this.m_width = width; |
| this.m_width = width; |
| this.m_scale = scale; |
| this.m_scale = scale; |
| this.m_distantLod = distantLod; |
| this.m_distantLod = distantLod; |
| this.m_worldGen = worldGen; |
| this.m_worldGen = worldGen; |
| } |
| } |
| |
| |
| public bool IsEqual(Vector3 center, int width, float scale, bool distantLod, WorldGenerator worldGen) |
| public bool IsEqual(Vector3 center, int width, float scale, bool distantLod, WorldGenerator worldGen) |
| { |
| { |
| return this.m_center == center && this.m_width == width && this.m_scale == scale && this.m_distantLod == distantLod && this.m_worldGen == worldGen; |
| return this.m_center == center && this.m_width == width && this.m_scale == scale && this.m_distantLod == distantLod && this.m_worldGen == worldGen; |
| } |
| } |
| |
| |
| public Vector3 m_center; |
| public Vector3 m_center; |
| |
| |
| public int m_width; |
| public int m_width; |
| |
| |
| public float m_scale; |
| public float m_scale; |
| |
| |
| public bool m_distantLod; |
| public bool m_distantLod; |
| |
| |
| public bool m_menu; |
| public bool m_menu; |
| |
| |
| public WorldGenerator m_worldGen; |
| public WorldGenerator m_worldGen; |
| |
| |
| public Heightmap.Biome[] m_cornerBiomes; |
| public Heightmap.Biome[] m_cornerBiomes; |
| |
| |
| public List<float> m_baseHeights; |
| public List<float> m_baseHeights; |
| |
| |
| public Color[] m_baseMask; |
| public Color[] m_baseMask; |
| } |
| } |
| } |
| } |
| |
| |