createVerticesFromQuantizedTerrainMesh.js 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034
  1. /* This file is automatically rebuilt by the Cesium build process. */
  2. define(['./when-e6985d2a', './Check-24cae389', './Math-392d0035', './Cartesian2-a5d6dde9', './Transforms-81680c41', './RuntimeError-61701d3e', './WebGLConstants-34c08bc0', './ComponentDatatype-cb08e294', './AttributeCompression-114c6354', './IndexDatatype-1be7d1f8', './IntersectionTests-f17c84f0', './Plane-ac6a1d3e', './WebMercatorProjection-a06fbf17', './createTaskProcessorWorker', './EllipsoidTangentPlane-85280670', './OrientedBoundingBox-d8219c10', './TerrainEncoding-a793a9ee'], function (when, Check, _Math, Cartesian2, Transforms, RuntimeError, WebGLConstants, ComponentDatatype, AttributeCompression, IndexDatatype, IntersectionTests, Plane, WebMercatorProjection, createTaskProcessorWorker, EllipsoidTangentPlane, OrientedBoundingBox, TerrainEncoding) { 'use strict';
  3. /**
  4. * Provides terrain or other geometry for the surface of an ellipsoid. The surface geometry is
  5. * organized into a pyramid of tiles according to a {@link TilingScheme}. This type describes an
  6. * interface and is not intended to be instantiated directly.
  7. *
  8. * @alias TerrainProvider
  9. * @constructor
  10. *
  11. * @see EllipsoidTerrainProvider
  12. * @see CesiumTerrainProvider
  13. * @see VRTheWorldTerrainProvider
  14. * @see GoogleEarthEnterpriseTerrainProvider
  15. */
  16. function TerrainProvider() {
  17. Check.DeveloperError.throwInstantiationError();
  18. }
  19. Object.defineProperties(TerrainProvider.prototype, {
  20. /**
  21. * Gets an event that is raised when the terrain provider encounters an asynchronous error.. By subscribing
  22. * to the event, you will be notified of the error and can potentially recover from it. Event listeners
  23. * are passed an instance of {@link TileProviderError}.
  24. * @memberof TerrainProvider.prototype
  25. * @type {Event}
  26. */
  27. errorEvent: {
  28. get: Check.DeveloperError.throwInstantiationError,
  29. },
  30. /**
  31. * Gets the credit to display when this terrain provider is active. Typically this is used to credit
  32. * the source of the terrain. This function should
  33. * not be called before {@link TerrainProvider#ready} returns true.
  34. * @memberof TerrainProvider.prototype
  35. * @type {Credit}
  36. */
  37. credit: {
  38. get: Check.DeveloperError.throwInstantiationError,
  39. },
  40. /**
  41. * Gets the tiling scheme used by the provider. This function should
  42. * not be called before {@link TerrainProvider#ready} returns true.
  43. * @memberof TerrainProvider.prototype
  44. * @type {TilingScheme}
  45. */
  46. tilingScheme: {
  47. get: Check.DeveloperError.throwInstantiationError,
  48. },
  49. /**
  50. * Gets a value indicating whether or not the provider is ready for use.
  51. * @memberof TerrainProvider.prototype
  52. * @type {Boolean}
  53. */
  54. ready: {
  55. get: Check.DeveloperError.throwInstantiationError,
  56. },
  57. /**
  58. * Gets a promise that resolves to true when the provider is ready for use.
  59. * @memberof TerrainProvider.prototype
  60. * @type {Promise.<Boolean>}
  61. * @readonly
  62. */
  63. readyPromise: {
  64. get: Check.DeveloperError.throwInstantiationError,
  65. },
  66. /**
  67. * Gets a value indicating whether or not the provider includes a water mask. The water mask
  68. * indicates which areas of the globe are water rather than land, so they can be rendered
  69. * as a reflective surface with animated waves. This function should not be
  70. * called before {@link TerrainProvider#ready} returns true.
  71. * @memberof TerrainProvider.prototype
  72. * @type {Boolean}
  73. */
  74. hasWaterMask: {
  75. get: Check.DeveloperError.throwInstantiationError,
  76. },
  77. /**
  78. * Gets a value indicating whether or not the requested tiles include vertex normals.
  79. * This function should not be called before {@link TerrainProvider#ready} returns true.
  80. * @memberof TerrainProvider.prototype
  81. * @type {Boolean}
  82. */
  83. hasVertexNormals: {
  84. get: Check.DeveloperError.throwInstantiationError,
  85. },
  86. /**
  87. * Gets an object that can be used to determine availability of terrain from this provider, such as
  88. * at points and in rectangles. This function should not be called before
  89. * {@link TerrainProvider#ready} returns true. This property may be undefined if availability
  90. * information is not available.
  91. * @memberof TerrainProvider.prototype
  92. * @type {TileAvailability}
  93. */
  94. availability: {
  95. get: Check.DeveloperError.throwInstantiationError,
  96. },
  97. });
  98. var regularGridIndicesCache = [];
  99. /**
  100. * Gets a list of indices for a triangle mesh representing a regular grid. Calling
  101. * this function multiple times with the same grid width and height returns the
  102. * same list of indices. The total number of vertices must be less than or equal
  103. * to 65536.
  104. *
  105. * @param {Number} width The number of vertices in the regular grid in the horizontal direction.
  106. * @param {Number} height The number of vertices in the regular grid in the vertical direction.
  107. * @returns {Uint16Array|Uint32Array} The list of indices. Uint16Array gets returned for 64KB or less and Uint32Array for 4GB or less.
  108. */
  109. TerrainProvider.getRegularGridIndices = function (width, height) {
  110. //>>includeStart('debug', pragmas.debug);
  111. if (width * height >= _Math.CesiumMath.FOUR_GIGABYTES) {
  112. throw new Check.DeveloperError(
  113. "The total number of vertices (width * height) must be less than 4,294,967,296."
  114. );
  115. }
  116. //>>includeEnd('debug');
  117. var byWidth = regularGridIndicesCache[width];
  118. if (!when.defined(byWidth)) {
  119. regularGridIndicesCache[width] = byWidth = [];
  120. }
  121. var indices = byWidth[height];
  122. if (!when.defined(indices)) {
  123. if (width * height < _Math.CesiumMath.SIXTY_FOUR_KILOBYTES) {
  124. indices = byWidth[height] = new Uint16Array(
  125. (width - 1) * (height - 1) * 6
  126. );
  127. } else {
  128. indices = byWidth[height] = new Uint32Array(
  129. (width - 1) * (height - 1) * 6
  130. );
  131. }
  132. addRegularGridIndices(width, height, indices, 0);
  133. }
  134. return indices;
  135. };
  136. var regularGridAndEdgeIndicesCache = [];
  137. /**
  138. * @private
  139. */
  140. TerrainProvider.getRegularGridIndicesAndEdgeIndices = function (width, height) {
  141. //>>includeStart('debug', pragmas.debug);
  142. if (width * height >= _Math.CesiumMath.FOUR_GIGABYTES) {
  143. throw new Check.DeveloperError(
  144. "The total number of vertices (width * height) must be less than 4,294,967,296."
  145. );
  146. }
  147. //>>includeEnd('debug');
  148. var byWidth = regularGridAndEdgeIndicesCache[width];
  149. if (!when.defined(byWidth)) {
  150. regularGridAndEdgeIndicesCache[width] = byWidth = [];
  151. }
  152. var indicesAndEdges = byWidth[height];
  153. if (!when.defined(indicesAndEdges)) {
  154. var indices = TerrainProvider.getRegularGridIndices(width, height);
  155. var edgeIndices = getEdgeIndices(width, height);
  156. var westIndicesSouthToNorth = edgeIndices.westIndicesSouthToNorth;
  157. var southIndicesEastToWest = edgeIndices.southIndicesEastToWest;
  158. var eastIndicesNorthToSouth = edgeIndices.eastIndicesNorthToSouth;
  159. var northIndicesWestToEast = edgeIndices.northIndicesWestToEast;
  160. indicesAndEdges = byWidth[height] = {
  161. indices: indices,
  162. westIndicesSouthToNorth: westIndicesSouthToNorth,
  163. southIndicesEastToWest: southIndicesEastToWest,
  164. eastIndicesNorthToSouth: eastIndicesNorthToSouth,
  165. northIndicesWestToEast: northIndicesWestToEast,
  166. };
  167. }
  168. return indicesAndEdges;
  169. };
  170. var regularGridAndSkirtAndEdgeIndicesCache = [];
  171. /**
  172. * @private
  173. */
  174. TerrainProvider.getRegularGridAndSkirtIndicesAndEdgeIndices = function (
  175. width,
  176. height
  177. ) {
  178. //>>includeStart('debug', pragmas.debug);
  179. if (width * height >= _Math.CesiumMath.FOUR_GIGABYTES) {
  180. throw new Check.DeveloperError(
  181. "The total number of vertices (width * height) must be less than 4,294,967,296."
  182. );
  183. }
  184. //>>includeEnd('debug');
  185. var byWidth = regularGridAndSkirtAndEdgeIndicesCache[width];
  186. if (!when.defined(byWidth)) {
  187. regularGridAndSkirtAndEdgeIndicesCache[width] = byWidth = [];
  188. }
  189. var indicesAndEdges = byWidth[height];
  190. if (!when.defined(indicesAndEdges)) {
  191. var gridVertexCount = width * height;
  192. var gridIndexCount = (width - 1) * (height - 1) * 6;
  193. var edgeVertexCount = width * 2 + height * 2;
  194. var edgeIndexCount = Math.max(0, edgeVertexCount - 4) * 6;
  195. var vertexCount = gridVertexCount + edgeVertexCount;
  196. var indexCount = gridIndexCount + edgeIndexCount;
  197. var edgeIndices = getEdgeIndices(width, height);
  198. var westIndicesSouthToNorth = edgeIndices.westIndicesSouthToNorth;
  199. var southIndicesEastToWest = edgeIndices.southIndicesEastToWest;
  200. var eastIndicesNorthToSouth = edgeIndices.eastIndicesNorthToSouth;
  201. var northIndicesWestToEast = edgeIndices.northIndicesWestToEast;
  202. var indices = IndexDatatype.IndexDatatype.createTypedArray(vertexCount, indexCount);
  203. addRegularGridIndices(width, height, indices, 0);
  204. TerrainProvider.addSkirtIndices(
  205. westIndicesSouthToNorth,
  206. southIndicesEastToWest,
  207. eastIndicesNorthToSouth,
  208. northIndicesWestToEast,
  209. gridVertexCount,
  210. indices,
  211. gridIndexCount
  212. );
  213. indicesAndEdges = byWidth[height] = {
  214. indices: indices,
  215. westIndicesSouthToNorth: westIndicesSouthToNorth,
  216. southIndicesEastToWest: southIndicesEastToWest,
  217. eastIndicesNorthToSouth: eastIndicesNorthToSouth,
  218. northIndicesWestToEast: northIndicesWestToEast,
  219. indexCountWithoutSkirts: gridIndexCount,
  220. };
  221. }
  222. return indicesAndEdges;
  223. };
  224. /**
  225. * @private
  226. */
  227. TerrainProvider.addSkirtIndices = function (
  228. westIndicesSouthToNorth,
  229. southIndicesEastToWest,
  230. eastIndicesNorthToSouth,
  231. northIndicesWestToEast,
  232. vertexCount,
  233. indices,
  234. offset
  235. ) {
  236. var vertexIndex = vertexCount;
  237. offset = addSkirtIndices(
  238. westIndicesSouthToNorth,
  239. vertexIndex,
  240. indices,
  241. offset
  242. );
  243. vertexIndex += westIndicesSouthToNorth.length;
  244. offset = addSkirtIndices(
  245. southIndicesEastToWest,
  246. vertexIndex,
  247. indices,
  248. offset
  249. );
  250. vertexIndex += southIndicesEastToWest.length;
  251. offset = addSkirtIndices(
  252. eastIndicesNorthToSouth,
  253. vertexIndex,
  254. indices,
  255. offset
  256. );
  257. vertexIndex += eastIndicesNorthToSouth.length;
  258. addSkirtIndices(northIndicesWestToEast, vertexIndex, indices, offset);
  259. };
  260. function getEdgeIndices(width, height) {
  261. var westIndicesSouthToNorth = new Array(height);
  262. var southIndicesEastToWest = new Array(width);
  263. var eastIndicesNorthToSouth = new Array(height);
  264. var northIndicesWestToEast = new Array(width);
  265. var i;
  266. for (i = 0; i < width; ++i) {
  267. northIndicesWestToEast[i] = i;
  268. southIndicesEastToWest[i] = width * height - 1 - i;
  269. }
  270. for (i = 0; i < height; ++i) {
  271. eastIndicesNorthToSouth[i] = (i + 1) * width - 1;
  272. westIndicesSouthToNorth[i] = (height - i - 1) * width;
  273. }
  274. return {
  275. westIndicesSouthToNorth: westIndicesSouthToNorth,
  276. southIndicesEastToWest: southIndicesEastToWest,
  277. eastIndicesNorthToSouth: eastIndicesNorthToSouth,
  278. northIndicesWestToEast: northIndicesWestToEast,
  279. };
  280. }
  281. function addRegularGridIndices(width, height, indices, offset) {
  282. var index = 0;
  283. for (var j = 0; j < height - 1; ++j) {
  284. for (var i = 0; i < width - 1; ++i) {
  285. var upperLeft = index;
  286. var lowerLeft = upperLeft + width;
  287. var lowerRight = lowerLeft + 1;
  288. var upperRight = upperLeft + 1;
  289. indices[offset++] = upperLeft;
  290. indices[offset++] = lowerLeft;
  291. indices[offset++] = upperRight;
  292. indices[offset++] = upperRight;
  293. indices[offset++] = lowerLeft;
  294. indices[offset++] = lowerRight;
  295. ++index;
  296. }
  297. ++index;
  298. }
  299. }
  300. function addSkirtIndices(edgeIndices, vertexIndex, indices, offset) {
  301. var previousIndex = edgeIndices[0];
  302. var length = edgeIndices.length;
  303. for (var i = 1; i < length; ++i) {
  304. var index = edgeIndices[i];
  305. indices[offset++] = previousIndex;
  306. indices[offset++] = index;
  307. indices[offset++] = vertexIndex;
  308. indices[offset++] = vertexIndex;
  309. indices[offset++] = index;
  310. indices[offset++] = vertexIndex + 1;
  311. previousIndex = index;
  312. ++vertexIndex;
  313. }
  314. return offset;
  315. }
  316. /**
  317. * Specifies the quality of terrain created from heightmaps. A value of 1.0 will
  318. * ensure that adjacent heightmap vertices are separated by no more than
  319. * {@link Globe.maximumScreenSpaceError} screen pixels and will probably go very slowly.
  320. * A value of 0.5 will cut the estimated level zero geometric error in half, allowing twice the
  321. * screen pixels between adjacent heightmap vertices and thus rendering more quickly.
  322. * @type {Number}
  323. */
  324. TerrainProvider.heightmapTerrainQuality = 0.25;
  325. /**
  326. * Determines an appropriate geometric error estimate when the geometry comes from a heightmap.
  327. *
  328. * @param {Ellipsoid} ellipsoid The ellipsoid to which the terrain is attached.
  329. * @param {Number} tileImageWidth The width, in pixels, of the heightmap associated with a single tile.
  330. * @param {Number} numberOfTilesAtLevelZero The number of tiles in the horizontal direction at tile level zero.
  331. * @returns {Number} An estimated geometric error.
  332. */
  333. TerrainProvider.getEstimatedLevelZeroGeometricErrorForAHeightmap = function (
  334. ellipsoid,
  335. tileImageWidth,
  336. numberOfTilesAtLevelZero
  337. ) {
  338. return (
  339. (ellipsoid.maximumRadius *
  340. 2 *
  341. Math.PI *
  342. TerrainProvider.heightmapTerrainQuality) /
  343. (tileImageWidth * numberOfTilesAtLevelZero)
  344. );
  345. };
  346. /**
  347. * Requests the geometry for a given tile. This function should not be called before
  348. * {@link TerrainProvider#ready} returns true. The result must include terrain data and
  349. * may optionally include a water mask and an indication of which child tiles are available.
  350. * @function
  351. *
  352. * @param {Number} x The X coordinate of the tile for which to request geometry.
  353. * @param {Number} y The Y coordinate of the tile for which to request geometry.
  354. * @param {Number} level The level of the tile for which to request geometry.
  355. * @param {Request} [request] The request object. Intended for internal use only.
  356. *
  357. * @returns {Promise.<TerrainData>|undefined} A promise for the requested geometry. If this method
  358. * returns undefined instead of a promise, it is an indication that too many requests are already
  359. * pending and the request will be retried later.
  360. */
  361. TerrainProvider.prototype.requestTileGeometry =
  362. Check.DeveloperError.throwInstantiationError;
  363. /**
  364. * Gets the maximum geometric error allowed in a tile at a given level. This function should not be
  365. * called before {@link TerrainProvider#ready} returns true.
  366. * @function
  367. *
  368. * @param {Number} level The tile level for which to get the maximum geometric error.
  369. * @returns {Number} The maximum geometric error.
  370. */
  371. TerrainProvider.prototype.getLevelMaximumGeometricError =
  372. Check.DeveloperError.throwInstantiationError;
  373. /**
  374. * Determines whether data for a tile is available to be loaded.
  375. * @function
  376. *
  377. * @param {Number} x The X coordinate of the tile for which to request geometry.
  378. * @param {Number} y The Y coordinate of the tile for which to request geometry.
  379. * @param {Number} level The level of the tile for which to request geometry.
  380. * @returns {Boolean} Undefined if not supported by the terrain provider, otherwise true or false.
  381. */
  382. TerrainProvider.prototype.getTileDataAvailable =
  383. Check.DeveloperError.throwInstantiationError;
  384. /**
  385. * Makes sure we load availability data for a tile
  386. * @function
  387. *
  388. * @param {Number} x The X coordinate of the tile for which to request geometry.
  389. * @param {Number} y The Y coordinate of the tile for which to request geometry.
  390. * @param {Number} level The level of the tile for which to request geometry.
  391. * @returns {undefined|Promise<void>} Undefined if nothing need to be loaded or a Promise that resolves when all required tiles are loaded
  392. */
  393. TerrainProvider.prototype.loadTileDataAvailability =
  394. Check.DeveloperError.throwInstantiationError;
  395. var maxShort = 32767;
  396. var cartesian3Scratch = new Cartesian2.Cartesian3();
  397. var scratchMinimum = new Cartesian2.Cartesian3();
  398. var scratchMaximum = new Cartesian2.Cartesian3();
  399. var cartographicScratch = new Cartesian2.Cartographic();
  400. var toPack = new Cartesian2.Cartesian2();
  401. var scratchNormal = new Cartesian2.Cartesian3();
  402. var scratchToENU = new Transforms.Matrix4();
  403. var scratchFromENU = new Transforms.Matrix4();
  404. function createVerticesFromQuantizedTerrainMesh(
  405. parameters,
  406. transferableObjects
  407. ) {
  408. var quantizedVertices = parameters.quantizedVertices;
  409. var quantizedVertexCount = quantizedVertices.length / 3;
  410. var octEncodedNormals = parameters.octEncodedNormals;
  411. var edgeVertexCount =
  412. parameters.westIndices.length +
  413. parameters.eastIndices.length +
  414. parameters.southIndices.length +
  415. parameters.northIndices.length;
  416. var includeWebMercatorT = parameters.includeWebMercatorT;
  417. var rectangle = Cartesian2.Rectangle.clone(parameters.rectangle);
  418. var west = rectangle.west;
  419. var south = rectangle.south;
  420. var east = rectangle.east;
  421. var north = rectangle.north;
  422. var ellipsoid = Cartesian2.Ellipsoid.clone(parameters.ellipsoid);
  423. var exaggeration = parameters.exaggeration;
  424. var minimumHeight = parameters.minimumHeight * exaggeration;
  425. var maximumHeight = parameters.maximumHeight * exaggeration;
  426. var center = parameters.relativeToCenter;
  427. var fromENU = Transforms.Transforms.eastNorthUpToFixedFrame(center, ellipsoid);
  428. var toENU = Transforms.Matrix4.inverseTransformation(fromENU, new Transforms.Matrix4());
  429. var southMercatorY;
  430. var oneOverMercatorHeight;
  431. if (includeWebMercatorT) {
  432. southMercatorY = WebMercatorProjection.WebMercatorProjection.geodeticLatitudeToMercatorAngle(
  433. south
  434. );
  435. oneOverMercatorHeight =
  436. 1.0 /
  437. (WebMercatorProjection.WebMercatorProjection.geodeticLatitudeToMercatorAngle(north) -
  438. southMercatorY);
  439. }
  440. var uBuffer = quantizedVertices.subarray(0, quantizedVertexCount);
  441. var vBuffer = quantizedVertices.subarray(
  442. quantizedVertexCount,
  443. 2 * quantizedVertexCount
  444. );
  445. var heightBuffer = quantizedVertices.subarray(
  446. quantizedVertexCount * 2,
  447. 3 * quantizedVertexCount
  448. );
  449. var hasVertexNormals = when.defined(octEncodedNormals);
  450. var uvs = new Array(quantizedVertexCount);
  451. var heights = new Array(quantizedVertexCount);
  452. var positions = new Array(quantizedVertexCount);
  453. var webMercatorTs = includeWebMercatorT
  454. ? new Array(quantizedVertexCount)
  455. : [];
  456. var minimum = scratchMinimum;
  457. minimum.x = Number.POSITIVE_INFINITY;
  458. minimum.y = Number.POSITIVE_INFINITY;
  459. minimum.z = Number.POSITIVE_INFINITY;
  460. var maximum = scratchMaximum;
  461. maximum.x = Number.NEGATIVE_INFINITY;
  462. maximum.y = Number.NEGATIVE_INFINITY;
  463. maximum.z = Number.NEGATIVE_INFINITY;
  464. var minLongitude = Number.POSITIVE_INFINITY;
  465. var maxLongitude = Number.NEGATIVE_INFINITY;
  466. var minLatitude = Number.POSITIVE_INFINITY;
  467. var maxLatitude = Number.NEGATIVE_INFINITY;
  468. for (var i = 0; i < quantizedVertexCount; ++i) {
  469. var rawU = uBuffer[i];
  470. var rawV = vBuffer[i];
  471. var u = rawU / maxShort;
  472. var v = rawV / maxShort;
  473. var height = _Math.CesiumMath.lerp(
  474. minimumHeight,
  475. maximumHeight,
  476. heightBuffer[i] / maxShort
  477. );
  478. cartographicScratch.longitude = _Math.CesiumMath.lerp(west, east, u);
  479. cartographicScratch.latitude = _Math.CesiumMath.lerp(south, north, v);
  480. cartographicScratch.height = height;
  481. minLongitude = Math.min(cartographicScratch.longitude, minLongitude);
  482. maxLongitude = Math.max(cartographicScratch.longitude, maxLongitude);
  483. minLatitude = Math.min(cartographicScratch.latitude, minLatitude);
  484. maxLatitude = Math.max(cartographicScratch.latitude, maxLatitude);
  485. var position = ellipsoid.cartographicToCartesian(cartographicScratch);
  486. uvs[i] = new Cartesian2.Cartesian2(u, v);
  487. heights[i] = height;
  488. positions[i] = position;
  489. if (includeWebMercatorT) {
  490. webMercatorTs[i] =
  491. (WebMercatorProjection.WebMercatorProjection.geodeticLatitudeToMercatorAngle(
  492. cartographicScratch.latitude
  493. ) -
  494. southMercatorY) *
  495. oneOverMercatorHeight;
  496. }
  497. Transforms.Matrix4.multiplyByPoint(toENU, position, cartesian3Scratch);
  498. Cartesian2.Cartesian3.minimumByComponent(cartesian3Scratch, minimum, minimum);
  499. Cartesian2.Cartesian3.maximumByComponent(cartesian3Scratch, maximum, maximum);
  500. }
  501. var westIndicesSouthToNorth = copyAndSort(parameters.westIndices, function (
  502. a,
  503. b
  504. ) {
  505. return uvs[a].y - uvs[b].y;
  506. });
  507. var eastIndicesNorthToSouth = copyAndSort(parameters.eastIndices, function (
  508. a,
  509. b
  510. ) {
  511. return uvs[b].y - uvs[a].y;
  512. });
  513. var southIndicesEastToWest = copyAndSort(parameters.southIndices, function (
  514. a,
  515. b
  516. ) {
  517. return uvs[b].x - uvs[a].x;
  518. });
  519. var northIndicesWestToEast = copyAndSort(parameters.northIndices, function (
  520. a,
  521. b
  522. ) {
  523. return uvs[a].x - uvs[b].x;
  524. });
  525. var orientedBoundingBox;
  526. var boundingSphere;
  527. if (exaggeration !== 1.0) {
  528. // Bounding volumes need to be recomputed since the tile payload assumes no exaggeration.
  529. boundingSphere = Transforms.BoundingSphere.fromPoints(positions);
  530. orientedBoundingBox = OrientedBoundingBox.OrientedBoundingBox.fromRectangle(
  531. rectangle,
  532. minimumHeight,
  533. maximumHeight,
  534. ellipsoid
  535. );
  536. }
  537. var occludeePointInScaledSpace;
  538. if (exaggeration !== 1.0 || minimumHeight < 0.0) {
  539. // Horizon culling point needs to be recomputed since the tile payload assumes no exaggeration.
  540. var occluder = new TerrainEncoding.EllipsoidalOccluder(ellipsoid);
  541. occludeePointInScaledSpace = occluder.computeHorizonCullingPointPossiblyUnderEllipsoid(
  542. center,
  543. positions,
  544. minimumHeight
  545. );
  546. }
  547. var hMin = minimumHeight;
  548. hMin = Math.min(
  549. hMin,
  550. findMinMaxSkirts(
  551. parameters.westIndices,
  552. parameters.westSkirtHeight,
  553. heights,
  554. uvs,
  555. rectangle,
  556. ellipsoid,
  557. toENU,
  558. minimum,
  559. maximum
  560. )
  561. );
  562. hMin = Math.min(
  563. hMin,
  564. findMinMaxSkirts(
  565. parameters.southIndices,
  566. parameters.southSkirtHeight,
  567. heights,
  568. uvs,
  569. rectangle,
  570. ellipsoid,
  571. toENU,
  572. minimum,
  573. maximum
  574. )
  575. );
  576. hMin = Math.min(
  577. hMin,
  578. findMinMaxSkirts(
  579. parameters.eastIndices,
  580. parameters.eastSkirtHeight,
  581. heights,
  582. uvs,
  583. rectangle,
  584. ellipsoid,
  585. toENU,
  586. minimum,
  587. maximum
  588. )
  589. );
  590. hMin = Math.min(
  591. hMin,
  592. findMinMaxSkirts(
  593. parameters.northIndices,
  594. parameters.northSkirtHeight,
  595. heights,
  596. uvs,
  597. rectangle,
  598. ellipsoid,
  599. toENU,
  600. minimum,
  601. maximum
  602. )
  603. );
  604. var aaBox = new EllipsoidTangentPlane.AxisAlignedBoundingBox(minimum, maximum, center);
  605. var encoding = new TerrainEncoding.TerrainEncoding(
  606. aaBox,
  607. hMin,
  608. maximumHeight,
  609. fromENU,
  610. hasVertexNormals,
  611. includeWebMercatorT
  612. );
  613. var vertexStride = encoding.getStride();
  614. var size =
  615. quantizedVertexCount * vertexStride + edgeVertexCount * vertexStride;
  616. var vertexBuffer = new Float32Array(size);
  617. var bufferIndex = 0;
  618. for (var j = 0; j < quantizedVertexCount; ++j) {
  619. if (hasVertexNormals) {
  620. var n = j * 2.0;
  621. toPack.x = octEncodedNormals[n];
  622. toPack.y = octEncodedNormals[n + 1];
  623. if (exaggeration !== 1.0) {
  624. var normal = AttributeCompression.AttributeCompression.octDecode(
  625. toPack.x,
  626. toPack.y,
  627. scratchNormal
  628. );
  629. var fromENUNormal = Transforms.Transforms.eastNorthUpToFixedFrame(
  630. positions[j],
  631. ellipsoid,
  632. scratchFromENU
  633. );
  634. var toENUNormal = Transforms.Matrix4.inverseTransformation(
  635. fromENUNormal,
  636. scratchToENU
  637. );
  638. Transforms.Matrix4.multiplyByPointAsVector(toENUNormal, normal, normal);
  639. normal.z *= exaggeration;
  640. Cartesian2.Cartesian3.normalize(normal, normal);
  641. Transforms.Matrix4.multiplyByPointAsVector(fromENUNormal, normal, normal);
  642. Cartesian2.Cartesian3.normalize(normal, normal);
  643. AttributeCompression.AttributeCompression.octEncode(normal, toPack);
  644. }
  645. }
  646. bufferIndex = encoding.encode(
  647. vertexBuffer,
  648. bufferIndex,
  649. positions[j],
  650. uvs[j],
  651. heights[j],
  652. toPack,
  653. webMercatorTs[j]
  654. );
  655. }
  656. var edgeTriangleCount = Math.max(0, (edgeVertexCount - 4) * 2);
  657. var indexBufferLength = parameters.indices.length + edgeTriangleCount * 3;
  658. var indexBuffer = IndexDatatype.IndexDatatype.createTypedArray(
  659. quantizedVertexCount + edgeVertexCount,
  660. indexBufferLength
  661. );
  662. indexBuffer.set(parameters.indices, 0);
  663. var percentage = 0.0001;
  664. var lonOffset = (maxLongitude - minLongitude) * percentage;
  665. var latOffset = (maxLatitude - minLatitude) * percentage;
  666. var westLongitudeOffset = -lonOffset;
  667. var westLatitudeOffset = 0.0;
  668. var eastLongitudeOffset = lonOffset;
  669. var eastLatitudeOffset = 0.0;
  670. var northLongitudeOffset = 0.0;
  671. var northLatitudeOffset = latOffset;
  672. var southLongitudeOffset = 0.0;
  673. var southLatitudeOffset = -latOffset;
  674. // Add skirts.
  675. var vertexBufferIndex = quantizedVertexCount * vertexStride;
  676. addSkirt(
  677. vertexBuffer,
  678. vertexBufferIndex,
  679. westIndicesSouthToNorth,
  680. encoding,
  681. heights,
  682. uvs,
  683. octEncodedNormals,
  684. ellipsoid,
  685. rectangle,
  686. parameters.westSkirtHeight,
  687. exaggeration,
  688. southMercatorY,
  689. oneOverMercatorHeight,
  690. westLongitudeOffset,
  691. westLatitudeOffset
  692. );
  693. vertexBufferIndex += parameters.westIndices.length * vertexStride;
  694. addSkirt(
  695. vertexBuffer,
  696. vertexBufferIndex,
  697. southIndicesEastToWest,
  698. encoding,
  699. heights,
  700. uvs,
  701. octEncodedNormals,
  702. ellipsoid,
  703. rectangle,
  704. parameters.southSkirtHeight,
  705. exaggeration,
  706. southMercatorY,
  707. oneOverMercatorHeight,
  708. southLongitudeOffset,
  709. southLatitudeOffset
  710. );
  711. vertexBufferIndex += parameters.southIndices.length * vertexStride;
  712. addSkirt(
  713. vertexBuffer,
  714. vertexBufferIndex,
  715. eastIndicesNorthToSouth,
  716. encoding,
  717. heights,
  718. uvs,
  719. octEncodedNormals,
  720. ellipsoid,
  721. rectangle,
  722. parameters.eastSkirtHeight,
  723. exaggeration,
  724. southMercatorY,
  725. oneOverMercatorHeight,
  726. eastLongitudeOffset,
  727. eastLatitudeOffset
  728. );
  729. vertexBufferIndex += parameters.eastIndices.length * vertexStride;
  730. addSkirt(
  731. vertexBuffer,
  732. vertexBufferIndex,
  733. northIndicesWestToEast,
  734. encoding,
  735. heights,
  736. uvs,
  737. octEncodedNormals,
  738. ellipsoid,
  739. rectangle,
  740. parameters.northSkirtHeight,
  741. exaggeration,
  742. southMercatorY,
  743. oneOverMercatorHeight,
  744. northLongitudeOffset,
  745. northLatitudeOffset
  746. );
  747. TerrainProvider.addSkirtIndices(
  748. westIndicesSouthToNorth,
  749. southIndicesEastToWest,
  750. eastIndicesNorthToSouth,
  751. northIndicesWestToEast,
  752. quantizedVertexCount,
  753. indexBuffer,
  754. parameters.indices.length
  755. );
  756. transferableObjects.push(vertexBuffer.buffer, indexBuffer.buffer);
  757. return {
  758. vertices: vertexBuffer.buffer,
  759. indices: indexBuffer.buffer,
  760. westIndicesSouthToNorth: westIndicesSouthToNorth,
  761. southIndicesEastToWest: southIndicesEastToWest,
  762. eastIndicesNorthToSouth: eastIndicesNorthToSouth,
  763. northIndicesWestToEast: northIndicesWestToEast,
  764. vertexStride: vertexStride,
  765. center: center,
  766. minimumHeight: minimumHeight,
  767. maximumHeight: maximumHeight,
  768. boundingSphere: boundingSphere,
  769. orientedBoundingBox: orientedBoundingBox,
  770. occludeePointInScaledSpace: occludeePointInScaledSpace,
  771. encoding: encoding,
  772. indexCountWithoutSkirts: parameters.indices.length,
  773. };
  774. }
  775. function findMinMaxSkirts(
  776. edgeIndices,
  777. edgeHeight,
  778. heights,
  779. uvs,
  780. rectangle,
  781. ellipsoid,
  782. toENU,
  783. minimum,
  784. maximum
  785. ) {
  786. var hMin = Number.POSITIVE_INFINITY;
  787. var north = rectangle.north;
  788. var south = rectangle.south;
  789. var east = rectangle.east;
  790. var west = rectangle.west;
  791. if (east < west) {
  792. east += _Math.CesiumMath.TWO_PI;
  793. }
  794. var length = edgeIndices.length;
  795. for (var i = 0; i < length; ++i) {
  796. var index = edgeIndices[i];
  797. var h = heights[index];
  798. var uv = uvs[index];
  799. cartographicScratch.longitude = _Math.CesiumMath.lerp(west, east, uv.x);
  800. cartographicScratch.latitude = _Math.CesiumMath.lerp(south, north, uv.y);
  801. cartographicScratch.height = h - edgeHeight;
  802. var position = ellipsoid.cartographicToCartesian(
  803. cartographicScratch,
  804. cartesian3Scratch
  805. );
  806. Transforms.Matrix4.multiplyByPoint(toENU, position, position);
  807. Cartesian2.Cartesian3.minimumByComponent(position, minimum, minimum);
  808. Cartesian2.Cartesian3.maximumByComponent(position, maximum, maximum);
  809. hMin = Math.min(hMin, cartographicScratch.height);
  810. }
  811. return hMin;
  812. }
  813. function addSkirt(
  814. vertexBuffer,
  815. vertexBufferIndex,
  816. edgeVertices,
  817. encoding,
  818. heights,
  819. uvs,
  820. octEncodedNormals,
  821. ellipsoid,
  822. rectangle,
  823. skirtLength,
  824. exaggeration,
  825. southMercatorY,
  826. oneOverMercatorHeight,
  827. longitudeOffset,
  828. latitudeOffset
  829. ) {
  830. var hasVertexNormals = when.defined(octEncodedNormals);
  831. var north = rectangle.north;
  832. var south = rectangle.south;
  833. var east = rectangle.east;
  834. var west = rectangle.west;
  835. if (east < west) {
  836. east += _Math.CesiumMath.TWO_PI;
  837. }
  838. var length = edgeVertices.length;
  839. for (var i = 0; i < length; ++i) {
  840. var index = edgeVertices[i];
  841. var h = heights[index];
  842. var uv = uvs[index];
  843. cartographicScratch.longitude =
  844. _Math.CesiumMath.lerp(west, east, uv.x) + longitudeOffset;
  845. cartographicScratch.latitude =
  846. _Math.CesiumMath.lerp(south, north, uv.y) + latitudeOffset;
  847. cartographicScratch.height = h - skirtLength;
  848. var position = ellipsoid.cartographicToCartesian(
  849. cartographicScratch,
  850. cartesian3Scratch
  851. );
  852. if (hasVertexNormals) {
  853. var n = index * 2.0;
  854. toPack.x = octEncodedNormals[n];
  855. toPack.y = octEncodedNormals[n + 1];
  856. if (exaggeration !== 1.0) {
  857. var normal = AttributeCompression.AttributeCompression.octDecode(
  858. toPack.x,
  859. toPack.y,
  860. scratchNormal
  861. );
  862. var fromENUNormal = Transforms.Transforms.eastNorthUpToFixedFrame(
  863. cartesian3Scratch,
  864. ellipsoid,
  865. scratchFromENU
  866. );
  867. var toENUNormal = Transforms.Matrix4.inverseTransformation(
  868. fromENUNormal,
  869. scratchToENU
  870. );
  871. Transforms.Matrix4.multiplyByPointAsVector(toENUNormal, normal, normal);
  872. normal.z *= exaggeration;
  873. Cartesian2.Cartesian3.normalize(normal, normal);
  874. Transforms.Matrix4.multiplyByPointAsVector(fromENUNormal, normal, normal);
  875. Cartesian2.Cartesian3.normalize(normal, normal);
  876. AttributeCompression.AttributeCompression.octEncode(normal, toPack);
  877. }
  878. }
  879. var webMercatorT;
  880. if (encoding.hasWebMercatorT) {
  881. webMercatorT =
  882. (WebMercatorProjection.WebMercatorProjection.geodeticLatitudeToMercatorAngle(
  883. cartographicScratch.latitude
  884. ) -
  885. southMercatorY) *
  886. oneOverMercatorHeight;
  887. }
  888. vertexBufferIndex = encoding.encode(
  889. vertexBuffer,
  890. vertexBufferIndex,
  891. position,
  892. uv,
  893. cartographicScratch.height,
  894. toPack,
  895. webMercatorT
  896. );
  897. }
  898. }
  899. function copyAndSort(typedArray, comparator) {
  900. var copy;
  901. if (typeof typedArray.slice === "function") {
  902. copy = typedArray.slice();
  903. if (typeof copy.sort !== "function") {
  904. // Sliced typed array isn't sortable, so we can't use it.
  905. copy = undefined;
  906. }
  907. }
  908. if (!when.defined(copy)) {
  909. copy = Array.prototype.slice.call(typedArray);
  910. }
  911. copy.sort(comparator);
  912. return copy;
  913. }
  914. var createVerticesFromQuantizedTerrainMesh$1 = createTaskProcessorWorker(
  915. createVerticesFromQuantizedTerrainMesh
  916. );
  917. return createVerticesFromQuantizedTerrainMesh$1;
  918. });