aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/TerrainData.cs
diff options
context:
space:
mode:
authorUbitUmarov2015-08-25 13:36:45 +0100
committerUbitUmarov2015-08-25 13:36:45 +0100
commit64d05bab0fe9e12038309275a677e68518fb9b15 (patch)
treec9c6049f06b2462d18029404c4f6119ea87f209f /OpenSim/Framework/TerrainData.cs
parent let mysql be happy with a NULL heighmap ( yeap i made several ) (diff)
downloadopensim-SC_OLD-64d05bab0fe9e12038309275a677e68518fb9b15.zip
opensim-SC_OLD-64d05bab0fe9e12038309275a677e68518fb9b15.tar.gz
opensim-SC_OLD-64d05bab0fe9e12038309275a677e68518fb9b15.tar.bz2
opensim-SC_OLD-64d05bab0fe9e12038309275a677e68518fb9b15.tar.xz
terrain stored as ushorts with gzip compression
Diffstat (limited to '')
-rw-r--r--OpenSim/Framework/TerrainData.cs251
1 files changed, 221 insertions, 30 deletions
diff --git a/OpenSim/Framework/TerrainData.cs b/OpenSim/Framework/TerrainData.cs
index d0eddc6..cc5b8f5 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;
@@ -102,6 +103,11 @@ namespace OpenSim.Framework
102 // "ushort compressedHeight = (ushort)(height * compressionFactor);" 103 // "ushort compressedHeight = (ushort)(height * compressionFactor);"
103 // The dimensions are presumed to be multiples of 16 and, more likely, multiples of 256. 104 // The dimensions are presumed to be multiples of 16 and, more likely, multiples of 256.
104 Compressed2D = 27, 105 Compressed2D = 27,
106 // as Compressed2D but using ushort[] in place of int16[]
107 Compressed2Du = 28,
108 // as Compressed2D but using ushort[] in place of int16[] with Gzip compression
109 Compressed2DuGzip = 29,
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 }
@@ -120,7 +126,8 @@ namespace OpenSim.Framework
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 FromCompressedHeight(m_heightmap[x, y]); }
123 set { 129 set
130 {
124 ushort newVal = ToCompressedHeight(value); 131 ushort newVal = ToCompressedHeight(value);
125 if (m_heightmap[x, y] != newVal) 132 if (m_heightmap[x, y] != newVal)
126 { 133 {
@@ -177,7 +184,7 @@ namespace OpenSim.Framework
177 { 184 {
178 int tx = xx / Constants.TerrainPatchSize; 185 int tx = xx / Constants.TerrainPatchSize;
179 int ty = yy / Constants.TerrainPatchSize; 186 int ty = yy / Constants.TerrainPatchSize;
180 bool ret = m_taint[tx, ty]; 187 bool ret = m_taint[tx, ty];
181 if (ret && clearOnTest) 188 if (ret && clearOnTest)
182 m_taint[tx, ty] = false; 189 m_taint[tx, ty] = false;
183 return ret; 190 return ret;
@@ -202,8 +209,8 @@ namespace OpenSim.Framework
202 } 209 }
203 else 210 else
204 { 211 {
205 DBRevisionCode = (int)DBTerrainRevision.Compressed2D; 212 DBRevisionCode = (int)DBTerrainRevision.Compressed2DuGzip;
206 blob = ToCompressedTerrainSerialization(); 213 blob = ToCompressedTerrainSerializationGzip();
207 ret = true; 214 ret = true;
208 } 215 }
209 return ret; 216 return ret;
@@ -276,6 +283,11 @@ namespace OpenSim.Framework
276 // to make for two decimal points). 283 // to make for two decimal points).
277 public ushort ToCompressedHeight(double pHeight) 284 public ushort ToCompressedHeight(double pHeight)
278 { 285 {
286 // clamp into valid range
287 if (pHeight < 0)
288 pHeight = 0;
289 else if (pHeight > 655.35f)
290 pHeight = 655.35f;
279 return (ushort)(pHeight * CompressionFactor); 291 return (ushort)(pHeight * CompressionFactor);
280 } 292 }
281 293
@@ -322,7 +334,8 @@ namespace OpenSim.Framework
322 ClearLand(0f); 334 ClearLand(0f);
323 } 335 }
324 336
325 public HeightmapTerrainData(ushort[] cmap, float pCompressionFactor, int pX, int pY, int pZ) : this(pX, pY, pZ) 337 public HeightmapTerrainData(ushort[] cmap, float pCompressionFactor, int pX, int pY, int pZ)
338 : this(pX, pY, pZ)
326 { 339 {
327 m_compressionFactor = pCompressionFactor; 340 m_compressionFactor = pCompressionFactor;
328 int ind = 0; 341 int ind = 0;
@@ -333,12 +346,21 @@ namespace OpenSim.Framework
333 } 346 }
334 347
335 // Create a heighmap from a database blob 348 // Create a heighmap from a database blob
336 public HeightmapTerrainData(int pSizeX, int pSizeY, int pSizeZ, int pFormatCode, byte[] pBlob) : this(pSizeX, pSizeY, pSizeZ) 349 public HeightmapTerrainData(int pSizeX, int pSizeY, int pSizeZ, int pFormatCode, byte[] pBlob)
350 : this(pSizeX, pSizeY, pSizeZ)
337 { 351 {
338 switch ((DBTerrainRevision)pFormatCode) 352 switch ((DBTerrainRevision)pFormatCode)
339 { 353 {
340 case DBTerrainRevision.Compressed2D: 354 case DBTerrainRevision.Compressed2DuGzip:
355 FromCompressedTerrainSerializationGZip(pBlob);
356 m_log.DebugFormat("{0} HeightmapTerrainData create from Gzip Compressed2D (unsigned shorts) serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY);
357 break;
358 case DBTerrainRevision.Compressed2Du:
341 FromCompressedTerrainSerialization(pBlob); 359 FromCompressedTerrainSerialization(pBlob);
360 m_log.DebugFormat("{0} HeightmapTerrainData create from Compressed2D (unsigned shorts) serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY);
361 break;
362 case DBTerrainRevision.Compressed2D:
363 FromCompressedTerrainSerialization2D(pBlob);
342 m_log.DebugFormat("{0} HeightmapTerrainData create from Compressed2D serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY); 364 m_log.DebugFormat("{0} HeightmapTerrainData create from Compressed2D serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY);
343 break; 365 break;
344 default: 366 default:
@@ -379,44 +401,132 @@ namespace OpenSim.Framework
379 // In case database info doesn't match real terrain size, initialize the whole terrain. 401 // In case database info doesn't match real terrain size, initialize the whole terrain.
380 ClearLand(); 402 ClearLand();
381 403
382 using (MemoryStream mstr = new MemoryStream(pBlob)) 404 try
383 { 405 {
384 using (BinaryReader br = new BinaryReader(mstr)) 406 using (MemoryStream mstr = new MemoryStream(pBlob))
385 { 407 {
386 for (int xx = 0; xx < (int)Constants.RegionSize; xx++) 408 using (BinaryReader br = new BinaryReader(mstr))
387 { 409 {
388 for (int yy = 0; yy < (int)Constants.RegionSize; yy++) 410 for (int xx = 0; xx < (int)Constants.RegionSize; xx++)
389 { 411 {
390 float val = (float)br.ReadDouble(); 412 for (int yy = 0; yy < (int)Constants.RegionSize; yy++)
391 if (xx < SizeX && yy < SizeY) 413 {
392 m_heightmap[xx, yy] = ToCompressedHeight(val); 414 float val = (float)br.ReadDouble();
415
416 if (xx < SizeX && yy < SizeY)
417 m_heightmap[xx, yy] = ToCompressedHeight(val);
418 }
393 } 419 }
394 } 420 }
395 } 421 }
396 ClearTaint();
397 } 422 }
423 catch
424 {
425 ClearLand();
426 }
427 ClearTaint();
428 }
429
430 public Array ToCompressedTerrainSerialization2D()
431 {
432 Array ret = null;
433 try
434 {
435 using (MemoryStream str = new MemoryStream((4 * sizeof(Int32)) + (SizeX * SizeY * sizeof(ushort))))
436 {
437 using (BinaryWriter bw = new BinaryWriter(str))
438 {
439 bw.Write((Int32)DBTerrainRevision.Compressed2D);
440 bw.Write((Int32)SizeX);
441 bw.Write((Int32)SizeY);
442 bw.Write((Int32)CompressionFactor);
443 for (int yy = 0; yy < SizeY; yy++)
444 for (int xx = 0; xx < SizeX; xx++)
445 {
446 bw.Write((Int16)m_heightmap[xx, yy]);
447 }
448 }
449 ret = str.ToArray();
450 }
451 }
452 catch
453 {
454
455 }
456 return ret;
398 } 457 }
399 458
400 // See the reader below. 459 // See the reader below.
401 public Array ToCompressedTerrainSerialization() 460 public Array ToCompressedTerrainSerialization()
402 { 461 {
403 Array ret = null; 462 Array ret = null;
404 using (MemoryStream str = new MemoryStream((3 * sizeof(Int32)) + (SizeX * SizeY * sizeof(ushort)))) 463 try
405 { 464 {
406 using (BinaryWriter bw = new BinaryWriter(str)) 465 using (MemoryStream str = new MemoryStream((4 * sizeof(Int32)) + (SizeX * SizeY * sizeof(ushort))))
407 { 466 {
408 bw.Write((Int32)DBTerrainRevision.Compressed2D); 467 using (BinaryWriter bw = new BinaryWriter(str))
409 bw.Write((Int32)SizeX); 468 {
410 bw.Write((Int32)SizeY); 469 bw.Write((Int32)DBTerrainRevision.Compressed2Du);
411 bw.Write((Int32)CompressionFactor); 470 bw.Write((Int32)SizeX);
412 for (int yy = 0; yy < SizeY; yy++) 471 bw.Write((Int32)SizeY);
413 for (int xx = 0; xx < SizeX; xx++) 472 bw.Write((Int32)CompressionFactor);
473 for (int yy = 0; yy < SizeY; yy++)
474 for (int xx = 0; xx < SizeX; xx++)
475 {
476 bw.Write((ushort)m_heightmap[xx, yy]);
477 }
478 }
479 ret = str.ToArray();
480 }
481 }
482 catch
483 {
484
485 }
486 return ret;
487 }
488
489 // as above with Gzip compression
490 public Array ToCompressedTerrainSerializationGzip()
491 {
492 Array ret = null;
493 try
494 {
495 using (MemoryStream inp = new MemoryStream((4 * sizeof(Int32)) + (SizeX * SizeY * sizeof(ushort))))
496 {
497 using (BinaryWriter bw = new BinaryWriter(inp))
498 {
499 bw.Write((Int32)DBTerrainRevision.Compressed2DuGzip);
500 bw.Write((Int32)SizeX);
501 bw.Write((Int32)SizeY);
502 bw.Write((Int32)CompressionFactor);
503 for (int yy = 0; yy < SizeY; yy++)
504 for (int xx = 0; xx < SizeX; xx++)
505 {
506 bw.Write((ushort)m_heightmap[xx, yy]);
507 }
508
509 bw.Flush();
510 inp.Seek(0,SeekOrigin.Begin);
511
512 using (MemoryStream outputStream = new MemoryStream())
414 { 513 {
415 bw.Write((ushort)m_heightmap[xx, yy]); 514 using (GZipStream compressionStream = new GZipStream(outputStream, CompressionMode.Compress))
515 {
516 inp.CopyStream(compressionStream, int.MaxValue);
517 compressionStream.Close();
518 ret = outputStream.ToArray();
519 }
416 } 520 }
521 }
417 } 522 }
418 ret = str.ToArray();
419 } 523 }
524 catch
525 {
526
527 }
528 m_log.InfoFormat("{0} terrain GZiped to {1} bytes (compressed2Dus)",
529 LogHeader, ret.Length);
420 return ret; 530 return ret;
421 } 531 }
422 532
@@ -426,7 +536,7 @@ namespace OpenSim.Framework
426 // the forth int is the compression factor for the following int16s 536 // 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 537 // 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. 538 // creation and any heights not initialized by theis blob are set to the default height.
429 public void FromCompressedTerrainSerialization(byte[] pBlob) 539 public void FromCompressedTerrainSerialization2D(byte[] pBlob)
430 { 540 {
431 Int32 hmFormatCode, hmSizeX, hmSizeY, hmCompressionFactor; 541 Int32 hmFormatCode, hmSizeX, hmSizeY, hmCompressionFactor;
432 542
@@ -448,17 +558,98 @@ namespace OpenSim.Framework
448 { 558 {
449 for (int xx = 0; xx < hmSizeX; xx++) 559 for (int xx = 0; xx < hmSizeX; xx++)
450 { 560 {
451 ushort val = br.ReadUInt16(); 561 short val = br.ReadInt16();
562 if (val < 0)
563 val = 0;
452 if (xx < SizeX && yy < SizeY) 564 if (xx < SizeX && yy < SizeY)
453 m_heightmap[xx, yy] = val; 565 m_heightmap[xx, yy] = (ushort)val;
454 } 566 }
455 } 567 }
456 } 568 }
457 ClearTaint(); 569 ClearTaint();
458 570
459 m_log.InfoFormat("{0} Read compressed 2d heightmap. Heightmap size=<{1},{2}>. Region size=<{3},{4}>. CompFact={5}", 571 m_log.InfoFormat("{0} Read (compressed2D) heightmap. Heightmap size=<{1},{2}>. Region size=<{3},{4}>. CompFact={5}",
460 LogHeader, hmSizeX, hmSizeY, SizeX, SizeY, hmCompressionFactor); 572 LogHeader, hmSizeX, hmSizeY, SizeX, SizeY, hmCompressionFactor);
461 } 573 }
462 } 574 }
575
576 // Initialize heightmap from blob consisting of:
577 // int32, int32, int32, int32, ushort[]
578 // where the first int32 is format code, next two int32s are the X and y of heightmap data and
579 // the forth int is the compression factor for the following int16s
580 // This is just sets heightmap info. The actual size of the region was set on this instance's
581 // creation and any heights not initialized by theis blob are set to the default height.
582 public void FromCompressedTerrainSerialization(byte[] pBlob)
583 {
584 Int32 hmFormatCode, hmSizeX, hmSizeY, hmCompressionFactor;
585 try
586 {
587 using (MemoryStream mstr = new MemoryStream(pBlob))
588 {
589 using (BinaryReader br = new BinaryReader(mstr))
590 {
591 hmFormatCode = br.ReadInt32();
592 hmSizeX = br.ReadInt32();
593 hmSizeY = br.ReadInt32();
594 hmCompressionFactor = br.ReadInt32();
595
596 m_compressionFactor = hmCompressionFactor;
597
598 // In case database info doesn't match real terrain size, initialize the whole terrain.
599 ClearLand();
600
601 for (int yy = 0; yy < hmSizeY; yy++)
602 {
603 for (int xx = 0; xx < hmSizeX; xx++)
604 {
605 ushort val = br.ReadUInt16();
606 if (xx < SizeX && yy < SizeY)
607 m_heightmap[xx, yy] = val;
608 }
609 }
610 }
611 }
612 }
613 catch (Exception e)
614 {
615 ClearTaint();
616 m_log.ErrorFormat("{0} Read (compressed2Dus) terrain error: {1} - terrain may be damaged",
617 LogHeader,e.Message);
618 return;
619 }
620 ClearTaint();
621
622 m_log.InfoFormat("{0} Read compressed2D terrain. Heightmap size=<{1},{2}>. Region size=<{3},{4}>. CompFact={5}",
623 LogHeader, hmSizeX, hmSizeY, SizeX, SizeY, hmCompressionFactor);
624
625 }
626
627 // as above but Gzip compressed
628 public void FromCompressedTerrainSerializationGZip(byte[] pBlob)
629 {
630 m_log.InfoFormat("{0} GZip {1} bytes for terrain",
631 LogHeader,pBlob.Length);
632 byte[] gzipout = null;
633 try
634 {
635 using (MemoryStream inputStream = new MemoryStream(pBlob))
636 {
637 using (GZipStream decompressionStream = new GZipStream(inputStream, CompressionMode.Decompress))
638 {
639 using (MemoryStream outputStream = new MemoryStream())
640 {
641 decompressionStream.Flush();
642 decompressionStream.CopyTo(outputStream);
643 gzipout = outputStream.ToArray();
644 }
645 }
646 }
647 }
648 catch
649 {
650 }
651
652 FromCompressedTerrainSerialization(gzipout);
653 }
463 } 654 }
464} 655}