createWallGeometry.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648
  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(['./defaultValue-a6eb9f34', './Matrix2-ab676047', './Transforms-c78c4637', './ComponentDatatype-e06f4e16', './RuntimeError-1088cc64', './GeometryAttribute-4f02e2ad', './GeometryAttributes-aff51037', './IndexDatatype-c2232ebd', './VertexFormat-65fd4be5', './WallGeometryLibrary-483f681f', './_commonjsHelpers-89c9b271', './combine-7cf28d88', './WebGLConstants-d81b330d', './arrayRemoveDuplicates-63722a6f', './PolylinePipeline-3b0ed402', './EllipsoidGeodesic-f7721517', './EllipsoidRhumbLine-34574f75', './IntersectionTests-f96cd46d', './Plane-c985a1d2'], (function (defaultValue, Matrix2, Transforms, ComponentDatatype, RuntimeError, GeometryAttribute, GeometryAttributes, IndexDatatype, VertexFormat, WallGeometryLibrary, _commonjsHelpers, combine, WebGLConstants, arrayRemoveDuplicates, PolylinePipeline, EllipsoidGeodesic, EllipsoidRhumbLine, IntersectionTests, Plane) { 'use strict';
  26. const scratchCartesian3Position1 = new Matrix2.Cartesian3();
  27. const scratchCartesian3Position2 = new Matrix2.Cartesian3();
  28. const scratchCartesian3Position4 = new Matrix2.Cartesian3();
  29. const scratchCartesian3Position5 = new Matrix2.Cartesian3();
  30. const scratchBitangent = new Matrix2.Cartesian3();
  31. const scratchTangent = new Matrix2.Cartesian3();
  32. const scratchNormal = new Matrix2.Cartesian3();
  33. /**
  34. * A description of a wall, which is similar to a KML line string. A wall is defined by a series of points,
  35. * which extrude down to the ground. Optionally, they can extrude downwards to a specified height.
  36. *
  37. * @alias WallGeometry
  38. * @constructor
  39. *
  40. * @param {Object} options Object with the following properties:
  41. * @param {Cartesian3[]} options.positions An array of Cartesian objects, which are the points of the wall.
  42. * @param {Number} [options.granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer.
  43. * @param {Number[]} [options.maximumHeights] An array parallel to <code>positions</code> that give the maximum height of the
  44. * wall at <code>positions</code>. If undefined, the height of each position in used.
  45. * @param {Number[]} [options.minimumHeights] An array parallel to <code>positions</code> that give the minimum height of the
  46. * wall at <code>positions</code>. If undefined, the height at each position is 0.0.
  47. * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid for coordinate manipulation
  48. * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed.
  49. *
  50. * @exception {DeveloperError} positions length must be greater than or equal to 2.
  51. * @exception {DeveloperError} positions and maximumHeights must have the same length.
  52. * @exception {DeveloperError} positions and minimumHeights must have the same length.
  53. *
  54. * @see WallGeometry#createGeometry
  55. * @see WallGeometry#fromConstantHeight
  56. *
  57. * @demo {@link https://sandcastle.cesium.com/index.html?src=Wall.html|Cesium Sandcastle Wall Demo}
  58. *
  59. * @example
  60. * // create a wall that spans from ground level to 10000 meters
  61. * const wall = new Cesium.WallGeometry({
  62. * positions : Cesium.Cartesian3.fromDegreesArrayHeights([
  63. * 19.0, 47.0, 10000.0,
  64. * 19.0, 48.0, 10000.0,
  65. * 20.0, 48.0, 10000.0,
  66. * 20.0, 47.0, 10000.0,
  67. * 19.0, 47.0, 10000.0
  68. * ])
  69. * });
  70. * const geometry = Cesium.WallGeometry.createGeometry(wall);
  71. */
  72. function WallGeometry(options) {
  73. options = defaultValue.defaultValue(options, defaultValue.defaultValue.EMPTY_OBJECT);
  74. const wallPositions = options.positions;
  75. const maximumHeights = options.maximumHeights;
  76. const minimumHeights = options.minimumHeights;
  77. //>>includeStart('debug', pragmas.debug);
  78. if (!defaultValue.defined(wallPositions)) {
  79. throw new RuntimeError.DeveloperError("options.positions is required.");
  80. }
  81. if (
  82. defaultValue.defined(maximumHeights) &&
  83. maximumHeights.length !== wallPositions.length
  84. ) {
  85. throw new RuntimeError.DeveloperError(
  86. "options.positions and options.maximumHeights must have the same length."
  87. );
  88. }
  89. if (
  90. defaultValue.defined(minimumHeights) &&
  91. minimumHeights.length !== wallPositions.length
  92. ) {
  93. throw new RuntimeError.DeveloperError(
  94. "options.positions and options.minimumHeights must have the same length."
  95. );
  96. }
  97. //>>includeEnd('debug');
  98. const vertexFormat = defaultValue.defaultValue(options.vertexFormat, VertexFormat.VertexFormat.DEFAULT);
  99. const granularity = defaultValue.defaultValue(
  100. options.granularity,
  101. ComponentDatatype.CesiumMath.RADIANS_PER_DEGREE
  102. );
  103. const ellipsoid = defaultValue.defaultValue(options.ellipsoid, Matrix2.Ellipsoid.WGS84);
  104. this._positions = wallPositions;
  105. this._minimumHeights = minimumHeights;
  106. this._maximumHeights = maximumHeights;
  107. this._vertexFormat = VertexFormat.VertexFormat.clone(vertexFormat);
  108. this._granularity = granularity;
  109. this._ellipsoid = Matrix2.Ellipsoid.clone(ellipsoid);
  110. this._workerName = "createWallGeometry";
  111. let numComponents = 1 + wallPositions.length * Matrix2.Cartesian3.packedLength + 2;
  112. if (defaultValue.defined(minimumHeights)) {
  113. numComponents += minimumHeights.length;
  114. }
  115. if (defaultValue.defined(maximumHeights)) {
  116. numComponents += maximumHeights.length;
  117. }
  118. /**
  119. * The number of elements used to pack the object into an array.
  120. * @type {Number}
  121. */
  122. this.packedLength =
  123. numComponents + Matrix2.Ellipsoid.packedLength + VertexFormat.VertexFormat.packedLength + 1;
  124. }
  125. /**
  126. * Stores the provided instance into the provided array.
  127. *
  128. * @param {WallGeometry} value The value to pack.
  129. * @param {Number[]} array The array to pack into.
  130. * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.
  131. *
  132. * @returns {Number[]} The array that was packed into
  133. */
  134. WallGeometry.pack = function (value, array, startingIndex) {
  135. //>>includeStart('debug', pragmas.debug);
  136. if (!defaultValue.defined(value)) {
  137. throw new RuntimeError.DeveloperError("value is required");
  138. }
  139. if (!defaultValue.defined(array)) {
  140. throw new RuntimeError.DeveloperError("array is required");
  141. }
  142. //>>includeEnd('debug');
  143. startingIndex = defaultValue.defaultValue(startingIndex, 0);
  144. let i;
  145. const positions = value._positions;
  146. let length = positions.length;
  147. array[startingIndex++] = length;
  148. for (i = 0; i < length; ++i, startingIndex += Matrix2.Cartesian3.packedLength) {
  149. Matrix2.Cartesian3.pack(positions[i], array, startingIndex);
  150. }
  151. const minimumHeights = value._minimumHeights;
  152. length = defaultValue.defined(minimumHeights) ? minimumHeights.length : 0;
  153. array[startingIndex++] = length;
  154. if (defaultValue.defined(minimumHeights)) {
  155. for (i = 0; i < length; ++i) {
  156. array[startingIndex++] = minimumHeights[i];
  157. }
  158. }
  159. const maximumHeights = value._maximumHeights;
  160. length = defaultValue.defined(maximumHeights) ? maximumHeights.length : 0;
  161. array[startingIndex++] = length;
  162. if (defaultValue.defined(maximumHeights)) {
  163. for (i = 0; i < length; ++i) {
  164. array[startingIndex++] = maximumHeights[i];
  165. }
  166. }
  167. Matrix2.Ellipsoid.pack(value._ellipsoid, array, startingIndex);
  168. startingIndex += Matrix2.Ellipsoid.packedLength;
  169. VertexFormat.VertexFormat.pack(value._vertexFormat, array, startingIndex);
  170. startingIndex += VertexFormat.VertexFormat.packedLength;
  171. array[startingIndex] = value._granularity;
  172. return array;
  173. };
  174. const scratchEllipsoid = Matrix2.Ellipsoid.clone(Matrix2.Ellipsoid.UNIT_SPHERE);
  175. const scratchVertexFormat = new VertexFormat.VertexFormat();
  176. const scratchOptions = {
  177. positions: undefined,
  178. minimumHeights: undefined,
  179. maximumHeights: undefined,
  180. ellipsoid: scratchEllipsoid,
  181. vertexFormat: scratchVertexFormat,
  182. granularity: undefined,
  183. };
  184. /**
  185. * Retrieves an instance from a packed array.
  186. *
  187. * @param {Number[]} array The packed array.
  188. * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.
  189. * @param {WallGeometry} [result] The object into which to store the result.
  190. * @returns {WallGeometry} The modified result parameter or a new WallGeometry instance if one was not provided.
  191. */
  192. WallGeometry.unpack = function (array, startingIndex, result) {
  193. //>>includeStart('debug', pragmas.debug);
  194. if (!defaultValue.defined(array)) {
  195. throw new RuntimeError.DeveloperError("array is required");
  196. }
  197. //>>includeEnd('debug');
  198. startingIndex = defaultValue.defaultValue(startingIndex, 0);
  199. let i;
  200. let length = array[startingIndex++];
  201. const positions = new Array(length);
  202. for (i = 0; i < length; ++i, startingIndex += Matrix2.Cartesian3.packedLength) {
  203. positions[i] = Matrix2.Cartesian3.unpack(array, startingIndex);
  204. }
  205. length = array[startingIndex++];
  206. let minimumHeights;
  207. if (length > 0) {
  208. minimumHeights = new Array(length);
  209. for (i = 0; i < length; ++i) {
  210. minimumHeights[i] = array[startingIndex++];
  211. }
  212. }
  213. length = array[startingIndex++];
  214. let maximumHeights;
  215. if (length > 0) {
  216. maximumHeights = new Array(length);
  217. for (i = 0; i < length; ++i) {
  218. maximumHeights[i] = array[startingIndex++];
  219. }
  220. }
  221. const ellipsoid = Matrix2.Ellipsoid.unpack(array, startingIndex, scratchEllipsoid);
  222. startingIndex += Matrix2.Ellipsoid.packedLength;
  223. const vertexFormat = VertexFormat.VertexFormat.unpack(
  224. array,
  225. startingIndex,
  226. scratchVertexFormat
  227. );
  228. startingIndex += VertexFormat.VertexFormat.packedLength;
  229. const granularity = array[startingIndex];
  230. if (!defaultValue.defined(result)) {
  231. scratchOptions.positions = positions;
  232. scratchOptions.minimumHeights = minimumHeights;
  233. scratchOptions.maximumHeights = maximumHeights;
  234. scratchOptions.granularity = granularity;
  235. return new WallGeometry(scratchOptions);
  236. }
  237. result._positions = positions;
  238. result._minimumHeights = minimumHeights;
  239. result._maximumHeights = maximumHeights;
  240. result._ellipsoid = Matrix2.Ellipsoid.clone(ellipsoid, result._ellipsoid);
  241. result._vertexFormat = VertexFormat.VertexFormat.clone(vertexFormat, result._vertexFormat);
  242. result._granularity = granularity;
  243. return result;
  244. };
  245. /**
  246. * A description of a wall, which is similar to a KML line string. A wall is defined by a series of points,
  247. * which extrude down to the ground. Optionally, they can extrude downwards to a specified height.
  248. *
  249. * @param {Object} options Object with the following properties:
  250. * @param {Cartesian3[]} options.positions An array of Cartesian objects, which are the points of the wall.
  251. * @param {Number} [options.maximumHeight] A constant that defines the maximum height of the
  252. * wall at <code>positions</code>. If undefined, the height of each position in used.
  253. * @param {Number} [options.minimumHeight] A constant that defines the minimum height of the
  254. * wall at <code>positions</code>. If undefined, the height at each position is 0.0.
  255. * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid for coordinate manipulation
  256. * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed.
  257. * @returns {WallGeometry}
  258. *
  259. *
  260. * @example
  261. * // create a wall that spans from 10000 meters to 20000 meters
  262. * const wall = Cesium.WallGeometry.fromConstantHeights({
  263. * positions : Cesium.Cartesian3.fromDegreesArray([
  264. * 19.0, 47.0,
  265. * 19.0, 48.0,
  266. * 20.0, 48.0,
  267. * 20.0, 47.0,
  268. * 19.0, 47.0,
  269. * ]),
  270. * minimumHeight : 20000.0,
  271. * maximumHeight : 10000.0
  272. * });
  273. * const geometry = Cesium.WallGeometry.createGeometry(wall);
  274. *
  275. * @see WallGeometry#createGeometry
  276. */
  277. WallGeometry.fromConstantHeights = function (options) {
  278. options = defaultValue.defaultValue(options, defaultValue.defaultValue.EMPTY_OBJECT);
  279. const positions = options.positions;
  280. //>>includeStart('debug', pragmas.debug);
  281. if (!defaultValue.defined(positions)) {
  282. throw new RuntimeError.DeveloperError("options.positions is required.");
  283. }
  284. //>>includeEnd('debug');
  285. let minHeights;
  286. let maxHeights;
  287. const min = options.minimumHeight;
  288. const max = options.maximumHeight;
  289. const doMin = defaultValue.defined(min);
  290. const doMax = defaultValue.defined(max);
  291. if (doMin || doMax) {
  292. const length = positions.length;
  293. minHeights = doMin ? new Array(length) : undefined;
  294. maxHeights = doMax ? new Array(length) : undefined;
  295. for (let i = 0; i < length; ++i) {
  296. if (doMin) {
  297. minHeights[i] = min;
  298. }
  299. if (doMax) {
  300. maxHeights[i] = max;
  301. }
  302. }
  303. }
  304. const newOptions = {
  305. positions: positions,
  306. maximumHeights: maxHeights,
  307. minimumHeights: minHeights,
  308. ellipsoid: options.ellipsoid,
  309. vertexFormat: options.vertexFormat,
  310. };
  311. return new WallGeometry(newOptions);
  312. };
  313. /**
  314. * Computes the geometric representation of a wall, including its vertices, indices, and a bounding sphere.
  315. *
  316. * @param {WallGeometry} wallGeometry A description of the wall.
  317. * @returns {Geometry|undefined} The computed vertices and indices.
  318. */
  319. WallGeometry.createGeometry = function (wallGeometry) {
  320. const wallPositions = wallGeometry._positions;
  321. const minimumHeights = wallGeometry._minimumHeights;
  322. const maximumHeights = wallGeometry._maximumHeights;
  323. const vertexFormat = wallGeometry._vertexFormat;
  324. const granularity = wallGeometry._granularity;
  325. const ellipsoid = wallGeometry._ellipsoid;
  326. const pos = WallGeometryLibrary.WallGeometryLibrary.computePositions(
  327. ellipsoid,
  328. wallPositions,
  329. maximumHeights,
  330. minimumHeights,
  331. granularity,
  332. true
  333. );
  334. if (!defaultValue.defined(pos)) {
  335. return;
  336. }
  337. const bottomPositions = pos.bottomPositions;
  338. const topPositions = pos.topPositions;
  339. const numCorners = pos.numCorners;
  340. let length = topPositions.length;
  341. let size = length * 2;
  342. const positions = vertexFormat.position ? new Float64Array(size) : undefined;
  343. const normals = vertexFormat.normal ? new Float32Array(size) : undefined;
  344. const tangents = vertexFormat.tangent ? new Float32Array(size) : undefined;
  345. const bitangents = vertexFormat.bitangent
  346. ? new Float32Array(size)
  347. : undefined;
  348. const textureCoordinates = vertexFormat.st
  349. ? new Float32Array((size / 3) * 2)
  350. : undefined;
  351. let positionIndex = 0;
  352. let normalIndex = 0;
  353. let bitangentIndex = 0;
  354. let tangentIndex = 0;
  355. let stIndex = 0;
  356. // add lower and upper points one after the other, lower
  357. // points being even and upper points being odd
  358. let normal = scratchNormal;
  359. let tangent = scratchTangent;
  360. let bitangent = scratchBitangent;
  361. let recomputeNormal = true;
  362. length /= 3;
  363. let i;
  364. let s = 0;
  365. const ds = 1 / (length - numCorners - 1);
  366. for (i = 0; i < length; ++i) {
  367. const i3 = i * 3;
  368. const topPosition = Matrix2.Cartesian3.fromArray(
  369. topPositions,
  370. i3,
  371. scratchCartesian3Position1
  372. );
  373. const bottomPosition = Matrix2.Cartesian3.fromArray(
  374. bottomPositions,
  375. i3,
  376. scratchCartesian3Position2
  377. );
  378. if (vertexFormat.position) {
  379. // insert the lower point
  380. positions[positionIndex++] = bottomPosition.x;
  381. positions[positionIndex++] = bottomPosition.y;
  382. positions[positionIndex++] = bottomPosition.z;
  383. // insert the upper point
  384. positions[positionIndex++] = topPosition.x;
  385. positions[positionIndex++] = topPosition.y;
  386. positions[positionIndex++] = topPosition.z;
  387. }
  388. if (vertexFormat.st) {
  389. textureCoordinates[stIndex++] = s;
  390. textureCoordinates[stIndex++] = 0.0;
  391. textureCoordinates[stIndex++] = s;
  392. textureCoordinates[stIndex++] = 1.0;
  393. }
  394. if (vertexFormat.normal || vertexFormat.tangent || vertexFormat.bitangent) {
  395. let nextTop = Matrix2.Cartesian3.clone(
  396. Matrix2.Cartesian3.ZERO,
  397. scratchCartesian3Position5
  398. );
  399. const groundPosition = Matrix2.Cartesian3.subtract(
  400. topPosition,
  401. ellipsoid.geodeticSurfaceNormal(
  402. topPosition,
  403. scratchCartesian3Position2
  404. ),
  405. scratchCartesian3Position2
  406. );
  407. if (i + 1 < length) {
  408. nextTop = Matrix2.Cartesian3.fromArray(
  409. topPositions,
  410. i3 + 3,
  411. scratchCartesian3Position5
  412. );
  413. }
  414. if (recomputeNormal) {
  415. const scalednextPosition = Matrix2.Cartesian3.subtract(
  416. nextTop,
  417. topPosition,
  418. scratchCartesian3Position4
  419. );
  420. const scaledGroundPosition = Matrix2.Cartesian3.subtract(
  421. groundPosition,
  422. topPosition,
  423. scratchCartesian3Position1
  424. );
  425. normal = Matrix2.Cartesian3.normalize(
  426. Matrix2.Cartesian3.cross(scaledGroundPosition, scalednextPosition, normal),
  427. normal
  428. );
  429. recomputeNormal = false;
  430. }
  431. if (
  432. Matrix2.Cartesian3.equalsEpsilon(topPosition, nextTop, ComponentDatatype.CesiumMath.EPSILON10)
  433. ) {
  434. recomputeNormal = true;
  435. } else {
  436. s += ds;
  437. if (vertexFormat.tangent) {
  438. tangent = Matrix2.Cartesian3.normalize(
  439. Matrix2.Cartesian3.subtract(nextTop, topPosition, tangent),
  440. tangent
  441. );
  442. }
  443. if (vertexFormat.bitangent) {
  444. bitangent = Matrix2.Cartesian3.normalize(
  445. Matrix2.Cartesian3.cross(normal, tangent, bitangent),
  446. bitangent
  447. );
  448. }
  449. }
  450. if (vertexFormat.normal) {
  451. normals[normalIndex++] = normal.x;
  452. normals[normalIndex++] = normal.y;
  453. normals[normalIndex++] = normal.z;
  454. normals[normalIndex++] = normal.x;
  455. normals[normalIndex++] = normal.y;
  456. normals[normalIndex++] = normal.z;
  457. }
  458. if (vertexFormat.tangent) {
  459. tangents[tangentIndex++] = tangent.x;
  460. tangents[tangentIndex++] = tangent.y;
  461. tangents[tangentIndex++] = tangent.z;
  462. tangents[tangentIndex++] = tangent.x;
  463. tangents[tangentIndex++] = tangent.y;
  464. tangents[tangentIndex++] = tangent.z;
  465. }
  466. if (vertexFormat.bitangent) {
  467. bitangents[bitangentIndex++] = bitangent.x;
  468. bitangents[bitangentIndex++] = bitangent.y;
  469. bitangents[bitangentIndex++] = bitangent.z;
  470. bitangents[bitangentIndex++] = bitangent.x;
  471. bitangents[bitangentIndex++] = bitangent.y;
  472. bitangents[bitangentIndex++] = bitangent.z;
  473. }
  474. }
  475. }
  476. const attributes = new GeometryAttributes.GeometryAttributes();
  477. if (vertexFormat.position) {
  478. attributes.position = new GeometryAttribute.GeometryAttribute({
  479. componentDatatype: ComponentDatatype.ComponentDatatype.DOUBLE,
  480. componentsPerAttribute: 3,
  481. values: positions,
  482. });
  483. }
  484. if (vertexFormat.normal) {
  485. attributes.normal = new GeometryAttribute.GeometryAttribute({
  486. componentDatatype: ComponentDatatype.ComponentDatatype.FLOAT,
  487. componentsPerAttribute: 3,
  488. values: normals,
  489. });
  490. }
  491. if (vertexFormat.tangent) {
  492. attributes.tangent = new GeometryAttribute.GeometryAttribute({
  493. componentDatatype: ComponentDatatype.ComponentDatatype.FLOAT,
  494. componentsPerAttribute: 3,
  495. values: tangents,
  496. });
  497. }
  498. if (vertexFormat.bitangent) {
  499. attributes.bitangent = new GeometryAttribute.GeometryAttribute({
  500. componentDatatype: ComponentDatatype.ComponentDatatype.FLOAT,
  501. componentsPerAttribute: 3,
  502. values: bitangents,
  503. });
  504. }
  505. if (vertexFormat.st) {
  506. attributes.st = new GeometryAttribute.GeometryAttribute({
  507. componentDatatype: ComponentDatatype.ComponentDatatype.FLOAT,
  508. componentsPerAttribute: 2,
  509. values: textureCoordinates,
  510. });
  511. }
  512. // prepare the side walls, two triangles for each wall
  513. //
  514. // A (i+1) B (i+3) E
  515. // +--------+-------+
  516. // | / | /| triangles: A C B
  517. // | / | / | B C D
  518. // | / | / |
  519. // | / | / |
  520. // | / | / |
  521. // | / | / |
  522. // +--------+-------+
  523. // C (i) D (i+2) F
  524. //
  525. const numVertices = size / 3;
  526. size -= 6 * (numCorners + 1);
  527. const indices = IndexDatatype.IndexDatatype.createTypedArray(numVertices, size);
  528. let edgeIndex = 0;
  529. for (i = 0; i < numVertices - 2; i += 2) {
  530. const LL = i;
  531. const LR = i + 2;
  532. const pl = Matrix2.Cartesian3.fromArray(
  533. positions,
  534. LL * 3,
  535. scratchCartesian3Position1
  536. );
  537. const pr = Matrix2.Cartesian3.fromArray(
  538. positions,
  539. LR * 3,
  540. scratchCartesian3Position2
  541. );
  542. if (Matrix2.Cartesian3.equalsEpsilon(pl, pr, ComponentDatatype.CesiumMath.EPSILON10)) {
  543. continue;
  544. }
  545. const UL = i + 1;
  546. const UR = i + 3;
  547. indices[edgeIndex++] = UL;
  548. indices[edgeIndex++] = LL;
  549. indices[edgeIndex++] = UR;
  550. indices[edgeIndex++] = UR;
  551. indices[edgeIndex++] = LL;
  552. indices[edgeIndex++] = LR;
  553. }
  554. return new GeometryAttribute.Geometry({
  555. attributes: attributes,
  556. indices: indices,
  557. primitiveType: GeometryAttribute.PrimitiveType.TRIANGLES,
  558. boundingSphere: new Transforms.BoundingSphere.fromVertices(positions),
  559. });
  560. };
  561. function createWallGeometry(wallGeometry, offset) {
  562. if (defaultValue.defined(offset)) {
  563. wallGeometry = WallGeometry.unpack(wallGeometry, offset);
  564. }
  565. wallGeometry._ellipsoid = Matrix2.Ellipsoid.clone(wallGeometry._ellipsoid);
  566. return WallGeometry.createGeometry(wallGeometry);
  567. }
  568. return createWallGeometry;
  569. }));