createVectorTileClampedPolylines.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  1. /* This file is automatically rebuilt by the Cesium build process. */
  2. define(['./AttributeCompression-3cfab808', './Matrix2-69c32d33', './combine-761d9c3f', './IndexDatatype-c4099fe9', './ComponentDatatype-b1ea011a', './createTaskProcessorWorker', './RuntimeError-c581ca93', './defaultValue-94c3e563', './WebGLConstants-7dccdc96'], (function (AttributeCompression, Matrix2, combine, IndexDatatype, ComponentDatatype, createTaskProcessorWorker, RuntimeError, defaultValue, WebGLConstants) { 'use strict';
  3. const MAX_SHORT = 32767;
  4. const MITER_BREAK = Math.cos(ComponentDatatype.CesiumMath.toRadians(150.0));
  5. const scratchBVCartographic = new Matrix2.Cartographic();
  6. const scratchEncodedPosition = new Matrix2.Cartesian3();
  7. function decodePositions(
  8. uBuffer,
  9. vBuffer,
  10. heightBuffer,
  11. rectangle,
  12. minimumHeight,
  13. maximumHeight,
  14. ellipsoid
  15. ) {
  16. const positionsLength = uBuffer.length;
  17. const decodedPositions = new Float64Array(positionsLength * 3);
  18. for (let i = 0; i < positionsLength; ++i) {
  19. const u = uBuffer[i];
  20. const v = vBuffer[i];
  21. const h = heightBuffer[i];
  22. const lon = ComponentDatatype.CesiumMath.lerp(rectangle.west, rectangle.east, u / MAX_SHORT);
  23. const lat = ComponentDatatype.CesiumMath.lerp(
  24. rectangle.south,
  25. rectangle.north,
  26. v / MAX_SHORT
  27. );
  28. const alt = ComponentDatatype.CesiumMath.lerp(minimumHeight, maximumHeight, h / MAX_SHORT);
  29. const cartographic = Matrix2.Cartographic.fromRadians(
  30. lon,
  31. lat,
  32. alt,
  33. scratchBVCartographic
  34. );
  35. const decodedPosition = ellipsoid.cartographicToCartesian(
  36. cartographic,
  37. scratchEncodedPosition
  38. );
  39. Matrix2.Cartesian3.pack(decodedPosition, decodedPositions, i * 3);
  40. }
  41. return decodedPositions;
  42. }
  43. function getPositionOffsets(counts) {
  44. const countsLength = counts.length;
  45. const positionOffsets = new Uint32Array(countsLength + 1);
  46. let offset = 0;
  47. for (let i = 0; i < countsLength; ++i) {
  48. positionOffsets[i] = offset;
  49. offset += counts[i];
  50. }
  51. positionOffsets[countsLength] = offset;
  52. return positionOffsets;
  53. }
  54. const previousCompressedCartographicScratch = new Matrix2.Cartographic();
  55. const currentCompressedCartographicScratch = new Matrix2.Cartographic();
  56. function removeDuplicates(uBuffer, vBuffer, heightBuffer, counts) {
  57. const countsLength = counts.length;
  58. const positionsLength = uBuffer.length;
  59. const markRemoval = new Uint8Array(positionsLength);
  60. const previous = previousCompressedCartographicScratch;
  61. const current = currentCompressedCartographicScratch;
  62. let offset = 0;
  63. for (let i = 0; i < countsLength; i++) {
  64. const count = counts[i];
  65. let updatedCount = count;
  66. for (let j = 1; j < count; j++) {
  67. const index = offset + j;
  68. const previousIndex = index - 1;
  69. current.longitude = uBuffer[index];
  70. current.latitude = vBuffer[index];
  71. previous.longitude = uBuffer[previousIndex];
  72. previous.latitude = vBuffer[previousIndex];
  73. if (Matrix2.Cartographic.equals(current, previous)) {
  74. updatedCount--;
  75. markRemoval[previousIndex] = 1;
  76. }
  77. }
  78. counts[i] = updatedCount;
  79. offset += count;
  80. }
  81. let nextAvailableIndex = 0;
  82. for (let k = 0; k < positionsLength; k++) {
  83. if (markRemoval[k] !== 1) {
  84. uBuffer[nextAvailableIndex] = uBuffer[k];
  85. vBuffer[nextAvailableIndex] = vBuffer[k];
  86. heightBuffer[nextAvailableIndex] = heightBuffer[k];
  87. nextAvailableIndex++;
  88. }
  89. }
  90. }
  91. function VertexAttributesAndIndices(volumesCount) {
  92. const vertexCount = volumesCount * 8;
  93. const vec3Floats = vertexCount * 3;
  94. const vec4Floats = vertexCount * 4;
  95. this.startEllipsoidNormals = new Float32Array(vec3Floats);
  96. this.endEllipsoidNormals = new Float32Array(vec3Floats);
  97. this.startPositionAndHeights = new Float32Array(vec4Floats);
  98. this.startFaceNormalAndVertexCornerIds = new Float32Array(vec4Floats);
  99. this.endPositionAndHeights = new Float32Array(vec4Floats);
  100. this.endFaceNormalAndHalfWidths = new Float32Array(vec4Floats);
  101. this.vertexBatchIds = new Uint16Array(vertexCount);
  102. this.indices = IndexDatatype.IndexDatatype.createTypedArray(vertexCount, 36 * volumesCount);
  103. this.vec3Offset = 0;
  104. this.vec4Offset = 0;
  105. this.batchIdOffset = 0;
  106. this.indexOffset = 0;
  107. this.volumeStartIndex = 0;
  108. }
  109. const towardCurrScratch = new Matrix2.Cartesian3();
  110. const towardNextScratch = new Matrix2.Cartesian3();
  111. function computeMiteredNormal(
  112. previousPosition,
  113. position,
  114. nextPosition,
  115. ellipsoidSurfaceNormal,
  116. result
  117. ) {
  118. const towardNext = Matrix2.Cartesian3.subtract(
  119. nextPosition,
  120. position,
  121. towardNextScratch
  122. );
  123. let towardCurr = Matrix2.Cartesian3.subtract(
  124. position,
  125. previousPosition,
  126. towardCurrScratch
  127. );
  128. Matrix2.Cartesian3.normalize(towardNext, towardNext);
  129. Matrix2.Cartesian3.normalize(towardCurr, towardCurr);
  130. if (Matrix2.Cartesian3.dot(towardNext, towardCurr) < MITER_BREAK) {
  131. towardCurr = Matrix2.Cartesian3.multiplyByScalar(
  132. towardCurr,
  133. -1.0,
  134. towardCurrScratch
  135. );
  136. }
  137. Matrix2.Cartesian3.add(towardNext, towardCurr, result);
  138. if (Matrix2.Cartesian3.equals(result, Matrix2.Cartesian3.ZERO)) {
  139. result = Matrix2.Cartesian3.subtract(previousPosition, position);
  140. }
  141. // Make sure the normal is orthogonal to the ellipsoid surface normal
  142. Matrix2.Cartesian3.cross(result, ellipsoidSurfaceNormal, result);
  143. Matrix2.Cartesian3.cross(ellipsoidSurfaceNormal, result, result);
  144. Matrix2.Cartesian3.normalize(result, result);
  145. return result;
  146. }
  147. // Winding order is reversed so each segment's volume is inside-out
  148. // 3-----------7
  149. // /| left /|
  150. // / | 1 / |
  151. // 2-----------6 5 end
  152. // | / | /
  153. // start |/ right |/
  154. // 0-----------4
  155. //
  156. const REFERENCE_INDICES = [
  157. 0,
  158. 2,
  159. 6,
  160. 0,
  161. 6,
  162. 4, // right
  163. 0,
  164. 1,
  165. 3,
  166. 0,
  167. 3,
  168. 2, // start face
  169. 0,
  170. 4,
  171. 5,
  172. 0,
  173. 5,
  174. 1, // bottom
  175. 5,
  176. 3,
  177. 1,
  178. 5,
  179. 7,
  180. 3, // left
  181. 7,
  182. 5,
  183. 4,
  184. 7,
  185. 4,
  186. 6, // end face
  187. 7,
  188. 6,
  189. 2,
  190. 7,
  191. 2,
  192. 3, // top
  193. ];
  194. const REFERENCE_INDICES_LENGTH = REFERENCE_INDICES.length;
  195. const positionScratch = new Matrix2.Cartesian3();
  196. const scratchStartEllipsoidNormal = new Matrix2.Cartesian3();
  197. const scratchStartFaceNormal = new Matrix2.Cartesian3();
  198. const scratchEndEllipsoidNormal = new Matrix2.Cartesian3();
  199. const scratchEndFaceNormal = new Matrix2.Cartesian3();
  200. VertexAttributesAndIndices.prototype.addVolume = function (
  201. preStartRTC,
  202. startRTC,
  203. endRTC,
  204. postEndRTC,
  205. startHeight,
  206. endHeight,
  207. halfWidth,
  208. batchId,
  209. center,
  210. ellipsoid
  211. ) {
  212. let position = Matrix2.Cartesian3.add(startRTC, center, positionScratch);
  213. const startEllipsoidNormal = ellipsoid.geodeticSurfaceNormal(
  214. position,
  215. scratchStartEllipsoidNormal
  216. );
  217. position = Matrix2.Cartesian3.add(endRTC, center, positionScratch);
  218. const endEllipsoidNormal = ellipsoid.geodeticSurfaceNormal(
  219. position,
  220. scratchEndEllipsoidNormal
  221. );
  222. const startFaceNormal = computeMiteredNormal(
  223. preStartRTC,
  224. startRTC,
  225. endRTC,
  226. startEllipsoidNormal,
  227. scratchStartFaceNormal
  228. );
  229. const endFaceNormal = computeMiteredNormal(
  230. postEndRTC,
  231. endRTC,
  232. startRTC,
  233. endEllipsoidNormal,
  234. scratchEndFaceNormal
  235. );
  236. const startEllipsoidNormals = this.startEllipsoidNormals;
  237. const endEllipsoidNormals = this.endEllipsoidNormals;
  238. const startPositionAndHeights = this.startPositionAndHeights;
  239. const startFaceNormalAndVertexCornerIds = this
  240. .startFaceNormalAndVertexCornerIds;
  241. const endPositionAndHeights = this.endPositionAndHeights;
  242. const endFaceNormalAndHalfWidths = this.endFaceNormalAndHalfWidths;
  243. const vertexBatchIds = this.vertexBatchIds;
  244. let batchIdOffset = this.batchIdOffset;
  245. let vec3Offset = this.vec3Offset;
  246. let vec4Offset = this.vec4Offset;
  247. let i;
  248. for (i = 0; i < 8; i++) {
  249. Matrix2.Cartesian3.pack(startEllipsoidNormal, startEllipsoidNormals, vec3Offset);
  250. Matrix2.Cartesian3.pack(endEllipsoidNormal, endEllipsoidNormals, vec3Offset);
  251. Matrix2.Cartesian3.pack(startRTC, startPositionAndHeights, vec4Offset);
  252. startPositionAndHeights[vec4Offset + 3] = startHeight;
  253. Matrix2.Cartesian3.pack(endRTC, endPositionAndHeights, vec4Offset);
  254. endPositionAndHeights[vec4Offset + 3] = endHeight;
  255. Matrix2.Cartesian3.pack(
  256. startFaceNormal,
  257. startFaceNormalAndVertexCornerIds,
  258. vec4Offset
  259. );
  260. startFaceNormalAndVertexCornerIds[vec4Offset + 3] = i;
  261. Matrix2.Cartesian3.pack(endFaceNormal, endFaceNormalAndHalfWidths, vec4Offset);
  262. endFaceNormalAndHalfWidths[vec4Offset + 3] = halfWidth;
  263. vertexBatchIds[batchIdOffset++] = batchId;
  264. vec3Offset += 3;
  265. vec4Offset += 4;
  266. }
  267. this.batchIdOffset = batchIdOffset;
  268. this.vec3Offset = vec3Offset;
  269. this.vec4Offset = vec4Offset;
  270. const indices = this.indices;
  271. const volumeStartIndex = this.volumeStartIndex;
  272. const indexOffset = this.indexOffset;
  273. for (i = 0; i < REFERENCE_INDICES_LENGTH; i++) {
  274. indices[indexOffset + i] = REFERENCE_INDICES[i] + volumeStartIndex;
  275. }
  276. this.volumeStartIndex += 8;
  277. this.indexOffset += REFERENCE_INDICES_LENGTH;
  278. };
  279. const scratchRectangle = new Matrix2.Rectangle();
  280. const scratchEllipsoid = new Matrix2.Ellipsoid();
  281. const scratchCenter = new Matrix2.Cartesian3();
  282. const scratchPrev = new Matrix2.Cartesian3();
  283. const scratchP0 = new Matrix2.Cartesian3();
  284. const scratchP1 = new Matrix2.Cartesian3();
  285. const scratchNext = new Matrix2.Cartesian3();
  286. function createVectorTileClampedPolylines(parameters, transferableObjects) {
  287. const encodedPositions = new Uint16Array(parameters.positions);
  288. const widths = new Uint16Array(parameters.widths);
  289. const counts = new Uint32Array(parameters.counts);
  290. const batchIds = new Uint16Array(parameters.batchIds);
  291. // Unpack tile decoding parameters
  292. const rectangle = scratchRectangle;
  293. const ellipsoid = scratchEllipsoid;
  294. const center = scratchCenter;
  295. const packedBuffer = new Float64Array(parameters.packedBuffer);
  296. let offset = 0;
  297. const minimumHeight = packedBuffer[offset++];
  298. const maximumHeight = packedBuffer[offset++];
  299. Matrix2.Rectangle.unpack(packedBuffer, offset, rectangle);
  300. offset += Matrix2.Rectangle.packedLength;
  301. Matrix2.Ellipsoid.unpack(packedBuffer, offset, ellipsoid);
  302. offset += Matrix2.Ellipsoid.packedLength;
  303. Matrix2.Cartesian3.unpack(packedBuffer, offset, center);
  304. let i;
  305. // Unpack positions and generate volumes
  306. let positionsLength = encodedPositions.length / 3;
  307. const uBuffer = encodedPositions.subarray(0, positionsLength);
  308. const vBuffer = encodedPositions.subarray(
  309. positionsLength,
  310. 2 * positionsLength
  311. );
  312. const heightBuffer = encodedPositions.subarray(
  313. 2 * positionsLength,
  314. 3 * positionsLength
  315. );
  316. AttributeCompression.AttributeCompression.zigZagDeltaDecode(uBuffer, vBuffer, heightBuffer);
  317. removeDuplicates(uBuffer, vBuffer, heightBuffer, counts);
  318. // Figure out how many volumes and how many vertices there will be.
  319. const countsLength = counts.length;
  320. let volumesCount = 0;
  321. for (i = 0; i < countsLength; i++) {
  322. const polylinePositionCount = counts[i];
  323. volumesCount += polylinePositionCount - 1;
  324. }
  325. const attribsAndIndices = new VertexAttributesAndIndices(volumesCount);
  326. const positions = decodePositions(
  327. uBuffer,
  328. vBuffer,
  329. heightBuffer,
  330. rectangle,
  331. minimumHeight,
  332. maximumHeight,
  333. ellipsoid);
  334. positionsLength = uBuffer.length;
  335. const positionsRTC = new Float32Array(positionsLength * 3);
  336. for (i = 0; i < positionsLength; ++i) {
  337. positionsRTC[i * 3] = positions[i * 3] - center.x;
  338. positionsRTC[i * 3 + 1] = positions[i * 3 + 1] - center.y;
  339. positionsRTC[i * 3 + 2] = positions[i * 3 + 2] - center.z;
  340. }
  341. let currentPositionIndex = 0;
  342. let currentHeightIndex = 0;
  343. for (i = 0; i < countsLength; i++) {
  344. const polylineVolumeCount = counts[i] - 1;
  345. const halfWidth = widths[i] * 0.5;
  346. const batchId = batchIds[i];
  347. const volumeFirstPositionIndex = currentPositionIndex;
  348. for (let j = 0; j < polylineVolumeCount; j++) {
  349. const volumeStart = Matrix2.Cartesian3.unpack(
  350. positionsRTC,
  351. currentPositionIndex,
  352. scratchP0
  353. );
  354. const volumeEnd = Matrix2.Cartesian3.unpack(
  355. positionsRTC,
  356. currentPositionIndex + 3,
  357. scratchP1
  358. );
  359. let startHeight = heightBuffer[currentHeightIndex];
  360. let endHeight = heightBuffer[currentHeightIndex + 1];
  361. startHeight = ComponentDatatype.CesiumMath.lerp(
  362. minimumHeight,
  363. maximumHeight,
  364. startHeight / MAX_SHORT
  365. );
  366. endHeight = ComponentDatatype.CesiumMath.lerp(
  367. minimumHeight,
  368. maximumHeight,
  369. endHeight / MAX_SHORT
  370. );
  371. currentHeightIndex++;
  372. let preStart = scratchPrev;
  373. let postEnd = scratchNext;
  374. if (j === 0) {
  375. // Check if this volume is like a loop
  376. const finalPositionIndex =
  377. volumeFirstPositionIndex + polylineVolumeCount * 3;
  378. const finalPosition = Matrix2.Cartesian3.unpack(
  379. positionsRTC,
  380. finalPositionIndex,
  381. scratchPrev
  382. );
  383. if (Matrix2.Cartesian3.equals(finalPosition, volumeStart)) {
  384. Matrix2.Cartesian3.unpack(positionsRTC, finalPositionIndex - 3, preStart);
  385. } else {
  386. const offsetPastStart = Matrix2.Cartesian3.subtract(
  387. volumeStart,
  388. volumeEnd,
  389. scratchPrev
  390. );
  391. preStart = Matrix2.Cartesian3.add(offsetPastStart, volumeStart, scratchPrev);
  392. }
  393. } else {
  394. Matrix2.Cartesian3.unpack(positionsRTC, currentPositionIndex - 3, preStart);
  395. }
  396. if (j === polylineVolumeCount - 1) {
  397. // Check if this volume is like a loop
  398. const firstPosition = Matrix2.Cartesian3.unpack(
  399. positionsRTC,
  400. volumeFirstPositionIndex,
  401. scratchNext
  402. );
  403. if (Matrix2.Cartesian3.equals(firstPosition, volumeEnd)) {
  404. Matrix2.Cartesian3.unpack(
  405. positionsRTC,
  406. volumeFirstPositionIndex + 3,
  407. postEnd
  408. );
  409. } else {
  410. const offsetPastEnd = Matrix2.Cartesian3.subtract(
  411. volumeEnd,
  412. volumeStart,
  413. scratchNext
  414. );
  415. postEnd = Matrix2.Cartesian3.add(offsetPastEnd, volumeEnd, scratchNext);
  416. }
  417. } else {
  418. Matrix2.Cartesian3.unpack(positionsRTC, currentPositionIndex + 6, postEnd);
  419. }
  420. attribsAndIndices.addVolume(
  421. preStart,
  422. volumeStart,
  423. volumeEnd,
  424. postEnd,
  425. startHeight,
  426. endHeight,
  427. halfWidth,
  428. batchId,
  429. center,
  430. ellipsoid
  431. );
  432. currentPositionIndex += 3;
  433. }
  434. currentPositionIndex += 3;
  435. currentHeightIndex++;
  436. }
  437. const indices = attribsAndIndices.indices;
  438. transferableObjects.push(attribsAndIndices.startEllipsoidNormals.buffer);
  439. transferableObjects.push(attribsAndIndices.endEllipsoidNormals.buffer);
  440. transferableObjects.push(attribsAndIndices.startPositionAndHeights.buffer);
  441. transferableObjects.push(
  442. attribsAndIndices.startFaceNormalAndVertexCornerIds.buffer
  443. );
  444. transferableObjects.push(attribsAndIndices.endPositionAndHeights.buffer);
  445. transferableObjects.push(attribsAndIndices.endFaceNormalAndHalfWidths.buffer);
  446. transferableObjects.push(attribsAndIndices.vertexBatchIds.buffer);
  447. transferableObjects.push(indices.buffer);
  448. let results = {
  449. indexDatatype:
  450. indices.BYTES_PER_ELEMENT === 2
  451. ? IndexDatatype.IndexDatatype.UNSIGNED_SHORT
  452. : IndexDatatype.IndexDatatype.UNSIGNED_INT,
  453. startEllipsoidNormals: attribsAndIndices.startEllipsoidNormals.buffer,
  454. endEllipsoidNormals: attribsAndIndices.endEllipsoidNormals.buffer,
  455. startPositionAndHeights: attribsAndIndices.startPositionAndHeights.buffer,
  456. startFaceNormalAndVertexCornerIds:
  457. attribsAndIndices.startFaceNormalAndVertexCornerIds.buffer,
  458. endPositionAndHeights: attribsAndIndices.endPositionAndHeights.buffer,
  459. endFaceNormalAndHalfWidths:
  460. attribsAndIndices.endFaceNormalAndHalfWidths.buffer,
  461. vertexBatchIds: attribsAndIndices.vertexBatchIds.buffer,
  462. indices: indices.buffer,
  463. };
  464. if (parameters.keepDecodedPositions) {
  465. const positionOffsets = getPositionOffsets(counts);
  466. transferableObjects.push(positions.buffer, positionOffsets.buffer);
  467. results = combine.combine(results, {
  468. decodedPositions: positions.buffer,
  469. decodedPositionOffsets: positionOffsets.buffer,
  470. });
  471. }
  472. return results;
  473. }
  474. var createVectorTileClampedPolylines$1 = createTaskProcessorWorker(createVectorTileClampedPolylines);
  475. return createVectorTileClampedPolylines$1;
  476. }));