TerrainCompressor.cs 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325
  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. using System;
  32. using System.Collections.Generic;
  33. using System.Reflection;
  34. using System.Diagnostics;
  35. using log4net;
  36. using OpenSim.Framework;
  37. using OpenSim.Region.Framework;
  38. using OpenSim.Region.Framework.Scenes;
  39. using OpenMetaverse;
  40. using OpenMetaverse.Packets;
  41. namespace OpenSim.Region.ClientStack.LindenUDP
  42. {
  43. public static class OpenSimTerrainCompressor
  44. {
  45. // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  46. #pragma warning disable 414
  47. private static string LogHeader = "[TERRAIN COMPRESSOR]";
  48. #pragma warning restore 414
  49. public const int END_OF_PATCHES = 97;
  50. private const float OO_SQRT2 = 0.7071067811865475244008443621049f;
  51. private const int STRIDE = 264;
  52. private const int ZERO_CODE = 0x0;
  53. private const int ZERO_EOB = 0x2;
  54. private const int POSITIVE_VALUE = 0x6;
  55. private const int NEGATIVE_VALUE = 0x7;
  56. // private static readonly float[] CosineTable16 = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
  57. private static readonly int[] CopyMatrix16 = new int[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
  58. private static readonly float[] QuantizeTable16 =
  59. new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
  60. private static readonly float[] DequantizeTable16 =
  61. new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
  62. static OpenSimTerrainCompressor()
  63. {
  64. // Initialize the decompression tables
  65. BuildDequantizeTable16();
  66. // SetupCosines16();
  67. BuildCopyMatrix16();
  68. BuildQuantizeTable16();
  69. }
  70. // Used to send cloud and wind patches
  71. public static LayerDataPacket CreateLayerDataPacketStandardSize(TerrainPatch[] patches, byte type)
  72. {
  73. LayerDataPacket layer = new LayerDataPacket { LayerID = { Type = type } };
  74. TerrainPatch.GroupHeader header = new TerrainPatch.GroupHeader
  75. { Stride = STRIDE, PatchSize = Constants.TerrainPatchSize };
  76. // Should be enough to fit even the most poorly packed data
  77. byte[] data = new byte[patches.Length * Constants.TerrainPatchSize * Constants.TerrainPatchSize * 2];
  78. BitPack bitpack = new BitPack(data, 0);
  79. bitpack.PackBits(header.Stride, 16);
  80. bitpack.PackBits(header.PatchSize, 8);
  81. bitpack.PackBits(type, 8);
  82. foreach (TerrainPatch t in patches)
  83. CreatePatchtStandardSize(bitpack, t.Data, t.X, t.Y);
  84. bitpack.PackBits(END_OF_PATCHES, 8);
  85. layer.LayerData.Data = new byte[bitpack.BytePos + 1];
  86. Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1);
  87. return layer;
  88. }
  89. public static void CreatePatchtStandardSize(BitPack output, float[] patchData, int x, int y)
  90. {
  91. TerrainPatch.Header header = PrescanPatch(patchData);
  92. header.QuantWBits = 136;
  93. header.PatchIDs = (y & 0x1F);
  94. header.PatchIDs += (x << 5);
  95. int wbits;
  96. int[] patch = CompressPatch(patchData, header, 10, out wbits);
  97. EncodePatchHeader(output, header, patch, false, ref wbits);
  98. EncodePatch(output, patch, 0, wbits);
  99. }
  100. private static TerrainPatch.Header PrescanPatch(float[] patch)
  101. {
  102. TerrainPatch.Header header = new TerrainPatch.Header();
  103. float zmax = -99999999.0f;
  104. float zmin = 99999999.0f;
  105. for (int i = 0; i < Constants.TerrainPatchSize * Constants.TerrainPatchSize; i++)
  106. {
  107. float val = patch[i];
  108. if (val > zmax) zmax = val;
  109. if (val < zmin) zmin = val;
  110. }
  111. header.DCOffset = zmin;
  112. header.Range = (int)((zmax - zmin) + 1.0f);
  113. return header;
  114. }
  115. private static int[] CompressPatch(float[] patchData, TerrainPatch.Header header, int prequant, out int wbits)
  116. {
  117. float[] block = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
  118. float oozrange = 1.0f / header.Range;
  119. float range = (1 << prequant);
  120. float premult = oozrange * range;
  121. float sub = 0.5f * header.Range + header.DCOffset;
  122. int wordsize = (prequant - 2) & 0x0f;
  123. header.QuantWBits = wordsize;
  124. header.QuantWBits |= wordsize << 4;
  125. int k = 0;
  126. for (int j = 0; j < Constants.TerrainPatchSize; j++)
  127. {
  128. for (int i = 0; i < Constants.TerrainPatchSize; i++)
  129. block[k++] = (patchData[j * Constants.TerrainPatchSize + i] - sub) * premult;
  130. }
  131. float[] ftemp = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
  132. int[] iout = new int[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
  133. wbits = (prequant >> 1);
  134. dct16x16(block, iout, ref wbits);
  135. return iout;
  136. }
  137. // new using terrain data and patchs indexes
  138. public static List<LayerDataPacket> CreateLayerDataPackets(TerrainData terrData, int[] x, int[] y, byte landPacketType)
  139. {
  140. List<LayerDataPacket> ret = new List<LayerDataPacket>();
  141. //create packet and global header
  142. LayerDataPacket layer = new LayerDataPacket();
  143. layer.LayerID.Type = landPacketType;
  144. byte[] data = new byte[x.Length * Constants.TerrainPatchSize * Constants.TerrainPatchSize * 2];
  145. BitPack bitpack = new BitPack(data, 0);
  146. bitpack.PackBits(STRIDE, 16);
  147. bitpack.PackBits(Constants.TerrainPatchSize, 8);
  148. bitpack.PackBits(landPacketType, 8);
  149. for (int i = 0; i < x.Length; i++)
  150. {
  151. CreatePatchFromTerrainData(bitpack, terrData, x[i], y[i]);
  152. if (bitpack.BytePos > 980 && i != x.Length - 1)
  153. {
  154. //finish this packet
  155. bitpack.PackBits(END_OF_PATCHES, 8);
  156. layer.LayerData.Data = new byte[bitpack.BytePos + 1];
  157. Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1);
  158. ret.Add(layer);
  159. // start another
  160. layer = new LayerDataPacket();
  161. layer.LayerID.Type = landPacketType;
  162. bitpack = new BitPack(data, 0);
  163. bitpack.PackBits(STRIDE, 16);
  164. bitpack.PackBits(Constants.TerrainPatchSize, 8);
  165. bitpack.PackBits(landPacketType, 8);
  166. }
  167. }
  168. bitpack.PackBits(END_OF_PATCHES, 8);
  169. layer.LayerData.Data = new byte[bitpack.BytePos + 1];
  170. Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1);
  171. ret.Add(layer);
  172. return ret;
  173. }
  174. public static void CreatePatchFromTerrainData(BitPack output, TerrainData terrData, int patchX, int patchY)
  175. {
  176. float frange;
  177. TerrainPatch.Header header = PrescanPatch(terrData, patchX, patchY, out frange);
  178. header.QuantWBits = 130;
  179. bool largeRegion = false;
  180. // If larger than legacy region size, pack patch X and Y info differently.
  181. if (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize)
  182. {
  183. header.PatchIDs = (patchY & 0xFFFF);
  184. header.PatchIDs += (patchX << 16);
  185. largeRegion = true;
  186. }
  187. else
  188. {
  189. header.PatchIDs = (patchY & 0x1F);
  190. header.PatchIDs += (patchX << 5);
  191. }
  192. if (Math.Round((double)frange, 2) == 1.0)
  193. {
  194. // flat terrain speed up things
  195. header.DCOffset -= 0.5f;
  196. header.QuantWBits = 0x00;
  197. output.PackBits(header.QuantWBits, 8);
  198. output.PackFloat(header.DCOffset);
  199. output.PackBits(1, 16);
  200. if (largeRegion)
  201. output.PackBits(header.PatchIDs, 32);
  202. else
  203. output.PackBits(header.PatchIDs, 10);
  204. // and thats all
  205. output.PackBits(ZERO_EOB, 2);
  206. return;
  207. }
  208. int wbits;
  209. int[] patch = CompressPatch(terrData, patchX, patchY, header, 10, out wbits);
  210. EncodePatchHeader(output, header, patch, largeRegion, ref wbits);
  211. EncodePatch(output, patch, 0, wbits);
  212. }
  213. // Scan the height info we're returning and return a patch packet header for this patch.
  214. private static TerrainPatch.Header PrescanPatch(TerrainData terrData, int patchX, int patchY, out float frange)
  215. {
  216. TerrainPatch.Header header = new TerrainPatch.Header();
  217. float zmax = float.MinValue;
  218. float zmin = float.MaxValue;
  219. int startx = patchX * Constants.TerrainPatchSize;
  220. int starty = patchY * Constants.TerrainPatchSize;
  221. for (int j = starty; j < starty + Constants.TerrainPatchSize; j++)
  222. {
  223. for (int i = startx; i < startx + Constants.TerrainPatchSize; i++)
  224. {
  225. float val = terrData[i, j];
  226. if (val > zmax) zmax = val;
  227. if (val < zmin) zmin = val;
  228. }
  229. }
  230. header.DCOffset = zmin;
  231. frange = ((zmax - zmin) + 1.0f);
  232. header.Range = (int)frange;
  233. return header;
  234. }
  235. private static void EncodePatchHeader(BitPack output, TerrainPatch.Header header, int[] patch, bool largeRegion, ref int wbits)
  236. {
  237. if (wbits > 17)
  238. wbits = 17;
  239. else if (wbits < 2)
  240. wbits = 2;
  241. header.QuantWBits &= 0xf0;
  242. header.QuantWBits |= (wbits - 2);
  243. output.PackBits(header.QuantWBits, 8);
  244. output.PackFloat(header.DCOffset);
  245. output.PackBits(header.Range, 16);
  246. if (largeRegion)
  247. output.PackBits(header.PatchIDs, 32);
  248. else
  249. output.PackBits(header.PatchIDs, 10);
  250. }
  251. private static void EncodePatch(BitPack output, int[] patch, int postquant, int wbits)
  252. {
  253. int maxwbitssize = (1 << wbits) - 1;
  254. int fullSize = Constants.TerrainPatchSize * Constants.TerrainPatchSize;
  255. if (postquant > fullSize || postquant < 0)
  256. {
  257. Logger.Log("Postquant is outside the range of allowed values in EncodePatch()", Helpers.LogLevel.Error);
  258. return;
  259. }
  260. if (postquant != 0)
  261. patch[fullSize - postquant] = 0;
  262. int lastZeroindx = fullSize - postquant;
  263. for (int i = 0; i < fullSize; i++)
  264. {
  265. int temp = patch[i];
  266. if (temp == 0)
  267. {
  268. bool eob = true;
  269. for (int j = i; j < lastZeroindx; j++)
  270. {
  271. if (patch[j] != 0)
  272. {
  273. eob = false;
  274. break;
  275. }
  276. }
  277. if (eob)
  278. {
  279. output.PackBits(ZERO_EOB, 2);
  280. return;
  281. }
  282. output.PackBits(ZERO_CODE, 1);
  283. }
  284. else
  285. {
  286. if (temp < 0)
  287. {
  288. temp *= -1;
  289. if (temp > maxwbitssize) temp = maxwbitssize;
  290. output.PackBits(NEGATIVE_VALUE, 3);
  291. output.PackBits(temp, wbits);
  292. }
  293. else
  294. {
  295. if (temp > maxwbitssize) temp = maxwbitssize;
  296. output.PackBits(POSITIVE_VALUE, 3);
  297. output.PackBits(temp, wbits);
  298. }
  299. }
  300. }
  301. }
  302. private static int[] CompressPatch(TerrainData terrData, int patchX, int patchY, TerrainPatch.Header header,
  303. int prequant, out int wbits)
  304. {
  305. float[] block = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
  306. int[] iout = new int[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
  307. float oozrange = 1.0f / header.Range;
  308. float invprequat = (1 << prequant);
  309. float premult = oozrange * invprequat;
  310. float sub = 0.5f * header.Range + header.DCOffset;
  311. int wordsize = (prequant - 2) & 0x0f;
  312. header.QuantWBits = wordsize;
  313. header.QuantWBits |= wordsize << 4;
  314. int k = 0;
  315. int startX = patchX * Constants.TerrainPatchSize;
  316. int startY = patchY * Constants.TerrainPatchSize;
  317. for (int y = startY; y < startY + Constants.TerrainPatchSize; y++)
  318. {
  319. for (int x = startX; x < startX + Constants.TerrainPatchSize; x++)
  320. {
  321. block[k++] = (terrData[x, y] - sub) * premult;
  322. }
  323. }
  324. wbits = (prequant >> 1);
  325. dct16x16(block, iout, ref wbits);
  326. return iout;
  327. }
  328. #region Initialization
  329. private static void BuildDequantizeTable16()
  330. {
  331. for (int j = 0; j < Constants.TerrainPatchSize; j++)
  332. {
  333. for (int i = 0; i < Constants.TerrainPatchSize; i++)
  334. {
  335. DequantizeTable16[j * Constants.TerrainPatchSize + i] = 1.0f + 2.0f * (i + j);
  336. }
  337. }
  338. }
  339. private static void BuildQuantizeTable16()
  340. {
  341. const float oosob = 2.0f / Constants.TerrainPatchSize;
  342. for (int j = 0; j < Constants.TerrainPatchSize; j++)
  343. {
  344. for (int i = 0; i < Constants.TerrainPatchSize; i++)
  345. {
  346. QuantizeTable16[j * Constants.TerrainPatchSize + i] = oosob / (1.0f + 2.0f * (i + (float)j));
  347. }
  348. }
  349. }
  350. private static void BuildCopyMatrix16()
  351. {
  352. bool diag = false;
  353. bool right = true;
  354. int i = 0;
  355. int j = 0;
  356. int count = 0;
  357. while (i < Constants.TerrainPatchSize && j < Constants.TerrainPatchSize)
  358. {
  359. CopyMatrix16[j * Constants.TerrainPatchSize + i] = count++;
  360. if (!diag)
  361. {
  362. if (right)
  363. {
  364. if (i < Constants.TerrainPatchSize - 1) i++;
  365. else j++;
  366. right = false;
  367. diag = true;
  368. }
  369. else
  370. {
  371. if (j < Constants.TerrainPatchSize - 1) j++;
  372. else i++;
  373. right = true;
  374. diag = true;
  375. }
  376. }
  377. else
  378. {
  379. if (right)
  380. {
  381. i++;
  382. j--;
  383. if (i == Constants.TerrainPatchSize - 1 || j == 0) diag = false;
  384. }
  385. else
  386. {
  387. i--;
  388. j++;
  389. if (j == Constants.TerrainPatchSize - 1 || i == 0) diag = false;
  390. }
  391. }
  392. }
  393. }
  394. #endregion Initialization
  395. #region DCT
  396. /* DCT (Discrete Cosine Transform)
  397. adaptation from
  398. General Purpose 2D,3D FFT (Fast Fourier Transform) Package
  399. by Takuya OOURA (email: [email protected])
  400. -------- 16x16 DCT (Discrete Cosine Transform) / Inverse of DCT --------
  401. [definition]
  402. <case1> Normalized 16x16 IDCT
  403. C[k1 + k2] = (1/8) * sum_j1=0^15 sum_j2=0^15
  404. tmp[j1 + j2] * s[j1] * s[j2] *
  405. cos(pi*j1*(k1+1/2)/16) *
  406. cos(pi*j2*(k2+1/2)/16), 0<=k1<16, 0<=k2<16
  407. (s[0] = 1/sqrt(2), s[j] = 1, j > 0)
  408. <case2> Normalized 16x16 DCT
  409. C[k1 + k2] = (1/8) * s[k1] * s[k2] * sum_j1=0^15 sum_j2=0^15
  410. tmp[j1 + j2] *
  411. cos(pi*(j1+1/2)*k1/16) *
  412. cos(pi*(j2+1/2)*k2/16), 0<=k1<16, 0<=k2<16
  413. (s[0] = 1/sqrt(2), s[j] = 1, j > 0)
  414. */
  415. /* Cn_kR = sqrt(2.0/n) * cos(pi/2*k/n) */
  416. /* Cn_kI = sqrt(2.0/n) * sin(pi/2*k/n) */
  417. /* Wn_kR = cos(pi/2*k/n) */
  418. /* Wn_kI = sin(pi/2*k/n) */
  419. const float C16_1R = 0.35185093438159561476f * 2.82842712474619f;
  420. const float C16_1I = 0.03465429229977286565f * 2.82842712474619f;
  421. const float C16_2R = 0.34675996133053686546f * 2.82842712474619f;
  422. const float C16_2I = 0.06897484482073575308f * 2.82842712474619f;
  423. const float C16_3R = 0.33832950029358816957f * 2.82842712474619f;
  424. const float C16_3I = 0.10263113188058934529f * 2.82842712474619f;
  425. const float C16_4R = 0.32664074121909413196f * 2.82842712474619f;
  426. const float C16_4I = 0.13529902503654924610f * 2.82842712474619f;
  427. const float C16_5R = 0.31180625324666780814f * 2.82842712474619f;
  428. const float C16_5I = 0.16666391461943662432f * 2.82842712474619f;
  429. const float C16_6R = 0.29396890060483967924f * 2.82842712474619f;
  430. const float C16_6I = 0.19642373959677554532f * 2.82842712474619f;
  431. const float C16_7R = 0.27330046675043937206f * 2.82842712474619f;
  432. const float C16_7I = 0.22429189658565907106f * 2.82842712474619f;
  433. const float C16_8R = 0.25f * 2.82842712474619f;
  434. const float W16_4R = 0.92387953251128675613f;
  435. const float W16_4I = 0.38268343236508977173f;
  436. const float W16_8R = 0.70710678118654752440f;
  437. static void dct16x16(float[] a, int[] iout, ref int wbits)
  438. {
  439. float[] tmp = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
  440. float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
  441. float x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i;
  442. float xr, xi;
  443. float ftmp;
  444. int fullSize = Constants.TerrainPatchSize * Constants.TerrainPatchSize;
  445. int itmp;
  446. int j, k;
  447. int indx;
  448. const int maxwbits = 17; // per header encoding
  449. int wbitsMaxValue = 1 << wbits;
  450. bool dowbits = wbits < 17;
  451. for (j = 0, k = 0; j < fullSize; j += Constants.TerrainPatchSize, k++)
  452. {
  453. x4r = a[0 + j] - a[15 + j];
  454. xr = a[0 + j] + a[15 + j];
  455. x4i = a[8 + j] - a[7 + j];
  456. xi = a[8 + j] + a[7 + j];
  457. x0r = xr + xi;
  458. x0i = xr - xi;
  459. x5r = a[2 + j] - a[13 + j];
  460. xr = a[2 + j] + a[13 + j];
  461. x5i = a[10 + j] - a[5 + j];
  462. xi = a[10 + j] + a[5 + j];
  463. x1r = xr + xi;
  464. x1i = xr - xi;
  465. x6r = a[4 + j] - a[11 + j];
  466. xr = a[4 + j] + a[11 + j];
  467. x6i = a[12 + j] - a[3 + j];
  468. xi = a[12 + j] + a[3 + j];
  469. x2r = xr + xi;
  470. x2i = xr - xi;
  471. x7r = a[6 + j] - a[9 + j];
  472. xr = a[6 + j] + a[9 + j];
  473. x7i = a[14 + j] - a[1 + j];
  474. xi = a[14 + j] + a[1 + j];
  475. x3r = xr + xi;
  476. x3i = xr - xi;
  477. xr = x0r + x2r;
  478. xi = x1r + x3r;
  479. tmp[k] = C16_8R * (xr + xi); //
  480. tmp[8 * Constants.TerrainPatchSize + k] = C16_8R * (xr - xi); //
  481. xr = x0r - x2r;
  482. xi = x1r - x3r;
  483. tmp[4 * Constants.TerrainPatchSize + k] = C16_4R * xr - C16_4I * xi; //
  484. tmp[12 * Constants.TerrainPatchSize + k] = C16_4R * xi + C16_4I * xr; //
  485. x0r = W16_8R * (x1i - x3i);
  486. x2r = W16_8R * (x1i + x3i);
  487. xr = x0i + x0r;
  488. xi = x2r + x2i;
  489. tmp[2 * Constants.TerrainPatchSize + k] = C16_2R * xr - C16_2I * xi; //
  490. tmp[14 * Constants.TerrainPatchSize + k] = C16_2R * xi + C16_2I * xr; //
  491. xr = x0i - x0r;
  492. xi = x2r - x2i;
  493. tmp[6 * Constants.TerrainPatchSize + k] = C16_6R * xr - C16_6I * xi; //
  494. tmp[10 * Constants.TerrainPatchSize + k] = C16_6R * xi + C16_6I * xr; //
  495. xr = W16_8R * (x6r - x6i);
  496. xi = W16_8R * (x6i + x6r);
  497. x6r = x4r - xr;
  498. x6i = x4i - xi;
  499. x4r += xr;
  500. x4i += xi;
  501. xr = W16_4I * x7r - W16_4R * x7i;
  502. xi = W16_4I * x7i + W16_4R * x7r;
  503. x7r = W16_4R * x5r - W16_4I * x5i;
  504. x7i = W16_4R * x5i + W16_4I * x5r;
  505. x5r = x7r + xr;
  506. x5i = x7i + xi;
  507. x7r -= xr;
  508. x7i -= xi;
  509. xr = x4r + x5r;
  510. xi = x5i + x4i;
  511. tmp[Constants.TerrainPatchSize + k] = C16_1R * xr - C16_1I * xi; //
  512. tmp[15 * Constants.TerrainPatchSize + k] = C16_1R * xi + C16_1I * xr; //
  513. xr = x4r - x5r;
  514. xi = x5i - x4i;
  515. tmp[7 * Constants.TerrainPatchSize + k] = C16_7R * xr - C16_7I * xi; //
  516. tmp[9 * Constants.TerrainPatchSize + k] = C16_7R * xi + C16_7I * xr; //
  517. xr = x6r - x7i;
  518. xi = x7r + x6i;
  519. tmp[5 * Constants.TerrainPatchSize + k] = C16_5R * xr - C16_5I * xi; //
  520. tmp[11 * Constants.TerrainPatchSize + k] = C16_5R * xi + C16_5I * xr; //
  521. xr = x6r + x7i;
  522. xi = x7r - x6i;
  523. tmp[3 * Constants.TerrainPatchSize + k] = C16_3R * xr - C16_3I * xi; //
  524. tmp[13 * Constants.TerrainPatchSize + k] = C16_3R * xi + C16_3I * xr; //
  525. }
  526. for (j = 0, k = 0; j < fullSize; j += Constants.TerrainPatchSize, k++)
  527. {
  528. x4r = tmp[0 + j] - tmp[15 + j];
  529. xr = tmp[0 + j] + tmp[15 + j];
  530. x4i = tmp[8 + j] - tmp[7 + j];
  531. xi = tmp[8 + j] + tmp[7 + j];
  532. x0r = xr + xi;
  533. x0i = xr - xi;
  534. x5r = tmp[2 + j] - tmp[13 + j];
  535. xr = tmp[2 + j] + tmp[13 + j];
  536. x5i = tmp[10 + j] - tmp[5 + j];
  537. xi = tmp[10 + j] + tmp[5 + j];
  538. x1r = xr + xi;
  539. x1i = xr - xi;
  540. x6r = tmp[4 + j] - tmp[11 + j];
  541. xr = tmp[4 + j] + tmp[11 + j];
  542. x6i = tmp[12 + j] - tmp[3 + j];
  543. xi = tmp[12 + j] + tmp[3 + j];
  544. x2r = xr + xi;
  545. x2i = xr - xi;
  546. x7r = tmp[6 + j] - tmp[9 + j];
  547. xr = tmp[6 + j] + tmp[9 + j];
  548. x7i = tmp[14 + j] - tmp[1 + j];
  549. xi = tmp[14 + j] + tmp[1 + j];
  550. x3r = xr + xi;
  551. x3i = xr - xi;
  552. xr = x0r + x2r;
  553. xi = x1r + x3r;
  554. //tmp[0 + k] = C16_8R * (xr + xi); //
  555. ftmp = C16_8R * (xr + xi);
  556. itmp = (int)(ftmp * QuantizeTable16[k]);
  557. iout[CopyMatrix16[k]] = 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[8 * Constants.TerrainPatchSize + k] = C16_8R * (xr - xi); //
  573. ftmp = C16_8R * (xr - xi);
  574. indx = 8 * Constants.TerrainPatchSize + k;
  575. itmp = (int)(ftmp * QuantizeTable16[indx]);
  576. iout[CopyMatrix16[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 = x0r - x2r;
  592. xi = x1r - x3r;
  593. //tmp[4 * Constants.TerrainPatchSize + k] = C16_4R * xr - C16_4I * xi; //
  594. ftmp = C16_4R * xr - C16_4I * xi;
  595. indx = 4 * Constants.TerrainPatchSize + k;
  596. itmp = (int)(ftmp * QuantizeTable16[indx]);
  597. iout[CopyMatrix16[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[12 * Constants.TerrainPatchSize + k] = C16_4R * xi + C16_4I * xr; //
  613. ftmp = C16_4R * xi + C16_4I * xr;
  614. indx = 12 * Constants.TerrainPatchSize + k;
  615. itmp = (int)(ftmp * QuantizeTable16[indx]);
  616. iout[CopyMatrix16[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. x0r = W16_8R * (x1i - x3i);
  632. x2r = W16_8R * (x1i + x3i);
  633. xr = x0i + x0r;
  634. xi = x2r + x2i;
  635. //tmp[2 * Constants.TerrainPatchSize + k] = C16_2R * xr - C16_2I * xi; //
  636. ftmp = C16_2R * xr - C16_2I * xi;
  637. indx = 2 * Constants.TerrainPatchSize + k;
  638. itmp = (int)(ftmp * QuantizeTable16[indx]);
  639. iout[CopyMatrix16[indx]] = itmp;
  640. if (dowbits)
  641. {
  642. if (itmp < 0) itmp *= -1;
  643. while (itmp > wbitsMaxValue)
  644. {
  645. wbits++;
  646. wbitsMaxValue = 1 << wbits;
  647. if (wbits == maxwbits)
  648. {
  649. dowbits = false;
  650. break;
  651. }
  652. }
  653. }
  654. //tmp[14 * Constants.TerrainPatchSize + k] = C16_2R * xi + C16_2I * xr; //
  655. ftmp = C16_2R * xi + C16_2I * xr;
  656. indx = 14 * Constants.TerrainPatchSize + k;
  657. itmp = (int)(ftmp * QuantizeTable16[indx]);
  658. iout[CopyMatrix16[indx]] = itmp;
  659. if (dowbits)
  660. {
  661. if (itmp < 0) itmp *= -1;
  662. while (itmp > wbitsMaxValue)
  663. {
  664. wbits++;
  665. wbitsMaxValue = 1 << wbits;
  666. if (wbits == maxwbits)
  667. {
  668. dowbits = false;
  669. break;
  670. }
  671. }
  672. }
  673. xr = x0i - x0r;
  674. xi = x2r - x2i;
  675. //tmp[6 * Constants.TerrainPatchSize + k] = C16_6R * xr - C16_6I * xi; //
  676. ftmp = C16_6R * xr - C16_6I * xi;
  677. indx = 6 * Constants.TerrainPatchSize + k;
  678. itmp = (int)(ftmp * QuantizeTable16[indx]);
  679. iout[CopyMatrix16[indx]] = itmp;
  680. if (dowbits)
  681. {
  682. if (itmp < 0) itmp *= -1;
  683. while (itmp > wbitsMaxValue)
  684. {
  685. wbits++;
  686. wbitsMaxValue = 1 << wbits;
  687. if (wbits == maxwbits)
  688. {
  689. dowbits = false;
  690. break;
  691. }
  692. }
  693. }
  694. //tmp[10 * Constants.TerrainPatchSize + k] = C16_6R * xi + C16_6I * xr; //
  695. ftmp = C16_6R * xi + C16_6I * xr;
  696. indx = 10 * Constants.TerrainPatchSize + k;
  697. itmp = (int)(ftmp * QuantizeTable16[indx]);
  698. iout[CopyMatrix16[indx]] = itmp;
  699. if (dowbits)
  700. {
  701. if (itmp < 0) itmp *= -1;
  702. while (itmp > wbitsMaxValue)
  703. {
  704. wbits++;
  705. wbitsMaxValue = 1 << wbits;
  706. if (wbits == maxwbits)
  707. {
  708. dowbits = false;
  709. break;
  710. }
  711. }
  712. }
  713. xr = W16_8R * (x6r - x6i);
  714. xi = W16_8R * (x6i + x6r);
  715. x6r = x4r - xr;
  716. x6i = x4i - xi;
  717. x4r += xr;
  718. x4i += xi;
  719. xr = W16_4I * x7r - W16_4R * x7i;
  720. xi = W16_4I * x7i + W16_4R * x7r;
  721. x7r = W16_4R * x5r - W16_4I * x5i;
  722. x7i = W16_4R * x5i + W16_4I * x5r;
  723. x5r = x7r + xr;
  724. x5i = x7i + xi;
  725. x7r -= xr;
  726. x7i -= xi;
  727. xr = x4r + x5r;
  728. xi = x5i + x4i;
  729. //tmp[1 * Constants.TerrainPatchSize + k] = C16_1R * xr - C16_1I * xi; //
  730. ftmp = C16_1R * xr - C16_1I * xi;
  731. indx = Constants.TerrainPatchSize + k;
  732. itmp = (int)(ftmp * QuantizeTable16[indx]);
  733. iout[CopyMatrix16[indx]] = itmp;
  734. if (dowbits)
  735. {
  736. if (itmp < 0) itmp *= -1;
  737. while (itmp > wbitsMaxValue)
  738. {
  739. wbits++;
  740. wbitsMaxValue = 1 << wbits;
  741. if (wbits == maxwbits)
  742. {
  743. dowbits = false;
  744. break;
  745. }
  746. }
  747. }
  748. //tmp[15 * Constants.TerrainPatchSize + k] = C16_1R * xi + C16_1I * xr; //
  749. ftmp = C16_1R * xi + C16_1I * xr;
  750. indx = 15 * Constants.TerrainPatchSize + k;
  751. itmp = (int)(ftmp * QuantizeTable16[indx]);
  752. iout[CopyMatrix16[indx]] = itmp;
  753. if (dowbits)
  754. {
  755. if (itmp < 0) itmp *= -1;
  756. while (itmp > wbitsMaxValue)
  757. {
  758. wbits++;
  759. wbitsMaxValue = 1 << wbits;
  760. if (wbits == maxwbits)
  761. {
  762. dowbits = false;
  763. break;
  764. }
  765. }
  766. }
  767. xr = x4r - x5r;
  768. xi = x5i - x4i;
  769. //tmp[7 * Constants.TerrainPatchSize + k] = C16_7R * xr - C16_7I * xi; //
  770. ftmp = C16_7R * xr - C16_7I * xi;
  771. indx = 7 * Constants.TerrainPatchSize + k;
  772. itmp = (int)(ftmp * QuantizeTable16[indx]);
  773. iout[CopyMatrix16[indx]] = itmp;
  774. if (dowbits)
  775. {
  776. if (itmp < 0) itmp *= -1;
  777. while (itmp > wbitsMaxValue)
  778. {
  779. wbits++;
  780. wbitsMaxValue = 1 << wbits;
  781. if (wbits == maxwbits)
  782. {
  783. dowbits = false;
  784. break;
  785. }
  786. }
  787. }
  788. //tmp[9 * Constants.TerrainPatchSize + k] = C16_7R * xi + C16_7I * xr; //
  789. ftmp = C16_7R * xi + C16_7I * xr;
  790. indx = 9 * Constants.TerrainPatchSize + k;
  791. itmp = (int)(ftmp * QuantizeTable16[indx]);
  792. iout[CopyMatrix16[indx]] = itmp;
  793. if (dowbits)
  794. {
  795. if (itmp < 0) itmp *= -1;
  796. while (itmp > wbitsMaxValue)
  797. {
  798. wbits++;
  799. wbitsMaxValue = 1 << wbits;
  800. if (wbits == maxwbits)
  801. {
  802. dowbits = false;
  803. break;
  804. }
  805. }
  806. }
  807. xr = x6r - x7i;
  808. xi = x7r + x6i;
  809. //tmp[5 * Constants.TerrainPatchSize + k] = C16_5R * xr - C16_5I * xi; //
  810. ftmp = C16_5R * xr - C16_5I * xi;
  811. indx = 5 * Constants.TerrainPatchSize + k;
  812. itmp = (int)(ftmp * QuantizeTable16[indx]);
  813. iout[CopyMatrix16[indx]] = itmp;
  814. if (dowbits)
  815. {
  816. if (itmp < 0) itmp *= -1;
  817. while (itmp > wbitsMaxValue)
  818. {
  819. wbits++;
  820. wbitsMaxValue = 1 << wbits;
  821. if (wbits == maxwbits)
  822. {
  823. dowbits = false;
  824. break;
  825. }
  826. }
  827. }
  828. //tmp[11 * Constants.TerrainPatchSize + k] = C16_5R * xi + C16_5I * xr; //
  829. ftmp = C16_5R * xi + C16_5I * xr;
  830. indx = 11 * Constants.TerrainPatchSize + k;
  831. itmp = (int)(ftmp * QuantizeTable16[indx]);
  832. iout[CopyMatrix16[indx]] = itmp;
  833. if (dowbits)
  834. {
  835. if (itmp < 0) itmp *= -1;
  836. while (itmp > wbitsMaxValue)
  837. {
  838. wbits++;
  839. wbitsMaxValue = 1 << wbits;
  840. if (wbits == maxwbits)
  841. {
  842. dowbits = false;
  843. break;
  844. }
  845. }
  846. }
  847. xr = x6r + x7i;
  848. xi = x7r - x6i;
  849. //tmp[3 * Constants.TerrainPatchSize + k] = C16_3R * xr - C16_3I * xi; //
  850. ftmp = C16_3R * xr - C16_3I * xi;
  851. indx = 3 * Constants.TerrainPatchSize + k;
  852. itmp = (int)(ftmp * QuantizeTable16[indx]);
  853. iout[CopyMatrix16[indx]] = itmp;
  854. if (dowbits)
  855. {
  856. if (itmp < 0) itmp *= -1;
  857. while (itmp > wbitsMaxValue)
  858. {
  859. wbits++;
  860. wbitsMaxValue = 1 << wbits;
  861. if (wbits == maxwbits)
  862. {
  863. dowbits = false;
  864. break;
  865. }
  866. }
  867. }
  868. //tmp[13 * Constants.TerrainPatchSize + k] = C16_3R * xi + C16_3I * xr; //
  869. ftmp = C16_3R * xi + C16_3I * xr;
  870. indx = 13 * Constants.TerrainPatchSize + k;
  871. itmp = (int)(ftmp * QuantizeTable16[indx]);
  872. iout[CopyMatrix16[indx]] = itmp;
  873. if (dowbits)
  874. {
  875. if (itmp < 0) itmp *= -1;
  876. while (itmp > wbitsMaxValue)
  877. {
  878. wbits++;
  879. wbitsMaxValue = 1 << wbits;
  880. if (wbits == maxwbits)
  881. {
  882. dowbits = false;
  883. break;
  884. }
  885. }
  886. }
  887. }
  888. }
  889. #endregion DCT
  890. #region Decode
  891. /*
  892. public static TerrainPatch.Header DecodePatchHeader(BitPack bitpack)
  893. {
  894. TerrainPatch.Header header = new TerrainPatch.Header { QuantWBits = bitpack.UnpackBits(8) };
  895. // Quantized word bits
  896. if (header.QuantWBits == END_OF_PATCHES)
  897. return header;
  898. // DC offset
  899. header.DCOffset = bitpack.UnpackFloat();
  900. // Range
  901. header.Range = bitpack.UnpackBits(16);
  902. // Patch IDs (10 bits)
  903. header.PatchIDs = bitpack.UnpackBits(10);
  904. // Word bits
  905. header.WordBits = (uint)((header.QuantWBits & 0x0f) + 2);
  906. return header;
  907. }
  908. */
  909. /*
  910. public static void DecodePatch(int[] patches, BitPack bitpack, TerrainPatch.Header header, int size)
  911. {
  912. for (int n = 0; n < size * size; n++)
  913. {
  914. // ?
  915. int temp = bitpack.UnpackBits(1);
  916. if (temp != 0)
  917. {
  918. // Value or EOB
  919. temp = bitpack.UnpackBits(1);
  920. if (temp != 0)
  921. {
  922. // Value
  923. temp = bitpack.UnpackBits(1);
  924. if (temp != 0)
  925. {
  926. // Negative
  927. temp = bitpack.UnpackBits((int)header.WordBits);
  928. patches[n] = temp * -1;
  929. }
  930. else
  931. {
  932. // Positive
  933. temp = bitpack.UnpackBits((int)header.WordBits);
  934. patches[n] = temp;
  935. }
  936. }
  937. else
  938. {
  939. // Set the rest to zero
  940. // TODO: This might not be necessary
  941. for (int o = n; o < size * size; o++)
  942. {
  943. patches[o] = 0;
  944. }
  945. break;
  946. }
  947. }
  948. else
  949. {
  950. patches[n] = 0;
  951. }
  952. }
  953. }
  954. */
  955. #region IDCT
  956. /* not in use
  957. private static void IDCTColumn16(float[] linein, float[] lineout, int column)
  958. {
  959. for (int n = 0; n < Constants.TerrainPatchSize; n++)
  960. {
  961. float total = OO_SQRT2 * linein[column];
  962. for (int u = 1; u < Constants.TerrainPatchSize; u++)
  963. {
  964. int usize = u * Constants.TerrainPatchSize;
  965. total += linein[usize + column] * CosineTable16[usize + n];
  966. }
  967. lineout[Constants.TerrainPatchSize * n + column] = total;
  968. }
  969. }
  970. private static void IDCTLine16(float[] linein, float[] lineout, int line)
  971. {
  972. const float oosob = 2.0f / Constants.TerrainPatchSize;
  973. int lineSize = line * Constants.TerrainPatchSize;
  974. for (int n = 0; n < Constants.TerrainPatchSize; n++)
  975. {
  976. float total = OO_SQRT2 * linein[lineSize];
  977. for (int u = 1; u < Constants.TerrainPatchSize; u++)
  978. {
  979. total += linein[lineSize + u] * CosineTable16[u * Constants.TerrainPatchSize + n];
  980. }
  981. lineout[lineSize + n] = total * oosob;
  982. }
  983. }
  984. /*
  985. private static void SetupCosines16()
  986. {
  987. const float hposz = (float)Math.PI * 0.5f / Constants.TerrainPatchSize;
  988. for (int u = 0; u < Constants.TerrainPatchSize; u++)
  989. {
  990. for (int n = 0; n < Constants.TerrainPatchSize; n++)
  991. {
  992. CosineTable16[u * Constants.TerrainPatchSize + n] = (float)Math.Cos((2.0f * n + 1.0f) * u * hposz);
  993. }
  994. }
  995. }
  996. */
  997. //not in use, and still not fixed
  998. /*
  999. static void idct16x16(float[] a)
  1000. {
  1001. int j;
  1002. float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
  1003. float x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i;
  1004. float xr, xi;
  1005. int fullSize = Constants.TerrainPatchSize * Constants.TerrainPatchSize;
  1006. for (j = 0; j < fullSize; j += Constants.TerrainPatchSize)
  1007. {
  1008. x5r = C16_1R * tmp[1 + j] + C16_1I * tmp[15 + j];
  1009. x5i = C16_1R * tmp[15 + j] - C16_1I * tmp[1 + j];
  1010. xr = C16_7R * tmp[7 + j] + C16_7I * tmp[9 + j];
  1011. xi = C16_7R * tmp[9 + j] - C16_7I * tmp[7 + j];
  1012. x4r = x5r + xr;
  1013. x4i = x5i - xi;
  1014. x5r -= xr;
  1015. x5i += xi;
  1016. x7r = C16_5R * tmp[5 + j] + C16_5I * tmp[11 + j];
  1017. x7i = C16_5R * tmp[11 + j] - C16_5I * tmp[5 + j];
  1018. xr = C16_3R * tmp[3 + j] + C16_3I * tmp[13 + j];
  1019. xi = C16_3R * tmp[13 + j] - C16_3I * tmp[3 + j];
  1020. x6r = x7r + xr;
  1021. x6i = x7i - xi;
  1022. x7r -= xr;
  1023. x7i += xi;
  1024. xr = x4r - x6r;
  1025. xi = x4i - x6i;
  1026. x4r += x6r;
  1027. x4i += x6i;
  1028. x6r = W16_8R * (xi + xr);
  1029. x6i = W16_8R * (xi - xr);
  1030. xr = x5r + x7i;
  1031. xi = x5i - x7r;
  1032. x5r -= x7i;
  1033. x5i += x7r;
  1034. x7r = W16_4I * x5r + W16_4R * x5i;
  1035. x7i = W16_4I * x5i - W16_4R * x5r;
  1036. x5r = W16_4R * xr + W16_4I * xi;
  1037. x5i = W16_4R * xi - W16_4I * xr;
  1038. xr = C16_4R * tmp[4 + j] + C16_4I * tmp[12 + j];
  1039. xi = C16_4R * tmp[12 + j] - C16_4I * tmp[4 + j];
  1040. x2r = C16_8R * (tmp[0 + j] + tmp[8 + j]);
  1041. x3r = C16_8R * (tmp[0 + j] - tmp[8 + j]);
  1042. x0r = x2r + xr;
  1043. x1r = x3r + xi;
  1044. x2r -= xr;
  1045. x3r -= xi;
  1046. x0i = C16_2R * tmp[2 + j] + C16_2I * tmp[14 + j];
  1047. x2i = C16_2R * tmp[14 + j] - C16_2I * tmp[2 + j];
  1048. x1i = C16_6R * tmp[6 + j] + C16_6I * tmp[10 + j];
  1049. x3i = C16_6R * tmp[10 + j] - C16_6I * tmp[6 + j];
  1050. xr = x0i - x1i;
  1051. xi = x2i + x3i;
  1052. x0i += x1i;
  1053. x2i -= x3i;
  1054. x1i = W16_8R * (xi + xr);
  1055. x3i = W16_8R * (xi - xr);
  1056. xr = x0r + x0i;
  1057. xi = x0r - x0i;
  1058. tmp[0 + j] = xr + x4r;
  1059. tmp[15 + j] = xr - x4r;
  1060. tmp[8 + j] = xi + x4i;
  1061. tmp[7 + j] = xi - x4i;
  1062. xr = x1r + x1i;
  1063. xi = x1r - x1i;
  1064. tmp[2 + j] = xr + x5r;
  1065. tmp[13 + j] = xr - x5r;
  1066. tmp[10 + j] = xi + x5i;
  1067. tmp[5 + j] = xi - x5i;
  1068. xr = x2r + x2i;
  1069. xi = x2r - x2i;
  1070. tmp[4 + j] = xr + x6r;
  1071. tmp[11 + j] = xr - x6r;
  1072. tmp[12 + j] = xi + x6i;
  1073. tmp[3 + j] = xi - x6i;
  1074. xr = x3r + x3i;
  1075. xi = x3r - x3i;
  1076. tmp[6 + j] = xr + x7r;
  1077. tmp[9 + j] = xr - x7r;
  1078. tmp[14 + j] = xi + x7i;
  1079. tmp[1 + j] = xi - x7i;
  1080. }
  1081. for (j = 0; j < fullSize; j += Constants.TerrainPatchSize)
  1082. {
  1083. x5r = C16_1R * tmp[j + 1] + C16_1I * tmp[j + 15];
  1084. x5i = C16_1R * tmp[j + 15] - C16_1I * tmp[j + 1];
  1085. xr = C16_7R * tmp[j + 7] + C16_7I * tmp[j + 9];
  1086. xi = C16_7R * tmp[j + 9] - C16_7I * tmp[j + 7];
  1087. x4r = x5r + xr;
  1088. x4i = x5i - xi;
  1089. x5r -= xr;
  1090. x5i += xi;
  1091. x7r = C16_5R * tmp[j + 5] + C16_5I * tmp[j + 11];
  1092. x7i = C16_5R * tmp[j + 11] - C16_5I * tmp[j + 5];
  1093. xr = C16_3R * tmp[j + 3] + C16_3I * tmp[j + 13];
  1094. xi = C16_3R * tmp[j + 13] - C16_3I * tmp[j + 3];
  1095. x6r = x7r + xr;
  1096. x6i = x7i - xi;
  1097. x7r -= xr;
  1098. x7i += xi;
  1099. xr = x4r - x6r;
  1100. xi = x4i - x6i;
  1101. x4r += x6r;
  1102. x4i += x6i;
  1103. x6r = W16_8R * (xi + xr);
  1104. x6i = W16_8R * (xi - xr);
  1105. xr = x5r + x7i;
  1106. xi = x5i - x7r;
  1107. x5r -= x7i;
  1108. x5i += x7r;
  1109. x7r = W16_4I * x5r + W16_4R * x5i;
  1110. x7i = W16_4I * x5i - W16_4R * x5r;
  1111. x5r = W16_4R * xr + W16_4I * xi;
  1112. x5i = W16_4R * xi - W16_4I * xr;
  1113. xr = C16_4R * tmp[j + 4] + C16_4I * tmp[j + 12];
  1114. xi = C16_4R * tmp[j + 12] - C16_4I * tmp[j + 4];
  1115. x2r = C16_8R * (tmp[j + 0] + tmp[j + 8]);
  1116. x3r = C16_8R * (tmp[j + 0] - tmp[j + 8]);
  1117. x0r = x2r + xr;
  1118. x1r = x3r + xi;
  1119. x2r -= xr;
  1120. x3r -= xi;
  1121. x0i = C16_2R * tmp[j + 2] + C16_2I * tmp[j + 14];
  1122. x2i = C16_2R * tmp[j + 14] - C16_2I * tmp[j + 2];
  1123. x1i = C16_6R * tmp[j + 6] + C16_6I * tmp[j + 10];
  1124. x3i = C16_6R * tmp[j + 10] - C16_6I * tmp[j + 6];
  1125. xr = x0i - x1i;
  1126. xi = x2i + x3i;
  1127. x0i += x1i;
  1128. x2i -= x3i;
  1129. x1i = W16_8R * (xi + xr);
  1130. x3i = W16_8R * (xi - xr);
  1131. xr = x0r + x0i;
  1132. xi = x0r - x0i;
  1133. tmp[j + 0] = xr + x4r;
  1134. tmp[j + 15] = xr - x4r;
  1135. tmp[j + 8] = xi + x4i;
  1136. tmp[j + 7] = xi - x4i;
  1137. xr = x1r + x1i;
  1138. xi = x1r - x1i;
  1139. tmp[j + 2] = xr + x5r;
  1140. tmp[j + 13] = xr - x5r;
  1141. tmp[j + 10] = xi + x5i;
  1142. tmp[j + 5] = xi - x5i;
  1143. xr = x2r + x2i;
  1144. xi = x2r - x2i;
  1145. tmp[j + 4] = xr + x6r;
  1146. tmp[j + 11] = xr - x6r;
  1147. tmp[j + 12] = xi + x6i;
  1148. tmp[j + 3] = xi - x6i;
  1149. xr = x3r + x3i;
  1150. xi = x3r - x3i;
  1151. tmp[j + 6] = xr + x7r;
  1152. tmp[j + 9] = xr - x7r;
  1153. tmp[j + 14] = xi + x7i;
  1154. tmp[j + 1] = xi - x7i;
  1155. }
  1156. }
  1157. */
  1158. #endregion IDCT
  1159. #endregion Decode
  1160. }
  1161. }