upsampleQuantizedTerrainMesh.js 30 KB

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