diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/TerrainCompressor.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/TerrainCompressor.cs | 233 |
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 | } |