1
0

TerrainCompressor.cs 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125
  1. /*
  2. * Copyright (c) Contributors, http://opensimulator.org/
  3. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the OpenSimulator Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. /* Freely adapted from the Aurora version of the terrain compressor.
  28. * Copyright (c) Contributors, http://aurora-sim.org/, http://opensimulator.org/
  29. * Aurora version created from libOpenMetaverse Library terrain compressor
  30. */
  31. // terrain patchs must be 16mx16m
  32. using System;
  33. using System.Collections.Generic;
  34. using log4net;
  35. using OpenSim.Framework;
  36. using OpenMetaverse;
  37. using OpenMetaverse.Packets;
  38. namespace OpenSim.Region.ClientStack.LindenUDP
  39. {
  40. public static class OpenSimTerrainCompressor
  41. {
  42. private const float OO_SQRT2 = 0.7071068f;
  43. private const int END_OF_PATCHES = 97;
  44. private const int STRIDE = 264;
  45. private const int ZERO_CODE = 0x0;
  46. private const int ZERO_EOB = 0x2;
  47. private const int POSITIVE_VALUE = 0x6;
  48. private const int NEGATIVE_VALUE = 0x7;
  49. private static readonly int[] CopyMatrix16 = new int[256];
  50. private static readonly float[] QuantizeTable16 = new float[256];
  51. private static readonly float[] DequantizeTable16 = new float[256];
  52. static OpenSimTerrainCompressor()
  53. {
  54. if(Constants.TerrainPatchSize != 16)
  55. throw new Exception("Terrain patch size must be 16m x 16m");
  56. // Initialize the compression tables
  57. BuildQuantizeTables16();
  58. BuildCopyMatrix16();
  59. }
  60. // Used to send cloud and wind patches
  61. public static LayerDataPacket CreateLayerDataPacketStandardSize(TerrainPatch[] patches, byte type)
  62. {
  63. LayerDataPacket layer = new LayerDataPacket { LayerID = { Type = type } };
  64. TerrainPatch.GroupHeader header = new TerrainPatch.GroupHeader { Stride = STRIDE, PatchSize = 16 };
  65. // Should be enough to fit even the most poorly packed data
  66. byte[] data = new byte[patches.Length * 256 * 2];
  67. BitPack bitpack = new BitPack(data, 0);
  68. bitpack.PackBits(header.Stride, 16);
  69. bitpack.PackBits(header.PatchSize, 8);
  70. bitpack.PackBits(type, 8);
  71. foreach (TerrainPatch t in patches)
  72. CreatePatchtStandardSize(bitpack, t.Data, t.X, t.Y);
  73. bitpack.PackBits(END_OF_PATCHES, 8);
  74. layer.LayerData.Data = new byte[bitpack.BytePos + 1];
  75. Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1);
  76. return layer;
  77. }
  78. public unsafe static void CreatePatchtStandardSize(BitPack output, float[] patchData, int x, int y)
  79. {
  80. TerrainPatch.Header header = PrescanPatch(patchData);
  81. header.QuantWBits = 136;
  82. header.PatchIDs = (y & 0x1F);
  83. header.PatchIDs += (x << 5);
  84. int wbits;
  85. int* patch = stackalloc int[256];
  86. CompressPatch(patchData, header, 10, out wbits, patch);
  87. EncodePatchHeader(output, header, false, ref wbits);
  88. EncodePatch(output, patch, 0, wbits);
  89. }
  90. private static TerrainPatch.Header PrescanPatch(float[] patch)
  91. {
  92. TerrainPatch.Header header = new TerrainPatch.Header();
  93. float zmax = -99999999.0f;
  94. float zmin = 99999999.0f;
  95. for (int i = 0; i < 256; i++)
  96. {
  97. float val = patch[i];
  98. if (val > zmax) zmax = val;
  99. if (val < zmin) zmin = val;
  100. }
  101. header.DCOffset = zmin;
  102. header.Range = (int)((zmax - zmin) + 1.0f);
  103. return header;
  104. }
  105. private unsafe static void CompressPatch(float[] patchData, TerrainPatch.Header header, int prequant, out int wbits, int* iout)
  106. {
  107. float* block = stackalloc float[256];
  108. float oozrange = 1.0f / header.Range;
  109. float range = (1 << prequant);
  110. float premult = oozrange * range;
  111. float sub = 0.5f * header.Range + header.DCOffset;
  112. int wordsize = (prequant - 2) & 0x0f;
  113. header.QuantWBits = wordsize | (wordsize << 4);
  114. int k = 0;
  115. for (int j = 0; j < 256 ; j += 16)
  116. {
  117. int nj = j + 16;
  118. for (int i = j; i < nj; ++i)
  119. block[k++] = (patchData[i] - sub) * premult;
  120. }
  121. wbits = (prequant >> 1);
  122. dct16x16(block, iout, ref wbits);
  123. }
  124. public unsafe static void CreatePatchFromTerrainData(BitPack output, TerrainData terrData, int patchX, int patchY)
  125. {
  126. TerrainPatch.Header header = PrescanPatch(terrData, patchX, patchY, out float frange);
  127. header.QuantWBits = 130;
  128. bool largeRegion = terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize;
  129. if (Math.Round(frange, 2) == 1.0)
  130. {
  131. // flat terrain speed up things
  132. output.PackBitsFromByte(0); //QuantWBits
  133. output.PackFloat(header.DCOffset - 0.5f);
  134. output.PackBitsFromByte(1); //range low
  135. output.PackBitsFromByte(0); //range high
  136. if (largeRegion)
  137. output.PackBits((patchX << 16) | (patchY & 0xFFFF), 32);
  138. else
  139. output.PackBits((patchX << 5) | (patchY & 0x1F) , 10);
  140. // and thats all
  141. output.PackBits(ZERO_EOB, 2);
  142. return;
  143. }
  144. header.PatchIDs = largeRegion ?
  145. (patchX << 16) | (patchY & 0xFFFF) :
  146. (patchX << 5) | (patchY & 0x1F);
  147. int* patch = stackalloc int[256];
  148. CompressPatch(terrData, patchX, patchY, header, 10, out int wbits, patch);
  149. EncodePatchHeader(output, header, largeRegion, ref wbits);
  150. EncodePatch(output, patch, 0, wbits);
  151. }
  152. // Scan the height info we're returning and return a patch packet header for this patch.
  153. private static TerrainPatch.Header PrescanPatch(TerrainData terrData, int patchX, int patchY, out float frange)
  154. {
  155. terrData.GetPatchMinMax(patchX, patchY, out float zmin, out float zmax);
  156. frange = ((zmax - zmin) + 1.0f);
  157. TerrainPatch.Header header = new TerrainPatch.Header()
  158. {
  159. DCOffset = zmin,
  160. Range = (int)frange
  161. };
  162. return header;
  163. }
  164. private static void EncodePatchHeader(BitPack output, TerrainPatch.Header header, bool largeRegion, ref int wbits)
  165. {
  166. if (wbits > 17)
  167. wbits = 17;
  168. else if (wbits < 2)
  169. wbits = 2;
  170. header.QuantWBits &= 0xf0;
  171. header.QuantWBits |= (wbits - 2);
  172. output.PackBitsFromByte((byte)header.QuantWBits);
  173. output.PackFloat(header.DCOffset);
  174. output.PackBits(header.Range, 16);
  175. output.PackBits(header.PatchIDs, largeRegion ? 32 : 10);
  176. }
  177. private unsafe static void EncodePatch(BitPack output, int* patch, int postquant, int wbits)
  178. {
  179. int maxwbitssize = (1 << wbits) - 1;
  180. if (postquant > 256 || postquant < 0)
  181. {
  182. Logger.Log("Postquant is outside the range of allowed values in EncodePatch()", Helpers.LogLevel.Error);
  183. return;
  184. }
  185. int lastZeroindx = 256 - postquant;
  186. if (lastZeroindx != 256)
  187. patch[lastZeroindx] = 0;
  188. int i = 0;
  189. while(i < 256)
  190. {
  191. int temp = patch[i];
  192. if (temp == 0)
  193. {
  194. int j = i + 1;
  195. while(j < lastZeroindx)
  196. {
  197. if (patch[j] != 0)
  198. break;
  199. ++j;
  200. }
  201. if (j == lastZeroindx)
  202. {
  203. output.PackBits(ZERO_EOB, 2);
  204. return;
  205. }
  206. i = j - i;
  207. while(i > 8)
  208. {
  209. output.PackBitsFromByte(ZERO_CODE);
  210. i -= 8;
  211. }
  212. if( i > 0)
  213. output.PackBitsFromByte(ZERO_CODE, i);
  214. i = j;
  215. continue;
  216. }
  217. else if (temp < 0)
  218. {
  219. temp *= -1;
  220. output.PackBits(NEGATIVE_VALUE, 3);
  221. }
  222. else
  223. {
  224. output.PackBits(POSITIVE_VALUE, 3);
  225. }
  226. output.PackBits(temp > maxwbitssize ? maxwbitssize : temp, wbits);
  227. ++i;
  228. }
  229. }
  230. private unsafe static void CompressPatch(TerrainData terrData, int patchX, int patchY, TerrainPatch.Header header,
  231. int prequant, out int wbits, int* iout)
  232. {
  233. float* block = stackalloc float[256];
  234. float sub = header.Range;
  235. float premult = (1 << prequant) / sub;
  236. sub = 0.5f * sub + header.DCOffset;
  237. terrData.GetPatchBlock(block, patchX, patchY, sub, premult);
  238. int wordsize = (prequant - 2) & 0x0f;
  239. header.QuantWBits = wordsize | (wordsize << 4);
  240. wbits = (prequant >> 1);
  241. dct16x16(block, iout, ref wbits);
  242. }
  243. #region Initialization
  244. private unsafe static void BuildQuantizeTables16()
  245. {
  246. const float oosob = 2.0f / 16;
  247. float tmp;
  248. fixed(float* fQuantizeTable16 = QuantizeTable16, fDeQuantizeTable16 = DequantizeTable16)
  249. {
  250. float* dqptr = fDeQuantizeTable16;
  251. float* qptr = fQuantizeTable16;
  252. for (int j = 0; j < 16; j++)
  253. {
  254. for (int i = 0; i < 16; i++)
  255. {
  256. tmp = 1.0f + 2.0f * (i + j);
  257. *dqptr++ = tmp;
  258. *qptr++ = oosob / tmp;
  259. }
  260. }
  261. }
  262. }
  263. private unsafe static void BuildCopyMatrix16()
  264. {
  265. bool diag = false;
  266. bool right = true;
  267. int i = 0;
  268. int j = 0;
  269. int count = 0;
  270. fixed (int* fCopyMatrix16 = CopyMatrix16)
  271. {
  272. while (i < 16 && j < 16)
  273. {
  274. fCopyMatrix16[j * 16 + i] = count++;
  275. if (!diag)
  276. {
  277. if (right)
  278. {
  279. if (i < 15) i++;
  280. else j++;
  281. right = false;
  282. diag = true;
  283. }
  284. else
  285. {
  286. if (j < 15 ) j++;
  287. else i++;
  288. right = true;
  289. diag = true;
  290. }
  291. }
  292. else
  293. {
  294. if (right)
  295. {
  296. i++;
  297. j--;
  298. if (i == 15 || j == 0) diag = false;
  299. }
  300. else
  301. {
  302. i--;
  303. j++;
  304. if (j == 15 || i == 0) diag = false;
  305. }
  306. }
  307. }
  308. }
  309. }
  310. #endregion Initialization
  311. #region DCT
  312. /* DCT (Discrete Cosine Transform)
  313. adaptation from
  314. General Purpose 2D,3D FFT (Fast Fourier Transform) Package
  315. by Takuya OOURA (email: [email protected])
  316. -------- 16x16 DCT (Discrete Cosine Transform) / Inverse of DCT --------
  317. [definition]
  318. <case1> Normalized 16x16 IDCT
  319. C[k1 + k2] = (1/8) * sum_j1=0^15 sum_j2=0^15
  320. tmp[j1 + j2] * s[j1] * s[j2] *
  321. cos(pi*j1*(k1+1/2)/16) *
  322. cos(pi*j2*(k2+1/2)/16), 0<=k1<16, 0<=k2<16
  323. (s[0] = 1/sqrt(2), s[j] = 1, j > 0)
  324. <case2> Normalized 16x16 DCT
  325. C[k1 + k2] = (1/8) * s[k1] * s[k2] * sum_j1=0^15 sum_j2=0^15
  326. tmp[j1 + j2] *
  327. cos(pi*(j1+1/2)*k1/16) *
  328. cos(pi*(j2+1/2)*k2/16), 0<=k1<16, 0<=k2<16
  329. (s[0] = 1/sqrt(2), s[j] = 1, j > 0)
  330. */
  331. /* Cn_kR = sqrt(2.0/n) * cos(pi/2*k/n) */
  332. /* Cn_kI = sqrt(2.0/n) * sin(pi/2*k/n) */
  333. /* Wn_kR = cos(pi/2*k/n) */
  334. /* Wn_kI = sin(pi/2*k/n) */
  335. const float C16_1R = 0.35185093438159561476f * 2.82842712474619f;
  336. const float C16_1I = 0.03465429229977286565f * 2.82842712474619f;
  337. const float C16_2R = 0.34675996133053686546f * 2.82842712474619f;
  338. const float C16_2I = 0.06897484482073575308f * 2.82842712474619f;
  339. const float C16_3R = 0.33832950029358816957f * 2.82842712474619f;
  340. const float C16_3I = 0.10263113188058934529f * 2.82842712474619f;
  341. const float C16_4R = 0.32664074121909413196f * 2.82842712474619f;
  342. const float C16_4I = 0.13529902503654924610f * 2.82842712474619f;
  343. const float C16_5R = 0.31180625324666780814f * 2.82842712474619f;
  344. const float C16_5I = 0.16666391461943662432f * 2.82842712474619f;
  345. const float C16_6R = 0.29396890060483967924f * 2.82842712474619f;
  346. const float C16_6I = 0.19642373959677554532f * 2.82842712474619f;
  347. const float C16_7R = 0.27330046675043937206f * 2.82842712474619f;
  348. const float C16_7I = 0.22429189658565907106f * 2.82842712474619f;
  349. const float C16_8R = 0.25f * 2.82842712474619f;
  350. const float W16_4R = 0.92387953251128675613f;
  351. const float W16_4I = 0.38268343236508977173f;
  352. const float W16_8R = 0.70710678118654752440f;
  353. unsafe static void dct16x16(float* a, int* iout, ref int wbits)
  354. {
  355. float* tmp = stackalloc float[256];
  356. float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
  357. float x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i;
  358. float xr, xi;
  359. float ftmp;
  360. int itmp;
  361. int j, k;
  362. int indx;
  363. const int maxwbits = 17; // per header encoding
  364. int wbitsMaxValue = 1 << wbits;
  365. bool dowbits = wbits < 17;
  366. fixed (float* fQuantizeTable16 = QuantizeTable16)
  367. fixed (int* fCopyMatrix16 = CopyMatrix16)
  368. {
  369. for (j = 0, k = 0; j < 256; j += 16, k++)
  370. {
  371. x4r = a[0 + j] - a[15 + j];
  372. xr = a[0 + j] + a[15 + j];
  373. x4i = a[8 + j] - a[7 + j];
  374. xi = a[8 + j] + a[7 + j];
  375. x0r = xr + xi;
  376. x0i = xr - xi;
  377. x5r = a[2 + j] - a[13 + j];
  378. xr = a[2 + j] + a[13 + j];
  379. x5i = a[10 + j] - a[5 + j];
  380. xi = a[10 + j] + a[5 + j];
  381. x1r = xr + xi;
  382. x1i = xr - xi;
  383. x6r = a[4 + j] - a[11 + j];
  384. xr = a[4 + j] + a[11 + j];
  385. x6i = a[12 + j] - a[3 + j];
  386. xi = a[12 + j] + a[3 + j];
  387. x2r = xr + xi;
  388. x2i = xr - xi;
  389. x7r = a[6 + j] - a[9 + j];
  390. xr = a[6 + j] + a[9 + j];
  391. x7i = a[14 + j] - a[1 + j];
  392. xi = a[14 + j] + a[1 + j];
  393. x3r = xr + xi;
  394. x3i = xr - xi;
  395. xr = x0r + x2r;
  396. xi = x1r + x3r;
  397. tmp[k] = C16_8R * (xr + xi); //
  398. tmp[8 * 16 + k] = C16_8R * (xr - xi); //
  399. xr = x0r - x2r;
  400. xi = x1r - x3r;
  401. tmp[4 * 16 + k] = C16_4R * xr - C16_4I * xi; //
  402. tmp[12 * 16 + k] = C16_4R * xi + C16_4I * xr; //
  403. x0r = W16_8R * (x1i - x3i);
  404. x2r = W16_8R * (x1i + x3i);
  405. xr = x0i + x0r;
  406. xi = x2r + x2i;
  407. tmp[2 * 16 + k] = C16_2R * xr - C16_2I * xi; //
  408. tmp[14 * 16 + k] = C16_2R * xi + C16_2I * xr; //
  409. xr = x0i - x0r;
  410. xi = x2r - x2i;
  411. tmp[6 * 16 + k] = C16_6R * xr - C16_6I * xi; //
  412. tmp[10 * 16 + k] = C16_6R * xi + C16_6I * xr; //
  413. xr = W16_8R * (x6r - x6i);
  414. xi = W16_8R * (x6i + x6r);
  415. x6r = x4r - xr;
  416. x6i = x4i - xi;
  417. x4r += xr;
  418. x4i += xi;
  419. xr = W16_4I * x7r - W16_4R * x7i;
  420. xi = W16_4I * x7i + W16_4R * x7r;
  421. x7r = W16_4R * x5r - W16_4I * x5i;
  422. x7i = W16_4R * x5i + W16_4I * x5r;
  423. x5r = x7r + xr;
  424. x5i = x7i + xi;
  425. x7r -= xr;
  426. x7i -= xi;
  427. xr = x4r + x5r;
  428. xi = x5i + x4i;
  429. tmp[16 + k] = C16_1R * xr - C16_1I * xi; //
  430. tmp[15 * 16 + k] = C16_1R * xi + C16_1I * xr; //
  431. xr = x4r - x5r;
  432. xi = x5i - x4i;
  433. tmp[7 * 16 + k] = C16_7R * xr - C16_7I * xi; //
  434. tmp[9 * 16 + k] = C16_7R * xi + C16_7I * xr; //
  435. xr = x6r - x7i;
  436. xi = x7r + x6i;
  437. tmp[5 * 16 + k] = C16_5R * xr - C16_5I * xi; //
  438. tmp[11 * 16 + k] = C16_5R * xi + C16_5I * xr; //
  439. xr = x6r + x7i;
  440. xi = x7r - x6i;
  441. tmp[3 * 16 + k] = C16_3R * xr - C16_3I * xi; //
  442. tmp[13 * 16 + k] = C16_3R * xi + C16_3I * xr; //
  443. }
  444. for (j = 0, k = 0; j < 256; j += 16, k++)
  445. {
  446. x4r = tmp[0 + j] - tmp[15 + j];
  447. xr = tmp[0 + j] + tmp[15 + j];
  448. x4i = tmp[8 + j] - tmp[7 + j];
  449. xi = tmp[8 + j] + tmp[7 + j];
  450. x0r = xr + xi;
  451. x0i = xr - xi;
  452. x5r = tmp[2 + j] - tmp[13 + j];
  453. xr = tmp[2 + j] + tmp[13 + j];
  454. x5i = tmp[10 + j] - tmp[5 + j];
  455. xi = tmp[10 + j] + tmp[5 + j];
  456. x1r = xr + xi;
  457. x1i = xr - xi;
  458. x6r = tmp[4 + j] - tmp[11 + j];
  459. xr = tmp[4 + j] + tmp[11 + j];
  460. x6i = tmp[12 + j] - tmp[3 + j];
  461. xi = tmp[12 + j] + tmp[3 + j];
  462. x2r = xr + xi;
  463. x2i = xr - xi;
  464. x7r = tmp[6 + j] - tmp[9 + j];
  465. xr = tmp[6 + j] + tmp[9 + j];
  466. x7i = tmp[14 + j] - tmp[1 + j];
  467. xi = tmp[14 + j] + tmp[1 + j];
  468. x3r = xr + xi;
  469. x3i = xr - xi;
  470. xr = x0r + x2r;
  471. xi = x1r + x3r;
  472. //tmp[0 + k] = C16_8R * (xr + xi); //
  473. ftmp = C16_8R * (xr + xi);
  474. itmp = (int)(ftmp * fQuantizeTable16[k]);
  475. iout[fCopyMatrix16[k]] = itmp;
  476. if (dowbits)
  477. {
  478. if (itmp < 0) itmp *= -1;
  479. while (itmp > wbitsMaxValue)
  480. {
  481. wbits++;
  482. wbitsMaxValue = 1 << wbits;
  483. if (wbits == maxwbits)
  484. {
  485. dowbits = false;
  486. break;
  487. }
  488. }
  489. }
  490. //tmp[8 * Constants.TerrainPatchSize + k] = C16_8R * (xr - xi); //
  491. ftmp = C16_8R * (xr - xi);
  492. indx = 8 * 16 + k;
  493. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  494. iout[fCopyMatrix16[indx]] = itmp;
  495. if (dowbits)
  496. {
  497. if (itmp < 0) itmp *= -1;
  498. while (itmp > wbitsMaxValue)
  499. {
  500. wbits++;
  501. wbitsMaxValue = 1 << wbits;
  502. if (wbits == maxwbits)
  503. {
  504. dowbits = false;
  505. break;
  506. }
  507. }
  508. }
  509. xr = x0r - x2r;
  510. xi = x1r - x3r;
  511. //tmp[4 * Constants.TerrainPatchSize + k] = C16_4R * xr - C16_4I * xi; //
  512. ftmp = C16_4R * xr - C16_4I * xi;
  513. indx = 4 * 16 + k;
  514. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  515. iout[fCopyMatrix16[indx]] = itmp;
  516. if (dowbits)
  517. {
  518. if (itmp < 0) itmp *= -1;
  519. while (itmp > wbitsMaxValue)
  520. {
  521. wbits++;
  522. wbitsMaxValue = 1 << wbits;
  523. if (wbits == maxwbits)
  524. {
  525. dowbits = false;
  526. break;
  527. }
  528. }
  529. }
  530. //tmp[12 * Constants.TerrainPatchSize + k] = C16_4R * xi + C16_4I * xr; //
  531. ftmp = C16_4R * xi + C16_4I * xr;
  532. indx = 12 * 16 + k;
  533. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  534. iout[fCopyMatrix16[indx]] = itmp;
  535. if (dowbits)
  536. {
  537. if (itmp < 0) itmp *= -1;
  538. while (itmp > wbitsMaxValue)
  539. {
  540. wbits++;
  541. wbitsMaxValue = 1 << wbits;
  542. if (wbits == maxwbits)
  543. {
  544. dowbits = false;
  545. break;
  546. }
  547. }
  548. }
  549. x0r = W16_8R * (x1i - x3i);
  550. x2r = W16_8R * (x1i + x3i);
  551. xr = x0i + x0r;
  552. xi = x2r + x2i;
  553. //tmp[2 * Constants.TerrainPatchSize + k] = C16_2R * xr - C16_2I * xi; //
  554. ftmp = C16_2R * xr - C16_2I * xi;
  555. indx = 2 * 16 + k;
  556. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  557. iout[fCopyMatrix16[indx]] = itmp;
  558. if (dowbits)
  559. {
  560. if (itmp < 0) itmp *= -1;
  561. while (itmp > wbitsMaxValue)
  562. {
  563. wbits++;
  564. wbitsMaxValue = 1 << wbits;
  565. if (wbits == maxwbits)
  566. {
  567. dowbits = false;
  568. break;
  569. }
  570. }
  571. }
  572. //tmp[14 * Constants.TerrainPatchSize + k] = C16_2R * xi + C16_2I * xr; //
  573. ftmp = C16_2R * xi + C16_2I * xr;
  574. indx = 14 * 16 + k;
  575. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  576. iout[fCopyMatrix16[indx]] = itmp;
  577. if (dowbits)
  578. {
  579. if (itmp < 0) itmp *= -1;
  580. while (itmp > wbitsMaxValue)
  581. {
  582. wbits++;
  583. wbitsMaxValue = 1 << wbits;
  584. if (wbits == maxwbits)
  585. {
  586. dowbits = false;
  587. break;
  588. }
  589. }
  590. }
  591. xr = x0i - x0r;
  592. xi = x2r - x2i;
  593. //tmp[6 * Constants.TerrainPatchSize + k] = C16_6R * xr - C16_6I * xi; //
  594. ftmp = C16_6R * xr - C16_6I * xi;
  595. indx = 6 * 16 + k;
  596. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  597. iout[fCopyMatrix16[indx]] = itmp;
  598. if (dowbits)
  599. {
  600. if (itmp < 0) itmp *= -1;
  601. while (itmp > wbitsMaxValue)
  602. {
  603. wbits++;
  604. wbitsMaxValue = 1 << wbits;
  605. if (wbits == maxwbits)
  606. {
  607. dowbits = false;
  608. break;
  609. }
  610. }
  611. }
  612. //tmp[10 * Constants.TerrainPatchSize + k] = C16_6R * xi + C16_6I * xr; //
  613. ftmp = C16_6R * xi + C16_6I * xr;
  614. indx = 10 * 16 + k;
  615. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  616. iout[fCopyMatrix16[indx]] = itmp;
  617. if (dowbits)
  618. {
  619. if (itmp < 0) itmp *= -1;
  620. while (itmp > wbitsMaxValue)
  621. {
  622. wbits++;
  623. wbitsMaxValue = 1 << wbits;
  624. if (wbits == maxwbits)
  625. {
  626. dowbits = false;
  627. break;
  628. }
  629. }
  630. }
  631. xr = W16_8R * (x6r - x6i);
  632. xi = W16_8R * (x6i + x6r);
  633. x6r = x4r - xr;
  634. x6i = x4i - xi;
  635. x4r += xr;
  636. x4i += xi;
  637. xr = W16_4I * x7r - W16_4R * x7i;
  638. xi = W16_4I * x7i + W16_4R * x7r;
  639. x7r = W16_4R * x5r - W16_4I * x5i;
  640. x7i = W16_4R * x5i + W16_4I * x5r;
  641. x5r = x7r + xr;
  642. x5i = x7i + xi;
  643. x7r -= xr;
  644. x7i -= xi;
  645. xr = x4r + x5r;
  646. xi = x5i + x4i;
  647. //tmp[1 * Constants.TerrainPatchSize + k] = C16_1R * xr - C16_1I * xi; //
  648. ftmp = C16_1R * xr - C16_1I * xi;
  649. indx = 16 + k;
  650. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  651. iout[fCopyMatrix16[indx]] = itmp;
  652. if (dowbits)
  653. {
  654. if (itmp < 0) itmp *= -1;
  655. while (itmp > wbitsMaxValue)
  656. {
  657. wbits++;
  658. wbitsMaxValue = 1 << wbits;
  659. if (wbits == maxwbits)
  660. {
  661. dowbits = false;
  662. break;
  663. }
  664. }
  665. }
  666. //tmp[15 * Constants.TerrainPatchSize + k] = C16_1R * xi + C16_1I * xr; //
  667. ftmp = C16_1R * xi + C16_1I * xr;
  668. indx = 15 * 16 + k;
  669. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  670. iout[fCopyMatrix16[indx]] = itmp;
  671. if (dowbits)
  672. {
  673. if (itmp < 0) itmp *= -1;
  674. while (itmp > wbitsMaxValue)
  675. {
  676. wbits++;
  677. wbitsMaxValue = 1 << wbits;
  678. if (wbits == maxwbits)
  679. {
  680. dowbits = false;
  681. break;
  682. }
  683. }
  684. }
  685. xr = x4r - x5r;
  686. xi = x5i - x4i;
  687. //tmp[7 * Constants.TerrainPatchSize + k] = C16_7R * xr - C16_7I * xi; //
  688. ftmp = C16_7R * xr - C16_7I * xi;
  689. indx = 7 * 16 + k;
  690. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  691. iout[fCopyMatrix16[indx]] = itmp;
  692. if (dowbits)
  693. {
  694. if (itmp < 0) itmp *= -1;
  695. while (itmp > wbitsMaxValue)
  696. {
  697. wbits++;
  698. wbitsMaxValue = 1 << wbits;
  699. if (wbits == maxwbits)
  700. {
  701. dowbits = false;
  702. break;
  703. }
  704. }
  705. }
  706. //tmp[9 * Constants.TerrainPatchSize + k] = C16_7R * xi + C16_7I * xr; //
  707. ftmp = C16_7R * xi + C16_7I * xr;
  708. indx = 9 * 16 + k;
  709. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  710. iout[fCopyMatrix16[indx]] = itmp;
  711. if (dowbits)
  712. {
  713. if (itmp < 0) itmp *= -1;
  714. while (itmp > wbitsMaxValue)
  715. {
  716. wbits++;
  717. wbitsMaxValue = 1 << wbits;
  718. if (wbits == maxwbits)
  719. {
  720. dowbits = false;
  721. break;
  722. }
  723. }
  724. }
  725. xr = x6r - x7i;
  726. xi = x7r + x6i;
  727. //tmp[5 * Constants.TerrainPatchSize + k] = C16_5R * xr - C16_5I * xi; //
  728. ftmp = C16_5R * xr - C16_5I * xi;
  729. indx = 5 * 16 + k;
  730. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  731. iout[fCopyMatrix16[indx]] = itmp;
  732. if (dowbits)
  733. {
  734. if (itmp < 0) itmp *= -1;
  735. while (itmp > wbitsMaxValue)
  736. {
  737. wbits++;
  738. wbitsMaxValue = 1 << wbits;
  739. if (wbits == maxwbits)
  740. {
  741. dowbits = false;
  742. break;
  743. }
  744. }
  745. }
  746. //tmp[11 * Constants.TerrainPatchSize + k] = C16_5R * xi + C16_5I * xr; //
  747. ftmp = C16_5R * xi + C16_5I * xr;
  748. indx = 11 * 16 + k;
  749. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  750. iout[fCopyMatrix16[indx]] = itmp;
  751. if (dowbits)
  752. {
  753. if (itmp < 0) itmp *= -1;
  754. while (itmp > wbitsMaxValue)
  755. {
  756. wbits++;
  757. wbitsMaxValue = 1 << wbits;
  758. if (wbits == maxwbits)
  759. {
  760. dowbits = false;
  761. break;
  762. }
  763. }
  764. }
  765. xr = x6r + x7i;
  766. xi = x7r - x6i;
  767. //tmp[3 * Constants.TerrainPatchSize + k] = C16_3R * xr - C16_3I * xi; //
  768. ftmp = C16_3R * xr - C16_3I * xi;
  769. indx = 3 * 16 + k;
  770. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  771. iout[fCopyMatrix16[indx]] = itmp;
  772. if (dowbits)
  773. {
  774. if (itmp < 0) itmp *= -1;
  775. while (itmp > wbitsMaxValue)
  776. {
  777. wbits++;
  778. wbitsMaxValue = 1 << wbits;
  779. if (wbits == maxwbits)
  780. {
  781. dowbits = false;
  782. break;
  783. }
  784. }
  785. }
  786. //tmp[13 * Constants.TerrainPatchSize + k] = C16_3R * xi + C16_3I * xr; //
  787. ftmp = C16_3R * xi + C16_3I * xr;
  788. indx = 13 * 16 + k;
  789. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  790. iout[fCopyMatrix16[indx]] = itmp;
  791. if (dowbits)
  792. {
  793. if (itmp < 0) itmp *= -1;
  794. while (itmp > wbitsMaxValue)
  795. {
  796. wbits++;
  797. wbitsMaxValue = 1 << wbits;
  798. if (wbits == maxwbits)
  799. {
  800. dowbits = false;
  801. break;
  802. }
  803. }
  804. }
  805. }
  806. }
  807. }
  808. #endregion DCT
  809. #region IDCT
  810. /* not in use
  811. private static void IDCTColumn16(float[] linein, float[] lineout, int column)
  812. {
  813. for (int n = 0; n < Constants.TerrainPatchSize; n++)
  814. {
  815. float total = OO_SQRT2 * linein[column];
  816. for (int u = 1; u < Constants.TerrainPatchSize; u++)
  817. {
  818. int usize = u * Constants.TerrainPatchSize;
  819. total += linein[usize + column] * CosineTable16[usize + n];
  820. }
  821. lineout[Constants.TerrainPatchSize * n + column] = total;
  822. }
  823. }
  824. private static void IDCTLine16(float[] linein, float[] lineout, int line)
  825. {
  826. const float oosob = 2.0f / Constants.TerrainPatchSize;
  827. int lineSize = line * Constants.TerrainPatchSize;
  828. for (int n = 0; n < Constants.TerrainPatchSize; n++)
  829. {
  830. float total = OO_SQRT2 * linein[lineSize];
  831. for (int u = 1; u < Constants.TerrainPatchSize; u++)
  832. {
  833. total += linein[lineSize + u] * CosineTable16[u * Constants.TerrainPatchSize + n];
  834. }
  835. lineout[lineSize + n] = total * oosob;
  836. }
  837. }
  838. //not in use, and still not fixed
  839. /*
  840. static void idct16x16(float[] a)
  841. {
  842. int j;
  843. float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
  844. float x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i;
  845. float xr, xi;
  846. int fullSize = Constants.TerrainPatchSize * Constants.TerrainPatchSize;
  847. for (j = 0; j < fullSize; j += Constants.TerrainPatchSize)
  848. {
  849. x5r = C16_1R * tmp[1 + j] + C16_1I * tmp[15 + j];
  850. x5i = C16_1R * tmp[15 + j] - C16_1I * tmp[1 + j];
  851. xr = C16_7R * tmp[7 + j] + C16_7I * tmp[9 + j];
  852. xi = C16_7R * tmp[9 + j] - C16_7I * tmp[7 + j];
  853. x4r = x5r + xr;
  854. x4i = x5i - xi;
  855. x5r -= xr;
  856. x5i += xi;
  857. x7r = C16_5R * tmp[5 + j] + C16_5I * tmp[11 + j];
  858. x7i = C16_5R * tmp[11 + j] - C16_5I * tmp[5 + j];
  859. xr = C16_3R * tmp[3 + j] + C16_3I * tmp[13 + j];
  860. xi = C16_3R * tmp[13 + j] - C16_3I * tmp[3 + j];
  861. x6r = x7r + xr;
  862. x6i = x7i - xi;
  863. x7r -= xr;
  864. x7i += xi;
  865. xr = x4r - x6r;
  866. xi = x4i - x6i;
  867. x4r += x6r;
  868. x4i += x6i;
  869. x6r = W16_8R * (xi + xr);
  870. x6i = W16_8R * (xi - xr);
  871. xr = x5r + x7i;
  872. xi = x5i - x7r;
  873. x5r -= x7i;
  874. x5i += x7r;
  875. x7r = W16_4I * x5r + W16_4R * x5i;
  876. x7i = W16_4I * x5i - W16_4R * x5r;
  877. x5r = W16_4R * xr + W16_4I * xi;
  878. x5i = W16_4R * xi - W16_4I * xr;
  879. xr = C16_4R * tmp[4 + j] + C16_4I * tmp[12 + j];
  880. xi = C16_4R * tmp[12 + j] - C16_4I * tmp[4 + j];
  881. x2r = C16_8R * (tmp[0 + j] + tmp[8 + j]);
  882. x3r = C16_8R * (tmp[0 + j] - tmp[8 + j]);
  883. x0r = x2r + xr;
  884. x1r = x3r + xi;
  885. x2r -= xr;
  886. x3r -= xi;
  887. x0i = C16_2R * tmp[2 + j] + C16_2I * tmp[14 + j];
  888. x2i = C16_2R * tmp[14 + j] - C16_2I * tmp[2 + j];
  889. x1i = C16_6R * tmp[6 + j] + C16_6I * tmp[10 + j];
  890. x3i = C16_6R * tmp[10 + j] - C16_6I * tmp[6 + j];
  891. xr = x0i - x1i;
  892. xi = x2i + x3i;
  893. x0i += x1i;
  894. x2i -= x3i;
  895. x1i = W16_8R * (xi + xr);
  896. x3i = W16_8R * (xi - xr);
  897. xr = x0r + x0i;
  898. xi = x0r - x0i;
  899. tmp[0 + j] = xr + x4r;
  900. tmp[15 + j] = xr - x4r;
  901. tmp[8 + j] = xi + x4i;
  902. tmp[7 + j] = xi - x4i;
  903. xr = x1r + x1i;
  904. xi = x1r - x1i;
  905. tmp[2 + j] = xr + x5r;
  906. tmp[13 + j] = xr - x5r;
  907. tmp[10 + j] = xi + x5i;
  908. tmp[5 + j] = xi - x5i;
  909. xr = x2r + x2i;
  910. xi = x2r - x2i;
  911. tmp[4 + j] = xr + x6r;
  912. tmp[11 + j] = xr - x6r;
  913. tmp[12 + j] = xi + x6i;
  914. tmp[3 + j] = xi - x6i;
  915. xr = x3r + x3i;
  916. xi = x3r - x3i;
  917. tmp[6 + j] = xr + x7r;
  918. tmp[9 + j] = xr - x7r;
  919. tmp[14 + j] = xi + x7i;
  920. tmp[1 + j] = xi - x7i;
  921. }
  922. for (j = 0; j < fullSize; j += Constants.TerrainPatchSize)
  923. {
  924. x5r = C16_1R * tmp[j + 1] + C16_1I * tmp[j + 15];
  925. x5i = C16_1R * tmp[j + 15] - C16_1I * tmp[j + 1];
  926. xr = C16_7R * tmp[j + 7] + C16_7I * tmp[j + 9];
  927. xi = C16_7R * tmp[j + 9] - C16_7I * tmp[j + 7];
  928. x4r = x5r + xr;
  929. x4i = x5i - xi;
  930. x5r -= xr;
  931. x5i += xi;
  932. x7r = C16_5R * tmp[j + 5] + C16_5I * tmp[j + 11];
  933. x7i = C16_5R * tmp[j + 11] - C16_5I * tmp[j + 5];
  934. xr = C16_3R * tmp[j + 3] + C16_3I * tmp[j + 13];
  935. xi = C16_3R * tmp[j + 13] - C16_3I * tmp[j + 3];
  936. x6r = x7r + xr;
  937. x6i = x7i - xi;
  938. x7r -= xr;
  939. x7i += xi;
  940. xr = x4r - x6r;
  941. xi = x4i - x6i;
  942. x4r += x6r;
  943. x4i += x6i;
  944. x6r = W16_8R * (xi + xr);
  945. x6i = W16_8R * (xi - xr);
  946. xr = x5r + x7i;
  947. xi = x5i - x7r;
  948. x5r -= x7i;
  949. x5i += x7r;
  950. x7r = W16_4I * x5r + W16_4R * x5i;
  951. x7i = W16_4I * x5i - W16_4R * x5r;
  952. x5r = W16_4R * xr + W16_4I * xi;
  953. x5i = W16_4R * xi - W16_4I * xr;
  954. xr = C16_4R * tmp[j + 4] + C16_4I * tmp[j + 12];
  955. xi = C16_4R * tmp[j + 12] - C16_4I * tmp[j + 4];
  956. x2r = C16_8R * (tmp[j + 0] + tmp[j + 8]);
  957. x3r = C16_8R * (tmp[j + 0] - tmp[j + 8]);
  958. x0r = x2r + xr;
  959. x1r = x3r + xi;
  960. x2r -= xr;
  961. x3r -= xi;
  962. x0i = C16_2R * tmp[j + 2] + C16_2I * tmp[j + 14];
  963. x2i = C16_2R * tmp[j + 14] - C16_2I * tmp[j + 2];
  964. x1i = C16_6R * tmp[j + 6] + C16_6I * tmp[j + 10];
  965. x3i = C16_6R * tmp[j + 10] - C16_6I * tmp[j + 6];
  966. xr = x0i - x1i;
  967. xi = x2i + x3i;
  968. x0i += x1i;
  969. x2i -= x3i;
  970. x1i = W16_8R * (xi + xr);
  971. x3i = W16_8R * (xi - xr);
  972. xr = x0r + x0i;
  973. xi = x0r - x0i;
  974. tmp[j + 0] = xr + x4r;
  975. tmp[j + 15] = xr - x4r;
  976. tmp[j + 8] = xi + x4i;
  977. tmp[j + 7] = xi - x4i;
  978. xr = x1r + x1i;
  979. xi = x1r - x1i;
  980. tmp[j + 2] = xr + x5r;
  981. tmp[j + 13] = xr - x5r;
  982. tmp[j + 10] = xi + x5i;
  983. tmp[j + 5] = xi - x5i;
  984. xr = x2r + x2i;
  985. xi = x2r - x2i;
  986. tmp[j + 4] = xr + x6r;
  987. tmp[j + 11] = xr - x6r;
  988. tmp[j + 12] = xi + x6i;
  989. tmp[j + 3] = xi - x6i;
  990. xr = x3r + x3i;
  991. xi = x3r - x3i;
  992. tmp[j + 6] = xr + x7r;
  993. tmp[j + 9] = xr - x7r;
  994. tmp[j + 14] = xi + x7i;
  995. tmp[j + 1] = xi - x7i;
  996. }
  997. }
  998. */
  999. #endregion IDCT
  1000. }
  1001. }