source: binary-improvements/MapRendering/MapRendering/MapRenderBlockBuffer.cs @ 332

Last change on this file since 332 was 332, checked in by alloc, 5 years ago

*Latest optimizations

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