34 using System.Collections.Generic;
35 using System.Reflection;
36 using System.Diagnostics;
40 using OpenSim.Framework;
41 using OpenSim.Region.Framework;
42 using OpenSim.Region.Framework.Scenes;
45 using OpenMetaverse.Packets;
47 namespace OpenSim.
Region.ClientStack.LindenUDP
49 public static class OpenSimTerrainCompressor
53 #pragma warning disable 414
54 private static string LogHeader =
"[TERRAIN COMPRESSOR]";
55 #pragma warning restore 414
57 public const int END_OF_PATCHES = 97;
59 private const float OO_SQRT2 = 0.7071067811865475244008443621049f;
60 private const int STRIDE = 264;
62 private const int ZERO_CODE = 0x0;
63 private const int ZERO_EOB = 0x2;
64 private const int POSITIVE_VALUE = 0x6;
65 private const int NEGATIVE_VALUE = 0x7;
69 private static readonly
int[] CopyMatrix16 =
new int[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
71 private static readonly
float[] QuantizeTable16 =
72 new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
73 private static readonly
float[] DequantizeTable16 =
74 new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
76 static OpenSimTerrainCompressor()
79 BuildDequantizeTable16();
82 BuildQuantizeTable16();
86 public static LayerDataPacket CreateLayerDataPacketStandardSize(TerrainPatch[] patches, byte type)
88 LayerDataPacket layer =
new LayerDataPacket { LayerID = {
Type = type } };
90 TerrainPatch.GroupHeader header =
new TerrainPatch.GroupHeader
91 { Stride = STRIDE, PatchSize = Constants.TerrainPatchSize };
94 byte[] data =
new byte[patches.Length * Constants.TerrainPatchSize * Constants.TerrainPatchSize * 2];
95 BitPack bitpack =
new BitPack(data, 0);
96 bitpack.PackBits(header.Stride, 16);
97 bitpack.PackBits(header.PatchSize, 8);
98 bitpack.PackBits(type, 8);
100 foreach (TerrainPatch t
in patches)
101 CreatePatchtStandardSize(bitpack, t.Data, t.X, t.Y);
103 bitpack.PackBits(END_OF_PATCHES, 8);
105 layer.LayerData.Data =
new byte[bitpack.BytePos + 1];
106 Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1);
111 public static void CreatePatchtStandardSize(BitPack output,
float[] patchData,
int x,
int y)
113 TerrainPatch.Header header = PrescanPatch(patchData);
114 header.QuantWBits = 136;
116 header.PatchIDs = (y & 0x1F);
117 header.PatchIDs += (x << 5);
120 int[] patch = CompressPatch(patchData, header, 10, out wbits);
121 EncodePatchHeader(output, header, patch,
false, ref wbits);
122 EncodePatch(output, patch, 0, wbits);
125 private static TerrainPatch.Header PrescanPatch(
float[] patch)
127 TerrainPatch.Header header =
new TerrainPatch.Header();
128 float zmax = -99999999.0f;
129 float zmin = 99999999.0f;
131 for (
int i = 0; i < Constants.TerrainPatchSize * Constants.TerrainPatchSize; i++)
133 float val = patch[i];
134 if (val > zmax) zmax = val;
135 if (val < zmin) zmin = val;
138 header.DCOffset = zmin;
139 header.Range = (int)((zmax - zmin) + 1.0f);
144 private static int[] CompressPatch(
float[] patchData, TerrainPatch.Header header,
int prequant, out
int wbits)
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;
152 float sub = 0.5f * header.Range + header.DCOffset;
154 int wordsize = (prequant - 2) & 0x0f;
155 header.QuantWBits = wordsize;
156 header.QuantWBits |= wordsize << 4;
159 for (
int j = 0; j < Constants.TerrainPatchSize; j++)
161 for (
int i = 0; i < Constants.TerrainPatchSize; i++)
165 float[] ftemp =
new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
166 int[] iout =
new int[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
168 wbits = (prequant >> 1);
170 dct16x16(block, iout, ref wbits);
176 public static List<LayerDataPacket> CreateLayerDataPackets(
TerrainData terrData,
int[] x,
int[] y, byte landPacketType)
178 List<LayerDataPacket> ret =
new List<LayerDataPacket>();
181 LayerDataPacket layer =
new LayerDataPacket();
183 layer.LayerID.Type = landPacketType;
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);
191 for (
int i = 0; i < x.Length; i++)
193 CreatePatchFromTerrainData(bitpack, terrData, x[i], y[i]);
194 if (bitpack.BytePos > 980 && i != x.Length - 1)
197 bitpack.PackBits(END_OF_PATCHES, 8);
199 layer.LayerData.Data =
new byte[bitpack.BytePos + 1];
200 Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1);
204 layer =
new LayerDataPacket();
205 layer.LayerID.Type = landPacketType;
207 bitpack =
new BitPack(data, 0);
208 bitpack.PackBits(STRIDE, 16);
209 bitpack.PackBits(Constants.TerrainPatchSize, 8);
210 bitpack.PackBits(landPacketType, 8);
214 bitpack.PackBits(END_OF_PATCHES, 8);
216 layer.LayerData.Data =
new byte[bitpack.BytePos + 1];
217 Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1);
223 public static void CreatePatchFromTerrainData(BitPack output,
TerrainData terrData,
int patchX,
int patchY)
226 TerrainPatch.Header header = PrescanPatch(terrData, patchX, patchY, out frange);
227 header.QuantWBits = 130;
229 bool largeRegion =
false;
233 header.PatchIDs = (patchY & 0xFFFF);
234 header.PatchIDs += (patchX << 16);
239 header.PatchIDs = (patchY & 0x1F);
240 header.PatchIDs += (patchX << 5);
243 if (Math.Round((
double)frange, 2) == 1.0)
247 header.DCOffset -= 0.5f;
249 header.QuantWBits = 0x00;
250 output.PackBits(header.QuantWBits, 8);
251 output.PackFloat(header.DCOffset);
252 output.PackBits(1, 16);
254 output.PackBits(header.PatchIDs, 32);
256 output.PackBits(header.PatchIDs, 10);
259 output.PackBits(ZERO_EOB, 2);
264 int[] patch = CompressPatch(terrData, patchX, patchY, header, 10, out wbits);
265 EncodePatchHeader(output, header, patch, largeRegion, ref wbits);
266 EncodePatch(output, patch, 0, wbits);
270 private static TerrainPatch.Header PrescanPatch(
TerrainData terrData,
int patchX,
int patchY, out
float frange)
272 TerrainPatch.Header header =
new TerrainPatch.Header();
273 float zmax = float.MinValue;
274 float zmin = float.MaxValue;
276 int startx = patchX * Constants.TerrainPatchSize;
277 int starty = patchY * Constants.TerrainPatchSize;
279 for (
int j = starty; j < starty + Constants.TerrainPatchSize; j++)
281 for (
int i = startx; i < startx + Constants.TerrainPatchSize; i++)
283 float val = terrData[i, j];
284 if (val > zmax) zmax = val;
285 if (val < zmin) zmin = val;
289 header.DCOffset = zmin;
290 frange = ((zmax - zmin) + 1.0f);
291 header.Range = (int)frange;
296 private static void EncodePatchHeader(BitPack output, TerrainPatch.Header header,
int[] patch,
bool largeRegion, ref
int wbits)
303 header.QuantWBits &= 0xf0;
304 header.QuantWBits |= (wbits - 2);
306 output.PackBits(header.QuantWBits, 8);
307 output.PackFloat(header.DCOffset);
308 output.PackBits(header.Range, 16);
310 output.PackBits(header.PatchIDs, 32);
312 output.PackBits(header.PatchIDs, 10);
315 private static void EncodePatch(BitPack output,
int[] patch,
int postquant,
int wbits)
317 int maxwbitssize = (1 << wbits) - 1;
318 int fullSize = Constants.TerrainPatchSize * Constants.TerrainPatchSize;
320 if (postquant > fullSize || postquant < 0)
322 Logger.Log(
"Postquant is outside the range of allowed values in EncodePatch()", Helpers.LogLevel.Error);
327 patch[fullSize - postquant] = 0;
329 int lastZeroindx = fullSize - postquant;
331 for (
int i = 0; i < fullSize; i++)
339 for (
int j = i; j < lastZeroindx; j++)
350 output.PackBits(ZERO_EOB, 2);
353 output.PackBits(ZERO_CODE, 1);
361 if (temp > maxwbitssize) temp = maxwbitssize;
363 output.PackBits(NEGATIVE_VALUE, 3);
364 output.PackBits(temp, wbits);
368 if (temp > maxwbitssize) temp = maxwbitssize;
370 output.PackBits(POSITIVE_VALUE, 3);
371 output.PackBits(temp, wbits);
377 private static int[] CompressPatch(
TerrainData terrData,
int patchX,
int patchY, TerrainPatch.Header header,
378 int prequant, out
int wbits)
380 float[] block =
new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
381 int[] iout =
new int[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
383 float oozrange = 1.0f / header.Range;
384 float invprequat = (1 << prequant);
385 float premult = oozrange * invprequat;
387 float sub = 0.5f * header.Range + header.DCOffset;
389 int wordsize = (prequant - 2) & 0x0f;
390 header.QuantWBits = wordsize;
391 header.QuantWBits |= wordsize << 4;
394 int startX = patchX * Constants.TerrainPatchSize;
395 int startY = patchY * Constants.TerrainPatchSize;
396 for (
int y = startY; y < startY + Constants.TerrainPatchSize; y++)
398 for (
int x = startX; x < startX + Constants.TerrainPatchSize; x++)
400 block[k++] = (terrData[x, y] - sub) * premult;
404 wbits = (prequant >> 1);
406 dct16x16(block, iout, ref wbits);
411 #region Initialization
413 private static void BuildDequantizeTable16()
415 for (
int j = 0; j < Constants.TerrainPatchSize; j++)
417 for (
int i = 0; i < Constants.TerrainPatchSize; i++)
419 DequantizeTable16[j * Constants.TerrainPatchSize + i] = 1.0f + 2.0f * (i + j);
424 private static void BuildQuantizeTable16()
426 const float oosob = 2.0f / Constants.TerrainPatchSize;
427 for (
int j = 0; j < Constants.TerrainPatchSize; j++)
429 for (
int i = 0; i < Constants.TerrainPatchSize; i++)
431 QuantizeTable16[j * Constants.TerrainPatchSize + i] = oosob / (1.0f + 2.0f * (i + (float)j));
436 private static void BuildCopyMatrix16()
446 CopyMatrix16[j * Constants.TerrainPatchSize + i] = count++;
485 #endregion Initialization
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;
537 static void dct16x16(
float[] a,
int[] iout, ref
int wbits)
539 float[] tmp =
new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
541 float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
542 float x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i;
546 int fullSize = Constants.TerrainPatchSize * Constants.TerrainPatchSize;
551 const int maxwbits = 17;
552 int wbitsMaxValue = 1 << wbits;
553 bool dowbits = wbits < 17;
555 for (j = 0, k = 0; j < fullSize; j += Constants.TerrainPatchSize, k++)
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];
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];
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];
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];
583 tmp[k] = C16_8R * (xr + xi);
584 tmp[8 * Constants.TerrainPatchSize + k] = C16_8R * (xr - xi);
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);
593 tmp[2 * Constants.TerrainPatchSize + k] = C16_2R * xr - C16_2I * xi;
594 tmp[14 * Constants.TerrainPatchSize + k] = C16_2R * xi + C16_2I * xr;
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);
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;
615 tmp[Constants.TerrainPatchSize + k] = C16_1R * xr - C16_1I * xi;
616 tmp[15 * Constants.TerrainPatchSize + k] = C16_1R * xi + C16_1I * xr;
619 tmp[7 * Constants.TerrainPatchSize + k] = C16_7R * xr - C16_7I * xi;
620 tmp[9 * Constants.TerrainPatchSize + k] = C16_7R * xi + C16_7I * xr;
623 tmp[5 * Constants.TerrainPatchSize + k] = C16_5R * xr - C16_5I * xi;
624 tmp[11 * Constants.TerrainPatchSize + k] = C16_5R * xi + C16_5I * xr;
627 tmp[3 * Constants.TerrainPatchSize + k] = C16_3R * xr - C16_3I * xi;
628 tmp[13 * Constants.TerrainPatchSize + k] = C16_3R * xi + C16_3I * xr;
631 for (j = 0, k = 0; j < fullSize; j += Constants.TerrainPatchSize, k++)
633 x4r = tmp[0 + j] - tmp[15 + j];
634 xr = tmp[0 + j] + tmp[15 + j];
635 x4i = tmp[8 + j] - tmp[7 + j];
636 xi = tmp[8 + j] + tmp[7 + j];
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];
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];
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];
661 ftmp = C16_8R * (xr + xi);
662 itmp = (int)(ftmp * QuantizeTable16[k]);
663 iout[CopyMatrix16[k]] = itmp;
667 if (itmp < 0) itmp *= -1;
668 while (itmp > wbitsMaxValue)
671 wbitsMaxValue = 1 << wbits;
672 if (wbits == maxwbits)
681 ftmp = C16_8R * (xr - xi);
682 indx = 8 * Constants.TerrainPatchSize + k;
683 itmp = (int)(ftmp * QuantizeTable16[indx]);
684 iout[CopyMatrix16[indx]] = itmp;
688 if (itmp < 0) itmp *= -1;
689 while (itmp > wbitsMaxValue)
692 wbitsMaxValue = 1 << wbits;
693 if (wbits == maxwbits)
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;
712 if (itmp < 0) itmp *= -1;
713 while (itmp > wbitsMaxValue)
716 wbitsMaxValue = 1 << wbits;
717 if (wbits == maxwbits)
726 ftmp = C16_4R * xi + C16_4I * xr;
727 indx = 12 * Constants.TerrainPatchSize + k;
728 itmp = (int)(ftmp * QuantizeTable16[indx]);
729 iout[CopyMatrix16[indx]] = itmp;
733 if (itmp < 0) itmp *= -1;
734 while (itmp > wbitsMaxValue)
737 wbitsMaxValue = 1 << wbits;
738 if (wbits == maxwbits)
746 x0r = W16_8R * (x1i - x3i);
747 x2r = W16_8R * (x1i + x3i);
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;
759 if (itmp < 0) itmp *= -1;
760 while (itmp > wbitsMaxValue)
763 wbitsMaxValue = 1 << wbits;
764 if (wbits == maxwbits)
773 ftmp = C16_2R * xi + C16_2I * xr;
774 indx = 14 * Constants.TerrainPatchSize + k;
775 itmp = (int)(ftmp * QuantizeTable16[indx]);
776 iout[CopyMatrix16[indx]] = itmp;
780 if (itmp < 0) itmp *= -1;
781 while (itmp > wbitsMaxValue)
784 wbitsMaxValue = 1 << wbits;
785 if (wbits == maxwbits)
797 ftmp = C16_6R * xr - C16_6I * xi;
798 indx = 6 * Constants.TerrainPatchSize + k;
799 itmp = (int)(ftmp * QuantizeTable16[indx]);
800 iout[CopyMatrix16[indx]] = itmp;
804 if (itmp < 0) itmp *= -1;
805 while (itmp > wbitsMaxValue)
808 wbitsMaxValue = 1 << wbits;
809 if (wbits == maxwbits)
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;
825 if (itmp < 0) itmp *= -1;
826 while (itmp > wbitsMaxValue)
829 wbitsMaxValue = 1 << wbits;
830 if (wbits == maxwbits)
838 xr = W16_8R * (x6r - x6i);
839 xi = W16_8R * (x6i + x6r);
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;
856 ftmp = C16_1R * xr - C16_1I * xi;
857 indx = Constants.TerrainPatchSize + k;
858 itmp = (int)(ftmp * QuantizeTable16[indx]);
859 iout[CopyMatrix16[indx]] = itmp;
863 if (itmp < 0) itmp *= -1;
864 while (itmp > wbitsMaxValue)
867 wbitsMaxValue = 1 << wbits;
868 if (wbits == maxwbits)
877 ftmp = C16_1R * xi + C16_1I * xr;
878 indx = 15 * Constants.TerrainPatchSize + k;
879 itmp = (int)(ftmp * QuantizeTable16[indx]);
880 iout[CopyMatrix16[indx]] = itmp;
884 if (itmp < 0) itmp *= -1;
885 while (itmp > wbitsMaxValue)
888 wbitsMaxValue = 1 << wbits;
889 if (wbits == maxwbits)
901 ftmp = C16_7R * xr - C16_7I * xi;
902 indx = 7 * Constants.TerrainPatchSize + k;
903 itmp = (int)(ftmp * QuantizeTable16[indx]);
904 iout[CopyMatrix16[indx]] = itmp;
908 if (itmp < 0) itmp *= -1;
909 while (itmp > wbitsMaxValue)
912 wbitsMaxValue = 1 << wbits;
913 if (wbits == maxwbits)
922 ftmp = C16_7R * xi + C16_7I * xr;
923 indx = 9 * Constants.TerrainPatchSize + k;
924 itmp = (int)(ftmp * QuantizeTable16[indx]);
925 iout[CopyMatrix16[indx]] = itmp;
929 if (itmp < 0) itmp *= -1;
930 while (itmp > wbitsMaxValue)
933 wbitsMaxValue = 1 << wbits;
934 if (wbits == maxwbits)
946 ftmp = C16_5R * xr - C16_5I * xi;
947 indx = 5 * Constants.TerrainPatchSize + k;
948 itmp = (int)(ftmp * QuantizeTable16[indx]);
949 iout[CopyMatrix16[indx]] = itmp;
953 if (itmp < 0) itmp *= -1;
954 while (itmp > wbitsMaxValue)
957 wbitsMaxValue = 1 << wbits;
958 if (wbits == maxwbits)
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;
974 if (itmp < 0) itmp *= -1;
975 while (itmp > wbitsMaxValue)
978 wbitsMaxValue = 1 << wbits;
979 if (wbits == maxwbits)
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;
998 if (itmp < 0) itmp *= -1;
999 while (itmp > wbitsMaxValue)
1002 wbitsMaxValue = 1 << wbits;
1003 if (wbits == maxwbits)
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;
1019 if (itmp < 0) itmp *= -1;
1020 while (itmp > wbitsMaxValue)
1023 wbitsMaxValue = 1 << wbits;
1024 if (wbits == maxwbits)
const int TerrainPatchSize