upsampleQuantizedTerrainMesh.js 30 KB

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