aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/TerrainCompressor.cs')
-rw-r--r--OpenSim/Region/Framework/Scenes/TerrainCompressor.cs233
1 files changed, 55 insertions, 178 deletions
diff --git a/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs b/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs
index 6b272fb..e0095e8 100644
--- a/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs
+++ b/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs
@@ -63,19 +63,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
63 private const int POSITIVE_VALUE = 0x6; 63 private const int POSITIVE_VALUE = 0x6;
64 private const int NEGATIVE_VALUE = 0x7; 64 private const int NEGATIVE_VALUE = 0x7;
65 65
66 private static readonly float[] DequantizeTable16 =
67 new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
68
69 private static readonly float[] DequantizeTable32 =
70 new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
71 66
72 private static readonly float[] CosineTable16 = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 67 private static readonly float[] CosineTable16 = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
73 //private static readonly float[] CosineTable32 = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
74 private static readonly int[] CopyMatrix16 = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 68 private static readonly int[] CopyMatrix16 = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
75 private static readonly int[] CopyMatrix32 = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
76 69
77 private static readonly float[] QuantizeTable16 = 70 private static readonly float[] QuantizeTable16 =
78 new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 71 new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
72 private static readonly float[] DequantizeTable16 =
73 new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
79 74
80 static OpenSimTerrainCompressor() 75 static OpenSimTerrainCompressor()
81 { 76 {
@@ -113,82 +108,66 @@ namespace OpenSim.Region.ClientStack.LindenUDP
113 return layer; 108 return layer;
114 } 109 }
115 110
116 // Create a land packet for a single patch. 111 public static void CreatePatch(BitPack output, float[] patchData, int x, int y, int pRegionSizeX, int pRegionSizeY)
117 public static LayerDataPacket CreateLandPacket(TerrainData terrData, int patchX, int patchY)
118 {
119 int[] xPieces = new int[1];
120 int[] yPieces = new int[1];
121 xPieces[0] = patchX; // patch X dimension
122 yPieces[0] = patchY;
123
124 return CreateLandPacket(terrData, xPieces, yPieces);
125 }
126
127 public static LayerDataPacket CreateLandPacket(TerrainData terrData, int[] xPieces, int[] yPieces)
128 { 112 {
129 byte landPacketType = (byte)TerrainPatch.LayerType.Land; 113 TerrainPatch.Header header = PrescanPatch(patchData);
130 if (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize) 114 header.QuantWBits = 136;
115 if (pRegionSizeX > Constants.RegionSize || pRegionSizeY > Constants.RegionSize)
116 {
117 header.PatchIDs = (y & 0xFFFF);
118 header.PatchIDs += (x << 16);
119 }
120 else
131 { 121 {
132 landPacketType = (byte)TerrainPatch.LayerType.LandExtended; 122 header.PatchIDs = (y & 0x1F);
123 header.PatchIDs += (x << 5);
133 } 124 }
134 125
135 return CreateLandPacket(terrData, xPieces, yPieces, landPacketType); 126 int wbits;
127 int[] patch = CompressPatch(patchData, header, 10, out wbits);
128 wbits = EncodePatchHeader(output, header, patch, Constants.RegionSize, Constants.RegionSize, wbits);
129 EncodePatch(output, patch, 0, wbits);
136 } 130 }
137 131
138 /// <summary> 132 private static int[] CompressPatch(float[] patchData, TerrainPatch.Header header, int prequant, out int wbits)
139 /// Creates a LayerData packet for compressed land data given a full
140 /// simulator heightmap and an array of indices of patches to compress
141 /// </summary>
142 /// <param name="terrData">
143 /// Terrain data that can result in a meter square heightmap.
144 /// </param>
145 /// <param name="x">
146 /// Array of indexes in the grid of patches
147 /// for this simulator.
148 /// If creating a packet for multiple patches, there will be entries in
149 /// both the X and Y arrays for each of the patches.
150 /// For example if patches 1 and 17 are to be sent,
151 /// x[] = {1,1} and y[] = {0,1} which specifies the patches at
152 /// indexes <1,0> and <1,1> (presuming the terrain size is 16x16 patches).
153 /// </param>
154 /// <param name="y">
155 /// Array of indexes in the grid of patches.
156 /// </param>
157 /// <param name="type"></param>
158 /// <returns></returns>
159 public static LayerDataPacket CreateLandPacket(TerrainData terrData, int[] x, int[] y, byte type)
160 { 133 {
161 LayerDataPacket layer = new LayerDataPacket(); 134 float[] block = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
162 layer.LayerID.Type = type; 135 float oozrange = 1.0f / header.Range;
136 float range = (1 << prequant);
137 float premult = oozrange * range;
163 138
164 byte[] data = new byte[x.Length * Constants.TerrainPatchSize * Constants.TerrainPatchSize * 2];
165 BitPack bitpack = new BitPack(data, 0);
166 bitpack.PackBits(STRIDE, 16);
167 bitpack.PackBits(Constants.TerrainPatchSize, 8);
168 bitpack.PackBits(type, 8);
169 139
170 for (int i = 0; i < x.Length; i++) 140 float sub = 0.5f * header.Range + header.DCOffset;
171 CreatePatchFromHeightmap(bitpack, terrData, x[i], y[i]);
172 141
173 bitpack.PackBits(END_OF_PATCHES, 8); 142 int wordsize = (prequant - 2) & 0x0f;
143 header.QuantWBits = wordsize;
144 header.QuantWBits |= wordsize << 4;
174 145
175 layer.LayerData.Data = new byte[bitpack.BytePos + 1]; 146 int k = 0;
176 Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1); 147 for (int j = 0; j < Constants.TerrainPatchSize; j++)
148 {
149 for (int i = 0; i < Constants.TerrainPatchSize; i++)
150 block[k++] = (patchData[j * Constants.TerrainPatchSize + i] - sub) * premult;
151 }
177 152
178 return layer; 153 float[] ftemp = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
154 int[] itemp = new int[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
155
156 wbits = (prequant >> 1);
157
158 for (int o = 0; o < Constants.TerrainPatchSize; o++)
159 DCTLine16(block, ftemp, o);
160 for (int o = 0; o < Constants.TerrainPatchSize; o++)
161 wbits = DCTColumn16Wbits(ftemp, itemp, o, wbits);
162
163 return itemp;
179 } 164 }
180 165
181 public static List<LayerDataPacket> CreateTerrainPatchsPacket(TerrainData terrData, int[] x, int[] y) 166 // new using terrain data and patchs indexes
167 public static List<LayerDataPacket> CreateLayerDataPackets(TerrainData terrData, int[] x, int[] y, byte landPacketType)
182 { 168 {
183 List<LayerDataPacket> ret = new List<LayerDataPacket>(); 169 List<LayerDataPacket> ret = new List<LayerDataPacket>();
184 170
185 // normal or large region
186 byte landPacketType;
187 if (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize)
188 landPacketType = (byte)TerrainPatch.LayerType.LandExtended;
189 else
190 landPacketType = (byte)TerrainPatch.LayerType.Land;
191
192 //create packet and global header 171 //create packet and global header
193 LayerDataPacket layer = new LayerDataPacket(); 172 LayerDataPacket layer = new LayerDataPacket();
194 173
@@ -232,29 +211,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
232 return ret; 211 return ret;
233 } 212 }
234 213
235 // Unused: left for historical reference.
236 // nopes.. in use by clouds and wind
237 public static void CreatePatch(BitPack output, float[] patchData, int x, int y, int pRegionSizeX, int pRegionSizeY)
238 {
239 TerrainPatch.Header header = PrescanPatch(patchData);
240 header.QuantWBits = 136;
241 if (pRegionSizeX > Constants.RegionSize || pRegionSizeY > Constants.RegionSize)
242 {
243 header.PatchIDs = (y & 0xFFFF);
244 header.PatchIDs += (x << 16);
245 }
246 else
247 {
248 header.PatchIDs = (y & 0x1F);
249 header.PatchIDs += (x << 5);
250 }
251
252 int wbits;
253 int[] patch = CompressPatch(patchData, header, 10, out wbits);
254 wbits = EncodePatchHeader(output, header, patch, Constants.RegionSize, Constants.RegionSize, wbits);
255 EncodePatch(output, patch, 0, wbits);
256 }
257
258 /// <summary> 214 /// <summary>
259 /// Add a patch of terrain to a BitPacker 215 /// Add a patch of terrain to a BitPacker
260 /// </summary> 216 /// </summary>
@@ -302,9 +258,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
302 output.PackBits(header.PatchIDs, 32); 258 output.PackBits(header.PatchIDs, 32);
303 else 259 else
304 output.PackBits(header.PatchIDs, 10); 260 output.PackBits(header.PatchIDs, 10);
305 261
306// output.PackBits(NEGATIVE_VALUE, 3);
307// output.PackBits(0x20, 6);
308 // and thats all 262 // and thats all
309 output.PackBits(ZERO_EOB, 2); 263 output.PackBits(ZERO_EOB, 2);
310 return; 264 return;
@@ -468,11 +422,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
468 } 422 }
469 } 423 }
470 424
471 private static int DCTColumn16Wbits(float[] linein, int[] lineout, int column, int wbits, int maxwbits) 425 private static int DCTColumn16Wbits(float[] linein, int[] lineout, int column, int wbits)
472 { 426 {
473 // input columns are in fact stored in lines now 427 // input columns are in fact stored in lines now
474 428
475 bool dowbits = wbits != maxwbits; 429 const int maxwbits = 17; // per header encoding
430
431 bool dowbits = wbits < 17;
432
476 int wbitsMaxValue = 1 << wbits; 433 int wbitsMaxValue = 1 << wbits;
477 434
478 float total = 0.0f; 435 float total = 0.0f;
@@ -484,7 +441,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
484 total += linein[inlinesptr + n]; 441 total += linein[inlinesptr + n];
485 } 442 }
486 443
487 // lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * oosob * QuantizeTable16[column]);
488 int tmp = (int) (OO_SQRT2*total*QuantizeTable16[column]); 444 int tmp = (int) (OO_SQRT2*total*QuantizeTable16[column]);
489 lineout[CopyMatrix16[column]] = tmp; 445 lineout[CopyMatrix16[column]] = tmp;
490 446
@@ -642,83 +598,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
642 } 598 }
643 } 599 }
644 600
645 public static float[] DecompressPatch(int[] patches, TerrainPatch.Header header, TerrainPatch.GroupHeader group)
646 {
647 float[] block = new float[group.PatchSize*group.PatchSize];
648 float[] output = new float[group.PatchSize*group.PatchSize];
649 int prequant = (header.QuantWBits >> 4) + 2;
650 int quantize = 1 << prequant;
651 float ooq = 1.0f/quantize;
652 float mult = ooq*header.Range;
653 float addval = mult*(1 << (prequant - 1)) + header.DCOffset;
654
655 if (group.PatchSize == Constants.TerrainPatchSize)
656 {
657 for (int n = 0; n < Constants.TerrainPatchSize*Constants.TerrainPatchSize; n++)
658 {
659 block[n] = patches[CopyMatrix16[n]]*DequantizeTable16[n];
660 }
661
662 float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
663
664 for (int o = 0; o < Constants.TerrainPatchSize; o++)
665 IDCTColumn16(block, ftemp, o);
666 for (int o = 0; o < Constants.TerrainPatchSize; o++)
667 IDCTLine16(ftemp, block, o);
668 }
669 else
670 {
671 for (int n = 0; n < Constants.TerrainPatchSize*2*Constants.TerrainPatchSize*2; n++)
672 {
673 block[n] = patches[CopyMatrix32[n]]*DequantizeTable32[n];
674 }
675
676 Logger.Log("Implement IDCTPatchLarge", Helpers.LogLevel.Error);
677 }
678
679 for (int j = 0; j < block.Length; j++)
680 {
681 output[j] = block[j]*mult + addval;
682 }
683
684 return output;
685 }
686
687 private static int[] CompressPatch(float[] patchData, TerrainPatch.Header header, int prequant, out int wbits)
688 {
689 float[] block = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
690 float oozrange = 1.0f/header.Range;
691 float range = (1 << prequant);
692 float premult = oozrange*range;
693
694
695 float sub = 0.5f * header.Range + header.DCOffset;
696
697 int wordsize = (prequant - 2) & 0x0f;
698 header.QuantWBits = wordsize;
699 header.QuantWBits |= wordsize << 4;
700
701 int k = 0;
702 for (int j = 0; j < Constants.TerrainPatchSize; j++)
703 {
704 for (int i = 0; i < Constants.TerrainPatchSize; i++)
705 block[k++] = (patchData[j*Constants.TerrainPatchSize + i] - sub) * premult;
706 }
707
708 float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
709 int[] itemp = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
710
711
712 int maxWbits = prequant + 5;
713 wbits = (prequant >> 1);
714
715 for (int o = 0; o < Constants.TerrainPatchSize; o++)
716 DCTLine16(block, ftemp, o);
717 for (int o = 0; o < Constants.TerrainPatchSize; o++)
718 wbits = DCTColumn16Wbits(ftemp, itemp, o, wbits, maxWbits);
719
720 return itemp;
721 }
722 601
723 private static int[] CompressPatch(float[,] patchData, TerrainPatch.Header header, int prequant, out int wbits) 602 private static int[] CompressPatch(float[,] patchData, TerrainPatch.Header header, int prequant, out int wbits)
724 { 603 {
@@ -743,13 +622,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
743 float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 622 float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
744 int[] itemp = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 623 int[] itemp = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
745 624
746 int maxWbits = prequant + 5;
747 wbits = (prequant >> 1); 625 wbits = (prequant >> 1);
748 626
749 for (int o = 0; o < Constants.TerrainPatchSize; o++) 627 for (int o = 0; o < Constants.TerrainPatchSize; o++)
750 DCTLine16(block, ftemp, o); 628 DCTLine16(block, ftemp, o);
751 for (int o = 0; o < Constants.TerrainPatchSize; o++) 629 for (int o = 0; o < Constants.TerrainPatchSize; o++)
752 wbits = DCTColumn16Wbits(ftemp, itemp, o, wbits, maxWbits); 630 wbits = DCTColumn16Wbits(ftemp, itemp, o, wbits);
753 631
754 return itemp; 632 return itemp;
755 } 633 }
@@ -790,13 +668,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
790 float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 668 float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
791 int[] itemp = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 669 int[] itemp = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
792 670
793 int maxWbits = prequant + 5;
794 wbits = (prequant >> 1); 671 wbits = (prequant >> 1);
795 672
796 for (int o = 0; o < Constants.TerrainPatchSize; o++) 673 for (int o = 0; o < Constants.TerrainPatchSize; o++)
797 DCTLine16(block, ftemp, o); 674 DCTLine16(block, ftemp, o);
798 for (int o = 0; o < Constants.TerrainPatchSize; o++) 675 for (int o = 0; o < Constants.TerrainPatchSize; o++)
799 wbits = DCTColumn16Wbits(ftemp, itemp, o, wbits, maxWbits); 676 wbits = DCTColumn16Wbits(ftemp, itemp, o, wbits);
800 677
801 return itemp; 678 return itemp;
802 } 679 }