diff options
Diffstat (limited to 'OpenSim')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/TerrainCompressor.cs | 235 |
1 files changed, 62 insertions, 173 deletions
diff --git a/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs b/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs index beca578..d77e1d7 100644 --- a/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs +++ b/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs | |||
@@ -248,9 +248,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
248 | header.PatchIDs = (y & 0x1F); | 248 | header.PatchIDs = (y & 0x1F); |
249 | header.PatchIDs += (x << 5); | 249 | header.PatchIDs += (x << 5); |
250 | } | 250 | } |
251 | 251 | ||
252 | // NOTE: No idea what prequant and postquant should be or what they do | ||
253 | |||
254 | int wbits; | 252 | int wbits; |
255 | int[] patch = CompressPatch(patchData, header, 10, out wbits); | 253 | int[] patch = CompressPatch(patchData, header, 10, out wbits); |
256 | wbits = EncodePatchHeader(output, header, patch, Constants.RegionSize, Constants.RegionSize, wbits); | 254 | wbits = EncodePatchHeader(output, header, patch, Constants.RegionSize, Constants.RegionSize, wbits); |
@@ -274,8 +272,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
274 | /// <param name="pRegionSizeY"></param> | 272 | /// <param name="pRegionSizeY"></param> |
275 | public static void CreatePatchFromHeightmap(BitPack output, TerrainData terrData, int patchX, int patchY) | 273 | public static void CreatePatchFromHeightmap(BitPack output, TerrainData terrData, int patchX, int patchY) |
276 | { | 274 | { |
277 | TerrainPatch.Header header = PrescanPatch(terrData, patchX, patchY); | 275 | float frange; |
278 | header.QuantWBits = 136; | 276 | TerrainPatch.Header header = PrescanPatch(terrData, patchX, patchY, out frange); |
277 | header.QuantWBits = 130; | ||
279 | 278 | ||
280 | // If larger than legacy region size, pack patch X and Y info differently. | 279 | // If larger than legacy region size, pack patch X and Y info differently. |
281 | if (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize) | 280 | if (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize) |
@@ -289,10 +288,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
289 | header.PatchIDs += (patchX << 5); | 288 | header.PatchIDs += (patchX << 5); |
290 | } | 289 | } |
291 | 290 | ||
292 | // m_log.DebugFormat("{0} CreatePatchFromHeightmap. patchX={1}, patchY={2}, DCOffset={3}, range={4}", | 291 | if(Math.Round((double)frange,2) == 1.0) |
293 | // LogHeader, patchX, patchY, header.DCOffset, header.Range); | 292 | { |
293 | // flat terrain spead up things | ||
294 | 294 | ||
295 | // NOTE: No idea what prequant and postquant should be or what they do | 295 | // prequant and quant 2 bits both |
296 | header.QuantWBits = 0x00; | ||
297 | output.PackBits(header.QuantWBits, 8); | ||
298 | output.PackFloat(header.DCOffset); | ||
299 | output.PackBits(1, 16); | ||
300 | if (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize) | ||
301 | output.PackBits(header.PatchIDs, 32); | ||
302 | else | ||
303 | output.PackBits(header.PatchIDs, 10); | ||
304 | // dc term is - max quant value | ||
305 | output.PackBits(NEGATIVE_VALUE, 3); | ||
306 | output.PackBits(3, 2); | ||
307 | // and thats all | ||
308 | output.PackBits(ZERO_EOB, 2); | ||
309 | return; | ||
310 | } | ||
311 | |||
296 | int wbits; | 312 | int wbits; |
297 | int[] patch = CompressPatch(terrData, patchX, patchY, header, 10, out wbits); | 313 | int[] patch = CompressPatch(terrData, patchX, patchY, header, 10, out wbits); |
298 | wbits = EncodePatchHeader(output, header, patch, (uint)terrData.SizeX, (uint)terrData.SizeY, wbits); | 314 | wbits = EncodePatchHeader(output, header, patch, (uint)terrData.SizeX, (uint)terrData.SizeY, wbits); |
@@ -319,15 +335,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
319 | } | 335 | } |
320 | 336 | ||
321 | // Scan the height info we're returning and return a patch packet header for this patch. | 337 | // Scan the height info we're returning and return a patch packet header for this patch. |
322 | private static TerrainPatch.Header PrescanPatch(TerrainData terrData, int patchX, int patchY) | 338 | private static TerrainPatch.Header PrescanPatch(TerrainData terrData, int patchX, int patchY, out float frange) |
323 | { | 339 | { |
324 | TerrainPatch.Header header = new TerrainPatch.Header(); | 340 | TerrainPatch.Header header = new TerrainPatch.Header(); |
325 | float zmax = -99999999.0f; | 341 | float zmax = -99999999.0f; |
326 | float zmin = 99999999.0f; | 342 | float zmin = 99999999.0f; |
343 | int startx = patchX * Constants.TerrainPatchSize; | ||
344 | int starty = patchY * Constants.TerrainPatchSize; | ||
327 | 345 | ||
328 | for (int j = patchY*Constants.TerrainPatchSize; j < (patchY + 1)*Constants.TerrainPatchSize; j++) | 346 | for (int j = starty; j < starty + Constants.TerrainPatchSize; j++) |
329 | { | 347 | { |
330 | for (int i = patchX*Constants.TerrainPatchSize; i < (patchX + 1)*Constants.TerrainPatchSize; i++) | 348 | for (int i = startx; i < startx + Constants.TerrainPatchSize; i++) |
331 | { | 349 | { |
332 | float val = terrData[i, j]; | 350 | float val = terrData[i, j]; |
333 | if (val > zmax) zmax = val; | 351 | if (val > zmax) zmax = val; |
@@ -336,7 +354,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
336 | } | 354 | } |
337 | 355 | ||
338 | header.DCOffset = zmin; | 356 | header.DCOffset = zmin; |
339 | header.Range = (int)((zmax - zmin) + 1.0f); | 357 | frange = ((zmax - zmin) + 1.0f); |
358 | header.Range = (int)frange; | ||
340 | 359 | ||
341 | return header; | 360 | return header; |
342 | } | 361 | } |
@@ -367,59 +386,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
367 | private static int EncodePatchHeader(BitPack output, TerrainPatch.Header header, int[] patch, uint pRegionSizeX, | 386 | private static int EncodePatchHeader(BitPack output, TerrainPatch.Header header, int[] patch, uint pRegionSizeX, |
368 | uint pRegionSizeY, int wbits) | 387 | uint pRegionSizeY, int wbits) |
369 | { | 388 | { |
370 | /* | ||
371 | int temp; | ||
372 | int wbits = (header.QuantWBits & 0x0f) + 2; | ||
373 | uint maxWbits = (uint)wbits + 5; | ||
374 | uint minWbits = ((uint)wbits >> 1); | ||
375 | int wbitsMaxValue; | ||
376 | */ | ||
377 | // goal is to determ minimum number of bits to use so all data fits | ||
378 | /* | ||
379 | wbits = (int)minWbits; | ||
380 | wbitsMaxValue = (1 << wbits); | ||
381 | |||
382 | for (int i = 0; i < patch.Length; i++) | ||
383 | { | ||
384 | temp = patch[i]; | ||
385 | if (temp != 0) | ||
386 | { | ||
387 | // Get the absolute value | ||
388 | if (temp < 0) temp *= -1; | ||
389 | |||
390 | no coments.. | ||
391 | |||
392 | for (int j = (int)maxWbits; j > (int)minWbits; j--) | ||
393 | { | ||
394 | if ((temp & (1 << j)) != 0) | ||
395 | { | ||
396 | if (j > wbits) wbits = j; | ||
397 | break; | ||
398 | } | ||
399 | } | ||
400 | |||
401 | while (temp > wbitsMaxValue) | ||
402 | { | ||
403 | wbits++; | ||
404 | if (wbits == maxWbits) | ||
405 | goto Done; | ||
406 | wbitsMaxValue = 1 << wbits; | ||
407 | } | ||
408 | } | ||
409 | } | ||
410 | |||
411 | Done: | ||
412 | |||
413 | // wbits += 1; | ||
414 | */ | ||
415 | // better check | ||
416 | if (wbits > 17) | 389 | if (wbits > 17) |
417 | wbits = 16; | 390 | wbits = 17; |
418 | else if (wbits < 3) | 391 | else if (wbits < 2) |
419 | wbits = 3; | 392 | wbits = 2; |
420 | 393 | ||
421 | header.QuantWBits &= 0xf0; | 394 | header.QuantWBits &= 0xf0; |
422 | |||
423 | header.QuantWBits |= (wbits - 2); | 395 | header.QuantWBits |= (wbits - 2); |
424 | 396 | ||
425 | output.PackBits(header.QuantWBits, 8); | 397 | output.PackBits(header.QuantWBits, 8); |
@@ -467,39 +439,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
467 | } | 439 | } |
468 | } | 440 | } |
469 | 441 | ||
470 | /* | ||
471 | private static void DCTLine16(float[] linein, float[] lineout, int line) | 442 | private static void DCTLine16(float[] linein, float[] lineout, int line) |
472 | { | 443 | { |
473 | float total = 0.0f; | 444 | // outputs transpose data |
474 | int lineSize = line * Constants.TerrainPatchSize; | ||
475 | |||
476 | for (int n = 0; n < Constants.TerrainPatchSize; n++) | ||
477 | { | ||
478 | total += linein[lineSize + n]; | ||
479 | } | ||
480 | |||
481 | lineout[lineSize] = OO_SQRT2 * total; | ||
482 | |||
483 | int uptr = 0; | ||
484 | for (int u = 1; u < Constants.TerrainPatchSize; u++) | ||
485 | { | ||
486 | total = 0.0f; | ||
487 | uptr += Constants.TerrainPatchSize; | ||
488 | |||
489 | for (int n = 0; n < Constants.TerrainPatchSize; n++) | ||
490 | { | ||
491 | total += linein[lineSize + n] * CosineTable16[uptr + n]; | ||
492 | } | ||
493 | |||
494 | lineout[lineSize + u] = total; | ||
495 | } | ||
496 | } | ||
497 | */ | ||
498 | 445 | ||
499 | private static void DCTLine16(float[] linein, float[] lineout, int line) | ||
500 | { | ||
501 | // outputs transpose data (lines exchanged with coluns ) | ||
502 | // so to save a bit of cpu when doing coluns | ||
503 | float total = 0.0f; | 446 | float total = 0.0f; |
504 | int lineSize = line*Constants.TerrainPatchSize; | 447 | int lineSize = line*Constants.TerrainPatchSize; |
505 | 448 | ||
@@ -524,68 +467,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
524 | } | 467 | } |
525 | } | 468 | } |
526 | 469 | ||
527 | |||
528 | /* | ||
529 | private static void DCTColumn16(float[] linein, int[] lineout, int column) | ||
530 | { | ||
531 | float total = 0.0f; | ||
532 | // const float oosob = 2.0f / Constants.TerrainPatchSize; | ||
533 | |||
534 | for (int n = 0; n < Constants.TerrainPatchSize; n++) | ||
535 | { | ||
536 | total += linein[Constants.TerrainPatchSize * n + column]; | ||
537 | } | ||
538 | |||
539 | // lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * oosob * QuantizeTable16[column]); | ||
540 | lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * QuantizeTable16[column]); | ||
541 | |||
542 | for (int uptr = Constants.TerrainPatchSize; uptr < Constants.TerrainPatchSize * Constants.TerrainPatchSize; uptr += Constants.TerrainPatchSize) | ||
543 | { | ||
544 | total = 0.0f; | ||
545 | |||
546 | for (int n = 0; n < Constants.TerrainPatchSize; n++) | ||
547 | { | ||
548 | total += linein[Constants.TerrainPatchSize * n + column] * CosineTable16[uptr + n]; | ||
549 | } | ||
550 | |||
551 | // lineout[CopyMatrix16[Constants.TerrainPatchSize * u + column]] = (int)(total * oosob * QuantizeTable16[Constants.TerrainPatchSize * u + column]); | ||
552 | lineout[CopyMatrix16[uptr + column]] = (int)(total * QuantizeTable16[uptr + column]); | ||
553 | } | ||
554 | } | ||
555 | |||
556 | private static void DCTColumn16(float[] linein, int[] lineout, int column) | ||
557 | { | ||
558 | // input columns are in fact stored in lines now | ||
559 | |||
560 | float total = 0.0f; | ||
561 | // const float oosob = 2.0f / Constants.TerrainPatchSize; | ||
562 | int inlinesptr = Constants.TerrainPatchSize*column; | ||
563 | |||
564 | for (int n = 0; n < Constants.TerrainPatchSize; n++) | ||
565 | { | ||
566 | total += linein[inlinesptr + n]; | ||
567 | } | ||
568 | |||
569 | // lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * oosob * QuantizeTable16[column]); | ||
570 | lineout[CopyMatrix16[column]] = (int) (OO_SQRT2*total*QuantizeTable16[column]); | ||
571 | |||
572 | for (int uptr = Constants.TerrainPatchSize; | ||
573 | uptr < Constants.TerrainPatchSize*Constants.TerrainPatchSize; | ||
574 | uptr += Constants.TerrainPatchSize) | ||
575 | { | ||
576 | total = 0.0f; | ||
577 | |||
578 | for (int n = inlinesptr, ptru = uptr; n < inlinesptr + Constants.TerrainPatchSize; n++, ptru++) | ||
579 | { | ||
580 | total += linein[n]*CosineTable16[ptru]; | ||
581 | } | ||
582 | |||
583 | // lineout[CopyMatrix16[Constants.TerrainPatchSize * u + column]] = (int)(total * oosob * QuantizeTable16[Constants.TerrainPatchSize * u + column]); | ||
584 | lineout[CopyMatrix16[uptr + column]] = (int) (total*QuantizeTable16[uptr + column]); | ||
585 | } | ||
586 | } | ||
587 | */ | ||
588 | |||
589 | private static int DCTColumn16Wbits(float[] linein, int[] lineout, int column, int wbits, int maxwbits) | 470 | private static int DCTColumn16Wbits(float[] linein, int[] lineout, int column, int wbits, int maxwbits) |
590 | { | 471 | { |
591 | // input columns are in fact stored in lines now | 472 | // input columns are in fact stored in lines now |
@@ -701,16 +582,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
701 | private static void EncodePatch(BitPack output, int[] patch, int postquant, int wbits) | 582 | private static void EncodePatch(BitPack output, int[] patch, int postquant, int wbits) |
702 | { | 583 | { |
703 | int maxwbitssize = (1 << wbits) - 1; | 584 | int maxwbitssize = (1 << wbits) - 1; |
585 | int fullSize = Constants.TerrainPatchSize * Constants.TerrainPatchSize; | ||
704 | 586 | ||
705 | if (postquant > Constants.TerrainPatchSize*Constants.TerrainPatchSize || postquant < 0) | 587 | if (postquant > fullSize || postquant < 0) |
706 | { | 588 | { |
707 | Logger.Log("Postquant is outside the range of allowed values in EncodePatch()", Helpers.LogLevel.Error); | 589 | Logger.Log("Postquant is outside the range of allowed values in EncodePatch()", Helpers.LogLevel.Error); |
708 | return; | 590 | return; |
709 | } | 591 | } |
710 | 592 | ||
711 | if (postquant != 0) patch[Constants.TerrainPatchSize*Constants.TerrainPatchSize - postquant] = 0; | 593 | if (postquant != 0) |
594 | patch[fullSize - postquant] = 0; | ||
712 | 595 | ||
713 | for (int i = 0; i < Constants.TerrainPatchSize*Constants.TerrainPatchSize; i++) | 596 | int lastZeroindx = fullSize - postquant; |
597 | |||
598 | for (int i = 0; i < fullSize; i++) | ||
714 | { | 599 | { |
715 | int temp = patch[i]; | 600 | int temp = patch[i]; |
716 | 601 | ||
@@ -718,7 +603,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
718 | { | 603 | { |
719 | bool eob = true; | 604 | bool eob = true; |
720 | 605 | ||
721 | for (int j = i; j < Constants.TerrainPatchSize*Constants.TerrainPatchSize - postquant; j++) | 606 | for (int j = i; j < lastZeroindx ; j++) |
722 | { | 607 | { |
723 | if (patch[j] != 0) | 608 | if (patch[j] != 0) |
724 | { | 609 | { |
@@ -800,13 +685,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
800 | 685 | ||
801 | private static int[] CompressPatch(float[] patchData, TerrainPatch.Header header, int prequant, out int wbits) | 686 | private static int[] CompressPatch(float[] patchData, TerrainPatch.Header header, int prequant, out int wbits) |
802 | { | 687 | { |
803 | float[] block = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; | 688 | float[] block = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; |
804 | int wordsize = (prequant - 2) & 0x0f; | ||
805 | float oozrange = 1.0f/header.Range; | 689 | float oozrange = 1.0f/header.Range; |
806 | float range = (1 << prequant); | 690 | float range = (1 << prequant); |
807 | float premult = oozrange*range; | 691 | float premult = oozrange*range; |
808 | float sub = (1 << (prequant - 1)) + header.DCOffset*premult; | ||
809 | 692 | ||
693 | |||
694 | float sub = 0.5f * header.Range + header.DCOffset; | ||
695 | |||
696 | int wordsize = (prequant - 2) & 0x0f; | ||
810 | header.QuantWBits = wordsize; | 697 | header.QuantWBits = wordsize; |
811 | header.QuantWBits |= wordsize << 4; | 698 | header.QuantWBits |= wordsize << 4; |
812 | 699 | ||
@@ -814,7 +701,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
814 | for (int j = 0; j < Constants.TerrainPatchSize; j++) | 701 | for (int j = 0; j < Constants.TerrainPatchSize; j++) |
815 | { | 702 | { |
816 | for (int i = 0; i < Constants.TerrainPatchSize; i++) | 703 | for (int i = 0; i < Constants.TerrainPatchSize; i++) |
817 | block[k++] = patchData[j*Constants.TerrainPatchSize + i]*premult - sub; | 704 | block[k++] = (patchData[j*Constants.TerrainPatchSize + i] - sub) * premult; |
818 | } | 705 | } |
819 | 706 | ||
820 | float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; | 707 | float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; |
@@ -838,9 +725,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
838 | float oozrange = 1.0f/header.Range; | 725 | float oozrange = 1.0f/header.Range; |
839 | float range = (1 << prequant); | 726 | float range = (1 << prequant); |
840 | float premult = oozrange*range; | 727 | float premult = oozrange*range; |
841 | float sub = (1 << (prequant - 1)) + header.DCOffset*premult; | ||
842 | int wordsize = (prequant - 2) & 0x0f; | ||
843 | 728 | ||
729 | float sub = 0.5f * header.Range + header.DCOffset; | ||
730 | |||
731 | int wordsize = (prequant - 2) & 0x0f; | ||
844 | header.QuantWBits = wordsize; | 732 | header.QuantWBits = wordsize; |
845 | header.QuantWBits |= wordsize << 4; | 733 | header.QuantWBits |= wordsize << 4; |
846 | 734 | ||
@@ -848,7 +736,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
848 | for (int j = 0; j < Constants.TerrainPatchSize; j++) | 736 | for (int j = 0; j < Constants.TerrainPatchSize; j++) |
849 | { | 737 | { |
850 | for (int i = 0; i < Constants.TerrainPatchSize; i++) | 738 | for (int i = 0; i < Constants.TerrainPatchSize; i++) |
851 | block[k++] = patchData[j, i]*premult - sub; | 739 | block[k++] = (patchData[j, i] - sub) * premult; |
852 | } | 740 | } |
853 | 741 | ||
854 | float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; | 742 | float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; |
@@ -869,14 +757,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
869 | int prequant, out int wbits) | 757 | int prequant, out int wbits) |
870 | { | 758 | { |
871 | float[] block = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; | 759 | float[] block = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; |
872 | int wordsize = prequant; | 760 | |
873 | float oozrange = 1.0f/header.Range; | 761 | float oozrange = 1.0f/header.Range; |
874 | float range = (1 << prequant); | 762 | float invprequat = (1 << prequant); |
875 | float premult = oozrange*range; | 763 | float premult = oozrange* invprequat; |
876 | float sub = (1 << (prequant - 1)) + header.DCOffset*premult; | 764 | |
765 | float sub = 0.5f * header.Range + header.DCOffset; | ||
877 | 766 | ||
878 | header.QuantWBits = wordsize - 2; | 767 | int wordsize = (prequant -2 ) & 0x0f; |
879 | header.QuantWBits |= (prequant - 2) << 4; | 768 | header.QuantWBits = wordsize; |
769 | header.QuantWBits |= wordsize << 4; | ||
880 | 770 | ||
881 | int k = 0; | 771 | int k = 0; |
882 | 772 | ||
@@ -892,7 +782,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
892 | { | 782 | { |
893 | for (int xx = patchX * Constants.TerrainPatchSize; xx < xPatchLimit; xx++) | 783 | for (int xx = patchX * Constants.TerrainPatchSize; xx < xPatchLimit; xx++) |
894 | { | 784 | { |
895 | block[k++] = terrData[xx, yy] * premult - sub; | 785 | block[k++] = (terrData[xx, yy] - sub) * premult; |
896 | } | 786 | } |
897 | } | 787 | } |
898 | 788 | ||
@@ -930,7 +820,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
930 | { | 820 | { |
931 | for (int i = 0; i < Constants.TerrainPatchSize; i++) | 821 | for (int i = 0; i < Constants.TerrainPatchSize; i++) |
932 | { | 822 | { |
933 | // QuantizeTable16[j * Constants.TerrainPatchSize + i] = 1.0f / (1.0f + 2.0f * ((float)i + (float)j)); | ||
934 | QuantizeTable16[j*Constants.TerrainPatchSize + i] = oosob/(1.0f + 2.0f*(i + (float) j)); | 823 | QuantizeTable16[j*Constants.TerrainPatchSize + i] = oosob/(1.0f + 2.0f*(i + (float) j)); |
935 | } | 824 | } |
936 | } | 825 | } |