aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs
diff options
context:
space:
mode:
authoronefang2019-09-11 16:36:50 +1000
committeronefang2019-09-11 16:36:50 +1000
commit50cd1ffd32f69228e566f2b0b89f86ea0d9fe489 (patch)
tree52f2ab0c04f1a5d7d6ac5dc872981b4b156447e7 /OpenSim/Region/Framework/Scenes/TerrainCompressor.cs
parentRenamed branch to SledjChisl. (diff)
parentBump to release flavour, build 0. (diff)
downloadopensim-SC_OLD-50cd1ffd32f69228e566f2b0b89f86ea0d9fe489.zip
opensim-SC_OLD-50cd1ffd32f69228e566f2b0b89f86ea0d9fe489.tar.gz
opensim-SC_OLD-50cd1ffd32f69228e566f2b0b89f86ea0d9fe489.tar.bz2
opensim-SC_OLD-50cd1ffd32f69228e566f2b0b89f86ea0d9fe489.tar.xz
Merge branch 'SledjChisl'
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/TerrainCompressor.cs')
-rw-r--r--OpenSim/Region/Framework/Scenes/TerrainCompressor.cs1589
1 files changed, 983 insertions, 606 deletions
diff --git a/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs b/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs
index fc8f8cd..9d1f815 100644
--- a/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs
+++ b/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs
@@ -27,10 +27,13 @@
27 27
28/* Freely adapted from the Aurora version of the terrain compressor. 28/* Freely adapted from the Aurora version of the terrain compressor.
29 * Copyright (c) Contributors, http://aurora-sim.org/, http://opensimulator.org/ 29 * Copyright (c) Contributors, http://aurora-sim.org/, http://opensimulator.org/
30 * Aurora version created from libOpenMetaverse Library terrain compressor
30 */ 31 */
31 32
32using System; 33using System;
34using System.Collections.Generic;
33using System.Reflection; 35using System.Reflection;
36using System.Diagnostics;
34 37
35using log4net; 38using log4net;
36 39
@@ -45,7 +48,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
45{ 48{
46 public static class OpenSimTerrainCompressor 49 public static class OpenSimTerrainCompressor
47 { 50 {
48// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 51 // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49 52
50#pragma warning disable 414 53#pragma warning disable 414
51 private static string LogHeader = "[TERRAIN COMPRESSOR]"; 54 private static string LogHeader = "[TERRAIN COMPRESSOR]";
@@ -61,47 +64,41 @@ namespace OpenSim.Region.ClientStack.LindenUDP
61 private const int POSITIVE_VALUE = 0x6; 64 private const int POSITIVE_VALUE = 0x6;
62 private const int NEGATIVE_VALUE = 0x7; 65 private const int NEGATIVE_VALUE = 0x7;
63 66
64 private static readonly float[] DequantizeTable16 =
65 new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
66
67 private static readonly float[] DequantizeTable32 =
68 new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
69 67
70 private static readonly float[] CosineTable16 = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 68// private static readonly float[] CosineTable16 = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
71 //private static readonly float[] CosineTable32 = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize]; 69 private static readonly int[] CopyMatrix16 = new int[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
72 private static readonly int[] CopyMatrix16 = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
73 private static readonly int[] CopyMatrix32 = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
74 70
75 private static readonly float[] QuantizeTable16 = 71 private static readonly float[] QuantizeTable16 =
76 new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 72 new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
73 private static readonly float[] DequantizeTable16 =
74 new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
77 75
78 static OpenSimTerrainCompressor() 76 static OpenSimTerrainCompressor()
79 { 77 {
80 // Initialize the decompression tables 78 // Initialize the decompression tables
81 BuildDequantizeTable16(); 79 BuildDequantizeTable16();
82 SetupCosines16(); 80// SetupCosines16();
83 BuildCopyMatrix16(); 81 BuildCopyMatrix16();
84 BuildQuantizeTable16(); 82 BuildQuantizeTable16();
85 } 83 }
86 84
87 // Used to send cloud and wind patches 85 // Used to send cloud and wind patches
88 public static LayerDataPacket CreateLayerDataPacket(TerrainPatch[] patches, byte type, int pRegionSizeX, 86 public static LayerDataPacket CreateLayerDataPacketStandardSize(TerrainPatch[] patches, byte type)
89 int pRegionSizeY)
90 { 87 {
91 LayerDataPacket layer = new LayerDataPacket {LayerID = {Type = type}}; 88 LayerDataPacket layer = new LayerDataPacket { LayerID = { Type = type } };
92 89
93 TerrainPatch.GroupHeader header = new TerrainPatch.GroupHeader 90 TerrainPatch.GroupHeader header = new TerrainPatch.GroupHeader
94 {Stride = STRIDE, PatchSize = Constants.TerrainPatchSize}; 91 { Stride = STRIDE, PatchSize = Constants.TerrainPatchSize };
95 92
96 // Should be enough to fit even the most poorly packed data 93 // Should be enough to fit even the most poorly packed data
97 byte[] data = new byte[patches.Length*Constants.TerrainPatchSize*Constants.TerrainPatchSize*2]; 94 byte[] data = new byte[patches.Length * Constants.TerrainPatchSize * Constants.TerrainPatchSize * 2];
98 BitPack bitpack = new BitPack(data, 0); 95 BitPack bitpack = new BitPack(data, 0);
99 bitpack.PackBits(header.Stride, 16); 96 bitpack.PackBits(header.Stride, 16);
100 bitpack.PackBits(header.PatchSize, 8); 97 bitpack.PackBits(header.PatchSize, 8);
101 bitpack.PackBits(type, 8); 98 bitpack.PackBits(type, 8);
102 99
103 foreach (TerrainPatch t in patches) 100 foreach (TerrainPatch t in patches)
104 CreatePatch(bitpack, t.Data, t.X, t.Y, pRegionSizeX, pRegionSizeY); 101 CreatePatchtStandardSize(bitpack, t.Data, t.X, t.Y);
105 102
106 bitpack.PackBits(END_OF_PATCHES, 8); 103 bitpack.PackBits(END_OF_PATCHES, 8);
107 104
@@ -111,122 +108,131 @@ namespace OpenSim.Region.ClientStack.LindenUDP
111 return layer; 108 return layer;
112 } 109 }
113 110
114 // Create a land packet for a single patch. 111 public static void CreatePatchtStandardSize(BitPack output, float[] patchData, int x, int y)
115 public static LayerDataPacket CreateLandPacket(TerrainData terrData, int patchX, int patchY)
116 { 112 {
117 int[] xPieces = new int[1]; 113 TerrainPatch.Header header = PrescanPatch(patchData);
118 int[] yPieces = new int[1]; 114 header.QuantWBits = 136;
119 xPieces[0] = patchX; // patch X dimension
120 yPieces[0] = patchY;
121 115
122 return CreateLandPacket(terrData, xPieces, yPieces); 116 header.PatchIDs = (y & 0x1F);
117 header.PatchIDs += (x << 5);
118
119 int wbits;
120 int[] patch = CompressPatch(patchData, header, 10, out wbits);
121 EncodePatchHeader(output, header, patch, false, ref wbits);
122 EncodePatch(output, patch, 0, wbits);
123 } 123 }
124 124
125 public static LayerDataPacket CreateLandPacket(TerrainData terrData, int[] xPieces, int[] yPieces) 125 private static TerrainPatch.Header PrescanPatch(float[] patch)
126 { 126 {
127 byte landPacketType = (byte)TerrainPatch.LayerType.Land; 127 TerrainPatch.Header header = new TerrainPatch.Header();
128 if (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize) 128 float zmax = -99999999.0f;
129 float zmin = 99999999.0f;
130
131 for (int i = 0; i < Constants.TerrainPatchSize * Constants.TerrainPatchSize; i++)
129 { 132 {
130 landPacketType = (byte)TerrainPatch.LayerType.LandExtended; 133 float val = patch[i];
134 if (val > zmax) zmax = val;
135 if (val < zmin) zmin = val;
131 } 136 }
132 137
133 return CreateLandPacket(terrData, xPieces, yPieces, landPacketType); 138 header.DCOffset = zmin;
139 header.Range = (int)((zmax - zmin) + 1.0f);
140
141 return header;
134 } 142 }
135 143
136 /// <summary> 144 private static int[] CompressPatch(float[] patchData, TerrainPatch.Header header, int prequant, out int wbits)
137 /// Creates a LayerData packet for compressed land data given a full
138 /// simulator heightmap and an array of indices of patches to compress
139 /// </summary>
140 /// <param name="terrData">
141 /// Terrain data that can result in a meter square heightmap.
142 /// </param>
143 /// <param name="x">
144 /// Array of indexes in the grid of patches
145 /// for this simulator.
146 /// If creating a packet for multiple patches, there will be entries in
147 /// both the X and Y arrays for each of the patches.
148 /// For example if patches 1 and 17 are to be sent,
149 /// x[] = {1,1} and y[] = {0,1} which specifies the patches at
150 /// indexes <1,0> and <1,1> (presuming the terrain size is 16x16 patches).
151 /// </param>
152 /// <param name="y">
153 /// Array of indexes in the grid of patches.
154 /// </param>
155 /// <param name="type"></param>
156 /// <returns></returns>
157 public static LayerDataPacket CreateLandPacket(TerrainData terrData, int[] x, int[] y, byte type)
158 { 145 {
159 LayerDataPacket layer = new LayerDataPacket {LayerID = {Type = type}}; 146 float[] block = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
147 float oozrange = 1.0f / header.Range;
148 float range = (1 << prequant);
149 float premult = oozrange * range;
160 150
161 TerrainPatch.GroupHeader header = new TerrainPatch.GroupHeader
162 {Stride = STRIDE, PatchSize = Constants.TerrainPatchSize};
163 151
164 byte[] data = new byte[x.Length * Constants.TerrainPatchSize * Constants.TerrainPatchSize * 2]; 152 float sub = 0.5f * header.Range + header.DCOffset;
165 BitPack bitpack = new BitPack(data, 0);
166 bitpack.PackBits(header.Stride, 16);
167 bitpack.PackBits(header.PatchSize, 8);
168 bitpack.PackBits(type, 8);
169 153
170 for (int i = 0; i < x.Length; i++) 154 int wordsize = (prequant - 2) & 0x0f;
171 CreatePatchFromHeightmap(bitpack, terrData, x[i], y[i]); 155 header.QuantWBits = wordsize;
156 header.QuantWBits |= wordsize << 4;
172 157
173 bitpack.PackBits(END_OF_PATCHES, 8); 158 int k = 0;
159 for (int j = 0; j < Constants.TerrainPatchSize; j++)
160 {
161 for (int i = 0; i < Constants.TerrainPatchSize; i++)
162 block[k++] = (patchData[j * Constants.TerrainPatchSize + i] - sub) * premult;
163 }
174 164
175 layer.LayerData.Data = new byte[bitpack.BytePos + 1]; 165 float[] ftemp = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
176 Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1); 166 int[] iout = new int[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
177 167
178 return layer; 168 wbits = (prequant >> 1);
169
170 dct16x16(block, iout, ref wbits);
171
172 return iout;
179 } 173 }
180 174
181 // Unused: left for historical reference. 175 // new using terrain data and patchs indexes
182 public static void CreatePatch(BitPack output, float[] patchData, int x, int y, int pRegionSizeX, int pRegionSizeY) 176 public static List<LayerDataPacket> CreateLayerDataPackets(TerrainData terrData, int[] x, int[] y, byte landPacketType)
183 { 177 {
184 TerrainPatch.Header header = PrescanPatch(patchData); 178 List<LayerDataPacket> ret = new List<LayerDataPacket>();
185 header.QuantWBits = 136; 179
186 if (pRegionSizeX > Constants.RegionSize || pRegionSizeY > Constants.RegionSize) 180 //create packet and global header
187 { 181 LayerDataPacket layer = new LayerDataPacket();
188 header.PatchIDs = (y & 0xFFFF); 182
189 header.PatchIDs += (x << 16); 183 layer.LayerID.Type = landPacketType;
190 } 184
191 else 185 byte[] data = new byte[x.Length * Constants.TerrainPatchSize * Constants.TerrainPatchSize * 2];
186 BitPack bitpack = new BitPack(data, 0);
187 bitpack.PackBits(STRIDE, 16);
188 bitpack.PackBits(Constants.TerrainPatchSize, 8);
189 bitpack.PackBits(landPacketType, 8);
190
191 for (int i = 0; i < x.Length; i++)
192 { 192 {
193 header.PatchIDs = (y & 0x1F); 193 CreatePatchFromTerrainData(bitpack, terrData, x[i], y[i]);
194 header.PatchIDs += (x << 5); 194 if (bitpack.BytePos > 980 && i != x.Length - 1)
195 {
196 //finish this packet
197 bitpack.PackBits(END_OF_PATCHES, 8);
198
199 layer.LayerData.Data = new byte[bitpack.BytePos + 1];
200 Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1);
201 ret.Add(layer);
202
203 // start another
204 layer = new LayerDataPacket();
205 layer.LayerID.Type = landPacketType;
206
207 bitpack = new BitPack(data, 0);
208 bitpack.PackBits(STRIDE, 16);
209 bitpack.PackBits(Constants.TerrainPatchSize, 8);
210 bitpack.PackBits(landPacketType, 8);
211 }
195 } 212 }
196 213
197 // NOTE: No idea what prequant and postquant should be or what they do 214 bitpack.PackBits(END_OF_PATCHES, 8);
198 215
199 int wbits; 216 layer.LayerData.Data = new byte[bitpack.BytePos + 1];
200 int[] patch = CompressPatch(patchData, header, 10, out wbits); 217 Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1);
201 wbits = EncodePatchHeader(output, header, patch, Constants.RegionSize, Constants.RegionSize, wbits); 218 ret.Add(layer);
202 EncodePatch(output, patch, 0, wbits); 219
220 return ret;
203 } 221 }
204 222
205 /// <summary> 223 public static void CreatePatchFromTerrainData(BitPack output, TerrainData terrData, int patchX, int patchY)
206 /// Add a patch of terrain to a BitPacker
207 /// </summary>
208 /// <param name="output">BitPacker to write the patch to</param>
209 /// <param name="heightmap">
210 /// Heightmap of the simulator. Presumed to be an sizeX*sizeY array.
211 /// </param>
212 /// <param name="patchX">
213 /// X offset of the patch to create.
214 /// </param>
215 /// <param name="patchY">
216 /// Y offset of the patch to create.
217 /// </param>
218 /// <param name="pRegionSizeX"></param>
219 /// <param name="pRegionSizeY"></param>
220 public static void CreatePatchFromHeightmap(BitPack output, TerrainData terrData, int patchX, int patchY)
221 { 224 {
222 TerrainPatch.Header header = PrescanPatch(terrData, patchX, patchY); 225 float frange;
223 header.QuantWBits = 136; 226 TerrainPatch.Header header = PrescanPatch(terrData, patchX, patchY, out frange);
227 header.QuantWBits = 130;
224 228
229 bool largeRegion = false;
225 // If larger than legacy region size, pack patch X and Y info differently. 230 // If larger than legacy region size, pack patch X and Y info differently.
226 if (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize) 231 if (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize)
227 { 232 {
228 header.PatchIDs = (patchY & 0xFFFF); 233 header.PatchIDs = (patchY & 0xFFFF);
229 header.PatchIDs += (patchX << 16); 234 header.PatchIDs += (patchX << 16);
235 largeRegion = true;
230 } 236 }
231 else 237 else
232 { 238 {
@@ -234,45 +240,45 @@ namespace OpenSim.Region.ClientStack.LindenUDP
234 header.PatchIDs += (patchX << 5); 240 header.PatchIDs += (patchX << 5);
235 } 241 }
236 242
237 // m_log.DebugFormat("{0} CreatePatchFromHeightmap. patchX={1}, patchY={2}, DCOffset={3}, range={4}", 243 if (Math.Round((double)frange, 2) == 1.0)
238 // LogHeader, patchX, patchY, header.DCOffset, header.Range); 244 {
245 // flat terrain speed up things
239 246
240 // NOTE: No idea what prequant and postquant should be or what they do 247 header.DCOffset -= 0.5f;
241 int wbits;
242 int[] patch = CompressPatch(terrData, patchX, patchY, header, 10, out wbits);
243 wbits = EncodePatchHeader(output, header, patch, (uint)terrData.SizeX, (uint)terrData.SizeY, wbits);
244 EncodePatch(output, patch, 0, wbits);
245 }
246 248
247 private static TerrainPatch.Header PrescanPatch(float[] patch) 249 header.QuantWBits = 0x00;
248 { 250 output.PackBits(header.QuantWBits, 8);
249 TerrainPatch.Header header = new TerrainPatch.Header(); 251 output.PackFloat(header.DCOffset);
250 float zmax = -99999999.0f; 252 output.PackBits(1, 16);
251 float zmin = 99999999.0f; 253 if (largeRegion)
254 output.PackBits(header.PatchIDs, 32);
255 else
256 output.PackBits(header.PatchIDs, 10);
252 257
253 for (int i = 0; i < Constants.TerrainPatchSize*Constants.TerrainPatchSize; i++) 258 // and thats all
254 { 259 output.PackBits(ZERO_EOB, 2);
255 float val = patch[i]; 260 return;
256 if (val > zmax) zmax = val;
257 if (val < zmin) zmin = val;
258 } 261 }
259 262
260 header.DCOffset = zmin; 263 int wbits;
261 header.Range = (int) ((zmax - zmin) + 1.0f); 264 int[] patch = CompressPatch(terrData, patchX, patchY, header, 10, out wbits);
262 265 EncodePatchHeader(output, header, patch, largeRegion, ref wbits);
263 return header; 266 EncodePatch(output, patch, 0, wbits);
264 } 267 }
265 268
266 // Scan the height info we're returning and return a patch packet header for this patch. 269 // Scan the height info we're returning and return a patch packet header for this patch.
267 private static TerrainPatch.Header PrescanPatch(TerrainData terrData, int patchX, int patchY) 270 private static TerrainPatch.Header PrescanPatch(TerrainData terrData, int patchX, int patchY, out float frange)
268 { 271 {
269 TerrainPatch.Header header = new TerrainPatch.Header(); 272 TerrainPatch.Header header = new TerrainPatch.Header();
270 float zmax = -99999999.0f; 273 float zmax = float.MinValue;
271 float zmin = 99999999.0f; 274 float zmin = float.MaxValue;
272 275
273 for (int j = patchY*Constants.TerrainPatchSize; j < (patchY + 1)*Constants.TerrainPatchSize; j++) 276 int startx = patchX * Constants.TerrainPatchSize;
277 int starty = patchY * Constants.TerrainPatchSize;
278
279 for (int j = starty; j < starty + Constants.TerrainPatchSize; j++)
274 { 280 {
275 for (int i = patchX*Constants.TerrainPatchSize; i < (patchX + 1)*Constants.TerrainPatchSize; i++) 281 for (int i = startx; i < startx + Constants.TerrainPatchSize; i++)
276 { 282 {
277 float val = terrData[i, j]; 283 float val = terrData[i, j];
278 if (val > zmax) zmax = val; 284 if (val > zmax) zmax = val;
@@ -281,309 +287,430 @@ namespace OpenSim.Region.ClientStack.LindenUDP
281 } 287 }
282 288
283 header.DCOffset = zmin; 289 header.DCOffset = zmin;
284 header.Range = (int)((zmax - zmin) + 1.0f); 290 frange = ((zmax - zmin) + 1.0f);
285 291 header.Range = (int)frange;
286 return header;
287 }
288
289 public static TerrainPatch.Header DecodePatchHeader(BitPack bitpack)
290 {
291 TerrainPatch.Header header = new TerrainPatch.Header {QuantWBits = bitpack.UnpackBits(8)};
292
293 // Quantized word bits
294 if (header.QuantWBits == END_OF_PATCHES)
295 return header;
296
297 // DC offset
298 header.DCOffset = bitpack.UnpackFloat();
299
300 // Range
301 header.Range = bitpack.UnpackBits(16);
302
303 // Patch IDs (10 bits)
304 header.PatchIDs = bitpack.UnpackBits(10);
305
306 // Word bits
307 header.WordBits = (uint) ((header.QuantWBits & 0x0f) + 2);
308 292
309 return header; 293 return header;
310 } 294 }
311 295
312 private static int EncodePatchHeader(BitPack output, TerrainPatch.Header header, int[] patch, uint pRegionSizeX, 296 private static void EncodePatchHeader(BitPack output, TerrainPatch.Header header, int[] patch, bool largeRegion, ref int wbits)
313 uint pRegionSizeY, int wbits)
314 { 297 {
315 /*
316 int temp;
317 int wbits = (header.QuantWBits & 0x0f) + 2;
318 uint maxWbits = (uint)wbits + 5;
319 uint minWbits = ((uint)wbits >> 1);
320 int wbitsMaxValue;
321 */
322 // goal is to determ minimum number of bits to use so all data fits
323 /*
324 wbits = (int)minWbits;
325 wbitsMaxValue = (1 << wbits);
326
327 for (int i = 0; i < patch.Length; i++)
328 {
329 temp = patch[i];
330 if (temp != 0)
331 {
332 // Get the absolute value
333 if (temp < 0) temp *= -1;
334
335 no coments..
336
337 for (int j = (int)maxWbits; j > (int)minWbits; j--)
338 {
339 if ((temp & (1 << j)) != 0)
340 {
341 if (j > wbits) wbits = j;
342 break;
343 }
344 }
345
346 while (temp > wbitsMaxValue)
347 {
348 wbits++;
349 if (wbits == maxWbits)
350 goto Done;
351 wbitsMaxValue = 1 << wbits;
352 }
353 }
354 }
355
356 Done:
357
358 // wbits += 1;
359 */
360 // better check
361 if (wbits > 17) 298 if (wbits > 17)
362 wbits = 16; 299 wbits = 17;
363 else if (wbits < 3) 300 else if (wbits < 2)
364 wbits = 3; 301 wbits = 2;
365 302
366 header.QuantWBits &= 0xf0; 303 header.QuantWBits &= 0xf0;
367
368 header.QuantWBits |= (wbits - 2); 304 header.QuantWBits |= (wbits - 2);
369 305
370 output.PackBits(header.QuantWBits, 8); 306 output.PackBits(header.QuantWBits, 8);
371 output.PackFloat(header.DCOffset); 307 output.PackFloat(header.DCOffset);
372 output.PackBits(header.Range, 16); 308 output.PackBits(header.Range, 16);
373 if (pRegionSizeX > Constants.RegionSize || pRegionSizeY > Constants.RegionSize) 309 if (largeRegion)
374 output.PackBits(header.PatchIDs, 32); 310 output.PackBits(header.PatchIDs, 32);
375 else 311 else
376 output.PackBits(header.PatchIDs, 10); 312 output.PackBits(header.PatchIDs, 10);
377
378 return wbits;
379 } 313 }
380 314
381 private static void IDCTColumn16(float[] linein, float[] lineout, int column) 315 private static void EncodePatch(BitPack output, int[] patch, int postquant, int wbits)
382 { 316 {
383 for (int n = 0; n < Constants.TerrainPatchSize; n++) 317 int maxwbitssize = (1 << wbits) - 1;
384 { 318 int fullSize = Constants.TerrainPatchSize * Constants.TerrainPatchSize;
385 float total = OO_SQRT2*linein[column];
386
387 for (int u = 1; u < Constants.TerrainPatchSize; u++)
388 {
389 int usize = u*Constants.TerrainPatchSize;
390 total += linein[usize + column]*CosineTable16[usize + n];
391 }
392 319
393 lineout[Constants.TerrainPatchSize*n + column] = total; 320 if (postquant > fullSize || postquant < 0)
321 {
322 Logger.Log("Postquant is outside the range of allowed values in EncodePatch()", Helpers.LogLevel.Error);
323 return;
394 } 324 }
395 }
396 325
397 private static void IDCTLine16(float[] linein, float[] lineout, int line) 326 if (postquant != 0)
398 { 327 patch[fullSize - postquant] = 0;
399 const float oosob = 2.0f/Constants.TerrainPatchSize;
400 int lineSize = line*Constants.TerrainPatchSize;
401 328
402 for (int n = 0; n < Constants.TerrainPatchSize; n++) 329 int lastZeroindx = fullSize - postquant;
330
331 for (int i = 0; i < fullSize; i++)
403 { 332 {
404 float total = OO_SQRT2*linein[lineSize]; 333 int temp = patch[i];
405 334
406 for (int u = 1; u < Constants.TerrainPatchSize; u++) 335 if (temp == 0)
407 { 336 {
408 total += linein[lineSize + u]*CosineTable16[u*Constants.TerrainPatchSize + n]; 337 bool eob = true;
338
339 for (int j = i; j < lastZeroindx; j++)
340 {
341 if (patch[j] != 0)
342 {
343 eob = false;
344 break;
345 }
346 }
347
348 if (eob)
349 {
350 output.PackBits(ZERO_EOB, 2);
351 return;
352 }
353 output.PackBits(ZERO_CODE, 1);
409 } 354 }
355 else
356 {
357 if (temp < 0)
358 {
359 temp *= -1;
360
361 if (temp > maxwbitssize) temp = maxwbitssize;
362
363 output.PackBits(NEGATIVE_VALUE, 3);
364 output.PackBits(temp, wbits);
365 }
366 else
367 {
368 if (temp > maxwbitssize) temp = maxwbitssize;
410 369
411 lineout[lineSize + n] = total*oosob; 370 output.PackBits(POSITIVE_VALUE, 3);
371 output.PackBits(temp, wbits);
372 }
373 }
412 } 374 }
413 } 375 }
414 376
415/* 377 private static int[] CompressPatch(TerrainData terrData, int patchX, int patchY, TerrainPatch.Header header,
416 private static void DCTLine16(float[] linein, float[] lineout, int line) 378 int prequant, out int wbits)
417 { 379 {
418 float total = 0.0f; 380 float[] block = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
419 int lineSize = line * Constants.TerrainPatchSize; 381 int[] iout = new int[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
420 382
421 for (int n = 0; n < Constants.TerrainPatchSize; n++) 383 float oozrange = 1.0f / header.Range;
422 { 384 float invprequat = (1 << prequant);
423 total += linein[lineSize + n]; 385 float premult = oozrange * invprequat;
424 }
425 386
426 lineout[lineSize] = OO_SQRT2 * total; 387 float sub = 0.5f * header.Range + header.DCOffset;
427 388
428 int uptr = 0; 389 int wordsize = (prequant - 2) & 0x0f;
429 for (int u = 1; u < Constants.TerrainPatchSize; u++) 390 header.QuantWBits = wordsize;
430 { 391 header.QuantWBits |= wordsize << 4;
431 total = 0.0f;
432 uptr += Constants.TerrainPatchSize;
433 392
434 for (int n = 0; n < Constants.TerrainPatchSize; n++) 393 int k = 0;
394 int startX = patchX * Constants.TerrainPatchSize;
395 int startY = patchY * Constants.TerrainPatchSize;
396 for (int y = startY; y < startY + Constants.TerrainPatchSize; y++)
397 {
398 for (int x = startX; x < startX + Constants.TerrainPatchSize; x++)
435 { 399 {
436 total += linein[lineSize + n] * CosineTable16[uptr + n]; 400 block[k++] = (terrData[x, y] - sub) * premult;
437 } 401 }
438
439 lineout[lineSize + u] = total;
440 } 402 }
403
404 wbits = (prequant >> 1);
405
406 dct16x16(block, iout, ref wbits);
407
408 return iout;
441 } 409 }
442*/
443 410
444 private static void DCTLine16(float[] linein, float[] lineout, int line) 411 #region Initialization
445 {
446 // outputs transpose data (lines exchanged with coluns )
447 // so to save a bit of cpu when doing coluns
448 float total = 0.0f;
449 int lineSize = line*Constants.TerrainPatchSize;
450 412
451 for (int n = 0; n < Constants.TerrainPatchSize; n++) 413 private static void BuildDequantizeTable16()
414 {
415 for (int j = 0; j < Constants.TerrainPatchSize; j++)
452 { 416 {
453 total += linein[lineSize + n]; 417 for (int i = 0; i < Constants.TerrainPatchSize; i++)
418 {
419 DequantizeTable16[j * Constants.TerrainPatchSize + i] = 1.0f + 2.0f * (i + j);
420 }
454 } 421 }
422 }
455 423
456 lineout[line] = OO_SQRT2*total; 424 private static void BuildQuantizeTable16()
457 425 {
458 for (int u = Constants.TerrainPatchSize; 426 const float oosob = 2.0f / Constants.TerrainPatchSize;
459 u < Constants.TerrainPatchSize*Constants.TerrainPatchSize; 427 for (int j = 0; j < Constants.TerrainPatchSize; j++)
460 u += Constants.TerrainPatchSize)
461 { 428 {
462 total = 0.0f; 429 for (int i = 0; i < Constants.TerrainPatchSize; i++)
463 for (int ptrn = lineSize, ptru = u; ptrn < lineSize + Constants.TerrainPatchSize; ptrn++,ptru++)
464 { 430 {
465 total += linein[ptrn]*CosineTable16[ptru]; 431 QuantizeTable16[j * Constants.TerrainPatchSize + i] = oosob / (1.0f + 2.0f * (i + (float)j));
466 } 432 }
467
468 lineout[line + u] = total;
469 } 433 }
470 } 434 }
471 435
436 private static void BuildCopyMatrix16()
437 {
438 bool diag = false;
439 bool right = true;
440 int i = 0;
441 int j = 0;
442 int count = 0;
443
444 while (i < Constants.TerrainPatchSize && j < Constants.TerrainPatchSize)
445 {
446 CopyMatrix16[j * Constants.TerrainPatchSize + i] = count++;
472 447
473 /* 448 if (!diag)
474 private static void DCTColumn16(float[] linein, int[] lineout, int column)
475 { 449 {
476 float total = 0.0f; 450 if (right)
477 // const float oosob = 2.0f / Constants.TerrainPatchSize;
478
479 for (int n = 0; n < Constants.TerrainPatchSize; n++)
480 { 451 {
481 total += linein[Constants.TerrainPatchSize * n + column]; 452 if (i < Constants.TerrainPatchSize - 1) i++;
482 } 453 else j++;
483
484 // lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * oosob * QuantizeTable16[column]);
485 lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * QuantizeTable16[column]);
486 454
487 for (int uptr = Constants.TerrainPatchSize; uptr < Constants.TerrainPatchSize * Constants.TerrainPatchSize; uptr += Constants.TerrainPatchSize) 455 right = false;
456 diag = true;
457 }
458 else
488 { 459 {
489 total = 0.0f; 460 if (j < Constants.TerrainPatchSize - 1) j++;
490 461 else i++;
491 for (int n = 0; n < Constants.TerrainPatchSize; n++)
492 {
493 total += linein[Constants.TerrainPatchSize * n + column] * CosineTable16[uptr + n];
494 }
495 462
496 // lineout[CopyMatrix16[Constants.TerrainPatchSize * u + column]] = (int)(total * oosob * QuantizeTable16[Constants.TerrainPatchSize * u + column]); 463 right = true;
497 lineout[CopyMatrix16[uptr + column]] = (int)(total * QuantizeTable16[uptr + column]); 464 diag = true;
498 } 465 }
466 }
467 else
468 {
469 if (right)
470 {
471 i++;
472 j--;
473 if (i == Constants.TerrainPatchSize - 1 || j == 0) diag = false;
474 }
475 else
476 {
477 i--;
478 j++;
479 if (j == Constants.TerrainPatchSize - 1 || i == 0) diag = false;
480 }
499 } 481 }
482 }
483 }
500 484
501 private static void DCTColumn16(float[] linein, int[] lineout, int column) 485 #endregion Initialization
502 {
503 // input columns are in fact stored in lines now
504 486
505 float total = 0.0f;
506// const float oosob = 2.0f / Constants.TerrainPatchSize;
507 int inlinesptr = Constants.TerrainPatchSize*column;
508 487
509 for (int n = 0; n < Constants.TerrainPatchSize; n++)
510 {
511 total += linein[inlinesptr + n];
512 }
513 488
514 // lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * oosob * QuantizeTable16[column]);
515 lineout[CopyMatrix16[column]] = (int) (OO_SQRT2*total*QuantizeTable16[column]);
516 489
517 for (int uptr = Constants.TerrainPatchSize; 490 #region DCT
518 uptr < Constants.TerrainPatchSize*Constants.TerrainPatchSize;
519 uptr += Constants.TerrainPatchSize)
520 {
521 total = 0.0f;
522 491
523 for (int n = inlinesptr, ptru = uptr; n < inlinesptr + Constants.TerrainPatchSize; n++, ptru++) 492 /* DCT (Discrete Cosine Transform)
524 { 493 adaptation from
525 total += linein[n]*CosineTable16[ptru]; 494 General Purpose 2D,3D FFT (Fast Fourier Transform) Package
526 } 495 by Takuya OOURA (email: ooura@kurims.kyoto-u.ac.jp)
527 496
528// lineout[CopyMatrix16[Constants.TerrainPatchSize * u + column]] = (int)(total * oosob * QuantizeTable16[Constants.TerrainPatchSize * u + column]); 497 -------- 16x16 DCT (Discrete Cosine Transform) / Inverse of DCT --------
529 lineout[CopyMatrix16[uptr + column]] = (int) (total*QuantizeTable16[uptr + column]); 498 [definition]
530 } 499 <case1> Normalized 16x16 IDCT
531 } 500 C[k1 + k2] = (1/8) * sum_j1=0^15 sum_j2=0^15
501 tmp[j1 + j2] * s[j1] * s[j2] *
502 cos(pi*j1*(k1+1/2)/16) *
503 cos(pi*j2*(k2+1/2)/16), 0<=k1<16, 0<=k2<16
504 (s[0] = 1/sqrt(2), s[j] = 1, j > 0)
505 <case2> Normalized 16x16 DCT
506 C[k1 + k2] = (1/8) * s[k1] * s[k2] * sum_j1=0^15 sum_j2=0^15
507 tmp[j1 + j2] *
508 cos(pi*(j1+1/2)*k1/16) *
509 cos(pi*(j2+1/2)*k2/16), 0<=k1<16, 0<=k2<16
510 (s[0] = 1/sqrt(2), s[j] = 1, j > 0)
532 */ 511 */
533 512
534 private static int DCTColumn16Wbits(float[] linein, int[] lineout, int column, int wbits, int maxwbits) 513 /* Cn_kR = sqrt(2.0/n) * cos(pi/2*k/n) */
514 /* Cn_kI = sqrt(2.0/n) * sin(pi/2*k/n) */
515 /* Wn_kR = cos(pi/2*k/n) */
516 /* Wn_kI = sin(pi/2*k/n) */
517
518 const float C16_1R = 0.35185093438159561476f * 2.82842712474619f;
519 const float C16_1I = 0.03465429229977286565f * 2.82842712474619f;
520 const float C16_2R = 0.34675996133053686546f * 2.82842712474619f;
521 const float C16_2I = 0.06897484482073575308f * 2.82842712474619f;
522 const float C16_3R = 0.33832950029358816957f * 2.82842712474619f;
523 const float C16_3I = 0.10263113188058934529f * 2.82842712474619f;
524 const float C16_4R = 0.32664074121909413196f * 2.82842712474619f;
525 const float C16_4I = 0.13529902503654924610f * 2.82842712474619f;
526 const float C16_5R = 0.31180625324666780814f * 2.82842712474619f;
527 const float C16_5I = 0.16666391461943662432f * 2.82842712474619f;
528 const float C16_6R = 0.29396890060483967924f * 2.82842712474619f;
529 const float C16_6I = 0.19642373959677554532f * 2.82842712474619f;
530 const float C16_7R = 0.27330046675043937206f * 2.82842712474619f;
531 const float C16_7I = 0.22429189658565907106f * 2.82842712474619f;
532 const float C16_8R = 0.25f * 2.82842712474619f;
533 const float W16_4R = 0.92387953251128675613f;
534 const float W16_4I = 0.38268343236508977173f;
535 const float W16_8R = 0.70710678118654752440f;
536
537 static void dct16x16(float[] a, int[] iout, ref int wbits)
535 { 538 {
536 // input columns are in fact stored in lines now 539 float[] tmp = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
537 540
538 bool dowbits = wbits != maxwbits; 541 float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
539 int wbitsMaxValue = 1 << wbits; 542 float x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i;
543 float xr, xi;
544 float ftmp;
540 545
541 float total = 0.0f; 546 int fullSize = Constants.TerrainPatchSize * Constants.TerrainPatchSize;
542 // const float oosob = 2.0f / Constants.TerrainPatchSize; 547 int itmp;
543 int inlinesptr = Constants.TerrainPatchSize*column; 548 int j, k;
549 int indx;
544 550
545 for (int n = 0; n < Constants.TerrainPatchSize; n++) 551 const int maxwbits = 17; // per header encoding
552 int wbitsMaxValue = 1 << wbits;
553 bool dowbits = wbits < 17;
554
555 for (j = 0, k = 0; j < fullSize; j += Constants.TerrainPatchSize, k++)
546 { 556 {
547 total += linein[inlinesptr + n]; 557 x4r = a[0 + j] - a[15 + j];
558 xr = a[0 + j] + a[15 + j];
559 x4i = a[8 + j] - a[7 + j];
560 xi = a[8 + j] + a[7 + j];
561 x0r = xr + xi;
562 x0i = xr - xi;
563 x5r = a[2 + j] - a[13 + j];
564 xr = a[2 + j] + a[13 + j];
565 x5i = a[10 + j] - a[5 + j];
566 xi = a[10 + j] + a[5 + j];
567 x1r = xr + xi;
568 x1i = xr - xi;
569 x6r = a[4 + j] - a[11 + j];
570 xr = a[4 + j] + a[11 + j];
571 x6i = a[12 + j] - a[3 + j];
572 xi = a[12 + j] + a[3 + j];
573 x2r = xr + xi;
574 x2i = xr - xi;
575 x7r = a[6 + j] - a[9 + j];
576 xr = a[6 + j] + a[9 + j];
577 x7i = a[14 + j] - a[1 + j];
578 xi = a[14 + j] + a[1 + j];
579 x3r = xr + xi;
580 x3i = xr - xi;
581 xr = x0r + x2r;
582 xi = x1r + x3r;
583 tmp[k] = C16_8R * (xr + xi); //
584 tmp[8 * Constants.TerrainPatchSize + k] = C16_8R * (xr - xi); //
585 xr = x0r - x2r;
586 xi = x1r - x3r;
587 tmp[4 * Constants.TerrainPatchSize + k] = C16_4R * xr - C16_4I * xi; //
588 tmp[12 * Constants.TerrainPatchSize + k] = C16_4R * xi + C16_4I * xr; //
589 x0r = W16_8R * (x1i - x3i);
590 x2r = W16_8R * (x1i + x3i);
591 xr = x0i + x0r;
592 xi = x2r + x2i;
593 tmp[2 * Constants.TerrainPatchSize + k] = C16_2R * xr - C16_2I * xi; //
594 tmp[14 * Constants.TerrainPatchSize + k] = C16_2R * xi + C16_2I * xr; //
595 xr = x0i - x0r;
596 xi = x2r - x2i;
597 tmp[6 * Constants.TerrainPatchSize + k] = C16_6R * xr - C16_6I * xi; //
598 tmp[10 * Constants.TerrainPatchSize + k] = C16_6R * xi + C16_6I * xr; //
599 xr = W16_8R * (x6r - x6i);
600 xi = W16_8R * (x6i + x6r);
601 x6r = x4r - xr;
602 x6i = x4i - xi;
603 x4r += xr;
604 x4i += xi;
605 xr = W16_4I * x7r - W16_4R * x7i;
606 xi = W16_4I * x7i + W16_4R * x7r;
607 x7r = W16_4R * x5r - W16_4I * x5i;
608 x7i = W16_4R * x5i + W16_4I * x5r;
609 x5r = x7r + xr;
610 x5i = x7i + xi;
611 x7r -= xr;
612 x7i -= xi;
613 xr = x4r + x5r;
614 xi = x5i + x4i;
615 tmp[Constants.TerrainPatchSize + k] = C16_1R * xr - C16_1I * xi; //
616 tmp[15 * Constants.TerrainPatchSize + k] = C16_1R * xi + C16_1I * xr; //
617 xr = x4r - x5r;
618 xi = x5i - x4i;
619 tmp[7 * Constants.TerrainPatchSize + k] = C16_7R * xr - C16_7I * xi; //
620 tmp[9 * Constants.TerrainPatchSize + k] = C16_7R * xi + C16_7I * xr; //
621 xr = x6r - x7i;
622 xi = x7r + x6i;
623 tmp[5 * Constants.TerrainPatchSize + k] = C16_5R * xr - C16_5I * xi; //
624 tmp[11 * Constants.TerrainPatchSize + k] = C16_5R * xi + C16_5I * xr; //
625 xr = x6r + x7i;
626 xi = x7r - x6i;
627 tmp[3 * Constants.TerrainPatchSize + k] = C16_3R * xr - C16_3I * xi; //
628 tmp[13 * Constants.TerrainPatchSize + k] = C16_3R * xi + C16_3I * xr; //
548 } 629 }
549 630
550 // lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * oosob * QuantizeTable16[column]); 631 for (j = 0, k = 0; j < fullSize; j += Constants.TerrainPatchSize, k++)
551 int tmp = (int) (OO_SQRT2*total*QuantizeTable16[column]);
552 lineout[CopyMatrix16[column]] = tmp;
553
554 if (dowbits)
555 { 632 {
556 if (tmp < 0) tmp *= -1; 633 x4r = tmp[0 + j] - tmp[15 + j];
557 while (tmp > wbitsMaxValue) 634 xr = tmp[0 + j] + tmp[15 + j];
635 x4i = tmp[8 + j] - tmp[7 + j];
636 xi = tmp[8 + j] + tmp[7 + j];
637 x0r = xr + xi;
638 x0i = xr - xi;
639 x5r = tmp[2 + j] - tmp[13 + j];
640 xr = tmp[2 + j] + tmp[13 + j];
641 x5i = tmp[10 + j] - tmp[5 + j];
642 xi = tmp[10 + j] + tmp[5 + j];
643 x1r = xr + xi;
644 x1i = xr - xi;
645 x6r = tmp[4 + j] - tmp[11 + j];
646 xr = tmp[4 + j] + tmp[11 + j];
647 x6i = tmp[12 + j] - tmp[3 + j];
648 xi = tmp[12 + j] + tmp[3 + j];
649 x2r = xr + xi;
650 x2i = xr - xi;
651 x7r = tmp[6 + j] - tmp[9 + j];
652 xr = tmp[6 + j] + tmp[9 + j];
653 x7i = tmp[14 + j] - tmp[1 + j];
654 xi = tmp[14 + j] + tmp[1 + j];
655 x3r = xr + xi;
656 x3i = xr - xi;
657 xr = x0r + x2r;
658 xi = x1r + x3r;
659
660 //tmp[0 + k] = C16_8R * (xr + xi); //
661 ftmp = C16_8R * (xr + xi);
662 itmp = (int)(ftmp * QuantizeTable16[k]);
663 iout[CopyMatrix16[k]] = itmp;
664
665 if (dowbits)
558 { 666 {
559 wbits++; 667 if (itmp < 0) itmp *= -1;
560 wbitsMaxValue = 1 << wbits; 668 while (itmp > wbitsMaxValue)
561 if (wbits == maxwbits)
562 { 669 {
563 dowbits = false; 670 wbits++;
564 break; 671 wbitsMaxValue = 1 << wbits;
672 if (wbits == maxwbits)
673 {
674 dowbits = false;
675 break;
676 }
565 } 677 }
566 } 678 }
567 }
568 679
569 for (int uptr = Constants.TerrainPatchSize; 680 //tmp[8 * Constants.TerrainPatchSize + k] = C16_8R * (xr - xi); //
570 uptr < Constants.TerrainPatchSize*Constants.TerrainPatchSize; 681 ftmp = C16_8R * (xr - xi);
571 uptr += Constants.TerrainPatchSize) 682 indx = 8 * Constants.TerrainPatchSize + k;
572 { 683 itmp = (int)(ftmp * QuantizeTable16[indx]);
573 total = 0.0f; 684 iout[CopyMatrix16[indx]] = itmp;
574 685
575 for (int n = inlinesptr, ptru = uptr; n < inlinesptr + Constants.TerrainPatchSize; n++, ptru++) 686 if (dowbits)
576 { 687 {
577 total += linein[n]*CosineTable16[ptru]; 688 if (itmp < 0) itmp *= -1;
689 while (itmp > wbitsMaxValue)
690 {
691 wbits++;
692 wbitsMaxValue = 1 << wbits;
693 if (wbits == maxwbits)
694 {
695 dowbits = false;
696 break;
697 }
698 }
578 } 699 }
579 700
580 tmp = (int) (total*QuantizeTable16[uptr + column]); 701 xr = x0r - x2r;
581 lineout[CopyMatrix16[uptr + column]] = tmp; 702 xi = x1r - x3r;
703
704 //tmp[4 * Constants.TerrainPatchSize + k] = C16_4R * xr - C16_4I * xi; //
705 ftmp = C16_4R * xr - C16_4I * xi;
706 indx = 4 * Constants.TerrainPatchSize + k;
707 itmp = (int)(ftmp * QuantizeTable16[indx]);
708 iout[CopyMatrix16[indx]] = itmp;
582 709
583 if (dowbits) 710 if (dowbits)
584 { 711 {
585 if (tmp < 0) tmp *= -1; 712 if (itmp < 0) itmp *= -1;
586 while (tmp > wbitsMaxValue) 713 while (itmp > wbitsMaxValue)
587 { 714 {
588 wbits++; 715 wbits++;
589 wbitsMaxValue = 1 << wbits; 716 wbitsMaxValue = 1 << wbits;
@@ -594,355 +721,605 @@ namespace OpenSim.Region.ClientStack.LindenUDP
594 } 721 }
595 } 722 }
596 } 723 }
597 }
598 return wbits;
599 }
600 724
601 public static void DecodePatch(int[] patches, BitPack bitpack, TerrainPatch.Header header, int size) 725 //tmp[12 * Constants.TerrainPatchSize + k] = C16_4R * xi + C16_4I * xr; //
602 { 726 ftmp = C16_4R * xi + C16_4I * xr;
603 for (int n = 0; n < size*size; n++) 727 indx = 12 * Constants.TerrainPatchSize + k;
604 { 728 itmp = (int)(ftmp * QuantizeTable16[indx]);
605 // ? 729 iout[CopyMatrix16[indx]] = itmp;
606 int temp = bitpack.UnpackBits(1); 730
607 if (temp != 0) 731 if (dowbits)
608 { 732 {
609 // Value or EOB 733 if (itmp < 0) itmp *= -1;
610 temp = bitpack.UnpackBits(1); 734 while (itmp > wbitsMaxValue)
611 if (temp != 0)
612 { 735 {
613 // Value 736 wbits++;
614 temp = bitpack.UnpackBits(1); 737 wbitsMaxValue = 1 << wbits;
615 if (temp != 0) 738 if (wbits == maxwbits)
616 {
617 // Negative
618 temp = bitpack.UnpackBits((int) header.WordBits);
619 patches[n] = temp*-1;
620 }
621 else
622 { 739 {
623 // Positive 740 dowbits = false;
624 temp = bitpack.UnpackBits((int) header.WordBits); 741 break;
625 patches[n] = temp;
626 } 742 }
627 } 743 }
628 else 744 }
745
746 x0r = W16_8R * (x1i - x3i);
747 x2r = W16_8R * (x1i + x3i);
748 xr = x0i + x0r;
749 xi = x2r + x2i;
750
751 //tmp[2 * Constants.TerrainPatchSize + k] = C16_2R * xr - C16_2I * xi; //
752 ftmp = C16_2R * xr - C16_2I * xi;
753 indx = 2 * Constants.TerrainPatchSize + k;
754 itmp = (int)(ftmp * QuantizeTable16[indx]);
755 iout[CopyMatrix16[indx]] = itmp;
756
757 if (dowbits)
758 {
759 if (itmp < 0) itmp *= -1;
760 while (itmp > wbitsMaxValue)
629 { 761 {
630 // Set the rest to zero 762 wbits++;
631 // TODO: This might not be necessary 763 wbitsMaxValue = 1 << wbits;
632 for (int o = n; o < size*size; o++) 764 if (wbits == maxwbits)
633 { 765 {
634 patches[o] = 0; 766 dowbits = false;
767 break;
635 } 768 }
636 break;
637 } 769 }
638 } 770 }
639 else
640 {
641 patches[n] = 0;
642 }
643 }
644 }
645 771
646 private static void EncodePatch(BitPack output, int[] patch, int postquant, int wbits) 772 //tmp[14 * Constants.TerrainPatchSize + k] = C16_2R * xi + C16_2I * xr; //
647 { 773 ftmp = C16_2R * xi + C16_2I * xr;
648 int maxwbitssize = (1 << wbits) - 1; 774 indx = 14 * Constants.TerrainPatchSize + k;
775 itmp = (int)(ftmp * QuantizeTable16[indx]);
776 iout[CopyMatrix16[indx]] = itmp;
649 777
650 if (postquant > Constants.TerrainPatchSize*Constants.TerrainPatchSize || postquant < 0) 778 if (dowbits)
651 { 779 {
652 Logger.Log("Postquant is outside the range of allowed values in EncodePatch()", Helpers.LogLevel.Error); 780 if (itmp < 0) itmp *= -1;
653 return; 781 while (itmp > wbitsMaxValue)
654 } 782 {
783 wbits++;
784 wbitsMaxValue = 1 << wbits;
785 if (wbits == maxwbits)
786 {
787 dowbits = false;
788 break;
789 }
790 }
791 }
655 792
656 if (postquant != 0) patch[Constants.TerrainPatchSize*Constants.TerrainPatchSize - postquant] = 0; 793 xr = x0i - x0r;
794 xi = x2r - x2i;
657 795
658 for (int i = 0; i < Constants.TerrainPatchSize*Constants.TerrainPatchSize; i++) 796 //tmp[6 * Constants.TerrainPatchSize + k] = C16_6R * xr - C16_6I * xi; //
659 { 797 ftmp = C16_6R * xr - C16_6I * xi;
660 int temp = patch[i]; 798 indx = 6 * Constants.TerrainPatchSize + k;
799 itmp = (int)(ftmp * QuantizeTable16[indx]);
800 iout[CopyMatrix16[indx]] = itmp;
661 801
662 if (temp == 0) 802 if (dowbits)
663 { 803 {
664 bool eob = true; 804 if (itmp < 0) itmp *= -1;
665 805 while (itmp > wbitsMaxValue)
666 for (int j = i; j < Constants.TerrainPatchSize*Constants.TerrainPatchSize - postquant; j++)
667 { 806 {
668 if (patch[j] != 0) 807 wbits++;
808 wbitsMaxValue = 1 << wbits;
809 if (wbits == maxwbits)
669 { 810 {
670 eob = false; 811 dowbits = false;
671 break; 812 break;
672 } 813 }
673 } 814 }
815 }
674 816
675 if (eob) 817 //tmp[10 * Constants.TerrainPatchSize + k] = C16_6R * xi + C16_6I * xr; //
818 ftmp = C16_6R * xi + C16_6I * xr;
819 indx = 10 * Constants.TerrainPatchSize + k;
820 itmp = (int)(ftmp * QuantizeTable16[indx]);
821 iout[CopyMatrix16[indx]] = itmp;
822
823 if (dowbits)
824 {
825 if (itmp < 0) itmp *= -1;
826 while (itmp > wbitsMaxValue)
676 { 827 {
677 output.PackBits(ZERO_EOB, 2); 828 wbits++;
678 return; 829 wbitsMaxValue = 1 << wbits;
830 if (wbits == maxwbits)
831 {
832 dowbits = false;
833 break;
834 }
679 } 835 }
680 output.PackBits(ZERO_CODE, 1);
681 } 836 }
682 else
683 {
684 if (temp < 0)
685 {
686 temp *= -1;
687 837
688 if (temp > maxwbitssize) temp = maxwbitssize; 838 xr = W16_8R * (x6r - x6i);
839 xi = W16_8R * (x6i + x6r);
840 x6r = x4r - xr;
841 x6i = x4i - xi;
842 x4r += xr;
843 x4i += xi;
844 xr = W16_4I * x7r - W16_4R * x7i;
845 xi = W16_4I * x7i + W16_4R * x7r;
846 x7r = W16_4R * x5r - W16_4I * x5i;
847 x7i = W16_4R * x5i + W16_4I * x5r;
848 x5r = x7r + xr;
849 x5i = x7i + xi;
850 x7r -= xr;
851 x7i -= xi;
852 xr = x4r + x5r;
853 xi = x5i + x4i;
854
855 //tmp[1 * Constants.TerrainPatchSize + k] = C16_1R * xr - C16_1I * xi; //
856 ftmp = C16_1R * xr - C16_1I * xi;
857 indx = Constants.TerrainPatchSize + k;
858 itmp = (int)(ftmp * QuantizeTable16[indx]);
859 iout[CopyMatrix16[indx]] = itmp;
689 860
690 output.PackBits(NEGATIVE_VALUE, 3); 861 if (dowbits)
691 output.PackBits(temp, wbits); 862 {
692 } 863 if (itmp < 0) itmp *= -1;
693 else 864 while (itmp > wbitsMaxValue)
694 { 865 {
695 if (temp > maxwbitssize) temp = maxwbitssize; 866 wbits++;
696 867 wbitsMaxValue = 1 << wbits;
697 output.PackBits(POSITIVE_VALUE, 3); 868 if (wbits == maxwbits)
698 output.PackBits(temp, wbits); 869 {
870 dowbits = false;
871 break;
872 }
699 } 873 }
700 } 874 }
701 }
702 }
703 875
704 public static float[] DecompressPatch(int[] patches, TerrainPatch.Header header, TerrainPatch.GroupHeader group) 876 //tmp[15 * Constants.TerrainPatchSize + k] = C16_1R * xi + C16_1I * xr; //
705 { 877 ftmp = C16_1R * xi + C16_1I * xr;
706 float[] block = new float[group.PatchSize*group.PatchSize]; 878 indx = 15 * Constants.TerrainPatchSize + k;
707 float[] output = new float[group.PatchSize*group.PatchSize]; 879 itmp = (int)(ftmp * QuantizeTable16[indx]);
708 int prequant = (header.QuantWBits >> 4) + 2; 880 iout[CopyMatrix16[indx]] = itmp;
709 int quantize = 1 << prequant; 881
710 float ooq = 1.0f/quantize; 882 if (dowbits)
711 float mult = ooq*header.Range;
712 float addval = mult*(1 << (prequant - 1)) + header.DCOffset;
713
714 if (group.PatchSize == Constants.TerrainPatchSize)
715 {
716 for (int n = 0; n < Constants.TerrainPatchSize*Constants.TerrainPatchSize; n++)
717 { 883 {
718 block[n] = patches[CopyMatrix16[n]]*DequantizeTable16[n]; 884 if (itmp < 0) itmp *= -1;
885 while (itmp > wbitsMaxValue)
886 {
887 wbits++;
888 wbitsMaxValue = 1 << wbits;
889 if (wbits == maxwbits)
890 {
891 dowbits = false;
892 break;
893 }
894 }
719 } 895 }
720 896
721 float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 897 xr = x4r - x5r;
898 xi = x5i - x4i;
722 899
723 for (int o = 0; o < Constants.TerrainPatchSize; o++) 900 //tmp[7 * Constants.TerrainPatchSize + k] = C16_7R * xr - C16_7I * xi; //
724 IDCTColumn16(block, ftemp, o); 901 ftmp = C16_7R * xr - C16_7I * xi;
725 for (int o = 0; o < Constants.TerrainPatchSize; o++) 902 indx = 7 * Constants.TerrainPatchSize + k;
726 IDCTLine16(ftemp, block, o); 903 itmp = (int)(ftmp * QuantizeTable16[indx]);
727 } 904 iout[CopyMatrix16[indx]] = itmp;
728 else 905
729 { 906 if (dowbits)
730 for (int n = 0; n < Constants.TerrainPatchSize*2*Constants.TerrainPatchSize*2; n++)
731 { 907 {
732 block[n] = patches[CopyMatrix32[n]]*DequantizeTable32[n]; 908 if (itmp < 0) itmp *= -1;
909 while (itmp > wbitsMaxValue)
910 {
911 wbits++;
912 wbitsMaxValue = 1 << wbits;
913 if (wbits == maxwbits)
914 {
915 dowbits = false;
916 break;
917 }
918 }
733 } 919 }
734 920
735 Logger.Log("Implement IDCTPatchLarge", Helpers.LogLevel.Error); 921 //tmp[9 * Constants.TerrainPatchSize + k] = C16_7R * xi + C16_7I * xr; //
736 } 922 ftmp = C16_7R * xi + C16_7I * xr;
737 923 indx = 9 * Constants.TerrainPatchSize + k;
738 for (int j = 0; j < block.Length; j++) 924 itmp = (int)(ftmp * QuantizeTable16[indx]);
739 { 925 iout[CopyMatrix16[indx]] = itmp;
740 output[j] = block[j]*mult + addval;
741 }
742
743 return output;
744 }
745 926
746 private static int[] CompressPatch(float[] patchData, TerrainPatch.Header header, int prequant, out int wbits) 927 if (dowbits)
747 { 928 {
748 float[] block = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 929 if (itmp < 0) itmp *= -1;
749 int wordsize = (prequant - 2) & 0x0f; 930 while (itmp > wbitsMaxValue)
750 float oozrange = 1.0f/header.Range; 931 {
751 float range = (1 << prequant); 932 wbits++;
752 float premult = oozrange*range; 933 wbitsMaxValue = 1 << wbits;
753 float sub = (1 << (prequant - 1)) + header.DCOffset*premult; 934 if (wbits == maxwbits)
935 {
936 dowbits = false;
937 break;
938 }
939 }
940 }
754 941
755 header.QuantWBits = wordsize; 942 xr = x6r - x7i;
756 header.QuantWBits |= wordsize << 4; 943 xi = x7r + x6i;
757 944
758 int k = 0; 945 //tmp[5 * Constants.TerrainPatchSize + k] = C16_5R * xr - C16_5I * xi; //
759 for (int j = 0; j < Constants.TerrainPatchSize; j++) 946 ftmp = C16_5R * xr - C16_5I * xi;
760 { 947 indx = 5 * Constants.TerrainPatchSize + k;
761 for (int i = 0; i < Constants.TerrainPatchSize; i++) 948 itmp = (int)(ftmp * QuantizeTable16[indx]);
762 block[k++] = patchData[j*Constants.TerrainPatchSize + i]*premult - sub; 949 iout[CopyMatrix16[indx]] = itmp;
763 }
764 950
765 float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 951 if (dowbits)
766 int[] itemp = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 952 {
953 if (itmp < 0) itmp *= -1;
954 while (itmp > wbitsMaxValue)
955 {
956 wbits++;
957 wbitsMaxValue = 1 << wbits;
958 if (wbits == maxwbits)
959 {
960 dowbits = false;
961 break;
962 }
963 }
964 }
767 965
966 //tmp[11 * Constants.TerrainPatchSize + k] = C16_5R * xi + C16_5I * xr; //
967 ftmp = C16_5R * xi + C16_5I * xr;
968 indx = 11 * Constants.TerrainPatchSize + k;
969 itmp = (int)(ftmp * QuantizeTable16[indx]);
970 iout[CopyMatrix16[indx]] = itmp;
768 971
769 int maxWbits = prequant + 5; 972 if (dowbits)
770 wbits = (prequant >> 1); 973 {
974 if (itmp < 0) itmp *= -1;
975 while (itmp > wbitsMaxValue)
976 {
977 wbits++;
978 wbitsMaxValue = 1 << wbits;
979 if (wbits == maxwbits)
980 {
981 dowbits = false;
982 break;
983 }
984 }
985 }
771 986
772 for (int o = 0; o < Constants.TerrainPatchSize; o++) 987 xr = x6r + x7i;
773 DCTLine16(block, ftemp, o); 988 xi = x7r - x6i;
774 for (int o = 0; o < Constants.TerrainPatchSize; o++)
775 wbits = DCTColumn16Wbits(ftemp, itemp, o, wbits, maxWbits);
776 989
777 return itemp; 990 //tmp[3 * Constants.TerrainPatchSize + k] = C16_3R * xr - C16_3I * xi; //
778 } 991 ftmp = C16_3R * xr - C16_3I * xi;
992 indx = 3 * Constants.TerrainPatchSize + k;
993 itmp = (int)(ftmp * QuantizeTable16[indx]);
994 iout[CopyMatrix16[indx]] = itmp;
779 995
780 private static int[] CompressPatch(float[,] patchData, TerrainPatch.Header header, int prequant, out int wbits) 996 if (dowbits)
781 { 997 {
782 float[] block = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 998 if (itmp < 0) itmp *= -1;
783 float oozrange = 1.0f/header.Range; 999 while (itmp > wbitsMaxValue)
784 float range = (1 << prequant); 1000 {
785 float premult = oozrange*range; 1001 wbits++;
786 float sub = (1 << (prequant - 1)) + header.DCOffset*premult; 1002 wbitsMaxValue = 1 << wbits;
787 int wordsize = (prequant - 2) & 0x0f; 1003 if (wbits == maxwbits)
1004 {
1005 dowbits = false;
1006 break;
1007 }
1008 }
1009 }
788 1010
789 header.QuantWBits = wordsize; 1011 //tmp[13 * Constants.TerrainPatchSize + k] = C16_3R * xi + C16_3I * xr; //
790 header.QuantWBits |= wordsize << 4; 1012 ftmp = C16_3R * xi + C16_3I * xr;
1013 indx = 13 * Constants.TerrainPatchSize + k;
1014 itmp = (int)(ftmp * QuantizeTable16[indx]);
1015 iout[CopyMatrix16[indx]] = itmp;
791 1016
792 int k = 0; 1017 if (dowbits)
793 for (int j = 0; j < Constants.TerrainPatchSize; j++) 1018 {
794 { 1019 if (itmp < 0) itmp *= -1;
795 for (int i = 0; i < Constants.TerrainPatchSize; i++) 1020 while (itmp > wbitsMaxValue)
796 block[k++] = patchData[j, i]*premult - sub; 1021 {
1022 wbits++;
1023 wbitsMaxValue = 1 << wbits;
1024 if (wbits == maxwbits)
1025 {
1026 dowbits = false;
1027 break;
1028 }
1029 }
1030 }
797 } 1031 }
1032 }
798 1033
799 float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 1034 #endregion DCT
800 int[] itemp = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
801
802 int maxWbits = prequant + 5;
803 wbits = (prequant >> 1);
804 1035
805 for (int o = 0; o < Constants.TerrainPatchSize; o++) 1036 #region Decode
806 DCTLine16(block, ftemp, o); 1037 /*
807 for (int o = 0; o < Constants.TerrainPatchSize; o++) 1038 public static TerrainPatch.Header DecodePatchHeader(BitPack bitpack)
808 wbits = DCTColumn16Wbits(ftemp, itemp, o, wbits, maxWbits); 1039 {
1040 TerrainPatch.Header header = new TerrainPatch.Header { QuantWBits = bitpack.UnpackBits(8) };
809 1041
810 return itemp; 1042 // Quantized word bits
811 } 1043 if (header.QuantWBits == END_OF_PATCHES)
1044 return header;
812 1045
813 private static int[] CompressPatch(TerrainData terrData, int patchX, int patchY, TerrainPatch.Header header, 1046 // DC offset
814 int prequant, out int wbits) 1047 header.DCOffset = bitpack.UnpackFloat();
815 {
816 float[] block = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
817 int wordsize = prequant;
818 float oozrange = 1.0f/header.Range;
819 float range = (1 << prequant);
820 float premult = oozrange*range;
821 float sub = (1 << (prequant - 1)) + header.DCOffset*premult;
822 1048
823 header.QuantWBits = wordsize - 2; 1049 // Range
824 header.QuantWBits |= (prequant - 2) << 4; 1050 header.Range = bitpack.UnpackBits(16);
825 1051
826 int k = 0; 1052 // Patch IDs (10 bits)
1053 header.PatchIDs = bitpack.UnpackBits(10);
827 1054
828 int yPatchLimit = patchY >= (terrData.SizeY / Constants.TerrainPatchSize) ? 1055 // Word bits
829 (terrData.SizeY - Constants.TerrainPatchSize) / Constants.TerrainPatchSize : patchY; 1056 header.WordBits = (uint)((header.QuantWBits & 0x0f) + 2);
830 yPatchLimit = (yPatchLimit + 1) * Constants.TerrainPatchSize;
831 1057
832 int xPatchLimit = patchX >= (terrData.SizeX / Constants.TerrainPatchSize) ? 1058 return header;
833 (terrData.SizeX - Constants.TerrainPatchSize) / Constants.TerrainPatchSize : patchX; 1059 }
834 xPatchLimit = (xPatchLimit + 1) * Constants.TerrainPatchSize; 1060 */
835 1061
836 for (int yy = patchY * Constants.TerrainPatchSize; yy < yPatchLimit; yy++) 1062 /*
837 { 1063 public static void DecodePatch(int[] patches, BitPack bitpack, TerrainPatch.Header header, int size)
838 for (int xx = patchX * Constants.TerrainPatchSize; xx < xPatchLimit; xx++)
839 { 1064 {
840 block[k++] = terrData[xx, yy] * premult - sub; 1065 for (int n = 0; n < size * size; n++)
1066 {
1067 // ?
1068 int temp = bitpack.UnpackBits(1);
1069 if (temp != 0)
1070 {
1071 // Value or EOB
1072 temp = bitpack.UnpackBits(1);
1073 if (temp != 0)
1074 {
1075 // Value
1076 temp = bitpack.UnpackBits(1);
1077 if (temp != 0)
1078 {
1079 // Negative
1080 temp = bitpack.UnpackBits((int)header.WordBits);
1081 patches[n] = temp * -1;
1082 }
1083 else
1084 {
1085 // Positive
1086 temp = bitpack.UnpackBits((int)header.WordBits);
1087 patches[n] = temp;
1088 }
1089 }
1090 else
1091 {
1092 // Set the rest to zero
1093 // TODO: This might not be necessary
1094 for (int o = n; o < size * size; o++)
1095 {
1096 patches[o] = 0;
1097 }
1098 break;
1099 }
1100 }
1101 else
1102 {
1103 patches[n] = 0;
1104 }
1105 }
841 } 1106 }
842 } 1107 */
843 1108 #region IDCT
844 float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 1109 /* not in use
845 int[] itemp = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 1110 private static void IDCTColumn16(float[] linein, float[] lineout, int column)
846
847 int maxWbits = prequant + 5;
848 wbits = (prequant >> 1);
849
850 for (int o = 0; o < Constants.TerrainPatchSize; o++)
851 DCTLine16(block, ftemp, o);
852 for (int o = 0; o < Constants.TerrainPatchSize; o++)
853 wbits = DCTColumn16Wbits(ftemp, itemp, o, wbits, maxWbits);
854
855 return itemp;
856 }
857
858 #region Initialization
859
860 private static void BuildDequantizeTable16()
861 { 1111 {
862 for (int j = 0; j < Constants.TerrainPatchSize; j++) 1112 for (int n = 0; n < Constants.TerrainPatchSize; n++)
863 { 1113 {
864 for (int i = 0; i < Constants.TerrainPatchSize; i++) 1114 float total = OO_SQRT2 * linein[column];
1115
1116 for (int u = 1; u < Constants.TerrainPatchSize; u++)
865 { 1117 {
866 DequantizeTable16[j*Constants.TerrainPatchSize + i] = 1.0f + 2.0f*(i + j); 1118 int usize = u * Constants.TerrainPatchSize;
1119 total += linein[usize + column] * CosineTable16[usize + n];
867 } 1120 }
1121
1122 lineout[Constants.TerrainPatchSize * n + column] = total;
868 } 1123 }
869 } 1124 }
870 1125
871 private static void BuildQuantizeTable16() 1126 private static void IDCTLine16(float[] linein, float[] lineout, int line)
872 { 1127 {
873 const float oosob = 2.0f/Constants.TerrainPatchSize; 1128 const float oosob = 2.0f / Constants.TerrainPatchSize;
874 for (int j = 0; j < Constants.TerrainPatchSize; j++) 1129 int lineSize = line * Constants.TerrainPatchSize;
1130
1131 for (int n = 0; n < Constants.TerrainPatchSize; n++)
875 { 1132 {
876 for (int i = 0; i < Constants.TerrainPatchSize; i++) 1133 float total = OO_SQRT2 * linein[lineSize];
1134
1135 for (int u = 1; u < Constants.TerrainPatchSize; u++)
877 { 1136 {
878// QuantizeTable16[j * Constants.TerrainPatchSize + i] = 1.0f / (1.0f + 2.0f * ((float)i + (float)j)); 1137 total += linein[lineSize + u] * CosineTable16[u * Constants.TerrainPatchSize + n];
879 QuantizeTable16[j*Constants.TerrainPatchSize + i] = oosob/(1.0f + 2.0f*(i + (float) j));
880 } 1138 }
1139
1140 lineout[lineSize + n] = total * oosob;
881 } 1141 }
882 } 1142 }
883 1143
1144/*
884 private static void SetupCosines16() 1145 private static void SetupCosines16()
885 { 1146 {
886 const float hposz = (float) Math.PI*0.5f/Constants.TerrainPatchSize; 1147 const float hposz = (float)Math.PI * 0.5f / Constants.TerrainPatchSize;
887 1148
888 for (int u = 0; u < Constants.TerrainPatchSize; u++) 1149 for (int u = 0; u < Constants.TerrainPatchSize; u++)
889 { 1150 {
890 for (int n = 0; n < Constants.TerrainPatchSize; n++) 1151 for (int n = 0; n < Constants.TerrainPatchSize; n++)
891 { 1152 {
892 CosineTable16[u*Constants.TerrainPatchSize + n] = (float) Math.Cos((2.0f*n + 1.0f)*u*hposz); 1153 CosineTable16[u * Constants.TerrainPatchSize + n] = (float)Math.Cos((2.0f * n + 1.0f) * u * hposz);
893 } 1154 }
894 } 1155 }
895 } 1156 }
1157*/
1158 //not in use, and still not fixed
1159 /*
1160 static void idct16x16(float[] a)
1161 {
1162 int j;
1163 float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
1164 float x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i;
1165 float xr, xi;
896 1166
897 private static void BuildCopyMatrix16() 1167 int fullSize = Constants.TerrainPatchSize * Constants.TerrainPatchSize;
898 {
899 bool diag = false;
900 bool right = true;
901 int i = 0;
902 int j = 0;
903 int count = 0;
904
905 while (i < Constants.TerrainPatchSize && j < Constants.TerrainPatchSize)
906 {
907 CopyMatrix16[j*Constants.TerrainPatchSize + i] = count++;
908
909 if (!diag)
910 {
911 if (right)
912 {
913 if (i < Constants.TerrainPatchSize - 1) i++;
914 else j++;
915
916 right = false;
917 diag = true;
918 }
919 else
920 {
921 if (j < Constants.TerrainPatchSize - 1) j++;
922 else i++;
923 1168
924 right = true; 1169 for (j = 0; j < fullSize; j += Constants.TerrainPatchSize)
925 diag = true; 1170 {
926 } 1171 x5r = C16_1R * tmp[1 + j] + C16_1I * tmp[15 + j];
927 } 1172 x5i = C16_1R * tmp[15 + j] - C16_1I * tmp[1 + j];
928 else 1173 xr = C16_7R * tmp[7 + j] + C16_7I * tmp[9 + j];
929 { 1174 xi = C16_7R * tmp[9 + j] - C16_7I * tmp[7 + j];
930 if (right) 1175 x4r = x5r + xr;
931 { 1176 x4i = x5i - xi;
932 i++; 1177 x5r -= xr;
933 j--; 1178 x5i += xi;
934 if (i == Constants.TerrainPatchSize - 1 || j == 0) diag = false; 1179 x7r = C16_5R * tmp[5 + j] + C16_5I * tmp[11 + j];
935 } 1180 x7i = C16_5R * tmp[11 + j] - C16_5I * tmp[5 + j];
936 else 1181 xr = C16_3R * tmp[3 + j] + C16_3I * tmp[13 + j];
937 { 1182 xi = C16_3R * tmp[13 + j] - C16_3I * tmp[3 + j];
938 i--; 1183 x6r = x7r + xr;
939 j++; 1184 x6i = x7i - xi;
940 if (j == Constants.TerrainPatchSize - 1 || i == 0) diag = false; 1185 x7r -= xr;
941 } 1186 x7i += xi;
942 } 1187 xr = x4r - x6r;
943 } 1188 xi = x4i - x6i;
944 } 1189 x4r += x6r;
945 1190 x4i += x6i;
946 #endregion Initialization 1191 x6r = W16_8R * (xi + xr);
1192 x6i = W16_8R * (xi - xr);
1193 xr = x5r + x7i;
1194 xi = x5i - x7r;
1195 x5r -= x7i;
1196 x5i += x7r;
1197 x7r = W16_4I * x5r + W16_4R * x5i;
1198 x7i = W16_4I * x5i - W16_4R * x5r;
1199 x5r = W16_4R * xr + W16_4I * xi;
1200 x5i = W16_4R * xi - W16_4I * xr;
1201 xr = C16_4R * tmp[4 + j] + C16_4I * tmp[12 + j];
1202 xi = C16_4R * tmp[12 + j] - C16_4I * tmp[4 + j];
1203 x2r = C16_8R * (tmp[0 + j] + tmp[8 + j]);
1204 x3r = C16_8R * (tmp[0 + j] - tmp[8 + j]);
1205 x0r = x2r + xr;
1206 x1r = x3r + xi;
1207 x2r -= xr;
1208 x3r -= xi;
1209 x0i = C16_2R * tmp[2 + j] + C16_2I * tmp[14 + j];
1210 x2i = C16_2R * tmp[14 + j] - C16_2I * tmp[2 + j];
1211 x1i = C16_6R * tmp[6 + j] + C16_6I * tmp[10 + j];
1212 x3i = C16_6R * tmp[10 + j] - C16_6I * tmp[6 + j];
1213 xr = x0i - x1i;
1214 xi = x2i + x3i;
1215 x0i += x1i;
1216 x2i -= x3i;
1217 x1i = W16_8R * (xi + xr);
1218 x3i = W16_8R * (xi - xr);
1219 xr = x0r + x0i;
1220 xi = x0r - x0i;
1221 tmp[0 + j] = xr + x4r;
1222 tmp[15 + j] = xr - x4r;
1223 tmp[8 + j] = xi + x4i;
1224 tmp[7 + j] = xi - x4i;
1225 xr = x1r + x1i;
1226 xi = x1r - x1i;
1227 tmp[2 + j] = xr + x5r;
1228 tmp[13 + j] = xr - x5r;
1229 tmp[10 + j] = xi + x5i;
1230 tmp[5 + j] = xi - x5i;
1231 xr = x2r + x2i;
1232 xi = x2r - x2i;
1233 tmp[4 + j] = xr + x6r;
1234 tmp[11 + j] = xr - x6r;
1235 tmp[12 + j] = xi + x6i;
1236 tmp[3 + j] = xi - x6i;
1237 xr = x3r + x3i;
1238 xi = x3r - x3i;
1239 tmp[6 + j] = xr + x7r;
1240 tmp[9 + j] = xr - x7r;
1241 tmp[14 + j] = xi + x7i;
1242 tmp[1 + j] = xi - x7i;
1243 }
1244 for (j = 0; j < fullSize; j += Constants.TerrainPatchSize)
1245 {
1246 x5r = C16_1R * tmp[j + 1] + C16_1I * tmp[j + 15];
1247 x5i = C16_1R * tmp[j + 15] - C16_1I * tmp[j + 1];
1248 xr = C16_7R * tmp[j + 7] + C16_7I * tmp[j + 9];
1249 xi = C16_7R * tmp[j + 9] - C16_7I * tmp[j + 7];
1250 x4r = x5r + xr;
1251 x4i = x5i - xi;
1252 x5r -= xr;
1253 x5i += xi;
1254 x7r = C16_5R * tmp[j + 5] + C16_5I * tmp[j + 11];
1255 x7i = C16_5R * tmp[j + 11] - C16_5I * tmp[j + 5];
1256 xr = C16_3R * tmp[j + 3] + C16_3I * tmp[j + 13];
1257 xi = C16_3R * tmp[j + 13] - C16_3I * tmp[j + 3];
1258 x6r = x7r + xr;
1259 x6i = x7i - xi;
1260 x7r -= xr;
1261 x7i += xi;
1262 xr = x4r - x6r;
1263 xi = x4i - x6i;
1264 x4r += x6r;
1265 x4i += x6i;
1266 x6r = W16_8R * (xi + xr);
1267 x6i = W16_8R * (xi - xr);
1268 xr = x5r + x7i;
1269 xi = x5i - x7r;
1270 x5r -= x7i;
1271 x5i += x7r;
1272 x7r = W16_4I * x5r + W16_4R * x5i;
1273 x7i = W16_4I * x5i - W16_4R * x5r;
1274 x5r = W16_4R * xr + W16_4I * xi;
1275 x5i = W16_4R * xi - W16_4I * xr;
1276 xr = C16_4R * tmp[j + 4] + C16_4I * tmp[j + 12];
1277 xi = C16_4R * tmp[j + 12] - C16_4I * tmp[j + 4];
1278 x2r = C16_8R * (tmp[j + 0] + tmp[j + 8]);
1279 x3r = C16_8R * (tmp[j + 0] - tmp[j + 8]);
1280 x0r = x2r + xr;
1281 x1r = x3r + xi;
1282 x2r -= xr;
1283 x3r -= xi;
1284 x0i = C16_2R * tmp[j + 2] + C16_2I * tmp[j + 14];
1285 x2i = C16_2R * tmp[j + 14] - C16_2I * tmp[j + 2];
1286 x1i = C16_6R * tmp[j + 6] + C16_6I * tmp[j + 10];
1287 x3i = C16_6R * tmp[j + 10] - C16_6I * tmp[j + 6];
1288 xr = x0i - x1i;
1289 xi = x2i + x3i;
1290 x0i += x1i;
1291 x2i -= x3i;
1292 x1i = W16_8R * (xi + xr);
1293 x3i = W16_8R * (xi - xr);
1294 xr = x0r + x0i;
1295 xi = x0r - x0i;
1296 tmp[j + 0] = xr + x4r;
1297 tmp[j + 15] = xr - x4r;
1298 tmp[j + 8] = xi + x4i;
1299 tmp[j + 7] = xi - x4i;
1300 xr = x1r + x1i;
1301 xi = x1r - x1i;
1302 tmp[j + 2] = xr + x5r;
1303 tmp[j + 13] = xr - x5r;
1304 tmp[j + 10] = xi + x5i;
1305 tmp[j + 5] = xi - x5i;
1306 xr = x2r + x2i;
1307 xi = x2r - x2i;
1308 tmp[j + 4] = xr + x6r;
1309 tmp[j + 11] = xr - x6r;
1310 tmp[j + 12] = xi + x6i;
1311 tmp[j + 3] = xi - x6i;
1312 xr = x3r + x3i;
1313 xi = x3r - x3i;
1314 tmp[j + 6] = xr + x7r;
1315 tmp[j + 9] = xr - x7r;
1316 tmp[j + 14] = xi + x7i;
1317 tmp[j + 1] = xi - x7i;
1318 }
1319 }
1320 */
1321 #endregion IDCT
1322 #endregion Decode
947 } 1323 }
1324
948} 1325}