upsampleQuantizedTerrainMesh.js 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048
  1. /**
  2. * @license
  3. * Cesium - https://github.com/CesiumGS/cesium
  4. * Version 1.97
  5. *
  6. * Copyright 2011-2022 Cesium Contributors
  7. *
  8. * Licensed under the Apache License, Version 2.0 (the "License");
  9. * you may not use this file except in compliance with the License.
  10. * You may obtain a copy of the License at
  11. *
  12. * http://www.apache.org/licenses/LICENSE-2.0
  13. *
  14. * Unless required by applicable law or agreed to in writing, software
  15. * distributed under the License is distributed on an "AS IS" BASIS,
  16. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17. * See the License for the specific language governing permissions and
  18. * limitations under the License.
  19. *
  20. * Columbus View (Pat. Pend.)
  21. *
  22. * Portions licensed separately.
  23. * See https://github.com/CesiumGS/cesium/blob/main/LICENSE.md for full licensing details.
  24. */
  25. define(['./AttributeCompression-8033f934', './Transforms-c78c4637', './Matrix2-ab676047', './defaultValue-a6eb9f34', './TerrainEncoding-74a00123', './IndexDatatype-c2232ebd', './RuntimeError-1088cc64', './ComponentDatatype-e06f4e16', './OrientedBoundingBox-28f77441', './createTaskProcessorWorker', './_commonjsHelpers-89c9b271', './combine-7cf28d88', './WebGLConstants-d81b330d', './EllipsoidTangentPlane-6691e012', './AxisAlignedBoundingBox-51d5a498', './IntersectionTests-f96cd46d', './Plane-c985a1d2'], (function (AttributeCompression, Transforms, Matrix2, defaultValue, TerrainEncoding, IndexDatatype, RuntimeError, ComponentDatatype, OrientedBoundingBox, createTaskProcessorWorker, _commonjsHelpers, combine, WebGLConstants, EllipsoidTangentPlane, AxisAlignedBoundingBox, IntersectionTests, Plane) { 'use strict';
  26. /**
  27. * Contains functions for operating on 2D triangles.
  28. *
  29. * @namespace Intersections2D
  30. */
  31. const Intersections2D = {};
  32. /**
  33. * Splits a 2D triangle at given axis-aligned threshold value and returns the resulting
  34. * polygon on a given side of the threshold. The resulting polygon may have 0, 1, 2,
  35. * 3, or 4 vertices.
  36. *
  37. * @param {Number} threshold The threshold coordinate value at which to clip the triangle.
  38. * @param {Boolean} keepAbove true to keep the portion of the triangle above the threshold, or false
  39. * to keep the portion below.
  40. * @param {Number} u0 The coordinate of the first vertex in the triangle, in counter-clockwise order.
  41. * @param {Number} u1 The coordinate of the second vertex in the triangle, in counter-clockwise order.
  42. * @param {Number} u2 The coordinate of the third vertex in the triangle, in counter-clockwise order.
  43. * @param {Number[]} [result] The array into which to copy the result. If this parameter is not supplied,
  44. * a new array is constructed and returned.
  45. * @returns {Number[]} The polygon that results after the clip, specified as a list of
  46. * vertices. The vertices are specified in counter-clockwise order.
  47. * Each vertex is either an index from the existing list (identified as
  48. * a 0, 1, or 2) or -1 indicating a new vertex not in the original triangle.
  49. * For new vertices, the -1 is followed by three additional numbers: the
  50. * index of each of the two original vertices forming the line segment that
  51. * the new vertex lies on, and the fraction of the distance from the first
  52. * vertex to the second one.
  53. *
  54. * @example
  55. * const result = Cesium.Intersections2D.clipTriangleAtAxisAlignedThreshold(0.5, false, 0.2, 0.6, 0.4);
  56. * // result === [2, 0, -1, 1, 0, 0.25, -1, 1, 2, 0.5]
  57. */
  58. Intersections2D.clipTriangleAtAxisAlignedThreshold = function (
  59. threshold,
  60. keepAbove,
  61. u0,
  62. u1,
  63. u2,
  64. result
  65. ) {
  66. //>>includeStart('debug', pragmas.debug);
  67. if (!defaultValue.defined(threshold)) {
  68. throw new RuntimeError.DeveloperError("threshold is required.");
  69. }
  70. if (!defaultValue.defined(keepAbove)) {
  71. throw new RuntimeError.DeveloperError("keepAbove is required.");
  72. }
  73. if (!defaultValue.defined(u0)) {
  74. throw new RuntimeError.DeveloperError("u0 is required.");
  75. }
  76. if (!defaultValue.defined(u1)) {
  77. throw new RuntimeError.DeveloperError("u1 is required.");
  78. }
  79. if (!defaultValue.defined(u2)) {
  80. throw new RuntimeError.DeveloperError("u2 is required.");
  81. }
  82. //>>includeEnd('debug');
  83. if (!defaultValue.defined(result)) {
  84. result = [];
  85. } else {
  86. result.length = 0;
  87. }
  88. let u0Behind;
  89. let u1Behind;
  90. let u2Behind;
  91. if (keepAbove) {
  92. u0Behind = u0 < threshold;
  93. u1Behind = u1 < threshold;
  94. u2Behind = u2 < threshold;
  95. } else {
  96. u0Behind = u0 > threshold;
  97. u1Behind = u1 > threshold;
  98. u2Behind = u2 > threshold;
  99. }
  100. const numBehind = u0Behind + u1Behind + u2Behind;
  101. let u01Ratio;
  102. let u02Ratio;
  103. let u12Ratio;
  104. let u10Ratio;
  105. let u20Ratio;
  106. let u21Ratio;
  107. if (numBehind === 1) {
  108. if (u0Behind) {
  109. u01Ratio = (threshold - u0) / (u1 - u0);
  110. u02Ratio = (threshold - u0) / (u2 - u0);
  111. result.push(1);
  112. result.push(2);
  113. if (u02Ratio !== 1.0) {
  114. result.push(-1);
  115. result.push(0);
  116. result.push(2);
  117. result.push(u02Ratio);
  118. }
  119. if (u01Ratio !== 1.0) {
  120. result.push(-1);
  121. result.push(0);
  122. result.push(1);
  123. result.push(u01Ratio);
  124. }
  125. } else if (u1Behind) {
  126. u12Ratio = (threshold - u1) / (u2 - u1);
  127. u10Ratio = (threshold - u1) / (u0 - u1);
  128. result.push(2);
  129. result.push(0);
  130. if (u10Ratio !== 1.0) {
  131. result.push(-1);
  132. result.push(1);
  133. result.push(0);
  134. result.push(u10Ratio);
  135. }
  136. if (u12Ratio !== 1.0) {
  137. result.push(-1);
  138. result.push(1);
  139. result.push(2);
  140. result.push(u12Ratio);
  141. }
  142. } else if (u2Behind) {
  143. u20Ratio = (threshold - u2) / (u0 - u2);
  144. u21Ratio = (threshold - u2) / (u1 - u2);
  145. result.push(0);
  146. result.push(1);
  147. if (u21Ratio !== 1.0) {
  148. result.push(-1);
  149. result.push(2);
  150. result.push(1);
  151. result.push(u21Ratio);
  152. }
  153. if (u20Ratio !== 1.0) {
  154. result.push(-1);
  155. result.push(2);
  156. result.push(0);
  157. result.push(u20Ratio);
  158. }
  159. }
  160. } else if (numBehind === 2) {
  161. if (!u0Behind && u0 !== threshold) {
  162. u10Ratio = (threshold - u1) / (u0 - u1);
  163. u20Ratio = (threshold - u2) / (u0 - u2);
  164. result.push(0);
  165. result.push(-1);
  166. result.push(1);
  167. result.push(0);
  168. result.push(u10Ratio);
  169. result.push(-1);
  170. result.push(2);
  171. result.push(0);
  172. result.push(u20Ratio);
  173. } else if (!u1Behind && u1 !== threshold) {
  174. u21Ratio = (threshold - u2) / (u1 - u2);
  175. u01Ratio = (threshold - u0) / (u1 - u0);
  176. result.push(1);
  177. result.push(-1);
  178. result.push(2);
  179. result.push(1);
  180. result.push(u21Ratio);
  181. result.push(-1);
  182. result.push(0);
  183. result.push(1);
  184. result.push(u01Ratio);
  185. } else if (!u2Behind && u2 !== threshold) {
  186. u02Ratio = (threshold - u0) / (u2 - u0);
  187. u12Ratio = (threshold - u1) / (u2 - u1);
  188. result.push(2);
  189. result.push(-1);
  190. result.push(0);
  191. result.push(2);
  192. result.push(u02Ratio);
  193. result.push(-1);
  194. result.push(1);
  195. result.push(2);
  196. result.push(u12Ratio);
  197. }
  198. } else if (numBehind !== 3) {
  199. // Completely in front of threshold
  200. result.push(0);
  201. result.push(1);
  202. result.push(2);
  203. }
  204. // else Completely behind threshold
  205. return result;
  206. };
  207. /**
  208. * Compute the barycentric coordinates of a 2D position within a 2D triangle.
  209. *
  210. * @param {Number} x The x coordinate of the position for which to find the barycentric coordinates.
  211. * @param {Number} y The y coordinate of the position for which to find the barycentric coordinates.
  212. * @param {Number} x1 The x coordinate of the triangle's first vertex.
  213. * @param {Number} y1 The y coordinate of the triangle's first vertex.
  214. * @param {Number} x2 The x coordinate of the triangle's second vertex.
  215. * @param {Number} y2 The y coordinate of the triangle's second vertex.
  216. * @param {Number} x3 The x coordinate of the triangle's third vertex.
  217. * @param {Number} y3 The y coordinate of the triangle's third vertex.
  218. * @param {Cartesian3} [result] The instance into to which to copy the result. If this parameter
  219. * is undefined, a new instance is created and returned.
  220. * @returns {Cartesian3} The barycentric coordinates of the position within the triangle.
  221. *
  222. * @example
  223. * const result = Cesium.Intersections2D.computeBarycentricCoordinates(0.0, 0.0, 0.0, 1.0, -1, -0.5, 1, -0.5);
  224. * // result === new Cesium.Cartesian3(1.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0);
  225. */
  226. Intersections2D.computeBarycentricCoordinates = function (
  227. x,
  228. y,
  229. x1,
  230. y1,
  231. x2,
  232. y2,
  233. x3,
  234. y3,
  235. result
  236. ) {
  237. //>>includeStart('debug', pragmas.debug);
  238. if (!defaultValue.defined(x)) {
  239. throw new RuntimeError.DeveloperError("x is required.");
  240. }
  241. if (!defaultValue.defined(y)) {
  242. throw new RuntimeError.DeveloperError("y is required.");
  243. }
  244. if (!defaultValue.defined(x1)) {
  245. throw new RuntimeError.DeveloperError("x1 is required.");
  246. }
  247. if (!defaultValue.defined(y1)) {
  248. throw new RuntimeError.DeveloperError("y1 is required.");
  249. }
  250. if (!defaultValue.defined(x2)) {
  251. throw new RuntimeError.DeveloperError("x2 is required.");
  252. }
  253. if (!defaultValue.defined(y2)) {
  254. throw new RuntimeError.DeveloperError("y2 is required.");
  255. }
  256. if (!defaultValue.defined(x3)) {
  257. throw new RuntimeError.DeveloperError("x3 is required.");
  258. }
  259. if (!defaultValue.defined(y3)) {
  260. throw new RuntimeError.DeveloperError("y3 is required.");
  261. }
  262. //>>includeEnd('debug');
  263. const x1mx3 = x1 - x3;
  264. const x3mx2 = x3 - x2;
  265. const y2my3 = y2 - y3;
  266. const y1my3 = y1 - y3;
  267. const inverseDeterminant = 1.0 / (y2my3 * x1mx3 + x3mx2 * y1my3);
  268. const ymy3 = y - y3;
  269. const xmx3 = x - x3;
  270. const l1 = (y2my3 * xmx3 + x3mx2 * ymy3) * inverseDeterminant;
  271. const l2 = (-y1my3 * xmx3 + x1mx3 * ymy3) * inverseDeterminant;
  272. const l3 = 1.0 - l1 - l2;
  273. if (defaultValue.defined(result)) {
  274. result.x = l1;
  275. result.y = l2;
  276. result.z = l3;
  277. return result;
  278. }
  279. return new Matrix2.Cartesian3(l1, l2, l3);
  280. };
  281. /**
  282. * Compute the intersection between 2 line segments
  283. *
  284. * @param {Number} x00 The x coordinate of the first line's first vertex.
  285. * @param {Number} y00 The y coordinate of the first line's first vertex.
  286. * @param {Number} x01 The x coordinate of the first line's second vertex.
  287. * @param {Number} y01 The y coordinate of the first line's second vertex.
  288. * @param {Number} x10 The x coordinate of the second line's first vertex.
  289. * @param {Number} y10 The y coordinate of the second line's first vertex.
  290. * @param {Number} x11 The x coordinate of the second line's second vertex.
  291. * @param {Number} y11 The y coordinate of the second line's second vertex.
  292. * @param {Cartesian2} [result] The instance into to which to copy the result. If this parameter
  293. * is undefined, a new instance is created and returned.
  294. * @returns {Cartesian2} The intersection point, undefined if there is no intersection point or lines are coincident.
  295. *
  296. * @example
  297. * const result = Cesium.Intersections2D.computeLineSegmentLineSegmentIntersection(0.0, 0.0, 0.0, 2.0, -1, 1, 1, 1);
  298. * // result === new Cesium.Cartesian2(0.0, 1.0);
  299. */
  300. Intersections2D.computeLineSegmentLineSegmentIntersection = function (
  301. x00,
  302. y00,
  303. x01,
  304. y01,
  305. x10,
  306. y10,
  307. x11,
  308. y11,
  309. result
  310. ) {
  311. //>>includeStart('debug', pragmas.debug);
  312. RuntimeError.Check.typeOf.number("x00", x00);
  313. RuntimeError.Check.typeOf.number("y00", y00);
  314. RuntimeError.Check.typeOf.number("x01", x01);
  315. RuntimeError.Check.typeOf.number("y01", y01);
  316. RuntimeError.Check.typeOf.number("x10", x10);
  317. RuntimeError.Check.typeOf.number("y10", y10);
  318. RuntimeError.Check.typeOf.number("x11", x11);
  319. RuntimeError.Check.typeOf.number("y11", y11);
  320. //>>includeEnd('debug');
  321. const numerator1A = (x11 - x10) * (y00 - y10) - (y11 - y10) * (x00 - x10);
  322. const numerator1B = (x01 - x00) * (y00 - y10) - (y01 - y00) * (x00 - x10);
  323. const denominator1 = (y11 - y10) * (x01 - x00) - (x11 - x10) * (y01 - y00);
  324. // If denominator = 0, then lines are parallel. If denominator = 0 and both numerators are 0, then coincident
  325. if (denominator1 === 0) {
  326. return;
  327. }
  328. const ua1 = numerator1A / denominator1;
  329. const ub1 = numerator1B / denominator1;
  330. if (ua1 >= 0 && ua1 <= 1 && ub1 >= 0 && ub1 <= 1) {
  331. if (!defaultValue.defined(result)) {
  332. result = new Matrix2.Cartesian2();
  333. }
  334. result.x = x00 + ua1 * (x01 - x00);
  335. result.y = y00 + ua1 * (y01 - y00);
  336. return result;
  337. }
  338. };
  339. var Intersections2D$1 = Intersections2D;
  340. const maxShort = 32767;
  341. const halfMaxShort = (maxShort / 2) | 0;
  342. const clipScratch = [];
  343. const clipScratch2 = [];
  344. const verticesScratch = [];
  345. const cartographicScratch = new Matrix2.Cartographic();
  346. let cartesian3Scratch = new Matrix2.Cartesian3();
  347. const uScratch = [];
  348. const vScratch = [];
  349. const heightScratch = [];
  350. const indicesScratch = [];
  351. const normalsScratch = [];
  352. const horizonOcclusionPointScratch = new Matrix2.Cartesian3();
  353. const boundingSphereScratch = new Transforms.BoundingSphere();
  354. const orientedBoundingBoxScratch = new OrientedBoundingBox.OrientedBoundingBox();
  355. const decodeTexCoordsScratch = new Matrix2.Cartesian2();
  356. const octEncodedNormalScratch = new Matrix2.Cartesian3();
  357. function upsampleQuantizedTerrainMesh(parameters, transferableObjects) {
  358. const isEastChild = parameters.isEastChild;
  359. const isNorthChild = parameters.isNorthChild;
  360. const minU = isEastChild ? halfMaxShort : 0;
  361. const maxU = isEastChild ? maxShort : halfMaxShort;
  362. const minV = isNorthChild ? halfMaxShort : 0;
  363. const maxV = isNorthChild ? maxShort : halfMaxShort;
  364. const uBuffer = uScratch;
  365. const vBuffer = vScratch;
  366. const heightBuffer = heightScratch;
  367. const normalBuffer = normalsScratch;
  368. uBuffer.length = 0;
  369. vBuffer.length = 0;
  370. heightBuffer.length = 0;
  371. normalBuffer.length = 0;
  372. const indices = indicesScratch;
  373. indices.length = 0;
  374. const vertexMap = {};
  375. const parentVertices = parameters.vertices;
  376. let parentIndices = parameters.indices;
  377. parentIndices = parentIndices.subarray(0, parameters.indexCountWithoutSkirts);
  378. const encoding = TerrainEncoding.TerrainEncoding.clone(parameters.encoding);
  379. const hasVertexNormals = encoding.hasVertexNormals;
  380. let vertexCount = 0;
  381. const quantizedVertexCount = parameters.vertexCountWithoutSkirts;
  382. const parentMinimumHeight = parameters.minimumHeight;
  383. const parentMaximumHeight = parameters.maximumHeight;
  384. const parentUBuffer = new Array(quantizedVertexCount);
  385. const parentVBuffer = new Array(quantizedVertexCount);
  386. const parentHeightBuffer = new Array(quantizedVertexCount);
  387. const parentNormalBuffer = hasVertexNormals
  388. ? new Array(quantizedVertexCount * 2)
  389. : undefined;
  390. const threshold = 20;
  391. let height;
  392. let i, n;
  393. let u, v;
  394. for (i = 0, n = 0; i < quantizedVertexCount; ++i, n += 2) {
  395. const texCoords = encoding.decodeTextureCoordinates(
  396. parentVertices,
  397. i,
  398. decodeTexCoordsScratch
  399. );
  400. height = encoding.decodeHeight(parentVertices, i);
  401. u = ComponentDatatype.CesiumMath.clamp((texCoords.x * maxShort) | 0, 0, maxShort);
  402. v = ComponentDatatype.CesiumMath.clamp((texCoords.y * maxShort) | 0, 0, maxShort);
  403. parentHeightBuffer[i] = ComponentDatatype.CesiumMath.clamp(
  404. (((height - parentMinimumHeight) /
  405. (parentMaximumHeight - parentMinimumHeight)) *
  406. maxShort) |
  407. 0,
  408. 0,
  409. maxShort
  410. );
  411. if (u < threshold) {
  412. u = 0;
  413. }
  414. if (v < threshold) {
  415. v = 0;
  416. }
  417. if (maxShort - u < threshold) {
  418. u = maxShort;
  419. }
  420. if (maxShort - v < threshold) {
  421. v = maxShort;
  422. }
  423. parentUBuffer[i] = u;
  424. parentVBuffer[i] = v;
  425. if (hasVertexNormals) {
  426. const encodedNormal = encoding.getOctEncodedNormal(
  427. parentVertices,
  428. i,
  429. octEncodedNormalScratch
  430. );
  431. parentNormalBuffer[n] = encodedNormal.x;
  432. parentNormalBuffer[n + 1] = encodedNormal.y;
  433. }
  434. if (
  435. ((isEastChild && u >= halfMaxShort) ||
  436. (!isEastChild && u <= halfMaxShort)) &&
  437. ((isNorthChild && v >= halfMaxShort) ||
  438. (!isNorthChild && v <= halfMaxShort))
  439. ) {
  440. vertexMap[i] = vertexCount;
  441. uBuffer.push(u);
  442. vBuffer.push(v);
  443. heightBuffer.push(parentHeightBuffer[i]);
  444. if (hasVertexNormals) {
  445. normalBuffer.push(parentNormalBuffer[n]);
  446. normalBuffer.push(parentNormalBuffer[n + 1]);
  447. }
  448. ++vertexCount;
  449. }
  450. }
  451. const triangleVertices = [];
  452. triangleVertices.push(new Vertex());
  453. triangleVertices.push(new Vertex());
  454. triangleVertices.push(new Vertex());
  455. const clippedTriangleVertices = [];
  456. clippedTriangleVertices.push(new Vertex());
  457. clippedTriangleVertices.push(new Vertex());
  458. clippedTriangleVertices.push(new Vertex());
  459. let clippedIndex;
  460. let clipped2;
  461. for (i = 0; i < parentIndices.length; i += 3) {
  462. const i0 = parentIndices[i];
  463. const i1 = parentIndices[i + 1];
  464. const i2 = parentIndices[i + 2];
  465. const u0 = parentUBuffer[i0];
  466. const u1 = parentUBuffer[i1];
  467. const u2 = parentUBuffer[i2];
  468. triangleVertices[0].initializeIndexed(
  469. parentUBuffer,
  470. parentVBuffer,
  471. parentHeightBuffer,
  472. parentNormalBuffer,
  473. i0
  474. );
  475. triangleVertices[1].initializeIndexed(
  476. parentUBuffer,
  477. parentVBuffer,
  478. parentHeightBuffer,
  479. parentNormalBuffer,
  480. i1
  481. );
  482. triangleVertices[2].initializeIndexed(
  483. parentUBuffer,
  484. parentVBuffer,
  485. parentHeightBuffer,
  486. parentNormalBuffer,
  487. i2
  488. );
  489. // Clip triangle on the east-west boundary.
  490. const clipped = Intersections2D$1.clipTriangleAtAxisAlignedThreshold(
  491. halfMaxShort,
  492. isEastChild,
  493. u0,
  494. u1,
  495. u2,
  496. clipScratch
  497. );
  498. // Get the first clipped triangle, if any.
  499. clippedIndex = 0;
  500. if (clippedIndex >= clipped.length) {
  501. continue;
  502. }
  503. clippedIndex = clippedTriangleVertices[0].initializeFromClipResult(
  504. clipped,
  505. clippedIndex,
  506. triangleVertices
  507. );
  508. if (clippedIndex >= clipped.length) {
  509. continue;
  510. }
  511. clippedIndex = clippedTriangleVertices[1].initializeFromClipResult(
  512. clipped,
  513. clippedIndex,
  514. triangleVertices
  515. );
  516. if (clippedIndex >= clipped.length) {
  517. continue;
  518. }
  519. clippedIndex = clippedTriangleVertices[2].initializeFromClipResult(
  520. clipped,
  521. clippedIndex,
  522. triangleVertices
  523. );
  524. // Clip the triangle against the North-south boundary.
  525. clipped2 = Intersections2D$1.clipTriangleAtAxisAlignedThreshold(
  526. halfMaxShort,
  527. isNorthChild,
  528. clippedTriangleVertices[0].getV(),
  529. clippedTriangleVertices[1].getV(),
  530. clippedTriangleVertices[2].getV(),
  531. clipScratch2
  532. );
  533. addClippedPolygon(
  534. uBuffer,
  535. vBuffer,
  536. heightBuffer,
  537. normalBuffer,
  538. indices,
  539. vertexMap,
  540. clipped2,
  541. clippedTriangleVertices,
  542. hasVertexNormals
  543. );
  544. // If there's another vertex in the original clipped result,
  545. // it forms a second triangle. Clip it as well.
  546. if (clippedIndex < clipped.length) {
  547. clippedTriangleVertices[2].clone(clippedTriangleVertices[1]);
  548. clippedTriangleVertices[2].initializeFromClipResult(
  549. clipped,
  550. clippedIndex,
  551. triangleVertices
  552. );
  553. clipped2 = Intersections2D$1.clipTriangleAtAxisAlignedThreshold(
  554. halfMaxShort,
  555. isNorthChild,
  556. clippedTriangleVertices[0].getV(),
  557. clippedTriangleVertices[1].getV(),
  558. clippedTriangleVertices[2].getV(),
  559. clipScratch2
  560. );
  561. addClippedPolygon(
  562. uBuffer,
  563. vBuffer,
  564. heightBuffer,
  565. normalBuffer,
  566. indices,
  567. vertexMap,
  568. clipped2,
  569. clippedTriangleVertices,
  570. hasVertexNormals
  571. );
  572. }
  573. }
  574. const uOffset = isEastChild ? -maxShort : 0;
  575. const vOffset = isNorthChild ? -maxShort : 0;
  576. const westIndices = [];
  577. const southIndices = [];
  578. const eastIndices = [];
  579. const northIndices = [];
  580. let minimumHeight = Number.MAX_VALUE;
  581. let maximumHeight = -minimumHeight;
  582. const cartesianVertices = verticesScratch;
  583. cartesianVertices.length = 0;
  584. const ellipsoid = Matrix2.Ellipsoid.clone(parameters.ellipsoid);
  585. const rectangle = Matrix2.Rectangle.clone(parameters.childRectangle);
  586. const north = rectangle.north;
  587. const south = rectangle.south;
  588. let east = rectangle.east;
  589. const west = rectangle.west;
  590. if (east < west) {
  591. east += ComponentDatatype.CesiumMath.TWO_PI;
  592. }
  593. for (i = 0; i < uBuffer.length; ++i) {
  594. u = Math.round(uBuffer[i]);
  595. if (u <= minU) {
  596. westIndices.push(i);
  597. u = 0;
  598. } else if (u >= maxU) {
  599. eastIndices.push(i);
  600. u = maxShort;
  601. } else {
  602. u = u * 2 + uOffset;
  603. }
  604. uBuffer[i] = u;
  605. v = Math.round(vBuffer[i]);
  606. if (v <= minV) {
  607. southIndices.push(i);
  608. v = 0;
  609. } else if (v >= maxV) {
  610. northIndices.push(i);
  611. v = maxShort;
  612. } else {
  613. v = v * 2 + vOffset;
  614. }
  615. vBuffer[i] = v;
  616. height = ComponentDatatype.CesiumMath.lerp(
  617. parentMinimumHeight,
  618. parentMaximumHeight,
  619. heightBuffer[i] / maxShort
  620. );
  621. if (height < minimumHeight) {
  622. minimumHeight = height;
  623. }
  624. if (height > maximumHeight) {
  625. maximumHeight = height;
  626. }
  627. heightBuffer[i] = height;
  628. cartographicScratch.longitude = ComponentDatatype.CesiumMath.lerp(west, east, u / maxShort);
  629. cartographicScratch.latitude = ComponentDatatype.CesiumMath.lerp(south, north, v / maxShort);
  630. cartographicScratch.height = height;
  631. ellipsoid.cartographicToCartesian(cartographicScratch, cartesian3Scratch);
  632. cartesianVertices.push(cartesian3Scratch.x);
  633. cartesianVertices.push(cartesian3Scratch.y);
  634. cartesianVertices.push(cartesian3Scratch.z);
  635. }
  636. const boundingSphere = Transforms.BoundingSphere.fromVertices(
  637. cartesianVertices,
  638. Matrix2.Cartesian3.ZERO,
  639. 3,
  640. boundingSphereScratch
  641. );
  642. const orientedBoundingBox = OrientedBoundingBox.OrientedBoundingBox.fromRectangle(
  643. rectangle,
  644. minimumHeight,
  645. maximumHeight,
  646. ellipsoid,
  647. orientedBoundingBoxScratch
  648. );
  649. const occluder = new TerrainEncoding.EllipsoidalOccluder(ellipsoid);
  650. const horizonOcclusionPoint = occluder.computeHorizonCullingPointFromVerticesPossiblyUnderEllipsoid(
  651. boundingSphere.center,
  652. cartesianVertices,
  653. 3,
  654. boundingSphere.center,
  655. minimumHeight,
  656. horizonOcclusionPointScratch
  657. );
  658. const heightRange = maximumHeight - minimumHeight;
  659. const vertices = new Uint16Array(
  660. uBuffer.length + vBuffer.length + heightBuffer.length
  661. );
  662. for (i = 0; i < uBuffer.length; ++i) {
  663. vertices[i] = uBuffer[i];
  664. }
  665. let start = uBuffer.length;
  666. for (i = 0; i < vBuffer.length; ++i) {
  667. vertices[start + i] = vBuffer[i];
  668. }
  669. start += vBuffer.length;
  670. for (i = 0; i < heightBuffer.length; ++i) {
  671. vertices[start + i] =
  672. (maxShort * (heightBuffer[i] - minimumHeight)) / heightRange;
  673. }
  674. const indicesTypedArray = IndexDatatype.IndexDatatype.createTypedArray(
  675. uBuffer.length,
  676. indices
  677. );
  678. let encodedNormals;
  679. if (hasVertexNormals) {
  680. const normalArray = new Uint8Array(normalBuffer);
  681. transferableObjects.push(
  682. vertices.buffer,
  683. indicesTypedArray.buffer,
  684. normalArray.buffer
  685. );
  686. encodedNormals = normalArray.buffer;
  687. } else {
  688. transferableObjects.push(vertices.buffer, indicesTypedArray.buffer);
  689. }
  690. return {
  691. vertices: vertices.buffer,
  692. encodedNormals: encodedNormals,
  693. indices: indicesTypedArray.buffer,
  694. minimumHeight: minimumHeight,
  695. maximumHeight: maximumHeight,
  696. westIndices: westIndices,
  697. southIndices: southIndices,
  698. eastIndices: eastIndices,
  699. northIndices: northIndices,
  700. boundingSphere: boundingSphere,
  701. orientedBoundingBox: orientedBoundingBox,
  702. horizonOcclusionPoint: horizonOcclusionPoint,
  703. };
  704. }
  705. function Vertex() {
  706. this.vertexBuffer = undefined;
  707. this.index = undefined;
  708. this.first = undefined;
  709. this.second = undefined;
  710. this.ratio = undefined;
  711. }
  712. Vertex.prototype.clone = function (result) {
  713. if (!defaultValue.defined(result)) {
  714. result = new Vertex();
  715. }
  716. result.uBuffer = this.uBuffer;
  717. result.vBuffer = this.vBuffer;
  718. result.heightBuffer = this.heightBuffer;
  719. result.normalBuffer = this.normalBuffer;
  720. result.index = this.index;
  721. result.first = this.first;
  722. result.second = this.second;
  723. result.ratio = this.ratio;
  724. return result;
  725. };
  726. Vertex.prototype.initializeIndexed = function (
  727. uBuffer,
  728. vBuffer,
  729. heightBuffer,
  730. normalBuffer,
  731. index
  732. ) {
  733. this.uBuffer = uBuffer;
  734. this.vBuffer = vBuffer;
  735. this.heightBuffer = heightBuffer;
  736. this.normalBuffer = normalBuffer;
  737. this.index = index;
  738. this.first = undefined;
  739. this.second = undefined;
  740. this.ratio = undefined;
  741. };
  742. Vertex.prototype.initializeFromClipResult = function (
  743. clipResult,
  744. index,
  745. vertices
  746. ) {
  747. let nextIndex = index + 1;
  748. if (clipResult[index] !== -1) {
  749. vertices[clipResult[index]].clone(this);
  750. } else {
  751. this.vertexBuffer = undefined;
  752. this.index = undefined;
  753. this.first = vertices[clipResult[nextIndex]];
  754. ++nextIndex;
  755. this.second = vertices[clipResult[nextIndex]];
  756. ++nextIndex;
  757. this.ratio = clipResult[nextIndex];
  758. ++nextIndex;
  759. }
  760. return nextIndex;
  761. };
  762. Vertex.prototype.getKey = function () {
  763. if (this.isIndexed()) {
  764. return this.index;
  765. }
  766. return JSON.stringify({
  767. first: this.first.getKey(),
  768. second: this.second.getKey(),
  769. ratio: this.ratio,
  770. });
  771. };
  772. Vertex.prototype.isIndexed = function () {
  773. return defaultValue.defined(this.index);
  774. };
  775. Vertex.prototype.getH = function () {
  776. if (defaultValue.defined(this.index)) {
  777. return this.heightBuffer[this.index];
  778. }
  779. return ComponentDatatype.CesiumMath.lerp(this.first.getH(), this.second.getH(), this.ratio);
  780. };
  781. Vertex.prototype.getU = function () {
  782. if (defaultValue.defined(this.index)) {
  783. return this.uBuffer[this.index];
  784. }
  785. return ComponentDatatype.CesiumMath.lerp(this.first.getU(), this.second.getU(), this.ratio);
  786. };
  787. Vertex.prototype.getV = function () {
  788. if (defaultValue.defined(this.index)) {
  789. return this.vBuffer[this.index];
  790. }
  791. return ComponentDatatype.CesiumMath.lerp(this.first.getV(), this.second.getV(), this.ratio);
  792. };
  793. let encodedScratch = new Matrix2.Cartesian2();
  794. // An upsampled triangle may be clipped twice before it is assigned an index
  795. // In this case, we need a buffer to handle the recursion of getNormalX() and getNormalY().
  796. let depth = -1;
  797. const cartesianScratch1 = [new Matrix2.Cartesian3(), new Matrix2.Cartesian3()];
  798. const cartesianScratch2 = [new Matrix2.Cartesian3(), new Matrix2.Cartesian3()];
  799. function lerpOctEncodedNormal(vertex, result) {
  800. ++depth;
  801. let first = cartesianScratch1[depth];
  802. let second = cartesianScratch2[depth];
  803. first = AttributeCompression.AttributeCompression.octDecode(
  804. vertex.first.getNormalX(),
  805. vertex.first.getNormalY(),
  806. first
  807. );
  808. second = AttributeCompression.AttributeCompression.octDecode(
  809. vertex.second.getNormalX(),
  810. vertex.second.getNormalY(),
  811. second
  812. );
  813. cartesian3Scratch = Matrix2.Cartesian3.lerp(
  814. first,
  815. second,
  816. vertex.ratio,
  817. cartesian3Scratch
  818. );
  819. Matrix2.Cartesian3.normalize(cartesian3Scratch, cartesian3Scratch);
  820. AttributeCompression.AttributeCompression.octEncode(cartesian3Scratch, result);
  821. --depth;
  822. return result;
  823. }
  824. Vertex.prototype.getNormalX = function () {
  825. if (defaultValue.defined(this.index)) {
  826. return this.normalBuffer[this.index * 2];
  827. }
  828. encodedScratch = lerpOctEncodedNormal(this, encodedScratch);
  829. return encodedScratch.x;
  830. };
  831. Vertex.prototype.getNormalY = function () {
  832. if (defaultValue.defined(this.index)) {
  833. return this.normalBuffer[this.index * 2 + 1];
  834. }
  835. encodedScratch = lerpOctEncodedNormal(this, encodedScratch);
  836. return encodedScratch.y;
  837. };
  838. const polygonVertices = [];
  839. polygonVertices.push(new Vertex());
  840. polygonVertices.push(new Vertex());
  841. polygonVertices.push(new Vertex());
  842. polygonVertices.push(new Vertex());
  843. function addClippedPolygon(
  844. uBuffer,
  845. vBuffer,
  846. heightBuffer,
  847. normalBuffer,
  848. indices,
  849. vertexMap,
  850. clipped,
  851. triangleVertices,
  852. hasVertexNormals
  853. ) {
  854. if (clipped.length === 0) {
  855. return;
  856. }
  857. let numVertices = 0;
  858. let clippedIndex = 0;
  859. while (clippedIndex < clipped.length) {
  860. clippedIndex = polygonVertices[numVertices++].initializeFromClipResult(
  861. clipped,
  862. clippedIndex,
  863. triangleVertices
  864. );
  865. }
  866. for (let i = 0; i < numVertices; ++i) {
  867. const polygonVertex = polygonVertices[i];
  868. if (!polygonVertex.isIndexed()) {
  869. const key = polygonVertex.getKey();
  870. if (defaultValue.defined(vertexMap[key])) {
  871. polygonVertex.newIndex = vertexMap[key];
  872. } else {
  873. const newIndex = uBuffer.length;
  874. uBuffer.push(polygonVertex.getU());
  875. vBuffer.push(polygonVertex.getV());
  876. heightBuffer.push(polygonVertex.getH());
  877. if (hasVertexNormals) {
  878. normalBuffer.push(polygonVertex.getNormalX());
  879. normalBuffer.push(polygonVertex.getNormalY());
  880. }
  881. polygonVertex.newIndex = newIndex;
  882. vertexMap[key] = newIndex;
  883. }
  884. } else {
  885. polygonVertex.newIndex = vertexMap[polygonVertex.index];
  886. polygonVertex.uBuffer = uBuffer;
  887. polygonVertex.vBuffer = vBuffer;
  888. polygonVertex.heightBuffer = heightBuffer;
  889. if (hasVertexNormals) {
  890. polygonVertex.normalBuffer = normalBuffer;
  891. }
  892. }
  893. }
  894. if (numVertices === 3) {
  895. // A triangle.
  896. indices.push(polygonVertices[0].newIndex);
  897. indices.push(polygonVertices[1].newIndex);
  898. indices.push(polygonVertices[2].newIndex);
  899. } else if (numVertices === 4) {
  900. // A quad - two triangles.
  901. indices.push(polygonVertices[0].newIndex);
  902. indices.push(polygonVertices[1].newIndex);
  903. indices.push(polygonVertices[2].newIndex);
  904. indices.push(polygonVertices[0].newIndex);
  905. indices.push(polygonVertices[2].newIndex);
  906. indices.push(polygonVertices[3].newIndex);
  907. }
  908. }
  909. var upsampleQuantizedTerrainMesh$1 = createTaskProcessorWorker(upsampleQuantizedTerrainMesh);
  910. return upsampleQuantizedTerrainMesh$1;
  911. }));