diff options
author | UbitUmarov | 2015-08-25 16:51:48 +0100 |
---|---|---|
committer | UbitUmarov | 2015-08-25 16:51:48 +0100 |
commit | 244f0c6352a920b8bba5e13fadda49cb5b368e06 (patch) | |
tree | 92d97bde9369dd1e7541f9b6e44d770b429fe503 /OpenSim | |
parent | terrain stored as ushorts with gzip compression (diff) | |
download | opensim-SC-244f0c6352a920b8bba5e13fadda49cb5b368e06.zip opensim-SC-244f0c6352a920b8bba5e13fadda49cb5b368e06.tar.gz opensim-SC-244f0c6352a920b8bba5e13fadda49cb5b368e06.tar.bz2 opensim-SC-244f0c6352a920b8bba5e13fadda49cb5b368e06.tar.xz |
change terrain internal representation to float. ushort work with legal
sl terrain, but may break existent terrain and that may cost a lot more
than the cost of memory
Diffstat (limited to 'OpenSim')
-rw-r--r-- | OpenSim/Framework/TerrainData.cs | 241 | ||||
-rw-r--r-- | OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs | 28 | ||||
-rw-r--r-- | OpenSim/Region/Framework/Scenes/TerrainChannel.cs | 4 |
3 files changed, 164 insertions, 109 deletions
diff --git a/OpenSim/Framework/TerrainData.cs b/OpenSim/Framework/TerrainData.cs index cc5b8f5..976c1f0 100644 --- a/OpenSim/Framework/TerrainData.cs +++ b/OpenSim/Framework/TerrainData.cs | |||
@@ -49,6 +49,7 @@ namespace OpenSim.Framework | |||
49 | 49 | ||
50 | public abstract float this[int x, int y] { get; set; } | 50 | public abstract float this[int x, int y] { get; set; } |
51 | // Someday terrain will have caves | 51 | // Someday terrain will have caves |
52 | // at most holes :p | ||
52 | 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; } |
53 | 54 | ||
54 | public abstract bool IsTaintedAt(int xx, int yy); | 55 | public abstract bool IsTaintedAt(int xx, int yy); |
@@ -74,7 +75,7 @@ namespace OpenSim.Framework | |||
74 | } | 75 | } |
75 | 76 | ||
76 | // return a special compressed representation of the heightmap in ushort | 77 | // return a special compressed representation of the heightmap in ushort |
77 | public abstract ushort[] GetCompressedMap(); | 78 | public abstract float[] GetCompressedMap(); |
78 | public abstract float CompressionFactor { get; } | 79 | public abstract float CompressionFactor { get; } |
79 | 80 | ||
80 | public abstract float[] GetFloatsSerialized(); | 81 | public abstract float[] GetFloatsSerialized(); |
@@ -95,16 +96,21 @@ namespace OpenSim.Framework | |||
95 | { | 96 | { |
96 | // Terrain is 'double[256,256]' | 97 | // Terrain is 'double[256,256]' |
97 | Legacy256 = 11, | 98 | Legacy256 = 11, |
99 | |||
98 | // 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 |
99 | // 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. |
100 | Variable2D = 22, | 102 | Variable2D = 22, |
103 | Variable2DGzip = 23, | ||
104 | |||
101 | // 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 |
102 | // 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 |
103 | // "ushort compressedHeight = (ushort)(height * compressionFactor);" | 107 | // "ushort compressedHeight = (ushort)(height * compressionFactor);" |
104 | // 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. |
105 | Compressed2D = 27, | 109 | Compressed2D = 27, |
110 | |||
106 | // as Compressed2D but using ushort[] in place of int16[] | 111 | // as Compressed2D but using ushort[] in place of int16[] |
107 | Compressed2Du = 28, | 112 | Compressed2Du = 28, |
113 | |||
108 | // as Compressed2D but using ushort[] in place of int16[] with Gzip compression | 114 | // as Compressed2D but using ushort[] in place of int16[] with Gzip compression |
109 | Compressed2DuGzip = 29, | 115 | Compressed2DuGzip = 29, |
110 | 116 | ||
@@ -125,13 +131,12 @@ namespace OpenSim.Framework | |||
125 | // TerrainData.this[x, y] | 131 | // TerrainData.this[x, y] |
126 | public override float this[int x, int y] | 132 | public override float this[int x, int y] |
127 | { | 133 | { |
128 | get { return FromCompressedHeight(m_heightmap[x, y]); } | 134 | get { return m_heightmap[x, y]; } |
129 | set | 135 | set |
130 | { | 136 | { |
131 | ushort newVal = ToCompressedHeight(value); | 137 | if (m_heightmap[x, y] != value) |
132 | if (m_heightmap[x, y] != newVal) | ||
133 | { | 138 | { |
134 | m_heightmap[x, y] = newVal; | 139 | m_heightmap[x, y] = value; |
135 | m_taint[x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize] = true; | 140 | m_taint[x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize] = true; |
136 | } | 141 | } |
137 | } | 142 | } |
@@ -171,10 +176,9 @@ namespace OpenSim.Framework | |||
171 | // TerrainData.ClearLand(float) | 176 | // TerrainData.ClearLand(float) |
172 | public override void ClearLand(float pHeight) | 177 | public override void ClearLand(float pHeight) |
173 | { | 178 | { |
174 | ushort flatHeight = ToCompressedHeight(pHeight); | ||
175 | for (int xx = 0; xx < SizeX; xx++) | 179 | for (int xx = 0; xx < SizeX; xx++) |
176 | for (int yy = 0; yy < SizeY; yy++) | 180 | for (int yy = 0; yy < SizeY; yy++) |
177 | m_heightmap[xx, yy] = flatHeight; | 181 | m_heightmap[xx, yy] = pHeight; |
178 | } | 182 | } |
179 | 183 | ||
180 | // Return 'true' of the patch that contains these region coordinates has been modified. | 184 | // Return 'true' of the patch that contains these region coordinates has been modified. |
@@ -209,8 +213,8 @@ namespace OpenSim.Framework | |||
209 | } | 213 | } |
210 | else | 214 | else |
211 | { | 215 | { |
212 | DBRevisionCode = (int)DBTerrainRevision.Compressed2DuGzip; | 216 | DBRevisionCode = (int)DBTerrainRevision.Variable2DGzip; |
213 | blob = ToCompressedTerrainSerializationGzip(); | 217 | blob = ToCompressedTerrainSerializationV2DGzip(); |
214 | ret = true; | 218 | ret = true; |
215 | } | 219 | } |
216 | return ret; | 220 | return ret; |
@@ -221,9 +225,9 @@ namespace OpenSim.Framework | |||
221 | public override float CompressionFactor { get { return m_compressionFactor; } } | 225 | public override float CompressionFactor { get { return m_compressionFactor; } } |
222 | 226 | ||
223 | // TerrainData.GetCompressedMap | 227 | // TerrainData.GetCompressedMap |
224 | public override ushort[] GetCompressedMap() | 228 | public override float[] GetCompressedMap() |
225 | { | 229 | { |
226 | ushort[] newMap = new ushort[SizeX * SizeY]; | 230 | float[] newMap = new float[SizeX * SizeY]; |
227 | 231 | ||
228 | int ind = 0; | 232 | int ind = 0; |
229 | for (int xx = 0; xx < SizeX; xx++) | 233 | for (int xx = 0; xx < SizeX; xx++) |
@@ -237,7 +241,7 @@ namespace OpenSim.Framework | |||
237 | public override TerrainData Clone() | 241 | public override TerrainData Clone() |
238 | { | 242 | { |
239 | HeightmapTerrainData ret = new HeightmapTerrainData(SizeX, SizeY, SizeZ); | 243 | HeightmapTerrainData ret = new HeightmapTerrainData(SizeX, SizeY, SizeZ); |
240 | ret.m_heightmap = (ushort[,])this.m_heightmap.Clone(); | 244 | ret.m_heightmap = (float[,])this.m_heightmap.Clone(); |
241 | return ret; | 245 | return ret; |
242 | } | 246 | } |
243 | 247 | ||
@@ -254,7 +258,7 @@ namespace OpenSim.Framework | |||
254 | for (int jj = 0; jj < SizeY; jj++) | 258 | for (int jj = 0; jj < SizeY; jj++) |
255 | for (int ii = 0; ii < SizeX; ii++) | 259 | for (int ii = 0; ii < SizeX; ii++) |
256 | { | 260 | { |
257 | heights[idx++] = FromCompressedHeight(m_heightmap[ii, jj]); | 261 | heights[idx++] = m_heightmap[ii, jj]; |
258 | } | 262 | } |
259 | 263 | ||
260 | return heights; | 264 | return heights; |
@@ -266,7 +270,7 @@ namespace OpenSim.Framework | |||
266 | double[,] ret = new double[SizeX, SizeY]; | 270 | double[,] ret = new double[SizeX, SizeY]; |
267 | for (int xx = 0; xx < SizeX; xx++) | 271 | for (int xx = 0; xx < SizeX; xx++) |
268 | for (int yy = 0; yy < SizeY; yy++) | 272 | for (int yy = 0; yy < SizeY; yy++) |
269 | ret[xx, yy] = FromCompressedHeight(m_heightmap[xx, yy]); | 273 | ret[xx, yy] = (double)m_heightmap[xx, yy]; |
270 | 274 | ||
271 | return ret; | 275 | return ret; |
272 | } | 276 | } |
@@ -274,21 +278,37 @@ namespace OpenSim.Framework | |||
274 | 278 | ||
275 | // ============================================================= | 279 | // ============================================================= |
276 | 280 | ||
277 | private ushort[,] m_heightmap; | 281 | private float[,] m_heightmap; |
278 | // Remember subregions of the heightmap that has changed. | 282 | // Remember subregions of the heightmap that has changed. |
279 | private bool[,] m_taint; | 283 | private bool[,] m_taint; |
280 | 284 | ||
281 | // To save space (especially for large regions), keep the height as a short integer | ||
282 | // 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' |
283 | // to make for two decimal points). | 286 | // to make for two decimal points). |
284 | public ushort ToCompressedHeight(double pHeight) | 287 | public short ToCompressedHeightshort(float pHeight) |
288 | { | ||
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; | ||
296 | } | ||
297 | |||
298 | public ushort ToCompressedHeightushort(float pHeight) | ||
285 | { | 299 | { |
286 | // clamp into valid range | 300 | // clamp into valid range |
287 | if (pHeight < 0) | 301 | pHeight *= CompressionFactor; |
288 | pHeight = 0; | 302 | if (pHeight < ushort.MinValue) |
289 | else if (pHeight > 655.35f) | 303 | return ushort.MinValue; |
290 | pHeight = 655.35f; | 304 | else if (pHeight > ushort.MaxValue) |
291 | return (ushort)(pHeight * CompressionFactor); | 305 | return ushort.MaxValue; |
306 | return (ushort)pHeight; | ||
307 | } | ||
308 | |||
309 | public float FromCompressedHeight(short pHeight) | ||
310 | { | ||
311 | return ((float)pHeight) / CompressionFactor; | ||
292 | } | 312 | } |
293 | 313 | ||
294 | public float FromCompressedHeight(ushort pHeight) | 314 | public float FromCompressedHeight(ushort pHeight) |
@@ -305,12 +325,12 @@ namespace OpenSim.Framework | |||
305 | SizeZ = (int)Constants.RegionHeight; | 325 | SizeZ = (int)Constants.RegionHeight; |
306 | m_compressionFactor = 100.0f; | 326 | m_compressionFactor = 100.0f; |
307 | 327 | ||
308 | m_heightmap = new ushort[SizeX, SizeY]; | 328 | m_heightmap = new float[SizeX, SizeY]; |
309 | for (int ii = 0; ii < SizeX; ii++) | 329 | for (int ii = 0; ii < SizeX; ii++) |
310 | { | 330 | { |
311 | for (int jj = 0; jj < SizeY; jj++) | 331 | for (int jj = 0; jj < SizeY; jj++) |
312 | { | 332 | { |
313 | m_heightmap[ii, jj] = ToCompressedHeight(pTerrain[ii, jj]); | 333 | m_heightmap[ii, jj] = (float)pTerrain[ii, jj]; |
314 | 334 | ||
315 | } | 335 | } |
316 | } | 336 | } |
@@ -327,14 +347,14 @@ namespace OpenSim.Framework | |||
327 | SizeY = pY; | 347 | SizeY = pY; |
328 | SizeZ = pZ; | 348 | SizeZ = pZ; |
329 | m_compressionFactor = 100.0f; | 349 | m_compressionFactor = 100.0f; |
330 | m_heightmap = new ushort[SizeX, SizeY]; | 350 | m_heightmap = new float[SizeX, SizeY]; |
331 | m_taint = new bool[SizeX / Constants.TerrainPatchSize, SizeY / Constants.TerrainPatchSize]; | 351 | m_taint = new bool[SizeX / Constants.TerrainPatchSize, SizeY / Constants.TerrainPatchSize]; |
332 | // 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); |
333 | ClearTaint(); | 353 | ClearTaint(); |
334 | ClearLand(0f); | 354 | ClearLand(0f); |
335 | } | 355 | } |
336 | 356 | ||
337 | public HeightmapTerrainData(ushort[] cmap, float pCompressionFactor, int pX, int pY, int pZ) | 357 | public HeightmapTerrainData(float[] cmap, float pCompressionFactor, int pX, int pY, int pZ) |
338 | : this(pX, pY, pZ) | 358 | : this(pX, pY, pZ) |
339 | { | 359 | { |
340 | m_compressionFactor = pCompressionFactor; | 360 | m_compressionFactor = pCompressionFactor; |
@@ -351,12 +371,22 @@ namespace OpenSim.Framework | |||
351 | { | 371 | { |
352 | switch ((DBTerrainRevision)pFormatCode) | 372 | switch ((DBTerrainRevision)pFormatCode) |
353 | { | 373 | { |
374 | case DBTerrainRevision.Variable2DGzip: | ||
375 | FromCompressedTerrainSerializationV2DGZip(pBlob); | ||
376 | m_log.DebugFormat("{0} HeightmapTerrainData create from Gzip Compressed2D (unsigned shorts) 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 Gzip Compressed2D (unsigned shorts) serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY); | ||
382 | break; | ||
383 | |||
354 | case DBTerrainRevision.Compressed2DuGzip: | 384 | case DBTerrainRevision.Compressed2DuGzip: |
355 | FromCompressedTerrainSerializationGZip(pBlob); | 385 | FromCompressedTerrainSerialization2DuGZip(pBlob); |
356 | m_log.DebugFormat("{0} HeightmapTerrainData create from Gzip Compressed2D (unsigned shorts) serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY); | 386 | m_log.DebugFormat("{0} HeightmapTerrainData create from Gzip Compressed2D (unsigned shorts) serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY); |
357 | break; | 387 | break; |
358 | case DBTerrainRevision.Compressed2Du: | 388 | case DBTerrainRevision.Compressed2Du: |
359 | FromCompressedTerrainSerialization(pBlob); | 389 | FromCompressedTerrainSerialization2D(pBlob); |
360 | m_log.DebugFormat("{0} HeightmapTerrainData create from Compressed2D (unsigned shorts) serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY); | 390 | m_log.DebugFormat("{0} HeightmapTerrainData create from Compressed2D (unsigned shorts) serialization. Size=<{1},{2}>", LogHeader, SizeX, SizeY); |
361 | break; | 391 | break; |
362 | case DBTerrainRevision.Compressed2D: | 392 | case DBTerrainRevision.Compressed2D: |
@@ -414,7 +444,7 @@ namespace OpenSim.Framework | |||
414 | float val = (float)br.ReadDouble(); | 444 | float val = (float)br.ReadDouble(); |
415 | 445 | ||
416 | if (xx < SizeX && yy < SizeY) | 446 | if (xx < SizeX && yy < SizeY) |
417 | m_heightmap[xx, yy] = ToCompressedHeight(val); | 447 | m_heightmap[xx, yy] = val; |
418 | } | 448 | } |
419 | } | 449 | } |
420 | } | 450 | } |
@@ -427,53 +457,33 @@ namespace OpenSim.Framework | |||
427 | ClearTaint(); | 457 | ClearTaint(); |
428 | } | 458 | } |
429 | 459 | ||
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 | 460 | ||
455 | } | 461 | // stores as variable2D |
456 | return ret; | 462 | // int32 format |
457 | } | 463 | // int32 sizeX |
464 | // int32 sizeY | ||
465 | // float[,] array | ||
458 | 466 | ||
459 | // See the reader below. | 467 | // may have endian issues like older |
460 | public Array ToCompressedTerrainSerialization() | 468 | |
469 | public Array ToCompressedTerrainSerializationV2D() | ||
461 | { | 470 | { |
462 | Array ret = null; | 471 | Array ret = null; |
463 | try | 472 | try |
464 | { | 473 | { |
465 | using (MemoryStream str = new MemoryStream((4 * sizeof(Int32)) + (SizeX * SizeY * sizeof(ushort)))) | 474 | using (MemoryStream str = new MemoryStream((3 * sizeof(Int32)) + (SizeX * SizeY * sizeof(float)))) |
466 | { | 475 | { |
467 | using (BinaryWriter bw = new BinaryWriter(str)) | 476 | using (BinaryWriter bw = new BinaryWriter(str)) |
468 | { | 477 | { |
469 | bw.Write((Int32)DBTerrainRevision.Compressed2Du); | 478 | bw.Write((Int32)DBTerrainRevision.Variable2D); |
470 | bw.Write((Int32)SizeX); | 479 | bw.Write((Int32)SizeX); |
471 | bw.Write((Int32)SizeY); | 480 | bw.Write((Int32)SizeY); |
472 | bw.Write((Int32)CompressionFactor); | ||
473 | for (int yy = 0; yy < SizeY; yy++) | 481 | for (int yy = 0; yy < SizeY; yy++) |
474 | for (int xx = 0; xx < SizeX; xx++) | 482 | for (int xx = 0; xx < SizeX; xx++) |
475 | { | 483 | { |
476 | bw.Write((ushort)m_heightmap[xx, yy]); | 484 | // reduce to 1cm resolution |
485 | float val = (float)Math.Round(m_heightmap[xx, yy],2,MidpointRounding.ToEven); | ||
486 | bw.Write(val); | ||
477 | } | 487 | } |
478 | } | 488 | } |
479 | ret = str.ToArray(); | 489 | ret = str.ToArray(); |
@@ -487,27 +497,26 @@ namespace OpenSim.Framework | |||
487 | } | 497 | } |
488 | 498 | ||
489 | // as above with Gzip compression | 499 | // as above with Gzip compression |
490 | public Array ToCompressedTerrainSerializationGzip() | 500 | public Array ToCompressedTerrainSerializationV2DGzip() |
491 | { | 501 | { |
492 | Array ret = null; | 502 | Array ret = null; |
493 | try | 503 | try |
494 | { | 504 | { |
495 | using (MemoryStream inp = new MemoryStream((4 * sizeof(Int32)) + (SizeX * SizeY * sizeof(ushort)))) | 505 | using (MemoryStream inp = new MemoryStream((3 * sizeof(Int32)) + (SizeX * SizeY * sizeof(float)))) |
496 | { | 506 | { |
497 | using (BinaryWriter bw = new BinaryWriter(inp)) | 507 | using (BinaryWriter bw = new BinaryWriter(inp)) |
498 | { | 508 | { |
499 | bw.Write((Int32)DBTerrainRevision.Compressed2DuGzip); | 509 | bw.Write((Int32)DBTerrainRevision.Variable2DGzip); |
500 | bw.Write((Int32)SizeX); | 510 | bw.Write((Int32)SizeX); |
501 | bw.Write((Int32)SizeY); | 511 | bw.Write((Int32)SizeY); |
502 | bw.Write((Int32)CompressionFactor); | ||
503 | for (int yy = 0; yy < SizeY; yy++) | 512 | for (int yy = 0; yy < SizeY; yy++) |
504 | for (int xx = 0; xx < SizeX; xx++) | 513 | for (int xx = 0; xx < SizeX; xx++) |
505 | { | 514 | { |
506 | bw.Write((ushort)m_heightmap[xx, yy]); | 515 | bw.Write((float)m_heightmap[xx, yy]); |
507 | } | 516 | } |
508 | 517 | ||
509 | bw.Flush(); | 518 | bw.Flush(); |
510 | inp.Seek(0,SeekOrigin.Begin); | 519 | inp.Seek(0, SeekOrigin.Begin); |
511 | 520 | ||
512 | using (MemoryStream outputStream = new MemoryStream()) | 521 | using (MemoryStream outputStream = new MemoryStream()) |
513 | { | 522 | { |
@@ -525,7 +534,7 @@ namespace OpenSim.Framework | |||
525 | { | 534 | { |
526 | 535 | ||
527 | } | 536 | } |
528 | m_log.InfoFormat("{0} terrain GZiped to {1} bytes (compressed2Dus)", | 537 | m_log.InfoFormat("{0} terrain GZiped to {1} bytes (V2DGzip)", |
529 | LogHeader, ret.Length); | 538 | LogHeader, ret.Length); |
530 | return ret; | 539 | return ret; |
531 | } | 540 | } |
@@ -558,11 +567,9 @@ namespace OpenSim.Framework | |||
558 | { | 567 | { |
559 | for (int xx = 0; xx < hmSizeX; xx++) | 568 | for (int xx = 0; xx < hmSizeX; xx++) |
560 | { | 569 | { |
561 | short val = br.ReadInt16(); | 570 | float val = FromCompressedHeight(br.ReadInt16()); |
562 | if (val < 0) | ||
563 | val = 0; | ||
564 | if (xx < SizeX && yy < SizeY) | 571 | if (xx < SizeX && yy < SizeY) |
565 | m_heightmap[xx, yy] = (ushort)val; | 572 | m_heightmap[xx, yy] = val; |
566 | } | 573 | } |
567 | } | 574 | } |
568 | } | 575 | } |
@@ -579,7 +586,7 @@ namespace OpenSim.Framework | |||
579 | // the forth int is the compression factor for the following int16s | 586 | // 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 | 587 | // 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. | 588 | // creation and any heights not initialized by theis blob are set to the default height. |
582 | public void FromCompressedTerrainSerialization(byte[] pBlob) | 589 | public void FromCompressedTerrainSerialization2Du(byte[] pBlob) |
583 | { | 590 | { |
584 | Int32 hmFormatCode, hmSizeX, hmSizeY, hmCompressionFactor; | 591 | Int32 hmFormatCode, hmSizeX, hmSizeY, hmCompressionFactor; |
585 | try | 592 | try |
@@ -602,7 +609,7 @@ namespace OpenSim.Framework | |||
602 | { | 609 | { |
603 | for (int xx = 0; xx < hmSizeX; xx++) | 610 | for (int xx = 0; xx < hmSizeX; xx++) |
604 | { | 611 | { |
605 | ushort val = br.ReadUInt16(); | 612 | float val = FromCompressedHeight(br.ReadUInt16()); |
606 | if (xx < SizeX && yy < SizeY) | 613 | if (xx < SizeX && yy < SizeY) |
607 | m_heightmap[xx, yy] = val; | 614 | m_heightmap[xx, yy] = val; |
608 | } | 615 | } |
@@ -614,7 +621,7 @@ namespace OpenSim.Framework | |||
614 | { | 621 | { |
615 | ClearTaint(); | 622 | ClearTaint(); |
616 | m_log.ErrorFormat("{0} Read (compressed2Dus) terrain error: {1} - terrain may be damaged", | 623 | m_log.ErrorFormat("{0} Read (compressed2Dus) terrain error: {1} - terrain may be damaged", |
617 | LogHeader,e.Message); | 624 | LogHeader, e.Message); |
618 | return; | 625 | return; |
619 | } | 626 | } |
620 | ClearTaint(); | 627 | ClearTaint(); |
@@ -625,10 +632,86 @@ namespace OpenSim.Framework | |||
625 | } | 632 | } |
626 | 633 | ||
627 | // as above but Gzip compressed | 634 | // as above but Gzip compressed |
628 | public void FromCompressedTerrainSerializationGZip(byte[] pBlob) | 635 | public void FromCompressedTerrainSerialization2DuGZip(byte[] pBlob) |
636 | { | ||
637 | m_log.InfoFormat("{0} GZip {1} bytes for terrain", | ||
638 | LogHeader, pBlob.Length); | ||
639 | byte[] gzipout = null; | ||
640 | try | ||
641 | { | ||
642 | using (MemoryStream inputStream = new MemoryStream(pBlob)) | ||
643 | { | ||
644 | using (GZipStream decompressionStream = new GZipStream(inputStream, CompressionMode.Decompress)) | ||
645 | { | ||
646 | using (MemoryStream outputStream = new MemoryStream()) | ||
647 | { | ||
648 | decompressionStream.Flush(); | ||
649 | decompressionStream.CopyTo(outputStream); | ||
650 | gzipout = outputStream.ToArray(); | ||
651 | } | ||
652 | } | ||
653 | } | ||
654 | } | ||
655 | catch | ||
656 | { | ||
657 | } | ||
658 | |||
659 | FromCompressedTerrainSerialization2Du(gzipout); | ||
660 | } | ||
661 | |||
662 | // Initialize heightmap from blob consisting of: | ||
663 | // int32, int32, int32, int32, ushort[] | ||
664 | // where the first int32 is format code, next two int32s are the X and y of heightmap data and | ||
665 | // the forth int is the compression factor for the following int16s | ||
666 | // This is just sets heightmap info. The actual size of the region was set on this instance's | ||
667 | // creation and any heights not initialized by theis blob are set to the default height. | ||
668 | public void FromCompressedTerrainSerializationV2D(byte[] pBlob) | ||
669 | { | ||
670 | Int32 hmFormatCode, hmSizeX, hmSizeY, hmCompressionFactor; | ||
671 | try | ||
672 | { | ||
673 | using (MemoryStream mstr = new MemoryStream(pBlob)) | ||
674 | { | ||
675 | using (BinaryReader br = new BinaryReader(mstr)) | ||
676 | { | ||
677 | hmFormatCode = br.ReadInt32(); | ||
678 | hmSizeX = br.ReadInt32(); | ||
679 | hmSizeY = br.ReadInt32(); | ||
680 | |||
681 | // In case database info doesn't match real terrain size, initialize the whole terrain. | ||
682 | ClearLand(); | ||
683 | |||
684 | for (int yy = 0; yy < hmSizeY; yy++) | ||
685 | { | ||
686 | for (int xx = 0; xx < hmSizeX; xx++) | ||
687 | { | ||
688 | float val = br.ReadSingle(); | ||
689 | if (xx < SizeX && yy < SizeY) | ||
690 | m_heightmap[xx, yy] = val; | ||
691 | } | ||
692 | } | ||
693 | } | ||
694 | } | ||
695 | } | ||
696 | catch (Exception e) | ||
697 | { | ||
698 | ClearTaint(); | ||
699 | m_log.ErrorFormat("{0} Read (Variable size format) terrain error: {1} - terrain may be damaged", | ||
700 | LogHeader, e.Message); | ||
701 | return; | ||
702 | } | ||
703 | ClearTaint(); | ||
704 | |||
705 | m_log.InfoFormat("{0} Read Variable size format terrain. Heightmap size=<{1},{2}>. Region size=<{3},{4}>", | ||
706 | LogHeader, hmSizeX, hmSizeY, SizeX, SizeY); | ||
707 | |||
708 | } | ||
709 | // as above but Gzip compressed | ||
710 | public void FromCompressedTerrainSerializationV2DGZip(byte[] pBlob) | ||
629 | { | 711 | { |
630 | m_log.InfoFormat("{0} GZip {1} bytes for terrain", | 712 | m_log.InfoFormat("{0} GZip {1} bytes for terrain", |
631 | LogHeader,pBlob.Length); | 713 | LogHeader, pBlob.Length); |
714 | |||
632 | byte[] gzipout = null; | 715 | byte[] gzipout = null; |
633 | try | 716 | try |
634 | { | 717 | { |
@@ -649,7 +732,7 @@ namespace OpenSim.Framework | |||
649 | { | 732 | { |
650 | } | 733 | } |
651 | 734 | ||
652 | FromCompressedTerrainSerialization(gzipout); | 735 | FromCompressedTerrainSerializationV2D(gzipout); |
653 | } | 736 | } |
654 | } | 737 | } |
655 | } | 738 | } |
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs index 135fe50..0209d16 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs | |||
@@ -1349,13 +1349,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1349 | double desiredMin = (double)args[0]; | 1349 | double desiredMin = (double)args[0]; |
1350 | double desiredMax = (double)args[1]; | 1350 | double desiredMax = (double)args[1]; |
1351 | 1351 | ||
1352 | if (desiredMin < 0 || desiredMin > 655.35 | ||
1353 | || desiredMax < 0 || desiredMax > 655.35) | ||
1354 | { | ||
1355 | m_log.Error("desired Min and Max must be in range 0.0 to 655.0m"); | ||
1356 | return; | ||
1357 | } | ||
1358 | |||
1359 | // determine desired scaling factor | 1352 | // determine desired scaling factor |
1360 | double desiredRange = desiredMax - desiredMin; | 1353 | double desiredRange = desiredMax - desiredMin; |
1361 | //m_log.InfoFormat("Desired {0}, {1} = {2}", new Object[] { desiredMin, desiredMax, desiredRange }); | 1354 | //m_log.InfoFormat("Desired {0}, {1} = {2}", new Object[] { desiredMin, desiredMax, desiredRange }); |
@@ -1413,11 +1406,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1413 | private void InterfaceElevateTerrain(Object[] args) | 1406 | private void InterfaceElevateTerrain(Object[] args) |
1414 | { | 1407 | { |
1415 | double val = (double)args[0]; | 1408 | double val = (double)args[0]; |
1416 | if (val < 0 || val > 655.35) | ||
1417 | { | ||
1418 | m_log.Error("elevation must be in range 0.0 to 655.0m"); | ||
1419 | return; | ||
1420 | } | ||
1421 | 1409 | ||
1422 | int x, y; | 1410 | int x, y; |
1423 | for (x = 0; x < m_channel.Width; x++) | 1411 | for (x = 0; x < m_channel.Width; x++) |
@@ -1439,7 +1427,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1439 | { | 1427 | { |
1440 | int x, y; | 1428 | int x, y; |
1441 | double val = (double)args[0]; | 1429 | double val = (double)args[0]; |
1442 | if (val < 0 || val > 655.35) | ||
1443 | 1430 | ||
1444 | for (x = 0; x < m_channel.Width; x++) | 1431 | for (x = 0; x < m_channel.Width; x++) |
1445 | for (y = 0; y < m_channel.Height; y++) | 1432 | for (y = 0; y < m_channel.Height; y++) |
@@ -1450,11 +1437,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1450 | { | 1437 | { |
1451 | int x, y; | 1438 | int x, y; |
1452 | double val = (double)args[0]; | 1439 | double val = (double)args[0]; |
1453 | if (val < 0 || val > 655.35) | ||
1454 | { | ||
1455 | m_log.Error("height must be in range 0.0 to 655.0m"); | ||
1456 | return; | ||
1457 | } | ||
1458 | 1440 | ||
1459 | for (x = 0; x < m_channel.Width; x++) | 1441 | for (x = 0; x < m_channel.Width; x++) |
1460 | for (y = 0; y < m_channel.Height; y++) | 1442 | for (y = 0; y < m_channel.Height; y++) |
@@ -1465,11 +1447,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1465 | { | 1447 | { |
1466 | int x, y; | 1448 | int x, y; |
1467 | double val = (double)args[0]; | 1449 | double val = (double)args[0]; |
1468 | if (val < 0 || val > 655.35) | ||
1469 | { | ||
1470 | m_log.Error("minimum must be in range 0.0 to 655.0m"); | ||
1471 | return; | ||
1472 | } | ||
1473 | for (x = 0; x < m_channel.Width; x++) | 1450 | for (x = 0; x < m_channel.Width; x++) |
1474 | { | 1451 | { |
1475 | for (y = 0; y < m_channel.Height; y++) | 1452 | for (y = 0; y < m_channel.Height; y++) |
@@ -1483,11 +1460,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1483 | { | 1460 | { |
1484 | int x, y; | 1461 | int x, y; |
1485 | double val = (double)args[0]; | 1462 | double val = (double)args[0]; |
1486 | if (val < 0 || val > 655.35) | ||
1487 | { | ||
1488 | m_log.Error("maximum must be in range 0.0 to 655.0m"); | ||
1489 | return; | ||
1490 | } | ||
1491 | for (x = 0; x < m_channel.Width; x++) | 1463 | for (x = 0; x < m_channel.Width; x++) |
1492 | { | 1464 | { |
1493 | for (y = 0; y < m_channel.Height; y++) | 1465 | for (y = 0; y < m_channel.Height; y++) |
diff --git a/OpenSim/Region/Framework/Scenes/TerrainChannel.cs b/OpenSim/Region/Framework/Scenes/TerrainChannel.cs index 75c3a3b..6abdc29 100644 --- a/OpenSim/Region/Framework/Scenes/TerrainChannel.cs +++ b/OpenSim/Region/Framework/Scenes/TerrainChannel.cs | |||
@@ -367,8 +367,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
367 | public int SizeY; | 367 | public int SizeY; |
368 | public int SizeZ; | 368 | public int SizeZ; |
369 | public float CompressionFactor; | 369 | public float CompressionFactor; |
370 | public ushort[] Map; | 370 | public float[] Map; |
371 | public TerrainChannelXMLPackage(int pX, int pY, int pZ, float pCompressionFactor, ushort[] pMap) | 371 | public TerrainChannelXMLPackage(int pX, int pY, int pZ, float pCompressionFactor, float[] pMap) |
372 | { | 372 | { |
373 | Version = 1; | 373 | Version = 1; |
374 | SizeX = pX; | 374 | SizeX = pX; |