aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/TerrainData.cs
diff options
context:
space:
mode:
authoronefang2019-09-11 16:36:50 +1000
committeronefang2019-09-11 16:36:50 +1000
commit50cd1ffd32f69228e566f2b0b89f86ea0d9fe489 (patch)
tree52f2ab0c04f1a5d7d6ac5dc872981b4b156447e7 /OpenSim/Framework/TerrainData.cs
parentRenamed branch to SledjChisl. (diff)
parentBump to release flavour, build 0. (diff)
downloadopensim-SC_OLD-50cd1ffd32f69228e566f2b0b89f86ea0d9fe489.zip
opensim-SC_OLD-50cd1ffd32f69228e566f2b0b89f86ea0d9fe489.tar.gz
opensim-SC_OLD-50cd1ffd32f69228e566f2b0b89f86ea0d9fe489.tar.bz2
opensim-SC_OLD-50cd1ffd32f69228e566f2b0b89f86ea0d9fe489.tar.xz
Merge branch 'SledjChisl'
Diffstat (limited to 'OpenSim/Framework/TerrainData.cs')
-rw-r--r--OpenSim/Framework/TerrainData.cs324
1 files changed, 268 insertions, 56 deletions
diff --git a/OpenSim/Framework/TerrainData.cs b/OpenSim/Framework/TerrainData.cs
index 6b1be4e..5cec2b5 100644
--- a/OpenSim/Framework/TerrainData.cs
+++ b/OpenSim/Framework/TerrainData.cs
@@ -28,6 +28,7 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.IO; 30using System.IO;
31using System.IO.Compression;
31using System.Reflection; 32using System.Reflection;
32 33
33using OpenMetaverse; 34using OpenMetaverse;
@@ -48,6 +49,7 @@ namespace OpenSim.Framework
48 49
49 public abstract float this[int x, int y] { get; set; } 50 public abstract float this[int x, int y] { get; set; }
50 // Someday terrain will have caves 51 // Someday terrain will have caves
52 // at most holes :p
51 public abstract float this[int x, int y, int z] { get; set; } 53 public abstract float this[int x, int y, int z] { get; set; }
52 54
53 public abstract bool IsTaintedAt(int xx, int yy); 55 public abstract bool IsTaintedAt(int xx, int yy);
@@ -72,8 +74,8 @@ namespace OpenSim.Framework
72 return new HeightmapTerrainData(pSizeX, pSizeY, pSizeZ, pFormatCode, pBlob); 74 return new HeightmapTerrainData(pSizeX, pSizeY, pSizeZ, pFormatCode, pBlob);
73 } 75 }
74 76
75 // return a special compressed representation of the heightmap in ints 77 // return a special compressed representation of the heightmap in ushort
76 public abstract int[] GetCompressedMap(); 78 public abstract float[] GetCompressedMap();
77 public abstract float CompressionFactor { get; } 79 public abstract float CompressionFactor { get; }
78 80
79 public abstract float[] GetFloatsSerialized(); 81 public abstract float[] GetFloatsSerialized();
@@ -94,14 +96,18 @@ namespace OpenSim.Framework
94 { 96 {
95 // Terrain is 'double[256,256]' 97 // Terrain is 'double[256,256]'
96 Legacy256 = 11, 98 Legacy256 = 11,
99
97 // Terrain is 'int32, int32, float[,]' where the ints are X and Y dimensions 100 // Terrain is 'int32, int32, float[,]' where the ints are X and Y dimensions
98 // The dimensions are presumed to be multiples of 16 and, more likely, multiples of 256. 101 // The dimensions are presumed to be multiples of 16 and, more likely, multiples of 256.
99 Variable2D = 22, 102 Variable2D = 22,
103 Variable2DGzip = 23,
104
100 // Terrain is 'int32, int32, int32, int16[]' where the ints are X and Y dimensions 105 // Terrain is 'int32, int32, int32, int16[]' where the ints are X and Y dimensions
101 // and third int is the 'compression factor'. The heights are compressed as 106 // and third int is the 'compression factor'. The heights are compressed as
102 // "int compressedHeight = (int)(height * compressionFactor);" 107 // "ushort compressedHeight = (ushort)(height * compressionFactor);"
103 // The dimensions are presumed to be multiples of 16 and, more likely, multiples of 256. 108 // The dimensions are presumed to be multiples of 16 and, more likely, multiples of 256.
104 Compressed2D = 27, 109 Compressed2D = 27,
110
105 // A revision that is not listed above or any revision greater than this value is 'Legacy256'. 111 // A revision that is not listed above or any revision greater than this value is 'Legacy256'.
106 RevisionHigh = 1234 112 RevisionHigh = 1234
107 } 113 }
@@ -109,7 +115,7 @@ namespace OpenSim.Framework
109 // Version of terrain that is a heightmap. 115 // Version of terrain that is a heightmap.
110 // This should really be 'LLOptimizedHeightmapTerrainData' as it includes knowledge 116 // This should really be 'LLOptimizedHeightmapTerrainData' as it includes knowledge
111 // of 'patches' which are 16x16 terrain areas which can be sent separately to the viewer. 117 // of 'patches' which are 16x16 terrain areas which can be sent separately to the viewer.
112 // The heighmap is kept as an array of integers. The integer values are converted to 118 // The heighmap is kept as an array of ushorts. The ushort values are converted to
113 // and from floats by TerrainCompressionFactor. 119 // and from floats by TerrainCompressionFactor.
114 public class HeightmapTerrainData : TerrainData 120 public class HeightmapTerrainData : TerrainData
115 { 121 {
@@ -119,12 +125,12 @@ namespace OpenSim.Framework
119 // TerrainData.this[x, y] 125 // TerrainData.this[x, y]
120 public override float this[int x, int y] 126 public override float this[int x, int y]
121 { 127 {
122 get { return FromCompressedHeight(m_heightmap[x, y]); } 128 get { return m_heightmap[x, y]; }
123 set { 129 set
124 int newVal = ToCompressedHeight(value); 130 {
125 if (m_heightmap[x, y] != newVal) 131 if (m_heightmap[x, y] != value)
126 { 132 {
127 m_heightmap[x, y] = newVal; 133 m_heightmap[x, y] = value;
128 m_taint[x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize] = true; 134 m_taint[x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize] = true;
129 } 135 }
130 } 136 }
@@ -164,10 +170,9 @@ namespace OpenSim.Framework
164 // TerrainData.ClearLand(float) 170 // TerrainData.ClearLand(float)
165 public override void ClearLand(float pHeight) 171 public override void ClearLand(float pHeight)
166 { 172 {
167 int flatHeight = ToCompressedHeight(pHeight);
168 for (int xx = 0; xx < SizeX; xx++) 173 for (int xx = 0; xx < SizeX; xx++)
169 for (int yy = 0; yy < SizeY; yy++) 174 for (int yy = 0; yy < SizeY; yy++)
170 m_heightmap[xx, yy] = flatHeight; 175 m_heightmap[xx, yy] = pHeight;
171 } 176 }
172 177
173 // Return 'true' of the patch that contains these region coordinates has been modified. 178 // Return 'true' of the patch that contains these region coordinates has been modified.
@@ -177,13 +182,15 @@ namespace OpenSim.Framework
177 { 182 {
178 int tx = xx / Constants.TerrainPatchSize; 183 int tx = xx / Constants.TerrainPatchSize;
179 int ty = yy / Constants.TerrainPatchSize; 184 int ty = yy / Constants.TerrainPatchSize;
180 bool ret = m_taint[tx, ty]; 185 bool ret = m_taint[tx, ty];
181 if (ret && clearOnTest) 186 if (ret && clearOnTest)
182 m_taint[tx, ty] = false; 187 m_taint[tx, ty] = false;
183 return ret; 188 return ret;
184 } 189 }
185 190
186 // Old form that clears the taint flag when we check it. 191 // Old form that clears the taint flag when we check it.
192 // ubit: this dangerus naming should be only check without clear
193 // keeping for old modules outthere
187 public override bool IsTaintedAt(int xx, int yy) 194 public override bool IsTaintedAt(int xx, int yy)
188 { 195 {
189 return IsTaintedAt(xx, yy, true /* clearOnTest */); 196 return IsTaintedAt(xx, yy, true /* clearOnTest */);
@@ -194,6 +201,7 @@ namespace OpenSim.Framework
194 public override bool GetDatabaseBlob(out int DBRevisionCode, out Array blob) 201 public override bool GetDatabaseBlob(out int DBRevisionCode, out Array blob)
195 { 202 {
196 bool ret = false; 203 bool ret = false;
204/* save all as Variable2DGzip
197 if (SizeX == Constants.RegionSize && SizeY == Constants.RegionSize) 205 if (SizeX == Constants.RegionSize && SizeY == Constants.RegionSize)
198 { 206 {
199 DBRevisionCode = (int)DBTerrainRevision.Legacy256; 207 DBRevisionCode = (int)DBTerrainRevision.Legacy256;
@@ -202,10 +210,13 @@ namespace OpenSim.Framework
202 } 210 }
203 else 211 else
204 { 212 {
205 DBRevisionCode = (int)DBTerrainRevision.Compressed2D; 213*/
206 blob = ToCompressedTerrainSerialization(); 214 DBRevisionCode = (int)DBTerrainRevision.Variable2DGzip;
215// DBRevisionCode = (int)DBTerrainRevision.Variable2D;
216 blob = ToCompressedTerrainSerializationV2DGzip();
217// blob = ToCompressedTerrainSerializationV2D();
207 ret = true; 218 ret = true;
208 } 219// }
209 return ret; 220 return ret;
210 } 221 }
211 222
@@ -214,9 +225,9 @@ namespace OpenSim.Framework
214 public override float CompressionFactor { get { return m_compressionFactor; } } 225 public override float CompressionFactor { get { return m_compressionFactor; } }
215 226
216 // TerrainData.GetCompressedMap 227 // TerrainData.GetCompressedMap
217 public override int[] GetCompressedMap() 228 public override float[] GetCompressedMap()
218 { 229 {
219 int[] newMap = new int[SizeX * SizeY]; 230 float[] newMap = new float[SizeX * SizeY];
220 231
221 int ind = 0; 232 int ind = 0;
222 for (int xx = 0; xx < SizeX; xx++) 233 for (int xx = 0; xx < SizeX; xx++)
@@ -230,7 +241,7 @@ namespace OpenSim.Framework
230 public override TerrainData Clone() 241 public override TerrainData Clone()
231 { 242 {
232 HeightmapTerrainData ret = new HeightmapTerrainData(SizeX, SizeY, SizeZ); 243 HeightmapTerrainData ret = new HeightmapTerrainData(SizeX, SizeY, SizeZ);
233 ret.m_heightmap = (int[,])this.m_heightmap.Clone(); 244 ret.m_heightmap = (float[,])this.m_heightmap.Clone();
234 return ret; 245 return ret;
235 } 246 }
236 247
@@ -247,7 +258,7 @@ namespace OpenSim.Framework
247 for (int jj = 0; jj < SizeY; jj++) 258 for (int jj = 0; jj < SizeY; jj++)
248 for (int ii = 0; ii < SizeX; ii++) 259 for (int ii = 0; ii < SizeX; ii++)
249 { 260 {
250 heights[idx++] = FromCompressedHeight(m_heightmap[ii, jj]); 261 heights[idx++] = m_heightmap[ii, jj];
251 } 262 }
252 263
253 return heights; 264 return heights;
@@ -259,7 +270,7 @@ namespace OpenSim.Framework
259 double[,] ret = new double[SizeX, SizeY]; 270 double[,] ret = new double[SizeX, SizeY];
260 for (int xx = 0; xx < SizeX; xx++) 271 for (int xx = 0; xx < SizeX; xx++)
261 for (int yy = 0; yy < SizeY; yy++) 272 for (int yy = 0; yy < SizeY; yy++)
262 ret[xx, yy] = FromCompressedHeight(m_heightmap[xx, yy]); 273 ret[xx, yy] = (double)m_heightmap[xx, yy];
263 274
264 return ret; 275 return ret;
265 } 276 }
@@ -267,19 +278,40 @@ namespace OpenSim.Framework
267 278
268 // ============================================================= 279 // =============================================================
269 280
270 private int[,] m_heightmap; 281 private float[,] m_heightmap;
271 // Remember subregions of the heightmap that has changed. 282 // Remember subregions of the heightmap that has changed.
272 private bool[,] m_taint; 283 private bool[,] m_taint;
273 284
274 // To save space (especially for large regions), keep the height as a short integer
275 // that is coded as the float height times the compression factor (usually '100' 285 // that is coded as the float height times the compression factor (usually '100'
276 // to make for two decimal points). 286 // to make for two decimal points).
277 public int ToCompressedHeight(double pHeight) 287 public short ToCompressedHeightshort(float pHeight)
278 { 288 {
279 return (int)(pHeight * CompressionFactor); 289 // clamp into valid range
290 pHeight *= CompressionFactor;
291 if (pHeight < short.MinValue)
292 return short.MinValue;
293 else if (pHeight > short.MaxValue)
294 return short.MaxValue;
295 return (short)pHeight;
280 } 296 }
281 297
282 public float FromCompressedHeight(int pHeight) 298 public ushort ToCompressedHeightushort(float pHeight)
299 {
300 // clamp into valid range
301 pHeight *= CompressionFactor;
302 if (pHeight < ushort.MinValue)
303 return ushort.MinValue;
304 else if (pHeight > ushort.MaxValue)
305 return ushort.MaxValue;
306 return (ushort)pHeight;
307 }
308
309 public float FromCompressedHeight(short pHeight)
310 {
311 return ((float)pHeight) / CompressionFactor;
312 }
313
314 public float FromCompressedHeight(ushort pHeight)
283 { 315 {
284 return ((float)pHeight) / CompressionFactor; 316 return ((float)pHeight) / CompressionFactor;
285 } 317 }
@@ -293,12 +325,12 @@ namespace OpenSim.Framework
293 SizeZ = (int)Constants.RegionHeight; 325 SizeZ = (int)Constants.RegionHeight;
294 m_compressionFactor = 100.0f; 326 m_compressionFactor = 100.0f;
295 327
296 m_heightmap = new int[SizeX, SizeY]; 328 m_heightmap = new float[SizeX, SizeY];
297 for (int ii = 0; ii < SizeX; ii++) 329 for (int ii = 0; ii < SizeX; ii++)
298 { 330 {
299 for (int jj = 0; jj < SizeY; jj++) 331 for (int jj = 0; jj < SizeY; jj++)
300 { 332 {
301 m_heightmap[ii, jj] = ToCompressedHeight(pTerrain[ii, jj]); 333 m_heightmap[ii, jj] = (float)pTerrain[ii, jj];
302 334
303 } 335 }
304 } 336 }
@@ -315,14 +347,15 @@ namespace OpenSim.Framework
315 SizeY = pY; 347 SizeY = pY;
316 SizeZ = pZ; 348 SizeZ = pZ;
317 m_compressionFactor = 100.0f; 349 m_compressionFactor = 100.0f;
318 m_heightmap = new int[SizeX, SizeY]; 350 m_heightmap = new float[SizeX, SizeY];
319 m_taint = new bool[SizeX / Constants.TerrainPatchSize, SizeY / Constants.TerrainPatchSize]; 351 m_taint = new bool[SizeX / Constants.TerrainPatchSize, SizeY / Constants.TerrainPatchSize];
320 // m_log.DebugFormat("{0} new by dimensions. sizeX={1}, sizeY={2}, sizeZ={3}", LogHeader, SizeX, SizeY, SizeZ); 352 // m_log.DebugFormat("{0} new by dimensions. sizeX={1}, sizeY={2}, sizeZ={3}", LogHeader, SizeX, SizeY, SizeZ);
321 ClearTaint(); 353 ClearTaint();
322 ClearLand(0f); 354 ClearLand(0f);
323 } 355 }
324 356
325 public HeightmapTerrainData(int[] cmap, float pCompressionFactor, int pX, int pY, int pZ) : this(pX, pY, pZ) 357 public HeightmapTerrainData(float[] cmap, float pCompressionFactor, int pX, int pY, int pZ)
358 : this(pX, pY, pZ)
326 { 359 {
327 m_compressionFactor = pCompressionFactor; 360 m_compressionFactor = pCompressionFactor;
328 int ind = 0; 361 int ind = 0;
@@ -333,12 +366,22 @@ namespace OpenSim.Framework
333 } 366 }
334 367
335 // Create a heighmap from a database blob 368 // Create a heighmap from a database blob
336 public HeightmapTerrainData(int pSizeX, int pSizeY, int pSizeZ, int pFormatCode, byte[] pBlob) : this(pSizeX, pSizeY, pSizeZ) 369 public HeightmapTerrainData(int pSizeX, int pSizeY, int pSizeZ, int pFormatCode, byte[] pBlob)
370 : this(pSizeX, pSizeY, pSizeZ)
337 { 371 {
338 switch ((DBTerrainRevision)pFormatCode) 372 switch ((DBTerrainRevision)pFormatCode)
339 { 373 {
374 case DBTerrainRevision.Variable2DGzip:
375 FromCompressedTerrainSerializationV2DGZip(pBlob);
376 m_log.DebugFormat("{0} HeightmapTerrainData create from Variable2DGzip serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY);
377 break;
378
379 case DBTerrainRevision.Variable2D:
380 FromCompressedTerrainSerializationV2D(pBlob);
381 m_log.DebugFormat("{0} HeightmapTerrainData create from Variable2D serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY);
382 break;
340 case DBTerrainRevision.Compressed2D: 383 case DBTerrainRevision.Compressed2D:
341 FromCompressedTerrainSerialization(pBlob); 384 FromCompressedTerrainSerialization2D(pBlob);
342 m_log.DebugFormat("{0} HeightmapTerrainData create from Compressed2D serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY); 385 m_log.DebugFormat("{0} HeightmapTerrainData create from Compressed2D serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY);
343 break; 386 break;
344 default: 387 default:
@@ -373,50 +416,116 @@ namespace OpenSim.Framework
373 return ret; 416 return ret;
374 } 417 }
375 418
376 // Just create an array of doubles. Presumes the caller implicitly knows the size. 419 // Presumes the caller implicitly knows the size.
377 public void FromLegacyTerrainSerialization(byte[] pBlob) 420 public void FromLegacyTerrainSerialization(byte[] pBlob)
378 { 421 {
379 // In case database info doesn't match real terrain size, initialize the whole terrain. 422 // In case database info doesn't match real terrain size, initialize the whole terrain.
380 ClearLand(); 423 ClearLand();
381 424
382 using (MemoryStream mstr = new MemoryStream(pBlob)) 425 try
383 { 426 {
384 using (BinaryReader br = new BinaryReader(mstr)) 427 using (MemoryStream mstr = new MemoryStream(pBlob))
385 { 428 {
386 for (int xx = 0; xx < (int)Constants.RegionSize; xx++) 429 using (BinaryReader br = new BinaryReader(mstr))
387 { 430 {
388 for (int yy = 0; yy < (int)Constants.RegionSize; yy++) 431 for (int xx = 0; xx < (int)Constants.RegionSize; xx++)
389 { 432 {
390 float val = (float)br.ReadDouble(); 433 for (int yy = 0; yy < (int)Constants.RegionSize; yy++)
391 if (xx < SizeX && yy < SizeY) 434 {
392 m_heightmap[xx, yy] = ToCompressedHeight(val); 435 float val = (float)br.ReadDouble();
436
437 if (xx < SizeX && yy < SizeY)
438 m_heightmap[xx, yy] = val;
439 }
393 } 440 }
394 } 441 }
395 } 442 }
396 ClearTaint();
397 } 443 }
444 catch
445 {
446 ClearLand();
447 }
448 ClearTaint();
449 }
450
451
452 // stores as variable2D
453 // int32 sizeX
454 // int32 sizeY
455 // float[,] array
456
457 public Array ToCompressedTerrainSerializationV2D()
458 {
459 Array ret = null;
460 try
461 {
462 using (MemoryStream str = new MemoryStream((2 * sizeof(Int32)) + (SizeX * SizeY * sizeof(float))))
463 {
464 using (BinaryWriter bw = new BinaryWriter(str))
465 {
466 bw.Write((Int32)SizeX);
467 bw.Write((Int32)SizeY);
468 for (int yy = 0; yy < SizeY; yy++)
469 for (int xx = 0; xx < SizeX; xx++)
470 {
471 // reduce to 1cm resolution
472 float val = (float)Math.Round(m_heightmap[xx, yy],2,MidpointRounding.ToEven);
473 bw.Write(val);
474 }
475 }
476 ret = str.ToArray();
477 }
478 }
479 catch
480 {
481
482 }
483
484 m_log.DebugFormat("{0} V2D {1} bytes",
485 LogHeader, ret.Length);
486
487 return ret;
398 } 488 }
399 489
400 // See the reader below. 490 // as above with Gzip compression
401 public Array ToCompressedTerrainSerialization() 491 public Array ToCompressedTerrainSerializationV2DGzip()
402 { 492 {
403 Array ret = null; 493 Array ret = null;
404 using (MemoryStream str = new MemoryStream((3 * sizeof(Int32)) + (SizeX * SizeY * sizeof(Int16)))) 494 try
405 { 495 {
406 using (BinaryWriter bw = new BinaryWriter(str)) 496 using (MemoryStream inp = new MemoryStream((2 * sizeof(Int32)) + (SizeX * SizeY * sizeof(float))))
407 { 497 {
408 bw.Write((Int32)DBTerrainRevision.Compressed2D); 498 using (BinaryWriter bw = new BinaryWriter(inp))
409 bw.Write((Int32)SizeX); 499 {
410 bw.Write((Int32)SizeY); 500 bw.Write((Int32)SizeX);
411 bw.Write((Int32)CompressionFactor); 501 bw.Write((Int32)SizeY);
412 for (int yy = 0; yy < SizeY; yy++) 502 for (int yy = 0; yy < SizeY; yy++)
413 for (int xx = 0; xx < SizeX; xx++) 503 for (int xx = 0; xx < SizeX; xx++)
504 {
505 bw.Write((float)m_heightmap[xx, yy]);
506 }
507
508 bw.Flush();
509 inp.Seek(0, SeekOrigin.Begin);
510
511 using (MemoryStream outputStream = new MemoryStream())
414 { 512 {
415 bw.Write((Int16)m_heightmap[xx, yy]); 513 using (GZipStream compressionStream = new GZipStream(outputStream, CompressionMode.Compress))
514 {
515 inp.CopyStream(compressionStream, int.MaxValue);
516 compressionStream.Close();
517 ret = outputStream.ToArray();
518 }
416 } 519 }
520 }
417 } 521 }
418 ret = str.ToArray();
419 } 522 }
523 catch
524 {
525
526 }
527 m_log.DebugFormat("{0} V2DGzip {1} bytes",
528 LogHeader, ret.Length);
420 return ret; 529 return ret;
421 } 530 }
422 531
@@ -426,7 +535,7 @@ namespace OpenSim.Framework
426 // the forth int is the compression factor for the following int16s 535 // the forth int is the compression factor for the following int16s
427 // This is just sets heightmap info. The actual size of the region was set on this instance's 536 // This is just sets heightmap info. The actual size of the region was set on this instance's
428 // creation and any heights not initialized by theis blob are set to the default height. 537 // creation and any heights not initialized by theis blob are set to the default height.
429 public void FromCompressedTerrainSerialization(byte[] pBlob) 538 public void FromCompressedTerrainSerialization2D(byte[] pBlob)
430 { 539 {
431 Int32 hmFormatCode, hmSizeX, hmSizeY, hmCompressionFactor; 540 Int32 hmFormatCode, hmSizeX, hmSizeY, hmCompressionFactor;
432 541
@@ -448,7 +557,7 @@ namespace OpenSim.Framework
448 { 557 {
449 for (int xx = 0; xx < hmSizeX; xx++) 558 for (int xx = 0; xx < hmSizeX; xx++)
450 { 559 {
451 Int16 val = br.ReadInt16(); 560 float val = FromCompressedHeight(br.ReadInt16());
452 if (xx < SizeX && yy < SizeY) 561 if (xx < SizeX && yy < SizeY)
453 m_heightmap[xx, yy] = val; 562 m_heightmap[xx, yy] = val;
454 } 563 }
@@ -456,9 +565,112 @@ namespace OpenSim.Framework
456 } 565 }
457 ClearTaint(); 566 ClearTaint();
458 567
459 m_log.InfoFormat("{0} Read compressed 2d heightmap. Heightmap size=<{1},{2}>. Region size=<{3},{4}>. CompFact={5}", 568 m_log.DebugFormat("{0} Read (compressed2D) heightmap. Heightmap size=<{1},{2}>. Region size=<{3},{4}>. CompFact={5}",
460 LogHeader, hmSizeX, hmSizeY, SizeX, SizeY, hmCompressionFactor); 569 LogHeader, hmSizeX, hmSizeY, SizeX, SizeY, hmCompressionFactor);
461 } 570 }
462 } 571 }
572
573 // Initialize heightmap from blob consisting of:
574 // int32, int32, int32, float[]
575 // where the first int32 is format code, next two int32s are the X and y of heightmap data
576 // This is just sets heightmap info. The actual size of the region was set on this instance's
577 // creation and any heights not initialized by theis blob are set to the default height.
578 public void FromCompressedTerrainSerializationV2D(byte[] pBlob)
579 {
580 Int32 hmSizeX, hmSizeY;
581 try
582 {
583 using (MemoryStream mstr = new MemoryStream(pBlob))
584 {
585 using (BinaryReader br = new BinaryReader(mstr))
586 {
587 hmSizeX = br.ReadInt32();
588 hmSizeY = br.ReadInt32();
589
590 // In case database info doesn't match real terrain size, initialize the whole terrain.
591 ClearLand();
592
593 for (int yy = 0; yy < hmSizeY; yy++)
594 {
595 for (int xx = 0; xx < hmSizeX; xx++)
596 {
597 float val = br.ReadSingle();
598 if (xx < SizeX && yy < SizeY)
599 m_heightmap[xx, yy] = val;
600 }
601 }
602 }
603 }
604 }
605 catch (Exception e)
606 {
607 ClearTaint();
608 m_log.ErrorFormat("{0} 2D error: {1} - terrain may be damaged",
609 LogHeader, e.Message);
610 return;
611 }
612 ClearTaint();
613
614 m_log.DebugFormat("{0} V2D Heightmap size=<{1},{2}>. Region size=<{3},{4}>",
615 LogHeader, hmSizeX, hmSizeY, SizeX, SizeY);
616
617 }
618
619 // as above but Gzip compressed
620 public void FromCompressedTerrainSerializationV2DGZip(byte[] pBlob)
621 {
622 m_log.InfoFormat("{0} VD2Gzip {1} bytes input",
623 LogHeader, pBlob.Length);
624
625 Int32 hmSizeX, hmSizeY;
626
627 try
628 {
629 using (MemoryStream outputStream = new MemoryStream())
630 {
631 using (MemoryStream inputStream = new MemoryStream(pBlob))
632 {
633 using (GZipStream decompressionStream = new GZipStream(inputStream, CompressionMode.Decompress))
634 {
635 decompressionStream.Flush();
636 decompressionStream.CopyTo(outputStream);
637 }
638 }
639
640 outputStream.Seek(0, SeekOrigin.Begin);
641
642 using (BinaryReader br = new BinaryReader(outputStream))
643 {
644 hmSizeX = br.ReadInt32();
645 hmSizeY = br.ReadInt32();
646
647 // In case database info doesn't match real terrain size, initialize the whole terrain.
648 ClearLand();
649
650 for (int yy = 0; yy < hmSizeY; yy++)
651 {
652 for (int xx = 0; xx < hmSizeX; xx++)
653 {
654 float val = br.ReadSingle();
655 if (xx < SizeX && yy < SizeY)
656 m_heightmap[xx, yy] = val;
657 }
658 }
659 }
660 }
661 }
662 catch( Exception e)
663 {
664 ClearTaint();
665 m_log.ErrorFormat("{0} V2DGzip error: {1} - terrain may be damaged",
666 LogHeader, e.Message);
667 return;
668 }
669
670 ClearTaint();
671 m_log.DebugFormat("{0} V2DGzip. Heightmap size=<{1},{2}>. Region size=<{3},{4}>",
672 LogHeader, hmSizeX, hmSizeY, SizeX, SizeY);
673
674 }
463 } 675 }
464} 676}