AttributeCompression-87682214.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. /* This file is automatically rebuilt by the Cesium build process. */
  2. define(['exports', './defined-26bd4a03', './Check-da037458', './Math-fa6e45cb', './Cartesian2-2a723276'], function (exports, defined, Check, _Math, Cartesian2) { 'use strict';
  3. var RIGHT_SHIFT = 1.0 / 256.0;
  4. var LEFT_SHIFT = 256.0;
  5. /**
  6. * Attribute compression and decompression functions.
  7. *
  8. * @exports AttributeCompression
  9. *
  10. * @private
  11. */
  12. var AttributeCompression = {};
  13. /**
  14. * Encodes a normalized vector into 2 SNORM values in the range of [0-rangeMax] following the 'oct' encoding.
  15. *
  16. * Oct encoding is a compact representation of unit length vectors.
  17. * The 'oct' encoding is described in "A Survey of Efficient Representations of Independent Unit Vectors",
  18. * Cigolle et al 2014: {@link http://jcgt.org/published/0003/02/01/}
  19. *
  20. * @param {Cartesian3} vector The normalized vector to be compressed into 2 component 'oct' encoding.
  21. * @param {Cartesian2} result The 2 component oct-encoded unit length vector.
  22. * @param {Number} rangeMax The maximum value of the SNORM range. The encoded vector is stored in log2(rangeMax+1) bits.
  23. * @returns {Cartesian2} The 2 component oct-encoded unit length vector.
  24. *
  25. * @exception {DeveloperError} vector must be normalized.
  26. *
  27. * @see AttributeCompression.octDecodeInRange
  28. */
  29. AttributeCompression.octEncodeInRange = function(vector, rangeMax, result) {
  30. //>>includeStart('debug', pragmas.debug);
  31. Check.Check.defined('vector', vector);
  32. Check.Check.defined('result', result);
  33. var magSquared = Cartesian2.Cartesian3.magnitudeSquared(vector);
  34. if (Math.abs(magSquared - 1.0) > _Math.CesiumMath.EPSILON6) {
  35. throw new Check.DeveloperError('vector must be normalized.');
  36. }
  37. //>>includeEnd('debug');
  38. result.x = vector.x / (Math.abs(vector.x) + Math.abs(vector.y) + Math.abs(vector.z));
  39. result.y = vector.y / (Math.abs(vector.x) + Math.abs(vector.y) + Math.abs(vector.z));
  40. if (vector.z < 0) {
  41. var x = result.x;
  42. var y = result.y;
  43. result.x = (1.0 - Math.abs(y)) * _Math.CesiumMath.signNotZero(x);
  44. result.y = (1.0 - Math.abs(x)) * _Math.CesiumMath.signNotZero(y);
  45. }
  46. result.x = _Math.CesiumMath.toSNorm(result.x, rangeMax);
  47. result.y = _Math.CesiumMath.toSNorm(result.y, rangeMax);
  48. return result;
  49. };
  50. /**
  51. * Encodes a normalized vector into 2 SNORM values in the range of [0-255] following the 'oct' encoding.
  52. *
  53. * @param {Cartesian3} vector The normalized vector to be compressed into 2 byte 'oct' encoding.
  54. * @param {Cartesian2} result The 2 byte oct-encoded unit length vector.
  55. * @returns {Cartesian2} The 2 byte oct-encoded unit length vector.
  56. *
  57. * @exception {DeveloperError} vector must be normalized.
  58. *
  59. * @see AttributeCompression.octEncodeInRange
  60. * @see AttributeCompression.octDecode
  61. */
  62. AttributeCompression.octEncode = function(vector, result) {
  63. return AttributeCompression.octEncodeInRange(vector, 255, result);
  64. };
  65. var octEncodeScratch = new Cartesian2.Cartesian2();
  66. var uint8ForceArray = new Uint8Array(1);
  67. function forceUint8(value) {
  68. uint8ForceArray[0] = value;
  69. return uint8ForceArray[0];
  70. }
  71. /**
  72. * @param {Cartesian3} vector The normalized vector to be compressed into 4 byte 'oct' encoding.
  73. * @param {Cartesian4} result The 4 byte oct-encoded unit length vector.
  74. * @returns {Cartesian4} The 4 byte oct-encoded unit length vector.
  75. *
  76. * @exception {DeveloperError} vector must be normalized.
  77. *
  78. * @see AttributeCompression.octEncodeInRange
  79. * @see AttributeCompression.octDecodeFromCartesian4
  80. */
  81. AttributeCompression.octEncodeToCartesian4 = function(vector, result) {
  82. AttributeCompression.octEncodeInRange(vector, 65535, octEncodeScratch);
  83. result.x = forceUint8(octEncodeScratch.x * RIGHT_SHIFT);
  84. result.y = forceUint8(octEncodeScratch.x);
  85. result.z = forceUint8(octEncodeScratch.y * RIGHT_SHIFT);
  86. result.w = forceUint8(octEncodeScratch.y);
  87. return result;
  88. };
  89. /**
  90. * Decodes a unit-length vector in 'oct' encoding to a normalized 3-component vector.
  91. *
  92. * @param {Number} x The x component of the oct-encoded unit length vector.
  93. * @param {Number} y The y component of the oct-encoded unit length vector.
  94. * @param {Number} rangeMax The maximum value of the SNORM range. The encoded vector is stored in log2(rangeMax+1) bits.
  95. * @param {Cartesian3} result The decoded and normalized vector
  96. * @returns {Cartesian3} The decoded and normalized vector.
  97. *
  98. * @exception {DeveloperError} x and y must be unsigned normalized integers between 0 and rangeMax.
  99. *
  100. * @see AttributeCompression.octEncodeInRange
  101. */
  102. AttributeCompression.octDecodeInRange = function(x, y, rangeMax, result) {
  103. //>>includeStart('debug', pragmas.debug);
  104. Check.Check.defined('result', result);
  105. if (x < 0 || x > rangeMax || y < 0 || y > rangeMax) {
  106. throw new Check.DeveloperError('x and y must be unsigned normalized integers between 0 and ' + rangeMax);
  107. }
  108. //>>includeEnd('debug');
  109. result.x = _Math.CesiumMath.fromSNorm(x, rangeMax);
  110. result.y = _Math.CesiumMath.fromSNorm(y, rangeMax);
  111. result.z = 1.0 - (Math.abs(result.x) + Math.abs(result.y));
  112. if (result.z < 0.0)
  113. {
  114. var oldVX = result.x;
  115. result.x = (1.0 - Math.abs(result.y)) * _Math.CesiumMath.signNotZero(oldVX);
  116. result.y = (1.0 - Math.abs(oldVX)) * _Math.CesiumMath.signNotZero(result.y);
  117. }
  118. return Cartesian2.Cartesian3.normalize(result, result);
  119. };
  120. /**
  121. * Decodes a unit-length vector in 2 byte 'oct' encoding to a normalized 3-component vector.
  122. *
  123. * @param {Number} x The x component of the oct-encoded unit length vector.
  124. * @param {Number} y The y component of the oct-encoded unit length vector.
  125. * @param {Cartesian3} result The decoded and normalized vector.
  126. * @returns {Cartesian3} The decoded and normalized vector.
  127. *
  128. * @exception {DeveloperError} x and y must be an unsigned normalized integer between 0 and 255.
  129. *
  130. * @see AttributeCompression.octDecodeInRange
  131. */
  132. AttributeCompression.octDecode = function(x, y, result) {
  133. return AttributeCompression.octDecodeInRange(x, y, 255, result);
  134. };
  135. /**
  136. * Decodes a unit-length vector in 4 byte 'oct' encoding to a normalized 3-component vector.
  137. *
  138. * @param {Cartesian4} encoded The oct-encoded unit length vector.
  139. * @param {Cartesian3} result The decoded and normalized vector.
  140. * @returns {Cartesian3} The decoded and normalized vector.
  141. *
  142. * @exception {DeveloperError} x, y, z, and w must be unsigned normalized integers between 0 and 255.
  143. *
  144. * @see AttributeCompression.octDecodeInRange
  145. * @see AttributeCompression.octEncodeToCartesian4
  146. */
  147. AttributeCompression.octDecodeFromCartesian4 = function(encoded, result) {
  148. //>>includeStart('debug', pragmas.debug);
  149. Check.Check.typeOf.object('encoded', encoded);
  150. Check.Check.typeOf.object('result', result);
  151. //>>includeEnd('debug');
  152. var x = encoded.x;
  153. var y = encoded.y;
  154. var z = encoded.z;
  155. var w = encoded.w;
  156. //>>includeStart('debug', pragmas.debug);
  157. if (x < 0 || x > 255 || y < 0 || y > 255 || z < 0 || z > 255 || w < 0 || w > 255) {
  158. throw new Check.DeveloperError('x, y, z, and w must be unsigned normalized integers between 0 and 255');
  159. }
  160. //>>includeEnd('debug');
  161. var xOct16 = x * LEFT_SHIFT + y;
  162. var yOct16 = z * LEFT_SHIFT + w;
  163. return AttributeCompression.octDecodeInRange(xOct16, yOct16, 65535, result);
  164. };
  165. /**
  166. * Packs an oct encoded vector into a single floating-point number.
  167. *
  168. * @param {Cartesian2} encoded The oct encoded vector.
  169. * @returns {Number} The oct encoded vector packed into a single float.
  170. *
  171. */
  172. AttributeCompression.octPackFloat = function(encoded) {
  173. //>>includeStart('debug', pragmas.debug);
  174. Check.Check.defined('encoded', encoded);
  175. //>>includeEnd('debug');
  176. return 256.0 * encoded.x + encoded.y;
  177. };
  178. var scratchEncodeCart2 = new Cartesian2.Cartesian2();
  179. /**
  180. * Encodes a normalized vector into 2 SNORM values in the range of [0-255] following the 'oct' encoding and
  181. * stores those values in a single float-point number.
  182. *
  183. * @param {Cartesian3} vector The normalized vector to be compressed into 2 byte 'oct' encoding.
  184. * @returns {Number} The 2 byte oct-encoded unit length vector.
  185. *
  186. * @exception {DeveloperError} vector must be normalized.
  187. */
  188. AttributeCompression.octEncodeFloat = function(vector) {
  189. AttributeCompression.octEncode(vector, scratchEncodeCart2);
  190. return AttributeCompression.octPackFloat(scratchEncodeCart2);
  191. };
  192. /**
  193. * Decodes a unit-length vector in 'oct' encoding packed in a floating-point number to a normalized 3-component vector.
  194. *
  195. * @param {Number} value The oct-encoded unit length vector stored as a single floating-point number.
  196. * @param {Cartesian3} result The decoded and normalized vector
  197. * @returns {Cartesian3} The decoded and normalized vector.
  198. *
  199. */
  200. AttributeCompression.octDecodeFloat = function(value, result) {
  201. //>>includeStart('debug', pragmas.debug);
  202. Check.Check.defined('value', value);
  203. //>>includeEnd('debug');
  204. var temp = value / 256.0;
  205. var x = Math.floor(temp);
  206. var y = (temp - x) * 256.0;
  207. return AttributeCompression.octDecode(x, y, result);
  208. };
  209. /**
  210. * Encodes three normalized vectors into 6 SNORM values in the range of [0-255] following the 'oct' encoding and
  211. * packs those into two floating-point numbers.
  212. *
  213. * @param {Cartesian3} v1 A normalized vector to be compressed.
  214. * @param {Cartesian3} v2 A normalized vector to be compressed.
  215. * @param {Cartesian3} v3 A normalized vector to be compressed.
  216. * @param {Cartesian2} result The 'oct' encoded vectors packed into two floating-point numbers.
  217. * @returns {Cartesian2} The 'oct' encoded vectors packed into two floating-point numbers.
  218. *
  219. */
  220. AttributeCompression.octPack = function(v1, v2, v3, result) {
  221. //>>includeStart('debug', pragmas.debug);
  222. Check.Check.defined('v1', v1);
  223. Check.Check.defined('v2', v2);
  224. Check.Check.defined('v3', v3);
  225. Check.Check.defined('result', result);
  226. //>>includeEnd('debug');
  227. var encoded1 = AttributeCompression.octEncodeFloat(v1);
  228. var encoded2 = AttributeCompression.octEncodeFloat(v2);
  229. var encoded3 = AttributeCompression.octEncode(v3, scratchEncodeCart2);
  230. result.x = 65536.0 * encoded3.x + encoded1;
  231. result.y = 65536.0 * encoded3.y + encoded2;
  232. return result;
  233. };
  234. /**
  235. * Decodes three unit-length vectors in 'oct' encoding packed into a floating-point number to a normalized 3-component vector.
  236. *
  237. * @param {Cartesian2} packed The three oct-encoded unit length vectors stored as two floating-point number.
  238. * @param {Cartesian3} v1 One decoded and normalized vector.
  239. * @param {Cartesian3} v2 One decoded and normalized vector.
  240. * @param {Cartesian3} v3 One decoded and normalized vector.
  241. */
  242. AttributeCompression.octUnpack = function(packed, v1, v2, v3) {
  243. //>>includeStart('debug', pragmas.debug);
  244. Check.Check.defined('packed', packed);
  245. Check.Check.defined('v1', v1);
  246. Check.Check.defined('v2', v2);
  247. Check.Check.defined('v3', v3);
  248. //>>includeEnd('debug');
  249. var temp = packed.x / 65536.0;
  250. var x = Math.floor(temp);
  251. var encodedFloat1 = (temp - x) * 65536.0;
  252. temp = packed.y / 65536.0;
  253. var y = Math.floor(temp);
  254. var encodedFloat2 = (temp - y) * 65536.0;
  255. AttributeCompression.octDecodeFloat(encodedFloat1, v1);
  256. AttributeCompression.octDecodeFloat(encodedFloat2, v2);
  257. AttributeCompression.octDecode(x, y, v3);
  258. };
  259. /**
  260. * Pack texture coordinates into a single float. The texture coordinates will only preserve 12 bits of precision.
  261. *
  262. * @param {Cartesian2} textureCoordinates The texture coordinates to compress. Both coordinates must be in the range 0.0-1.0.
  263. * @returns {Number} The packed texture coordinates.
  264. *
  265. */
  266. AttributeCompression.compressTextureCoordinates = function(textureCoordinates) {
  267. //>>includeStart('debug', pragmas.debug);
  268. Check.Check.defined('textureCoordinates', textureCoordinates);
  269. //>>includeEnd('debug');
  270. // Move x and y to the range 0-4095;
  271. var x = (textureCoordinates.x * 4095.0) | 0;
  272. var y = (textureCoordinates.y * 4095.0) | 0;
  273. return 4096.0 * x + y;
  274. };
  275. /**
  276. * Decompresses texture coordinates that were packed into a single float.
  277. *
  278. * @param {Number} compressed The compressed texture coordinates.
  279. * @param {Cartesian2} result The decompressed texture coordinates.
  280. * @returns {Cartesian2} The modified result parameter.
  281. *
  282. */
  283. AttributeCompression.decompressTextureCoordinates = function(compressed, result) {
  284. //>>includeStart('debug', pragmas.debug);
  285. Check.Check.defined('compressed', compressed);
  286. Check.Check.defined('result', result);
  287. //>>includeEnd('debug');
  288. var temp = compressed / 4096.0;
  289. var xZeroTo4095 = Math.floor(temp);
  290. result.x = xZeroTo4095 / 4095.0;
  291. result.y = (compressed - xZeroTo4095 * 4096) / 4095;
  292. return result;
  293. };
  294. function zigZagDecode(value) {
  295. return (value >> 1) ^ (-(value & 1));
  296. }
  297. /**
  298. * Decodes delta and ZigZag encoded vertices. This modifies the buffers in place.
  299. *
  300. * @param {Uint16Array} uBuffer The buffer view of u values.
  301. * @param {Uint16Array} vBuffer The buffer view of v values.
  302. * @param {Uint16Array} [heightBuffer] The buffer view of height values.
  303. *
  304. * @see {@link https://github.com/AnalyticalGraphicsInc/quantized-mesh|quantized-mesh-1.0 terrain format}
  305. */
  306. AttributeCompression.zigZagDeltaDecode = function(uBuffer, vBuffer, heightBuffer) {
  307. //>>includeStart('debug', pragmas.debug);
  308. Check.Check.defined('uBuffer', uBuffer);
  309. Check.Check.defined('vBuffer', vBuffer);
  310. Check.Check.typeOf.number.equals('uBuffer.length', 'vBuffer.length', uBuffer.length, vBuffer.length);
  311. if (defined.defined(heightBuffer)) {
  312. Check.Check.typeOf.number.equals('uBuffer.length', 'heightBuffer.length', uBuffer.length, heightBuffer.length);
  313. }
  314. //>>includeEnd('debug');
  315. var count = uBuffer.length;
  316. var u = 0;
  317. var v = 0;
  318. var height = 0;
  319. for (var i = 0; i < count; ++i) {
  320. u += zigZagDecode(uBuffer[i]);
  321. v += zigZagDecode(vBuffer[i]);
  322. uBuffer[i] = u;
  323. vBuffer[i] = v;
  324. if (defined.defined(heightBuffer)) {
  325. height += zigZagDecode(heightBuffer[i]);
  326. heightBuffer[i] = height;
  327. }
  328. }
  329. };
  330. exports.AttributeCompression = AttributeCompression;
  331. });