- Timestamp:
- Sep 4, 2018, 1:00:48 PM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
binary-improvements/MapRendering/MapRendering/MapRendering.cs
r299 r325 1 using AllocsFixes.JSON;2 1 using System; 2 using System.Collections; 3 3 using System.Collections.Generic; 4 4 using System.IO; 5 5 using System.Text; 6 6 using System.Threading; 7 using System.Timers; 8 using AllocsFixes.FileCache; 9 using AllocsFixes.JSON; 7 10 using UnityEngine; 8 9 namespace AllocsFixes.MapRendering 10 { 11 public class MapRendering 12 { 11 using Object = UnityEngine.Object; 12 13 namespace AllocsFixes.MapRendering { 14 public class MapRendering { 13 15 private static MapRendering instance; 16 17 private static readonly object lockObject = new object (); 18 public static bool renderingEnabled = true; 19 private readonly MapTileCache cache = new MapTileCache (Constants.MAP_BLOCK_SIZE); 20 private readonly Dictionary<Vector2i, Color32[]> dirtyChunks = new Dictionary<Vector2i, Color32[]> (); 21 private readonly MicroStopwatch msw = new MicroStopwatch (); 22 private readonly MapRenderBlockBuffer[] zoomLevelBuffers; 23 private Coroutine renderCoroutineRef; 24 private bool renderingFullMap; 25 private float renderTimeout = float.MaxValue; 26 27 private MapRendering () { 28 Constants.MAP_DIRECTORY = GameUtils.GetSaveGameDir () + "/map"; 29 30 lock (lockObject) { 31 if (!LoadMapInfo ()) { 32 WriteMapInfo (); 33 } 34 } 35 36 cache.SetZoomCount (Constants.ZOOMLEVELS); 37 38 zoomLevelBuffers = new MapRenderBlockBuffer[Constants.ZOOMLEVELS]; 39 for (int i = 0; i < Constants.ZOOMLEVELS; i++) { 40 zoomLevelBuffers [i] = new MapRenderBlockBuffer (i, cache); 41 } 42 43 renderCoroutineRef = ThreadManager.StartCoroutine (renderCoroutine ()); 44 } 14 45 15 46 public static MapRendering Instance { … … 18 49 instance = new MapRendering (); 19 50 } 51 20 52 return instance; 21 53 } 22 54 } 23 55 24 private static object lockObject = new object (); 25 private MapRenderBlockBuffer[] zoomLevelBuffers; 26 private Dictionary<Vector2i, Color32[]> dirtyChunks = new Dictionary<Vector2i, Color32[]> (); 27 private bool renderingFullMap = false; 28 public static bool renderingEnabled = true; 29 private MicroStopwatch msw = new MicroStopwatch (); 30 private AllocsFixes.FileCache.MapTileCache cache = new AllocsFixes.FileCache.MapTileCache (Constants.MAP_BLOCK_SIZE); 31 private float renderTimeout = float.MaxValue; 32 private Coroutine renderCoroutineRef; 33 34 public static AllocsFixes.FileCache.MapTileCache GetTileCache() { 56 public static MapTileCache GetTileCache () { 35 57 return Instance.cache; 36 58 } 37 59 38 private MapRendering () 39 { 40 Constants.MAP_DIRECTORY = GameUtils.GetSaveGameDir () + "/map"; 41 42 lock (lockObject) { 43 if (!LoadMapInfo ()) 44 WriteMapInfo (); 45 } 46 47 cache.SetZoomCount (Constants.ZOOMLEVELS); 48 49 zoomLevelBuffers = new MapRenderBlockBuffer[Constants.ZOOMLEVELS]; 50 for (int i = 0; i < Constants.ZOOMLEVELS; i++) { 51 zoomLevelBuffers [i] = new MapRenderBlockBuffer (i, cache); 52 } 53 54 renderCoroutineRef = ThreadManager.StartCoroutine (renderCoroutine ()); 55 } 56 57 public static void Shutdown () 58 { 60 public static void Shutdown () { 59 61 if (Instance.renderCoroutineRef != null) { 60 62 ThreadManager.StopCoroutine (Instance.renderCoroutineRef); … … 63 65 } 64 66 65 public static void RenderSingleChunk (Chunk chunk) 66 { 67 public static void RenderSingleChunk (Chunk chunk) { 67 68 if (renderingEnabled) { 68 ThreadPool.UnsafeQueueUserWorkItem ((o) => 69 { 69 ThreadPool.UnsafeQueueUserWorkItem (o => { 70 70 try { 71 71 if (!Instance.renderingFullMap) { 72 72 lock (lockObject) { 73 Chunk c = (Chunk) o;73 Chunk c = (Chunk) o; 74 74 Vector3i cPos = c.GetWorldPos (); 75 Vector2i cPos2 = new Vector2i (cPos.x / Constants.MAP_CHUNK_SIZE, cPos.z / Constants.MAP_CHUNK_SIZE); 75 Vector2i cPos2 = new Vector2i (cPos.x / Constants.MAP_CHUNK_SIZE, 76 cPos.z / Constants.MAP_CHUNK_SIZE); 76 77 77 78 ushort[] mapColors = c.GetMapColors (); 78 79 if (mapColors != null) { 79 Color32[] realColors = new Color32[Constants.MAP_CHUNK_SIZE * Constants.MAP_CHUNK_SIZE]; 80 Color32[] realColors = 81 new Color32[Constants.MAP_CHUNK_SIZE * Constants.MAP_CHUNK_SIZE]; 80 82 for (int i_colors = 0; i_colors < mapColors.Length; i_colors++) { 81 83 realColors [i_colors] = shortColorToColor32 (mapColors [i_colors]); 82 84 } 85 83 86 Instance.dirtyChunks [cPos2] = realColors; 87 84 88 //Log.Out ("Add Dirty: " + cPos2); 85 89 } … … 93 97 } 94 98 95 public void RenderFullMap () 96 { 99 public void RenderFullMap () { 97 100 MicroStopwatch microStopwatch = new MicroStopwatch (); 98 101 … … 101 104 Texture2D fullMapTexture = null; 102 105 103 Vector2i minChunk = default (Vector2i), maxChunk = default(Vector2i);104 Vector2i minPos = default (Vector2i), maxPos = default(Vector2i);106 Vector2i minChunk = default (Vector2i), maxChunk = default (Vector2i); 107 Vector2i minPos = default (Vector2i), maxPos = default (Vector2i); 105 108 int widthChunks, heightChunks, widthPix, heightPix; 106 getWorldExtent (rfm, out minChunk, out maxChunk, out minPos, out maxPos, out widthChunks, out heightChunks, out widthPix, out heightPix); 107 108 Log.Out (String.Format ("RenderMap: min: {0}, max: {1}, minPos: {2}, maxPos: {3}, w/h: {4}/{5}, wP/hP: {6}/{7}", 109 minChunk.ToString (), maxChunk.ToString (), 110 minPos.ToString (), maxPos.ToString (), 111 widthChunks, heightChunks, 112 widthPix, heightPix) 109 getWorldExtent (rfm, out minChunk, out maxChunk, out minPos, out maxPos, out widthChunks, out heightChunks, 110 out widthPix, out heightPix); 111 112 Log.Out (string.Format ( 113 "RenderMap: min: {0}, max: {1}, minPos: {2}, maxPos: {3}, w/h: {4}/{5}, wP/hP: {6}/{7}", 114 minChunk.ToString (), maxChunk.ToString (), 115 minPos.ToString (), maxPos.ToString (), 116 widthChunks, heightChunks, 117 widthPix, heightPix) 113 118 ); 114 119 … … 121 126 Directory.Delete (Constants.MAP_DIRECTORY, true); 122 127 } 128 123 129 WriteMapInfo (); 124 130 125 131 renderingFullMap = true; 126 132 127 if (widthPix <= 8192 && heightPix <= 8192) 133 if (widthPix <= 8192 && heightPix <= 8192) { 128 134 fullMapTexture = new Texture2D (widthPix, heightPix); 129 130 Vector2i curFullMapPos = default(Vector2i); 131 Vector2i curChunkPos = default(Vector2i); 135 } 136 137 Vector2i curFullMapPos = default (Vector2i); 138 Vector2i curChunkPos = default (Vector2i); 132 139 for (curFullMapPos.x = 0; curFullMapPos.x < widthPix; curFullMapPos.x += Constants.MAP_CHUNK_SIZE) { 133 for (curFullMapPos.y = 0; curFullMapPos.y < heightPix; curFullMapPos.y += Constants.MAP_CHUNK_SIZE) { 134 curChunkPos.x = (curFullMapPos.x / Constants.MAP_CHUNK_SIZE) + minChunk.x; 135 curChunkPos.y = (curFullMapPos.y / Constants.MAP_CHUNK_SIZE) + minChunk.y; 140 for (curFullMapPos.y = 0; 141 curFullMapPos.y < heightPix; 142 curFullMapPos.y += Constants.MAP_CHUNK_SIZE) { 143 curChunkPos.x = curFullMapPos.x / Constants.MAP_CHUNK_SIZE + minChunk.x; 144 curChunkPos.y = curFullMapPos.y / Constants.MAP_CHUNK_SIZE + minChunk.y; 136 145 137 146 try { … … 141 150 ushort[] mapColors = c.GetMapColors (); 142 151 if (mapColors != null) { 143 Color32[] realColors = new Color32[Constants.MAP_CHUNK_SIZE * Constants.MAP_CHUNK_SIZE]; 152 Color32[] realColors = 153 new Color32[Constants.MAP_CHUNK_SIZE * Constants.MAP_CHUNK_SIZE]; 144 154 for (int i_colors = 0; i_colors < mapColors.Length; i_colors++) { 145 155 realColors [i_colors] = shortColorToColor32 (mapColors [i_colors]); 146 156 } 157 147 158 dirtyChunks [curChunkPos] = realColors; 148 if (fullMapTexture != null) 149 fullMapTexture.SetPixels32 (curFullMapPos.x, curFullMapPos.y, Constants.MAP_CHUNK_SIZE, Constants.MAP_CHUNK_SIZE, realColors); 159 if (fullMapTexture != null) { 160 fullMapTexture.SetPixels32 (curFullMapPos.x, curFullMapPos.y, 161 Constants.MAP_CHUNK_SIZE, Constants.MAP_CHUNK_SIZE, realColors); 162 } 150 163 } 151 164 } … … 159 172 } 160 173 161 Log.Out (String.Format ("RenderMap: {0}/{1} ({2}%)", curFullMapPos.x, widthPix, (int)((float)curFullMapPos.x / widthPix * 100))); 174 Log.Out (string.Format ("RenderMap: {0}/{1} ({2}%)", curFullMapPos.x, widthPix, 175 (int) ((float) curFullMapPos.x / widthPix * 100))); 162 176 } 163 177 } … … 166 180 byte[] array = fullMapTexture.EncodeToPNG (); 167 181 File.WriteAllBytes (Constants.MAP_DIRECTORY + "/map.png", array); 168 UnityEngine.Object.Destroy (fullMapTexture);182 Object.Destroy (fullMapTexture); 169 183 fullMapTexture = null; 170 184 } … … 176 190 } 177 191 178 private void SaveAllBlockMaps (object source, System.Timers.ElapsedEventArgs e) 179 { 192 private void SaveAllBlockMaps (object source, ElapsedEventArgs e) { 180 193 for (int i = 0; i < Constants.ZOOMLEVELS; i++) { 181 194 zoomLevelBuffers [i].SaveBlock (); … … 183 196 } 184 197 185 private System.Collections.IEnumerator renderCoroutine () {198 private IEnumerator renderCoroutine () { 186 199 while (true) { 187 200 lock (lockObject) { … … 189 202 renderTimeout = Time.time + 0.5f; 190 203 } 204 191 205 if (Time.time > renderTimeout || dirtyChunks.Count > 200) { 192 206 RenderDirtyChunks (); 193 207 } 194 208 } 209 195 210 yield return new WaitForSeconds (0.2f); 196 211 } 197 212 } 198 213 199 private void RenderDirtyChunks () 200 { 214 private void RenderDirtyChunks () { 201 215 msw.ResetAndRestart (); 202 216 … … 210 224 //Log.Out ("Start Dirty: " + chunkPos); 211 225 212 Vector2i block = default(Vector2i), blockOffset = default(Vector2i); 213 getBlockNumber (chunkPos, out block, out blockOffset, Constants.MAP_BLOCK_TO_CHUNK_DIV, Constants.MAP_CHUNK_SIZE); 226 Vector2i block = default (Vector2i), blockOffset = default (Vector2i); 227 getBlockNumber (chunkPos, out block, out blockOffset, Constants.MAP_BLOCK_TO_CHUNK_DIV, 228 Constants.MAP_CHUNK_SIZE); 214 229 215 230 zoomLevelBuffers [Constants.ZOOMLEVELS - 1].LoadBlock (block); 216 231 217 Vector2i v_block = default (Vector2i), v_blockOffset = default(Vector2i);232 Vector2i v_block = default (Vector2i), v_blockOffset = default (Vector2i); 218 233 foreach (Vector2i v in keys) { 219 getBlockNumber (v, out v_block, out v_blockOffset, Constants.MAP_BLOCK_TO_CHUNK_DIV, Constants.MAP_CHUNK_SIZE); 234 getBlockNumber (v, out v_block, out v_blockOffset, Constants.MAP_BLOCK_TO_CHUNK_DIV, 235 Constants.MAP_CHUNK_SIZE); 220 236 if (v_block.Equals (block)) { 221 237 //Log.Out ("Dirty: " + v + " render: true"); 222 238 chunksDone.Add (v); 223 239 if (dirtyChunks [v].Length != Constants.MAP_CHUNK_SIZE * Constants.MAP_CHUNK_SIZE) { 224 Log.Error (string.Format ("Rendering chunk has incorrect data size of {0} instead of {1}", dirtyChunks [v].Length, Constants.MAP_CHUNK_SIZE * Constants.MAP_CHUNK_SIZE)); 225 } 226 zoomLevelBuffers [Constants.ZOOMLEVELS - 1].SetPart (v_blockOffset, Constants.MAP_CHUNK_SIZE, dirtyChunks [v]); 227 } else { 228 //Log.Out ("Dirty: " + v + " render: false"); 229 } 230 } 231 232 foreach (Vector2i v in chunksDone) 240 Log.Error (string.Format ("Rendering chunk has incorrect data size of {0} instead of {1}", 241 dirtyChunks [v].Length, Constants.MAP_CHUNK_SIZE * Constants.MAP_CHUNK_SIZE)); 242 } 243 244 zoomLevelBuffers [Constants.ZOOMLEVELS - 1] 245 .SetPart (v_blockOffset, Constants.MAP_CHUNK_SIZE, dirtyChunks [v]); 246 } 247 } 248 249 foreach (Vector2i v in chunksDone) { 233 250 dirtyChunks.Remove (v); 251 } 234 252 235 253 RenderZoomLevel (Constants.ZOOMLEVELS - 1, block); … … 239 257 } 240 258 241 private void RenderZoomLevel (int level, Vector2i innerBlock) 242 { 259 private void RenderZoomLevel (int level, Vector2i innerBlock) { 243 260 if (level > 0) { 244 Vector2i block = default (Vector2i), blockOffset = default(Vector2i);261 Vector2i block = default (Vector2i), blockOffset = default (Vector2i); 245 262 getBlockNumber (innerBlock, out block, out blockOffset, 2, Constants.MAP_BLOCK_SIZE / 2); 246 263 247 264 zoomLevelBuffers [level - 1].LoadBlock (block); 248 zoomLevelBuffers [level - 1].SetPart (blockOffset, Constants.MAP_BLOCK_SIZE / 2, zoomLevelBuffers [level].GetHalfScaled ()); 265 zoomLevelBuffers [level - 1].SetPart (blockOffset, Constants.MAP_BLOCK_SIZE / 2, 266 zoomLevelBuffers [level].GetHalfScaled ()); 249 267 250 268 RenderZoomLevel (level - 1, block); … … 252 270 } 253 271 254 private void getBlockNumber (Vector2i innerPos, out Vector2i block, out Vector2i blockOffset, int scaleFactor, int offsetSize) 255 { 256 block = default(Vector2i); 257 blockOffset = default(Vector2i); 258 block.x = ((innerPos.x + 16777216) / scaleFactor) - (16777216 / scaleFactor); 259 block.y = ((innerPos.y + 16777216) / scaleFactor) - (16777216 / scaleFactor); 260 blockOffset.x = ((innerPos.x + 16777216) % scaleFactor) * offsetSize; 261 blockOffset.y = ((innerPos.y + 16777216) % scaleFactor) * offsetSize; 262 } 263 264 private void WriteMapInfo () 265 { 272 private void getBlockNumber (Vector2i innerPos, out Vector2i block, out Vector2i blockOffset, int scaleFactor, 273 int offsetSize) { 274 block = default (Vector2i); 275 blockOffset = default (Vector2i); 276 block.x = (innerPos.x + 16777216) / scaleFactor - 16777216 / scaleFactor; 277 block.y = (innerPos.y + 16777216) / scaleFactor - 16777216 / scaleFactor; 278 blockOffset.x = (innerPos.x + 16777216) % scaleFactor * offsetSize; 279 blockOffset.y = (innerPos.y + 16777216) % scaleFactor * offsetSize; 280 } 281 282 private void WriteMapInfo () { 266 283 JSONObject mapInfo = new JSONObject (); 267 284 mapInfo.Add ("blockSize", new JSONNumber (Constants.MAP_BLOCK_SIZE)); … … 272 289 } 273 290 274 private bool LoadMapInfo () 275 { 291 private bool LoadMapInfo () { 276 292 if (File.Exists (Constants.MAP_DIRECTORY + "/mapinfo.json")) { 277 293 string json = File.ReadAllText (Constants.MAP_DIRECTORY + "/mapinfo.json", Encoding.UTF8); … … 279 295 JSONNode node = Parser.Parse (json); 280 296 if (node is JSONObject) { 281 JSONObject jo = (JSONObject)node; 282 if (jo.ContainsKey ("blockSize")) 283 Constants.MAP_BLOCK_SIZE = ((JSONNumber)jo ["blockSize"]).GetInt (); 284 if (jo.ContainsKey ("maxZoom")) 285 Constants.ZOOMLEVELS = ((JSONNumber)jo ["maxZoom"]).GetInt () + 1; 297 JSONObject jo = (JSONObject) node; 298 if (jo.ContainsKey ("blockSize")) { 299 Constants.MAP_BLOCK_SIZE = ((JSONNumber) jo ["blockSize"]).GetInt (); 300 } 301 302 if (jo.ContainsKey ("maxZoom")) { 303 Constants.ZOOMLEVELS = ((JSONNumber) jo ["maxZoom"]).GetInt () + 1; 304 } 305 286 306 return true; 287 307 } … … 292 312 } 293 313 } 314 294 315 return false; 295 316 } 296 317 297 318 private void getWorldExtent (RegionFileManager rfm, out Vector2i minChunk, out Vector2i maxChunk, 298 out Vector2i minPos, out Vector2i maxPos, 299 out int widthChunks, out int heightChunks, 300 out int widthPix, out int heightPix) 301 { 302 minChunk = default(Vector2i); 303 maxChunk = default(Vector2i); 304 minPos = default(Vector2i); 305 maxPos = default(Vector2i); 319 out Vector2i minPos, out Vector2i maxPos, 320 out int widthChunks, out int heightChunks, 321 out int widthPix, out int heightPix) { 322 minChunk = default (Vector2i); 323 maxChunk = default (Vector2i); 324 minPos = default (Vector2i); 325 maxPos = default (Vector2i); 306 326 307 327 long[] keys = rfm.GetAllChunkKeys (); 308 int minX = Int32.MaxValue;309 int minY = Int32.MaxValue;310 int maxX = Int32.MinValue;311 int maxY = Int32.MinValue;328 int minX = int.MaxValue; 329 int minY = int.MaxValue; 330 int maxX = int.MinValue; 331 int maxY = int.MinValue; 312 332 foreach (long key in keys) { 313 333 int x = WorldChunkCache.extractX (key); 314 334 int y = WorldChunkCache.extractZ (key); 315 335 316 if (x < minX) 336 if (x < minX) { 317 337 minX = x; 318 if (x > maxX) 338 } 339 340 if (x > maxX) { 319 341 maxX = x; 320 if (y < minY) 342 } 343 344 if (y < minY) { 321 345 minY = y; 322 if (y > maxY) 346 } 347 348 if (y > maxY) { 323 349 maxY = y; 350 } 324 351 } 325 352 … … 343 370 } 344 371 345 private static Color shortColorToColor (ushort col) 346 { 347 return new Color (((float)(col >> 10 & 31) / 31f), ((float)(col >> 5 & 31) / 31f), ((float)(col & 31) / 31f), 255); 348 } 349 350 private static Color32 shortColorToColor32 (ushort col) 351 { 352 byte r = (byte)(256 * (col >> 10 & 31) / 32); 353 byte g = (byte)(256 * (col >> 5 & 31) / 32); 354 byte b = (byte)(256 * (col & 31) / 32); 372 private static Color shortColorToColor (ushort col) { 373 return new Color (((col >> 10) & 31) / 31f, ((col >> 5) & 31) / 31f, (col & 31) / 31f, 255); 374 } 375 376 private static Color32 shortColorToColor32 (ushort col) { 377 byte r = (byte) (256 * ((col >> 10) & 31) / 32); 378 byte g = (byte) (256 * ((col >> 5) & 31) / 32); 379 byte b = (byte) (256 * (col & 31) / 32); 355 380 byte a = 255; 356 381 return new Color32 (r, g, b, a);
Note:
See TracChangeset
for help on using the changeset viewer.