source: TFP-WebServer/MapRendering/src/MapRenderBlockBuffer.cs@ 477

Last change on this file since 477 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
Line 
1using System;
2using System.IO;
3using Unity.Collections;
4using UnityEngine;
5using UnityEngine.Profiling;
6
7namespace MapRendering {
8 public class MapRenderBlockBuffer {
9 private readonly Texture2D blockMap = new Texture2D (Constants.MapBlockSize, Constants.MapBlockSize, Constants.DefaultTextureFormat, false);
10 private readonly MapTileCache cache;
11 private readonly NativeArray<int> emptyImageData;
12 private readonly Texture2D zoomBuffer = new Texture2D (Constants.MapBlockSize / 2, Constants.MapBlockSize / 2, Constants.DefaultTextureFormat, false);
13 private readonly int zoomLevel;
14 private readonly string folderBase;
15
16 private Vector2i currentBlockMapPos = new Vector2i (int.MinValue, int.MinValue);
17 private string currentBlockMapFolder = string.Empty;
18
19 public MapRenderBlockBuffer (int _level, MapTileCache _cache) {
20 zoomLevel = _level;
21 cache = _cache;
22 folderBase = $"{Constants.MapDirectory}/{zoomLevel}/";
23
24 {
25 // Initialize empty tile data
26 Color nullColor = new Color (0, 0, 0, 0);
27 for (int x = 0; x < Constants.MapBlockSize; x++) {
28 for (int y = 0; y < Constants.MapBlockSize; y++) {
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 }
38 }
39
40 public TextureFormat FormatSelf => blockMap.format;
41
42 public void ResetBlock () {
43 currentBlockMapFolder = string.Empty;
44 currentBlockMapPos = new Vector2i (int.MinValue, int.MinValue);
45 cache.ResetTile (zoomLevel);
46 }
47
48 public void SaveBlock () {
49 Profiler.BeginSample ("SaveBlock");
50 try {
51 saveTextureToFile ();
52 } catch (Exception e) {
53 Log.Warning ($"Exception in MapRenderBlockBuffer.SaveBlock(): {e}");
54 }
55 Profiler.EndSample ();
56 }
57
58 public bool LoadBlock (Vector2i _block) {
59 Profiler.BeginSample ("LoadBlock");
60 lock (blockMap) {
61 if (currentBlockMapPos != _block) {
62 Profiler.BeginSample ("LoadBlock.Strings");
63 string folder;
64 if (currentBlockMapPos.x != _block.x) {
65 folder = $"{folderBase}{_block.x}/";
66
67 Profiler.BeginSample ("LoadBlock.Directory");
68 Directory.CreateDirectory (folder);
69 Profiler.EndSample ();
70 } else {
71 folder = currentBlockMapFolder;
72 }
73
74 string fileName = $"{folder}{_block.y}.png";
75 Profiler.EndSample ();
76
77 SaveBlock ();
78 loadTextureFromFile (fileName);
79
80 currentBlockMapFolder = folder;
81 currentBlockMapPos = _block;
82
83 Profiler.EndSample ();
84 return true;
85 }
86 }
87
88 Profiler.EndSample ();
89 return false;
90 }
91
92 public void SetPart (Vector2i _offset, int _partSize, Color32[] _pixels) {
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})");
96 return;
97 }
98
99 Profiler.BeginSample ("SetPart");
100 blockMap.SetPixels32 (_offset.x, _offset.y, _partSize, _partSize, _pixels);
101 Profiler.EndSample ();
102 }
103
104 public Color32[] GetHalfScaled () {
105 Profiler.BeginSample ("HalfScaled.ResizeBuffer");
106 zoomBuffer.Reinitialize (Constants.MapBlockSize, Constants.MapBlockSize);
107 Profiler.EndSample ();
108
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");
124 TextureScale.Point (zoomBuffer, Constants.MapBlockSize / 2, Constants.MapBlockSize / 2);
125 Profiler.EndSample ();
126
127 Profiler.BeginSample ("HalfScaled.Return");
128 Color32[] result = zoomBuffer.GetPixels32 ();
129 Profiler.EndSample ();
130
131 return result;
132 }
133
134 public void SetPartNative (Vector2i _offset, int _partSize, NativeArray<int> _pixels) {
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})");
138 return;
139 }
140
141 Profiler.BeginSample ("SetPartNative");
142 NativeArray<int> destData = blockMap.GetRawTextureData<int> ();
143
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];
149 }
150 }
151 Profiler.EndSample ();
152 }
153
154 public NativeArray<int> GetHalfScaledNative () {
155 Profiler.BeginSample ("HalfScaledNative.ResizeBuffer");
156 if (zoomBuffer.format != blockMap.format || zoomBuffer.height != Constants.MapBlockSize / 2 || zoomBuffer.width != Constants.MapBlockSize / 2) {
157 zoomBuffer.Reinitialize (Constants.MapBlockSize / 2, Constants.MapBlockSize / 2, blockMap.format, false);
158 }
159 Profiler.EndSample ();
160
161 Profiler.BeginSample ("HalfScaledNative.Scale");
162 ScaleNative (blockMap, zoomBuffer);
163 Profiler.EndSample ();
164
165 return zoomBuffer.GetRawTextureData<int> ();
166 }
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
177 float ratioX = (float) oldWidth / newWidth;
178 float ratioY = (float) oldHeight / newHeight;
179
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++) {
184 targetData [newLineStart + x] = srcData [(int) (oldLineStart + ratioX * x)];
185 }
186 }
187 }
188
189 private void loadTextureFromFile (string _fileName) {
190 Profiler.BeginSample ("LoadTexture");
191
192 Profiler.BeginSample ("LoadFile");
193 byte[] array = cache.LoadTile (zoomLevel, _fileName);
194 Profiler.EndSample ();
195
196 Profiler.BeginSample ("LoadImage");
197 if (array != null && blockMap.LoadImage (array) && blockMap.height == Constants.MapBlockSize &&
198 blockMap.width == Constants.MapBlockSize) {
199 Profiler.EndSample ();
200
201 Profiler.EndSample ();
202 return;
203 }
204 Profiler.EndSample ();
205
206 if (array != null) {
207 Log.Error ($"Map image tile {_fileName} has been corrupted, recreating tile");
208 }
209
210 if (blockMap.format != Constants.DefaultTextureFormat || blockMap.height != Constants.MapBlockSize ||
211 blockMap.width != Constants.MapBlockSize) {
212 blockMap.Reinitialize (Constants.MapBlockSize, Constants.MapBlockSize, Constants.DefaultTextureFormat,
213 false);
214 }
215
216 blockMap.LoadRawTextureData (emptyImageData);
217
218 Profiler.EndSample ();
219 }
220
221 private void saveTextureToFile () {
222 Profiler.BeginSample ("EncodePNG");
223 byte[] array = blockMap.EncodeToPNG ();
224 Profiler.EndSample ();
225
226 cache.SaveTile (zoomLevel, array);
227 }
228 }
229}
Note: See TracBrowser for help on using the repository browser.