aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/TerrainData.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Framework/TerrainData.cs320
1 files changed, 265 insertions, 55 deletions
diff --git a/OpenSim/Framework/TerrainData.cs b/OpenSim/Framework/TerrainData.cs
index 6b1be4e..d2e1c6a 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 */);
@@ -202,8 +209,10 @@ namespace OpenSim.Framework
202 } 209 }
203 else 210 else
204 { 211 {
205 DBRevisionCode = (int)DBTerrainRevision.Compressed2D; 212 DBRevisionCode = (int)DBTerrainRevision.Variable2DGzip;
206 blob = ToCompressedTerrainSerialization(); 213// DBRevisionCode = (int)DBTerrainRevision.Variable2D;
214 blob = ToCompressedTerrainSerializationV2DGzip();
215// blob = ToCompressedTerrainSerializationV2D();
207 ret = true; 216 ret = true;
208 } 217 }
209 return ret; 218 return ret;
@@ -214,9 +223,9 @@ namespace OpenSim.Framework
214 public override float CompressionFactor { get { return m_compressionFactor; } } 223 public override float CompressionFactor { get { return m_compressionFactor; } }
215 224
216 // TerrainData.GetCompressedMap 225 // TerrainData.GetCompressedMap
217 public override int[] GetCompressedMap() 226 public override float[] GetCompressedMap()
218 { 227 {
219 int[] newMap = new int[SizeX * SizeY]; 228 float[] newMap = new float[SizeX * SizeY];
220 229
221 int ind = 0; 230 int ind = 0;
222 for (int xx = 0; xx < SizeX; xx++) 231 for (int xx = 0; xx < SizeX; xx++)
@@ -230,7 +239,7 @@ namespace OpenSim.Framework
230 public override TerrainData Clone() 239 public override TerrainData Clone()
231 { 240 {
232 HeightmapTerrainData ret = new HeightmapTerrainData(SizeX, SizeY, SizeZ); 241 HeightmapTerrainData ret = new HeightmapTerrainData(SizeX, SizeY, SizeZ);
233 ret.m_heightmap = (int[,])this.m_heightmap.Clone(); 242 ret.m_heightmap = (float[,])this.m_heightmap.Clone();
234 return ret; 243 return ret;
235 } 244 }
236 245
@@ -247,7 +256,7 @@ namespace OpenSim.Framework
247 for (int jj = 0; jj < SizeY; jj++) 256 for (int jj = 0; jj < SizeY; jj++)
248 for (int ii = 0; ii < SizeX; ii++) 257 for (int ii = 0; ii < SizeX; ii++)
249 { 258 {
250 heights[idx++] = FromCompressedHeight(m_heightmap[ii, jj]); 259 heights[idx++] = m_heightmap[ii, jj];
251 } 260 }
252 261
253 return heights; 262 return heights;
@@ -259,7 +268,7 @@ namespace OpenSim.Framework
259 double[,] ret = new double[SizeX, SizeY]; 268 double[,] ret = new double[SizeX, SizeY];
260 for (int xx = 0; xx < SizeX; xx++) 269 for (int xx = 0; xx < SizeX; xx++)
261 for (int yy = 0; yy < SizeY; yy++) 270 for (int yy = 0; yy < SizeY; yy++)
262 ret[xx, yy] = FromCompressedHeight(m_heightmap[xx, yy]); 271 ret[xx, yy] = (double)m_heightmap[xx, yy];
263 272
264 return ret; 273 return ret;
265 } 274 }
@@ -267,19 +276,40 @@ namespace OpenSim.Framework
267 276
268 // ============================================================= 277 // =============================================================
269 278
270 private int[,] m_heightmap; 279 private float[,] m_heightmap;
271 // Remember subregions of the heightmap that has changed. 280 // Remember subregions of the heightmap that has changed.
272 private bool[,] m_taint; 281 private bool[,] m_taint;
273 282
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' 283 // that is coded as the float height times the compression factor (usually '100'
276 // to make for two decimal points). 284 // to make for two decimal points).
277 public int ToCompressedHeight(double pHeight) 285 public short ToCompressedHeightshort(float pHeight)
286 {
287 // clamp into valid range
288 pHeight *= CompressionFactor;
289 if (pHeight < short.MinValue)
290 return short.MinValue;
291 else if (pHeight > short.MaxValue)
292 return short.MaxValue;
293 return (short)pHeight;
294 }
295
296 public ushort ToCompressedHeightushort(float pHeight)
278 { 297 {
279 return (int)(pHeight * CompressionFactor); 298 // clamp into valid range
299 pHeight *= CompressionFactor;
300 if (pHeight < ushort.MinValue)
301 return ushort.MinValue;
302 else if (pHeight > ushort.MaxValue)
303 return ushort.MaxValue;
304 return (ushort)pHeight;
280 } 305 }
281 306
282 public float FromCompressedHeight(int pHeight) 307 public float FromCompressedHeight(short pHeight)
308 {
309 return ((float)pHeight) / CompressionFactor;
310 }
311
312 public float FromCompressedHeight(ushort pHeight)
283 { 313 {
284 return ((float)pHeight) / CompressionFactor; 314 return ((float)pHeight) / CompressionFactor;
285 } 315 }
@@ -293,12 +323,12 @@ namespace OpenSim.Framework
293 SizeZ = (int)Constants.RegionHeight; 323 SizeZ = (int)Constants.RegionHeight;
294 m_compressionFactor = 100.0f; 324 m_compressionFactor = 100.0f;
295 325
296 m_heightmap = new int[SizeX, SizeY]; 326 m_heightmap = new float[SizeX, SizeY];
297 for (int ii = 0; ii < SizeX; ii++) 327 for (int ii = 0; ii < SizeX; ii++)
298 { 328 {
299 for (int jj = 0; jj < SizeY; jj++) 329 for (int jj = 0; jj < SizeY; jj++)
300 { 330 {
301 m_heightmap[ii, jj] = ToCompressedHeight(pTerrain[ii, jj]); 331 m_heightmap[ii, jj] = (float)pTerrain[ii, jj];
302 332
303 } 333 }
304 } 334 }
@@ -315,14 +345,15 @@ namespace OpenSim.Framework
315 SizeY = pY; 345 SizeY = pY;
316 SizeZ = pZ; 346 SizeZ = pZ;
317 m_compressionFactor = 100.0f; 347 m_compressionFactor = 100.0f;
318 m_heightmap = new int[SizeX, SizeY]; 348 m_heightmap = new float[SizeX, SizeY];
319 m_taint = new bool[SizeX / Constants.TerrainPatchSize, SizeY / Constants.TerrainPatchSize]; 349 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); 350 // m_log.DebugFormat("{0} new by dimensions. sizeX={1}, sizeY={2}, sizeZ={3}", LogHeader, SizeX, SizeY, SizeZ);
321 ClearTaint(); 351 ClearTaint();
322 ClearLand(0f); 352 ClearLand(0f);
323 } 353 }
324 354
325 public HeightmapTerrainData(int[] cmap, float pCompressionFactor, int pX, int pY, int pZ) : this(pX, pY, pZ) 355 public HeightmapTerrainData(float[] cmap, float pCompressionFactor, int pX, int pY, int pZ)
356 : this(pX, pY, pZ)
326 { 357 {
327 m_compressionFactor = pCompressionFactor; 358 m_compressionFactor = pCompressionFactor;
328 int ind = 0; 359 int ind = 0;
@@ -333,12 +364,22 @@ namespace OpenSim.Framework
333 } 364 }
334 365
335 // Create a heighmap from a database blob 366 // Create a heighmap from a database blob
336 public HeightmapTerrainData(int pSizeX, int pSizeY, int pSizeZ, int pFormatCode, byte[] pBlob) : this(pSizeX, pSizeY, pSizeZ) 367 public HeightmapTerrainData(int pSizeX, int pSizeY, int pSizeZ, int pFormatCode, byte[] pBlob)
368 : this(pSizeX, pSizeY, pSizeZ)
337 { 369 {
338 switch ((DBTerrainRevision)pFormatCode) 370 switch ((DBTerrainRevision)pFormatCode)
339 { 371 {
372 case DBTerrainRevision.Variable2DGzip:
373 FromCompressedTerrainSerializationV2DGZip(pBlob);
374 m_log.DebugFormat("{0} HeightmapTerrainData create from Variable2DGzip serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY);
375 break;
376
377 case DBTerrainRevision.Variable2D:
378 FromCompressedTerrainSerializationV2D(pBlob);
379 m_log.DebugFormat("{0} HeightmapTerrainData create from Variable2D serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY);
380 break;
340 case DBTerrainRevision.Compressed2D: 381 case DBTerrainRevision.Compressed2D:
341 FromCompressedTerrainSerialization(pBlob); 382 FromCompressedTerrainSerialization2D(pBlob);
342 m_log.DebugFormat("{0} HeightmapTerrainData create from Compressed2D serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY); 383 m_log.DebugFormat("{0} HeightmapTerrainData create from Compressed2D serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY);
343 break; 384 break;
344 default: 385 default:
@@ -373,50 +414,116 @@ namespace OpenSim.Framework
373 return ret; 414 return ret;
374 } 415 }
375 416
376 // Just create an array of doubles. Presumes the caller implicitly knows the size. 417 // Presumes the caller implicitly knows the size.
377 public void FromLegacyTerrainSerialization(byte[] pBlob) 418 public void FromLegacyTerrainSerialization(byte[] pBlob)
378 { 419 {
379 // In case database info doesn't match real terrain size, initialize the whole terrain. 420 // In case database info doesn't match real terrain size, initialize the whole terrain.
380 ClearLand(); 421 ClearLand();
381 422
382 using (MemoryStream mstr = new MemoryStream(pBlob)) 423 try
383 { 424 {
384 using (BinaryReader br = new BinaryReader(mstr)) 425 using (MemoryStream mstr = new MemoryStream(pBlob))
385 { 426 {
386 for (int xx = 0; xx < (int)Constants.RegionSize; xx++) 427 using (BinaryReader br = new BinaryReader(mstr))
387 { 428 {
388 for (int yy = 0; yy < (int)Constants.RegionSize; yy++) 429 for (int xx = 0; xx < (int)Constants.RegionSize; xx++)
389 { 430 {
390 float val = (float)br.ReadDouble(); 431 for (int yy = 0; yy < (int)Constants.RegionSize; yy++)
391 if (xx < SizeX && yy < SizeY) 432 {
392 m_heightmap[xx, yy] = ToCompressedHeight(val); 433 float val = (float)br.ReadDouble();
434
435 if (xx < SizeX && yy < SizeY)
436 m_heightmap[xx, yy] = val;
437 }
393 } 438 }
394 } 439 }
395 } 440 }
396 ClearTaint();
397 } 441 }
442 catch
443 {
444 ClearLand();
445 }
446 ClearTaint();
398 } 447 }
399 448
400 // See the reader below. 449
401 public Array ToCompressedTerrainSerialization() 450 // stores as variable2D
451 // int32 sizeX
452 // int32 sizeY
453 // float[,] array
454
455 public Array ToCompressedTerrainSerializationV2D()
402 { 456 {
403 Array ret = null; 457 Array ret = null;
404 using (MemoryStream str = new MemoryStream((3 * sizeof(Int32)) + (SizeX * SizeY * sizeof(Int16)))) 458 try
405 { 459 {
406 using (BinaryWriter bw = new BinaryWriter(str)) 460 using (MemoryStream str = new MemoryStream((2 * sizeof(Int32)) + (SizeX * SizeY * sizeof(float))))
461 {
462 using (BinaryWriter bw = new BinaryWriter(str))
463 {
464 bw.Write((Int32)SizeX);
465 bw.Write((Int32)SizeY);
466 for (int yy = 0; yy < SizeY; yy++)
467 for (int xx = 0; xx < SizeX; xx++)
468 {
469 // reduce to 1cm resolution
470 float val = (float)Math.Round(m_heightmap[xx, yy],2,MidpointRounding.ToEven);
471 bw.Write(val);
472 }
473 }
474 ret = str.ToArray();
475 }
476 }
477 catch
478 {
479
480 }
481
482 m_log.DebugFormat("{0} V2D {1} bytes",
483 LogHeader, ret.Length);
484
485 return ret;
486 }
487
488 // as above with Gzip compression
489 public Array ToCompressedTerrainSerializationV2DGzip()
490 {
491 Array ret = null;
492 try
493 {
494 using (MemoryStream inp = new MemoryStream((2 * sizeof(Int32)) + (SizeX * SizeY * sizeof(float))))
407 { 495 {
408 bw.Write((Int32)DBTerrainRevision.Compressed2D); 496 using (BinaryWriter bw = new BinaryWriter(inp))
409 bw.Write((Int32)SizeX); 497 {
410 bw.Write((Int32)SizeY); 498 bw.Write((Int32)SizeX);
411 bw.Write((Int32)CompressionFactor); 499 bw.Write((Int32)SizeY);
412 for (int yy = 0; yy < SizeY; yy++) 500 for (int yy = 0; yy < SizeY; yy++)
413 for (int xx = 0; xx < SizeX; xx++) 501 for (int xx = 0; xx < SizeX; xx++)
502 {
503 bw.Write((float)m_heightmap[xx, yy]);
504 }
505
506 bw.Flush();
507 inp.Seek(0, SeekOrigin.Begin);
508
509 using (MemoryStream outputStream = new MemoryStream())
414 { 510 {
415 bw.Write((Int16)m_heightmap[xx, yy]); 511 using (GZipStream compressionStream = new GZipStream(outputStream, CompressionMode.Compress))
512 {
513 inp.CopyStream(compressionStream, int.MaxValue);
514 compressionStream.Close();
515 ret = outputStream.ToArray();
516 }
416 } 517 }
518 }
417 } 519 }
418 ret = str.ToArray();
419 } 520 }
521 catch
522 {
523
524 }
525 m_log.DebugFormat("{0} V2DGzip {1} bytes",
526 LogHeader, ret.Length);
420 return ret; 527 return ret;
421 } 528 }
422 529
@@ -426,7 +533,7 @@ namespace OpenSim.Framework
426 // the forth int is the compression factor for the following int16s 533 // 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 534 // 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. 535 // creation and any heights not initialized by theis blob are set to the default height.
429 public void FromCompressedTerrainSerialization(byte[] pBlob) 536 public void FromCompressedTerrainSerialization2D(byte[] pBlob)
430 { 537 {
431 Int32 hmFormatCode, hmSizeX, hmSizeY, hmCompressionFactor; 538 Int32 hmFormatCode, hmSizeX, hmSizeY, hmCompressionFactor;
432 539
@@ -448,7 +555,7 @@ namespace OpenSim.Framework
448 { 555 {
449 for (int xx = 0; xx < hmSizeX; xx++) 556 for (int xx = 0; xx < hmSizeX; xx++)
450 { 557 {
451 Int16 val = br.ReadInt16(); 558 float val = FromCompressedHeight(br.ReadInt16());
452 if (xx < SizeX && yy < SizeY) 559 if (xx < SizeX && yy < SizeY)
453 m_heightmap[xx, yy] = val; 560 m_heightmap[xx, yy] = val;
454 } 561 }
@@ -456,9 +563,112 @@ namespace OpenSim.Framework
456 } 563 }
457 ClearTaint(); 564 ClearTaint();
458 565
459 m_log.InfoFormat("{0} Read compressed 2d heightmap. Heightmap size=<{1},{2}>. Region size=<{3},{4}>. CompFact={5}", 566 m_log.DebugFormat("{0} Read (compressed2D) heightmap. Heightmap size=<{1},{2}>. Region size=<{3},{4}>. CompFact={5}",
460 LogHeader, hmSizeX, hmSizeY, SizeX, SizeY, hmCompressionFactor); 567 LogHeader, hmSizeX, hmSizeY, SizeX, SizeY, hmCompressionFactor);
461 } 568 }
462 } 569 }
570
571 // Initialize heightmap from blob consisting of:
572 // int32, int32, int32, float[]
573 // where the first int32 is format code, next two int32s are the X and y of heightmap data
574 // This is just sets heightmap info. The actual size of the region was set on this instance's
575 // creation and any heights not initialized by theis blob are set to the default height.
576 public void FromCompressedTerrainSerializationV2D(byte[] pBlob)
577 {
578 Int32 hmSizeX, hmSizeY;
579 try
580 {
581 using (MemoryStream mstr = new MemoryStream(pBlob))
582 {
583 using (BinaryReader br = new BinaryReader(mstr))
584 {
585 hmSizeX = br.ReadInt32();
586 hmSizeY = br.ReadInt32();
587
588 // In case database info doesn't match real terrain size, initialize the whole terrain.
589 ClearLand();
590
591 for (int yy = 0; yy < hmSizeY; yy++)
592 {
593 for (int xx = 0; xx < hmSizeX; xx++)
594 {
595 float val = br.ReadSingle();
596 if (xx < SizeX && yy < SizeY)
597 m_heightmap[xx, yy] = val;
598 }
599 }
600 }
601 }
602 }
603 catch (Exception e)
604 {
605 ClearTaint();
606 m_log.ErrorFormat("{0} 2D error: {1} - terrain may be damaged",
607 LogHeader, e.Message);
608 return;
609 }
610 ClearTaint();
611
612 m_log.DebugFormat("{0} V2D Heightmap size=<{1},{2}>. Region size=<{3},{4}>",
613 LogHeader, hmSizeX, hmSizeY, SizeX, SizeY);
614
615 }
616
617 // as above but Gzip compressed
618 public void FromCompressedTerrainSerializationV2DGZip(byte[] pBlob)
619 {
620 m_log.InfoFormat("{0} VD2Gzip {1} bytes input",
621 LogHeader, pBlob.Length);
622
623 Int32 hmSizeX, hmSizeY;
624
625 try
626 {
627 using (MemoryStream outputStream = new MemoryStream())
628 {
629 using (MemoryStream inputStream = new MemoryStream(pBlob))
630 {
631 using (GZipStream decompressionStream = new GZipStream(inputStream, CompressionMode.Decompress))
632 {
633 decompressionStream.Flush();
634 decompressionStream.CopyTo(outputStream);
635 }
636 }
637
638 outputStream.Seek(0, SeekOrigin.Begin);
639
640 using (BinaryReader br = new BinaryReader(outputStream))
641 {
642 hmSizeX = br.ReadInt32();
643 hmSizeY = br.ReadInt32();
644
645 // In case database info doesn't match real terrain size, initialize the whole terrain.
646 ClearLand();
647
648 for (int yy = 0; yy < hmSizeY; yy++)
649 {
650 for (int xx = 0; xx < hmSizeX; xx++)
651 {
652 float val = br.ReadSingle();
653 if (xx < SizeX && yy < SizeY)
654 m_heightmap[xx, yy] = val;
655 }
656 }
657 }
658 }
659 }
660 catch( Exception e)
661 {
662 ClearTaint();
663 m_log.ErrorFormat("{0} V2DGzip error: {1} - terrain may be damaged",
664 LogHeader, e.Message);
665 return;
666 }
667
668 ClearTaint();
669 m_log.DebugFormat("{0} V2DGzip. Heightmap size=<{1},{2}>. Region size=<{3},{4}>",
670 LogHeader, hmSizeX, hmSizeY, SizeX, SizeY);
671
672 }
463 } 673 }
464} 674}