source: binary-improvements2/MapRendering/src/MapRenderBlockBuffer.cs@ 410

Last change on this file since 410 was 402, checked in by alloc, 22 months ago
  • Major refactoring
  • Using Utf8Json for (de)serialization
  • Moving APIs to REST
  • Removing dependencies from WebServer and MapRenderer to ServerFixes
File size: 7.4 KB
RevLine 
[224]1using System;
2using System.IO;
[329]3using Unity.Collections;
[224]4using UnityEngine;
[329]5using UnityEngine.Profiling;
[224]6
[391]7namespace MapRendering {
[325]8 public class MapRenderBlockBuffer {
[391]9 private readonly Texture2D blockMap = new Texture2D (Constants.MapBlockSize, Constants.MapBlockSize, Constants.DefaultTextureFormat, false);
[325]10 private readonly MapTileCache cache;
[331]11 private readonly NativeArray<int> emptyImageData;
[391]12 private readonly Texture2D zoomBuffer = new Texture2D (Constants.MapBlockSize / 2, Constants.MapBlockSize / 2, Constants.DefaultTextureFormat, false);
[325]13 private readonly int zoomLevel;
[329]14 private readonly string folderBase;
15
[391]16 private Vector2i currentBlockMapPos = new Vector2i (int.MinValue, int.MinValue);
[329]17 private string currentBlockMapFolder = string.Empty;
[224]18
[351]19 public MapRenderBlockBuffer (int _level, MapTileCache _cache) {
20 zoomLevel = _level;
21 cache = _cache;
[402]22 folderBase = $"{Constants.MapDirectory}/{zoomLevel}/";
[331]23
24 {
25 // Initialize empty tile data
26 Color nullColor = new Color (0, 0, 0, 0);
[391]27 for (int x = 0; x < Constants.MapBlockSize; x++) {
28 for (int y = 0; y < Constants.MapBlockSize; y++) {
[331]29 blockMap.SetPixel (x, y, nullColor);
30 }
31 }
32
33 NativeArray<int> blockMapData = blockMap.GetRawTextureData<int> ();
34 emptyImageData = new NativeArray<int> (blockMapData.Length, Allocator.Persistent,
35 NativeArrayOptions.UninitializedMemory);
36 blockMapData.CopyTo (emptyImageData);
37 }
[224]38 }
39
[391]40 public TextureFormat FormatSelf => blockMap.format;
[329]41
[325]42 public void ResetBlock () {
[329]43 currentBlockMapFolder = string.Empty;
[391]44 currentBlockMapPos = new Vector2i (int.MinValue, int.MinValue);
[346]45 cache.ResetTile (zoomLevel);
[224]46 }
47
[325]48 public void SaveBlock () {
[331]49 Profiler.BeginSample ("SaveBlock");
[224]50 try {
[331]51 saveTextureToFile ();
[224]52 } catch (Exception e) {
[402]53 Log.Warning ($"Exception in MapRenderBlockBuffer.SaveBlock(): {e}");
[224]54 }
[331]55 Profiler.EndSample ();
[224]56 }
57
[351]58 public bool LoadBlock (Vector2i _block) {
[331]59 Profiler.BeginSample ("LoadBlock");
[224]60 lock (blockMap) {
[351]61 if (currentBlockMapPos != _block) {
[329]62 Profiler.BeginSample ("LoadBlock.Strings");
63 string folder;
[351]64 if (currentBlockMapPos.x != _block.x) {
[402]65 folder = $"{folderBase}{_block.x}/";
[329]66
67 Profiler.BeginSample ("LoadBlock.Directory");
68 Directory.CreateDirectory (folder);
69 Profiler.EndSample ();
70 } else {
71 folder = currentBlockMapFolder;
72 }
73
[402]74 string fileName = $"{folder}{_block.y}.png";
[329]75 Profiler.EndSample ();
76
[331]77 SaveBlock ();
78 loadTextureFromFile (fileName);
[329]79
80 currentBlockMapFolder = folder;
[351]81 currentBlockMapPos = _block;
[331]82
83 Profiler.EndSample ();
84 return true;
[224]85 }
86 }
[325]87
[331]88 Profiler.EndSample ();
89 return false;
[224]90 }
91
[351]92 public void SetPart (Vector2i _offset, int _partSize, Color32[] _pixels) {
[391]93 if (_offset.x + _partSize > Constants.MapBlockSize || _offset.y + _partSize > Constants.MapBlockSize) {
94 Log.Error (
95 $"MapBlockBuffer[{zoomLevel}].SetPart ({_offset}, {_partSize}, {_pixels.Length}) has blockMap.size ({Constants.MapBlockSize}/{Constants.MapBlockSize})");
[230]96 return;
97 }
[325]98
[329]99 Profiler.BeginSample ("SetPart");
[351]100 blockMap.SetPixels32 (_offset.x, _offset.y, _partSize, _partSize, _pixels);
[329]101 Profiler.EndSample ();
[224]102 }
103
[325]104 public Color32[] GetHalfScaled () {
[329]105 Profiler.BeginSample ("HalfScaled.ResizeBuffer");
[402]106 zoomBuffer.Reinitialize (Constants.MapBlockSize, Constants.MapBlockSize);
[329]107 Profiler.EndSample ();
[224]108
[329]109 Profiler.BeginSample ("HalfScaled.CopyPixels");
110 if (blockMap.format == zoomBuffer.format) {
111 Profiler.BeginSample ("Native");
112 NativeArray<byte> dataSrc = blockMap.GetRawTextureData<byte> ();
113 NativeArray<byte> dataZoom = zoomBuffer.GetRawTextureData<byte> ();
114 dataSrc.CopyTo (dataZoom);
115 Profiler.EndSample ();
116 } else {
117 Profiler.BeginSample ("GetSetPixels");
118 zoomBuffer.SetPixels32 (blockMap.GetPixels32 ());
119 Profiler.EndSample ();
120 }
121 Profiler.EndSample ();
122
123 Profiler.BeginSample ("HalfScaled.Scale");
[391]124 TextureScale.Point (zoomBuffer, Constants.MapBlockSize / 2, Constants.MapBlockSize / 2);
[329]125 Profiler.EndSample ();
[224]126
[329]127 Profiler.BeginSample ("HalfScaled.Return");
128 Color32[] result = zoomBuffer.GetPixels32 ();
129 Profiler.EndSample ();
130
131 return result;
[224]132 }
133
[351]134 public void SetPartNative (Vector2i _offset, int _partSize, NativeArray<int> _pixels) {
[391]135 if (_offset.x + _partSize > Constants.MapBlockSize || _offset.y + _partSize > Constants.MapBlockSize) {
136 Log.Error (
137 $"MapBlockBuffer[{zoomLevel}].SetPart ({_offset}, {_partSize}, {_pixels.Length}) has blockMap.size ({Constants.MapBlockSize}/{Constants.MapBlockSize})");
[329]138 return;
139 }
140
141 Profiler.BeginSample ("SetPartNative");
142 NativeArray<int> destData = blockMap.GetRawTextureData<int> ();
143
[351]144 for (int y = 0; y < _partSize; y++) {
145 int srcLineStartIdx = _partSize * y;
146 int destLineStartIdx = blockMap.width * (_offset.y + y) + _offset.x;
147 for (int x = 0; x < _partSize; x++) {
148 destData [destLineStartIdx + x] = _pixels [srcLineStartIdx + x];
[329]149 }
150 }
151 Profiler.EndSample ();
152 }
153
154 public NativeArray<int> GetHalfScaledNative () {
155 Profiler.BeginSample ("HalfScaledNative.ResizeBuffer");
[391]156 if (zoomBuffer.format != blockMap.format || zoomBuffer.height != Constants.MapBlockSize / 2 || zoomBuffer.width != Constants.MapBlockSize / 2) {
[402]157 zoomBuffer.Reinitialize (Constants.MapBlockSize / 2, Constants.MapBlockSize / 2, blockMap.format, false);
[329]158 }
159 Profiler.EndSample ();
160
161 Profiler.BeginSample ("HalfScaledNative.Scale");
[331]162 ScaleNative (blockMap, zoomBuffer);
[329]163 Profiler.EndSample ();
164
165 return zoomBuffer.GetRawTextureData<int> ();
166 }
[331]167
168 private static void ScaleNative (Texture2D _sourceTex, Texture2D _targetTex) {
169 NativeArray<int> srcData = _sourceTex.GetRawTextureData<int> ();
170 NativeArray<int> targetData = _targetTex.GetRawTextureData<int> ();
171
172 int oldWidth = _sourceTex.width;
173 int oldHeight = _sourceTex.height;
174 int newWidth = _targetTex.width;
175 int newHeight = _targetTex.height;
176
[391]177 float ratioX = (float) oldWidth / newWidth;
178 float ratioY = (float) oldHeight / newHeight;
[329]179
[391]180 for (int y = 0; y < newHeight; y++) {
181 int oldLineStart = (int) (ratioY * y) * oldWidth;
182 int newLineStart = y * newWidth;
183 for (int x = 0; x < newWidth; x++) {
[331]184 targetData [newLineStart + x] = srcData [(int) (oldLineStart + ratioX * x)];
185 }
186 }
187 }
188
[325]189 private void loadTextureFromFile (string _fileName) {
[329]190 Profiler.BeginSample ("LoadTexture");
191
192 Profiler.BeginSample ("LoadFile");
[224]193 byte[] array = cache.LoadTile (zoomLevel, _fileName);
[329]194 Profiler.EndSample ();
195
196 Profiler.BeginSample ("LoadImage");
[391]197 if (array != null && blockMap.LoadImage (array) && blockMap.height == Constants.MapBlockSize &&
198 blockMap.width == Constants.MapBlockSize) {
[329]199 Profiler.EndSample ();
200
201 Profiler.EndSample ();
[326]202 return;
203 }
[329]204 Profiler.EndSample ();
[233]205
[326]206 if (array != null) {
[402]207 Log.Error ($"Map image tile {_fileName} has been corrupted, recreating tile");
[326]208 }
[325]209
[391]210 if (blockMap.format != Constants.DefaultTextureFormat || blockMap.height != Constants.MapBlockSize ||
211 blockMap.width != Constants.MapBlockSize) {
[402]212 blockMap.Reinitialize (Constants.MapBlockSize, Constants.MapBlockSize, Constants.DefaultTextureFormat,
[331]213 false);
[326]214 }
215
[331]216 blockMap.LoadRawTextureData (emptyImageData);
217
[329]218 Profiler.EndSample ();
[224]219 }
220
[331]221 private void saveTextureToFile () {
[329]222 Profiler.BeginSample ("EncodePNG");
[224]223 byte[] array = blockMap.EncodeToPNG ();
[329]224 Profiler.EndSample ();
225
[224]226 cache.SaveTile (zoomLevel, array);
227 }
228 }
[325]229}
Note: See TracBrowser for help on using the repository browser.