createVectorTilePolygons.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  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', './Color-b81cce6d', './defaultValue-81eec7ed', './IndexDatatype-bed3935d', './ComponentDatatype-9e86ac8f', './OrientedBoundingBox-0b41570b', './createTaskProcessorWorker', './RuntimeError-8952249c', './Transforms-f0a54c7b', './_commonjsHelpers-3aae1032-26891ab7', './combine-3c023bda', './WebGLConstants-508b9636', './EllipsoidTangentPlane-2abe082d', './AxisAlignedBoundingBox-7b93960a', './IntersectionTests-a25e058d', './Plane-24f22488'], (function (AttributeCompression, Matrix2, Color, defaultValue, IndexDatatype, ComponentDatatype, OrientedBoundingBox, createTaskProcessorWorker, RuntimeError, Transforms, _commonjsHelpers3aae1032, combine, WebGLConstants, EllipsoidTangentPlane, AxisAlignedBoundingBox, IntersectionTests, Plane) { 'use strict';
  24. const scratchCenter = new Matrix2.Cartesian3();
  25. const scratchEllipsoid = new Matrix2.Ellipsoid();
  26. const scratchRectangle = new Matrix2.Rectangle();
  27. const scratchScalars = {
  28. min: undefined,
  29. max: undefined,
  30. indexBytesPerElement: undefined,
  31. };
  32. function unpackBuffer(buffer) {
  33. const packedBuffer = new Float64Array(buffer);
  34. let offset = 0;
  35. scratchScalars.indexBytesPerElement = packedBuffer[offset++];
  36. scratchScalars.min = packedBuffer[offset++];
  37. scratchScalars.max = packedBuffer[offset++];
  38. Matrix2.Cartesian3.unpack(packedBuffer, offset, scratchCenter);
  39. offset += Matrix2.Cartesian3.packedLength;
  40. Matrix2.Ellipsoid.unpack(packedBuffer, offset, scratchEllipsoid);
  41. offset += Matrix2.Ellipsoid.packedLength;
  42. Matrix2.Rectangle.unpack(packedBuffer, offset, scratchRectangle);
  43. }
  44. function packedBatchedIndicesLength(batchedIndices) {
  45. const length = batchedIndices.length;
  46. let count = 0;
  47. for (let i = 0; i < length; ++i) {
  48. count += Color.Color.packedLength + 3 + batchedIndices[i].batchIds.length;
  49. }
  50. return count;
  51. }
  52. function packBuffer(indexDatatype, boundingVolumes, batchedIndices) {
  53. const numBVs = boundingVolumes.length;
  54. const length =
  55. 1 +
  56. 1 +
  57. numBVs * OrientedBoundingBox.OrientedBoundingBox.packedLength +
  58. 1 +
  59. packedBatchedIndicesLength(batchedIndices);
  60. const packedBuffer = new Float64Array(length);
  61. let offset = 0;
  62. packedBuffer[offset++] = indexDatatype;
  63. packedBuffer[offset++] = numBVs;
  64. for (let i = 0; i < numBVs; ++i) {
  65. OrientedBoundingBox.OrientedBoundingBox.pack(boundingVolumes[i], packedBuffer, offset);
  66. offset += OrientedBoundingBox.OrientedBoundingBox.packedLength;
  67. }
  68. const indicesLength = batchedIndices.length;
  69. packedBuffer[offset++] = indicesLength;
  70. for (let j = 0; j < indicesLength; ++j) {
  71. const batchedIndex = batchedIndices[j];
  72. Color.Color.pack(batchedIndex.color, packedBuffer, offset);
  73. offset += Color.Color.packedLength;
  74. packedBuffer[offset++] = batchedIndex.offset;
  75. packedBuffer[offset++] = batchedIndex.count;
  76. const batchIds = batchedIndex.batchIds;
  77. const batchIdsLength = batchIds.length;
  78. packedBuffer[offset++] = batchIdsLength;
  79. for (let k = 0; k < batchIdsLength; ++k) {
  80. packedBuffer[offset++] = batchIds[k];
  81. }
  82. }
  83. return packedBuffer;
  84. }
  85. const maxShort = 32767;
  86. const scratchEncodedPosition = new Matrix2.Cartesian3();
  87. const scratchNormal = new Matrix2.Cartesian3();
  88. const scratchScaledNormal = new Matrix2.Cartesian3();
  89. const scratchMinHeightPosition = new Matrix2.Cartesian3();
  90. const scratchMaxHeightPosition = new Matrix2.Cartesian3();
  91. const scratchBVCartographic = new Matrix2.Cartographic();
  92. const scratchBVRectangle = new Matrix2.Rectangle();
  93. function createVectorTilePolygons(parameters, transferableObjects) {
  94. unpackBuffer(parameters.packedBuffer);
  95. let indices;
  96. const indexBytesPerElement = scratchScalars.indexBytesPerElement;
  97. if (indexBytesPerElement === 2) {
  98. indices = new Uint16Array(parameters.indices);
  99. } else {
  100. indices = new Uint32Array(parameters.indices);
  101. }
  102. const positions = new Uint16Array(parameters.positions);
  103. const counts = new Uint32Array(parameters.counts);
  104. const indexCounts = new Uint32Array(parameters.indexCounts);
  105. const batchIds = new Uint32Array(parameters.batchIds);
  106. const batchTableColors = new Uint32Array(parameters.batchTableColors);
  107. const boundingVolumes = new Array(counts.length);
  108. const center = scratchCenter;
  109. const ellipsoid = scratchEllipsoid;
  110. let rectangle = scratchRectangle;
  111. const minHeight = scratchScalars.min;
  112. const maxHeight = scratchScalars.max;
  113. let minimumHeights = parameters.minimumHeights;
  114. let maximumHeights = parameters.maximumHeights;
  115. if (defaultValue.defined(minimumHeights) && defaultValue.defined(maximumHeights)) {
  116. minimumHeights = new Float32Array(minimumHeights);
  117. maximumHeights = new Float32Array(maximumHeights);
  118. }
  119. let i;
  120. let j;
  121. let rgba;
  122. const positionsLength = positions.length / 2;
  123. const uBuffer = positions.subarray(0, positionsLength);
  124. const vBuffer = positions.subarray(positionsLength, 2 * positionsLength);
  125. AttributeCompression.AttributeCompression.zigZagDeltaDecode(uBuffer, vBuffer);
  126. const decodedPositions = new Float64Array(positionsLength * 3);
  127. for (i = 0; i < positionsLength; ++i) {
  128. const u = uBuffer[i];
  129. const v = vBuffer[i];
  130. const x = ComponentDatatype.CesiumMath.lerp(rectangle.west, rectangle.east, u / maxShort);
  131. const y = ComponentDatatype.CesiumMath.lerp(rectangle.south, rectangle.north, v / maxShort);
  132. const cart = Matrix2.Cartographic.fromRadians(x, y, 0.0, scratchBVCartographic);
  133. const decodedPosition = ellipsoid.cartographicToCartesian(
  134. cart,
  135. scratchEncodedPosition
  136. );
  137. Matrix2.Cartesian3.pack(decodedPosition, decodedPositions, i * 3);
  138. }
  139. const countsLength = counts.length;
  140. const offsets = new Array(countsLength);
  141. const indexOffsets = new Array(countsLength);
  142. let currentOffset = 0;
  143. let currentIndexOffset = 0;
  144. for (i = 0; i < countsLength; ++i) {
  145. offsets[i] = currentOffset;
  146. indexOffsets[i] = currentIndexOffset;
  147. currentOffset += counts[i];
  148. currentIndexOffset += indexCounts[i];
  149. }
  150. const batchedPositions = new Float32Array(positionsLength * 3 * 2);
  151. const batchedIds = new Uint16Array(positionsLength * 2);
  152. const batchedIndexOffsets = new Uint32Array(indexOffsets.length);
  153. const batchedIndexCounts = new Uint32Array(indexCounts.length);
  154. let batchedIndices = [];
  155. const colorToBuffers = {};
  156. for (i = 0; i < countsLength; ++i) {
  157. rgba = batchTableColors[i];
  158. if (!defaultValue.defined(colorToBuffers[rgba])) {
  159. colorToBuffers[rgba] = {
  160. positionLength: counts[i],
  161. indexLength: indexCounts[i],
  162. offset: 0,
  163. indexOffset: 0,
  164. batchIds: [i],
  165. };
  166. } else {
  167. colorToBuffers[rgba].positionLength += counts[i];
  168. colorToBuffers[rgba].indexLength += indexCounts[i];
  169. colorToBuffers[rgba].batchIds.push(i);
  170. }
  171. }
  172. // get the offsets and counts for the positions and indices of each primitive
  173. let buffer;
  174. let byColorPositionOffset = 0;
  175. let byColorIndexOffset = 0;
  176. for (rgba in colorToBuffers) {
  177. if (colorToBuffers.hasOwnProperty(rgba)) {
  178. buffer = colorToBuffers[rgba];
  179. buffer.offset = byColorPositionOffset;
  180. buffer.indexOffset = byColorIndexOffset;
  181. const positionLength = buffer.positionLength * 2;
  182. const indexLength = buffer.indexLength * 2 + buffer.positionLength * 6;
  183. byColorPositionOffset += positionLength;
  184. byColorIndexOffset += indexLength;
  185. buffer.indexLength = indexLength;
  186. }
  187. }
  188. const batchedDrawCalls = [];
  189. for (rgba in colorToBuffers) {
  190. if (colorToBuffers.hasOwnProperty(rgba)) {
  191. buffer = colorToBuffers[rgba];
  192. batchedDrawCalls.push({
  193. color: Color.Color.fromRgba(parseInt(rgba)),
  194. offset: buffer.indexOffset,
  195. count: buffer.indexLength,
  196. batchIds: buffer.batchIds,
  197. });
  198. }
  199. }
  200. for (i = 0; i < countsLength; ++i) {
  201. rgba = batchTableColors[i];
  202. buffer = colorToBuffers[rgba];
  203. const positionOffset = buffer.offset;
  204. let positionIndex = positionOffset * 3;
  205. let batchIdIndex = positionOffset;
  206. const polygonOffset = offsets[i];
  207. const polygonCount = counts[i];
  208. const batchId = batchIds[i];
  209. let polygonMinimumHeight = minHeight;
  210. let polygonMaximumHeight = maxHeight;
  211. if (defaultValue.defined(minimumHeights) && defaultValue.defined(maximumHeights)) {
  212. polygonMinimumHeight = minimumHeights[i];
  213. polygonMaximumHeight = maximumHeights[i];
  214. }
  215. let minLat = Number.POSITIVE_INFINITY;
  216. let maxLat = Number.NEGATIVE_INFINITY;
  217. let minLon = Number.POSITIVE_INFINITY;
  218. let maxLon = Number.NEGATIVE_INFINITY;
  219. for (j = 0; j < polygonCount; ++j) {
  220. const position = Matrix2.Cartesian3.unpack(
  221. decodedPositions,
  222. polygonOffset * 3 + j * 3,
  223. scratchEncodedPosition
  224. );
  225. ellipsoid.scaleToGeodeticSurface(position, position);
  226. const carto = ellipsoid.cartesianToCartographic(
  227. position,
  228. scratchBVCartographic
  229. );
  230. const lat = carto.latitude;
  231. const lon = carto.longitude;
  232. minLat = Math.min(lat, minLat);
  233. maxLat = Math.max(lat, maxLat);
  234. minLon = Math.min(lon, minLon);
  235. maxLon = Math.max(lon, maxLon);
  236. const normal = ellipsoid.geodeticSurfaceNormal(position, scratchNormal);
  237. let scaledNormal = Matrix2.Cartesian3.multiplyByScalar(
  238. normal,
  239. polygonMinimumHeight,
  240. scratchScaledNormal
  241. );
  242. const minHeightPosition = Matrix2.Cartesian3.add(
  243. position,
  244. scaledNormal,
  245. scratchMinHeightPosition
  246. );
  247. scaledNormal = Matrix2.Cartesian3.multiplyByScalar(
  248. normal,
  249. polygonMaximumHeight,
  250. scaledNormal
  251. );
  252. const maxHeightPosition = Matrix2.Cartesian3.add(
  253. position,
  254. scaledNormal,
  255. scratchMaxHeightPosition
  256. );
  257. Matrix2.Cartesian3.subtract(maxHeightPosition, center, maxHeightPosition);
  258. Matrix2.Cartesian3.subtract(minHeightPosition, center, minHeightPosition);
  259. Matrix2.Cartesian3.pack(maxHeightPosition, batchedPositions, positionIndex);
  260. Matrix2.Cartesian3.pack(minHeightPosition, batchedPositions, positionIndex + 3);
  261. batchedIds[batchIdIndex] = batchId;
  262. batchedIds[batchIdIndex + 1] = batchId;
  263. positionIndex += 6;
  264. batchIdIndex += 2;
  265. }
  266. rectangle = scratchBVRectangle;
  267. rectangle.west = minLon;
  268. rectangle.east = maxLon;
  269. rectangle.south = minLat;
  270. rectangle.north = maxLat;
  271. boundingVolumes[i] = OrientedBoundingBox.OrientedBoundingBox.fromRectangle(
  272. rectangle,
  273. minHeight,
  274. maxHeight,
  275. ellipsoid
  276. );
  277. let indicesIndex = buffer.indexOffset;
  278. const indexOffset = indexOffsets[i];
  279. const indexCount = indexCounts[i];
  280. batchedIndexOffsets[i] = indicesIndex;
  281. for (j = 0; j < indexCount; j += 3) {
  282. const i0 = indices[indexOffset + j] - polygonOffset;
  283. const i1 = indices[indexOffset + j + 1] - polygonOffset;
  284. const i2 = indices[indexOffset + j + 2] - polygonOffset;
  285. // triangle on the top of the extruded polygon
  286. batchedIndices[indicesIndex++] = i0 * 2 + positionOffset;
  287. batchedIndices[indicesIndex++] = i1 * 2 + positionOffset;
  288. batchedIndices[indicesIndex++] = i2 * 2 + positionOffset;
  289. // triangle on the bottom of the extruded polygon
  290. batchedIndices[indicesIndex++] = i2 * 2 + 1 + positionOffset;
  291. batchedIndices[indicesIndex++] = i1 * 2 + 1 + positionOffset;
  292. batchedIndices[indicesIndex++] = i0 * 2 + 1 + positionOffset;
  293. }
  294. // indices for the walls of the extruded polygon
  295. for (j = 0; j < polygonCount; ++j) {
  296. const v0 = j;
  297. const v1 = (j + 1) % polygonCount;
  298. batchedIndices[indicesIndex++] = v0 * 2 + 1 + positionOffset;
  299. batchedIndices[indicesIndex++] = v1 * 2 + positionOffset;
  300. batchedIndices[indicesIndex++] = v0 * 2 + positionOffset;
  301. batchedIndices[indicesIndex++] = v0 * 2 + 1 + positionOffset;
  302. batchedIndices[indicesIndex++] = v1 * 2 + 1 + positionOffset;
  303. batchedIndices[indicesIndex++] = v1 * 2 + positionOffset;
  304. }
  305. buffer.offset += polygonCount * 2;
  306. buffer.indexOffset = indicesIndex;
  307. batchedIndexCounts[i] = indicesIndex - batchedIndexOffsets[i];
  308. }
  309. batchedIndices = IndexDatatype.IndexDatatype.createTypedArray(
  310. batchedPositions.length / 3,
  311. batchedIndices
  312. );
  313. const batchedIndicesLength = batchedDrawCalls.length;
  314. for (let m = 0; m < batchedIndicesLength; ++m) {
  315. const tempIds = batchedDrawCalls[m].batchIds;
  316. let count = 0;
  317. const tempIdsLength = tempIds.length;
  318. for (let n = 0; n < tempIdsLength; ++n) {
  319. count += batchedIndexCounts[tempIds[n]];
  320. }
  321. batchedDrawCalls[m].count = count;
  322. }
  323. const indexDatatype =
  324. batchedIndices.BYTES_PER_ELEMENT === 2
  325. ? IndexDatatype.IndexDatatype.UNSIGNED_SHORT
  326. : IndexDatatype.IndexDatatype.UNSIGNED_INT;
  327. const packedBuffer = packBuffer(
  328. indexDatatype,
  329. boundingVolumes,
  330. batchedDrawCalls
  331. );
  332. transferableObjects.push(
  333. batchedPositions.buffer,
  334. batchedIndices.buffer,
  335. batchedIndexOffsets.buffer,
  336. batchedIndexCounts.buffer,
  337. batchedIds.buffer,
  338. packedBuffer.buffer
  339. );
  340. return {
  341. positions: batchedPositions.buffer,
  342. indices: batchedIndices.buffer,
  343. indexOffsets: batchedIndexOffsets.buffer,
  344. indexCounts: batchedIndexCounts.buffer,
  345. batchIds: batchedIds.buffer,
  346. packedBuffer: packedBuffer.buffer,
  347. };
  348. }
  349. var createVectorTilePolygons$1 = createTaskProcessorWorker(createVectorTilePolygons);
  350. return createVectorTilePolygons$1;
  351. }));
  352. //# sourceMappingURL=createVectorTilePolygons.js.map