createVectorTileClampedPolylines.js 18 KB

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