智慧水务管理系统 - 精河县供水工程综合管理平台

VoxelEllipsoidShape.js 34KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124
  1. import defined from "../Core/defined.js";
  2. import BoundingSphere from "../Core/BoundingSphere.js";
  3. import Cartesian2 from "../Core/Cartesian2.js";
  4. import Cartesian3 from "../Core/Cartesian3.js";
  5. import Cartographic from "../Core/Cartographic.js";
  6. import Check from "../Core/Check.js";
  7. import Ellipsoid from "../Core/Ellipsoid.js";
  8. import CesiumMath from "../Core/Math.js";
  9. import Matrix3 from "../Core/Matrix3.js";
  10. import Matrix4 from "../Core/Matrix4.js";
  11. import OrientedBoundingBox from "../Core/OrientedBoundingBox.js";
  12. import Rectangle from "../Core/Rectangle.js";
  13. import Transforms from "../Core/Transforms.js";
  14. /**
  15. * An ellipsoid {@link VoxelShape}.
  16. *
  17. * @alias VoxelEllipsoidShape
  18. * @constructor
  19. *
  20. * @see VoxelShape
  21. * @see VoxelBoxShape
  22. * @see VoxelCylinderShape
  23. * @see VoxelShapeType
  24. *
  25. * @private
  26. */
  27. function VoxelEllipsoidShape() {
  28. this._orientedBoundingBox = new OrientedBoundingBox();
  29. this._boundingSphere = new BoundingSphere();
  30. this._boundTransform = new Matrix4();
  31. this._shapeTransform = new Matrix4();
  32. /**
  33. * @type {Rectangle}
  34. * @private
  35. */
  36. this._rectangle = new Rectangle();
  37. /**
  38. * @type {number}
  39. * @private
  40. */
  41. this._minimumHeight = VoxelEllipsoidShape.DefaultMinBounds.z;
  42. /**
  43. * @type {number}
  44. * @private
  45. */
  46. this._maximumHeight = VoxelEllipsoidShape.DefaultMaxBounds.z;
  47. /**
  48. * @type {Ellipsoid}
  49. * @private
  50. */
  51. this._ellipsoid = new Ellipsoid();
  52. /**
  53. * @type {Cartesian3}
  54. * @private
  55. */
  56. this._translation = new Cartesian3();
  57. /**
  58. * @type {Matrix3}
  59. * @private
  60. */
  61. this._rotation = new Matrix3();
  62. /**
  63. * UV space transformation translations (JS-only, not shader uniforms)
  64. * Components: [longitude, latitude, height] translation
  65. * @type {Cartesian3}
  66. * @private
  67. */
  68. this._localToShapeUvTranslate = new Cartesian3();
  69. this._shaderUniforms = {
  70. cameraPositionCartographic: new Cartesian3(),
  71. ellipsoidEcToEastNorthUp: new Matrix3(),
  72. ellipsoidRadii: new Cartesian3(),
  73. eccentricitySquared: 0.0,
  74. evoluteScale: new Cartesian2(),
  75. ellipsoidCurvatureAtLatitude: new Cartesian2(),
  76. ellipsoidInverseRadiiSquared: new Cartesian3(),
  77. ellipsoidRenderLongitudeMinMax: new Cartesian2(),
  78. ellipsoidShapeUvLongitudeRangeOrigin: 0.0,
  79. ellipsoidShapeUvLongitudeMinMaxMid: new Cartesian3(),
  80. ellipsoidLocalToShapeUvScale: new Cartesian3(),
  81. ellipsoidRenderLatitudeSinMinMax: new Cartesian2(),
  82. clipMinMaxHeight: new Cartesian2(),
  83. };
  84. this._shaderDefines = {
  85. ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE: undefined,
  86. ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_RANGE_EQUAL_ZERO: undefined,
  87. ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_RANGE_UNDER_HALF: undefined,
  88. ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_RANGE_OVER_HALF: undefined,
  89. ELLIPSOID_HAS_SHAPE_BOUNDS_LONGITUDE: undefined,
  90. ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX_UNDER_HALF: undefined,
  91. ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX_EQUAL_HALF: undefined,
  92. ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX_OVER_HALF: undefined,
  93. ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_UNDER_HALF: undefined,
  94. ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_EQUAL_HALF: undefined,
  95. ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_OVER_HALF: undefined,
  96. ELLIPSOID_HAS_SHAPE_BOUNDS_LATITUDE: undefined,
  97. ELLIPSOID_INTERSECTION_INDEX_LONGITUDE: undefined,
  98. ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MAX: undefined,
  99. ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MIN: undefined,
  100. ELLIPSOID_INTERSECTION_INDEX_HEIGHT_MAX: undefined,
  101. ELLIPSOID_INTERSECTION_INDEX_HEIGHT_MIN: undefined,
  102. };
  103. this._shaderMaximumIntersectionsLength = 0; // not known until update
  104. }
  105. Object.defineProperties(VoxelEllipsoidShape.prototype, {
  106. /**
  107. * An oriented bounding box containing the bounded shape.
  108. *
  109. * @memberof VoxelEllipsoidShape.prototype
  110. * @type {OrientedBoundingBox}
  111. * @readonly
  112. * @private
  113. */
  114. orientedBoundingBox: {
  115. get: function () {
  116. return this._orientedBoundingBox;
  117. },
  118. },
  119. /**
  120. * A bounding sphere containing the bounded shape.
  121. *
  122. * @memberof VoxelEllipsoidShape.prototype
  123. * @type {BoundingSphere}
  124. * @readonly
  125. * @private
  126. */
  127. boundingSphere: {
  128. get: function () {
  129. return this._boundingSphere;
  130. },
  131. },
  132. /**
  133. * A transformation matrix containing the bounded shape.
  134. *
  135. * @memberof VoxelEllipsoidShape.prototype
  136. * @type {Matrix4}
  137. * @readonly
  138. * @private
  139. */
  140. boundTransform: {
  141. get: function () {
  142. return this._boundTransform;
  143. },
  144. },
  145. /**
  146. * A transformation matrix containing the shape, ignoring the bounds.
  147. *
  148. * @memberof VoxelEllipsoidShape.prototype
  149. * @type {Matrix4}
  150. * @readonly
  151. * @private
  152. */
  153. shapeTransform: {
  154. get: function () {
  155. return this._shapeTransform;
  156. },
  157. },
  158. /**
  159. * @memberof VoxelEllipsoidShape.prototype
  160. * @type {Object<string, any>}
  161. * @readonly
  162. * @private
  163. */
  164. shaderUniforms: {
  165. get: function () {
  166. return this._shaderUniforms;
  167. },
  168. },
  169. /**
  170. * @memberof VoxelEllipsoidShape.prototype
  171. * @type {Object<string, any>}
  172. * @readonly
  173. * @private
  174. */
  175. shaderDefines: {
  176. get: function () {
  177. return this._shaderDefines;
  178. },
  179. },
  180. /**
  181. * The maximum number of intersections against the shape for any ray direction.
  182. * @memberof VoxelEllipsoidShape.prototype
  183. * @type {number}
  184. * @readonly
  185. * @private
  186. */
  187. shaderMaximumIntersectionsLength: {
  188. get: function () {
  189. return this._shaderMaximumIntersectionsLength;
  190. },
  191. },
  192. });
  193. const scratchActualMinBounds = new Cartesian3();
  194. const scratchShapeMinBounds = new Cartesian3();
  195. const scratchShapeMaxBounds = new Cartesian3();
  196. const scratchClipMinBounds = new Cartesian3();
  197. const scratchClipMaxBounds = new Cartesian3();
  198. const scratchRenderMinBounds = new Cartesian3();
  199. const scratchRenderMaxBounds = new Cartesian3();
  200. const scratchScale = new Cartesian3();
  201. const scratchShapeOuterExtent = new Cartesian3();
  202. const scratchRenderOuterExtent = new Cartesian3();
  203. const scratchRenderRectangle = new Rectangle();
  204. /**
  205. * Update the shape's state.
  206. * @private
  207. * @param {Matrix4} modelMatrix The model matrix.
  208. * @param {Cartesian3} minBounds The minimum bounds.
  209. * @param {Cartesian3} maxBounds The maximum bounds.
  210. * @param {Cartesian3} [clipMinBounds=VoxelEllipsoidShape.DefaultMinBounds] The minimum clip bounds.
  211. * @param {Cartesian3} [clipMaxBounds=VoxelEllipsoidShape.DefaultMaxBounds] The maximum clip bounds.
  212. * @returns {boolean} Whether the shape is visible.
  213. */
  214. VoxelEllipsoidShape.prototype.update = function (
  215. modelMatrix,
  216. minBounds,
  217. maxBounds,
  218. clipMinBounds,
  219. clipMaxBounds,
  220. ) {
  221. const { DefaultMinBounds, DefaultMaxBounds } = VoxelEllipsoidShape;
  222. clipMinBounds = clipMinBounds ?? DefaultMinBounds;
  223. clipMaxBounds = clipMaxBounds ?? DefaultMaxBounds;
  224. //>>includeStart('debug', pragmas.debug);
  225. Check.typeOf.object("modelMatrix", modelMatrix);
  226. Check.typeOf.object("minBounds", minBounds);
  227. Check.typeOf.object("maxBounds", maxBounds);
  228. //>>includeEnd('debug');
  229. const epsilonZeroScale = CesiumMath.EPSILON10;
  230. const epsilonLongitude = CesiumMath.EPSILON10;
  231. const epsilonLatitude = CesiumMath.EPSILON10;
  232. const epsilonLatitudeFlat = CesiumMath.EPSILON3; // 0.001 radians = 0.05729578 degrees
  233. // Don't let the height go below the center of the ellipsoid.
  234. const radii = Matrix4.getScale(modelMatrix, scratchScale);
  235. const actualMinBounds = Cartesian3.clone(
  236. DefaultMinBounds,
  237. scratchActualMinBounds,
  238. );
  239. actualMinBounds.z = -Cartesian3.minimumComponent(radii);
  240. const shapeMinBounds = Cartesian3.clamp(
  241. minBounds,
  242. actualMinBounds,
  243. DefaultMaxBounds,
  244. scratchShapeMinBounds,
  245. );
  246. const shapeMaxBounds = Cartesian3.clamp(
  247. maxBounds,
  248. actualMinBounds,
  249. DefaultMaxBounds,
  250. scratchShapeMaxBounds,
  251. );
  252. const clampedClipMinBounds = Cartesian3.clamp(
  253. clipMinBounds,
  254. actualMinBounds,
  255. DefaultMaxBounds,
  256. scratchClipMinBounds,
  257. );
  258. const clampedClipMaxBounds = Cartesian3.clamp(
  259. clipMaxBounds,
  260. actualMinBounds,
  261. DefaultMaxBounds,
  262. scratchClipMaxBounds,
  263. );
  264. const renderMinBounds = Cartesian3.maximumByComponent(
  265. shapeMinBounds,
  266. clampedClipMinBounds,
  267. scratchRenderMinBounds,
  268. );
  269. const renderMaxBounds = Cartesian3.minimumByComponent(
  270. shapeMaxBounds,
  271. clampedClipMaxBounds,
  272. scratchRenderMaxBounds,
  273. );
  274. // Compute the farthest a point can be from the center of the ellipsoid.
  275. const shapeOuterExtent = Cartesian3.add(
  276. radii,
  277. Cartesian3.fromElements(
  278. shapeMaxBounds.z,
  279. shapeMaxBounds.z,
  280. shapeMaxBounds.z,
  281. scratchShapeOuterExtent,
  282. ),
  283. scratchShapeOuterExtent,
  284. );
  285. const renderOuterExtent = Cartesian3.add(
  286. radii,
  287. Cartesian3.fromElements(
  288. renderMaxBounds.z,
  289. renderMaxBounds.z,
  290. renderMaxBounds.z,
  291. scratchRenderOuterExtent,
  292. ),
  293. scratchRenderOuterExtent,
  294. );
  295. // Exit early if the shape is not visible.
  296. // Note that minLongitude may be greater than maxLongitude when crossing the 180th meridian.
  297. if (
  298. renderMinBounds.y > renderMaxBounds.y ||
  299. renderMinBounds.y === DefaultMaxBounds.y ||
  300. renderMaxBounds.y === DefaultMinBounds.y ||
  301. renderMinBounds.z > renderMaxBounds.z ||
  302. CesiumMath.equalsEpsilon(
  303. renderOuterExtent,
  304. Cartesian3.ZERO,
  305. undefined,
  306. epsilonZeroScale,
  307. )
  308. ) {
  309. return false;
  310. }
  311. this._rectangle = Rectangle.fromRadians(
  312. shapeMinBounds.x,
  313. shapeMinBounds.y,
  314. shapeMaxBounds.x,
  315. shapeMaxBounds.y,
  316. );
  317. this._translation = Matrix4.getTranslation(modelMatrix, this._translation);
  318. this._rotation = Matrix4.getRotation(modelMatrix, this._rotation);
  319. this._ellipsoid = Ellipsoid.fromCartesian3(radii, this._ellipsoid);
  320. this._minimumHeight = shapeMinBounds.z;
  321. this._maximumHeight = shapeMaxBounds.z;
  322. const renderRectangle = Rectangle.fromRadians(
  323. renderMinBounds.x,
  324. renderMinBounds.y,
  325. renderMaxBounds.x,
  326. renderMaxBounds.y,
  327. scratchRenderRectangle,
  328. );
  329. this._orientedBoundingBox = getEllipsoidChunkObb(
  330. renderRectangle,
  331. renderMinBounds.z,
  332. renderMaxBounds.z,
  333. this._ellipsoid,
  334. this._translation,
  335. this._rotation,
  336. this._orientedBoundingBox,
  337. );
  338. this._shapeTransform = Matrix4.fromRotationTranslation(
  339. this._rotation,
  340. this._translation,
  341. this._shapeTransform,
  342. );
  343. this._boundTransform = Matrix4.fromRotationTranslation(
  344. this._orientedBoundingBox.halfAxes,
  345. this._orientedBoundingBox.center,
  346. this._boundTransform,
  347. );
  348. this._boundingSphere = BoundingSphere.fromOrientedBoundingBox(
  349. this._orientedBoundingBox,
  350. this._boundingSphere,
  351. );
  352. // Longitude
  353. const defaultLongitudeRange = DefaultMaxBounds.x - DefaultMinBounds.x;
  354. const defaultLongitudeRangeHalf = 0.5 * defaultLongitudeRange;
  355. const renderIsLongitudeReversed = renderMaxBounds.x < renderMinBounds.x;
  356. const renderLongitudeRange =
  357. renderMaxBounds.x -
  358. renderMinBounds.x +
  359. renderIsLongitudeReversed * defaultLongitudeRange;
  360. const renderIsLongitudeRangeZero = renderLongitudeRange <= epsilonLongitude;
  361. const renderIsLongitudeRangeUnderHalf =
  362. renderLongitudeRange >= defaultLongitudeRangeHalf - epsilonLongitude &&
  363. renderLongitudeRange < defaultLongitudeRange - epsilonLongitude;
  364. const renderIsLongitudeRangeOverHalf =
  365. renderLongitudeRange > epsilonLongitude &&
  366. renderLongitudeRange < defaultLongitudeRangeHalf - epsilonLongitude;
  367. const renderHasLongitude =
  368. renderIsLongitudeRangeZero ||
  369. renderIsLongitudeRangeUnderHalf ||
  370. renderIsLongitudeRangeOverHalf;
  371. const shapeIsLongitudeReversed = shapeMaxBounds.x < shapeMinBounds.x;
  372. const shapeLongitudeRange =
  373. shapeMaxBounds.x -
  374. shapeMinBounds.x +
  375. shapeIsLongitudeReversed * defaultLongitudeRange;
  376. const shapeIsLongitudeRangeUnderHalf =
  377. shapeLongitudeRange > defaultLongitudeRangeHalf + epsilonLongitude &&
  378. shapeLongitudeRange < defaultLongitudeRange - epsilonLongitude;
  379. const shapeIsLongitudeRangeHalf =
  380. shapeLongitudeRange >= defaultLongitudeRangeHalf - epsilonLongitude &&
  381. shapeLongitudeRange <= defaultLongitudeRangeHalf + epsilonLongitude;
  382. const shapeIsLongitudeRangeOverHalf =
  383. shapeLongitudeRange < defaultLongitudeRangeHalf - epsilonLongitude;
  384. const shapeHasLongitude =
  385. shapeIsLongitudeRangeUnderHalf ||
  386. shapeIsLongitudeRangeHalf ||
  387. shapeIsLongitudeRangeOverHalf;
  388. // Latitude
  389. const renderIsLatitudeMaxUnderHalf = renderMaxBounds.y < -epsilonLatitudeFlat;
  390. const renderIsLatitudeMaxHalf =
  391. renderMaxBounds.y >= -epsilonLatitudeFlat &&
  392. renderMaxBounds.y <= +epsilonLatitudeFlat;
  393. const renderIsLatitudeMaxOverHalf =
  394. renderMaxBounds.y > +epsilonLatitudeFlat &&
  395. renderMaxBounds.y < DefaultMaxBounds.y - epsilonLatitude;
  396. const renderHasLatitudeMax =
  397. renderIsLatitudeMaxUnderHalf ||
  398. renderIsLatitudeMaxHalf ||
  399. renderIsLatitudeMaxOverHalf;
  400. const renderIsLatitudeMinUnderHalf =
  401. renderMinBounds.y > DefaultMinBounds.y + epsilonLatitude &&
  402. renderMinBounds.y < -epsilonLatitudeFlat;
  403. const renderIsLatitudeMinHalf =
  404. renderMinBounds.y >= -epsilonLatitudeFlat &&
  405. renderMinBounds.y <= +epsilonLatitudeFlat;
  406. const renderIsLatitudeMinOverHalf = renderMinBounds.y > +epsilonLatitudeFlat;
  407. const renderHasLatitudeMin =
  408. renderIsLatitudeMinUnderHalf ||
  409. renderIsLatitudeMinHalf ||
  410. renderIsLatitudeMinOverHalf;
  411. const renderHasLatitude = renderHasLatitudeMax || renderHasLatitudeMin;
  412. const shapeLatitudeRange = shapeMaxBounds.y - shapeMinBounds.y;
  413. const shapeIsLatitudeMaxUnderHalf = shapeMaxBounds.y < -epsilonLatitudeFlat;
  414. const shapeIsLatitudeMaxHalf =
  415. shapeMaxBounds.y >= -epsilonLatitudeFlat &&
  416. shapeMaxBounds.y <= +epsilonLatitudeFlat;
  417. const shapeIsLatitudeMaxOverHalf =
  418. shapeMaxBounds.y > +epsilonLatitudeFlat &&
  419. shapeMaxBounds.y < DefaultMaxBounds.y - epsilonLatitude;
  420. const shapeHasLatitudeMax =
  421. shapeIsLatitudeMaxUnderHalf ||
  422. shapeIsLatitudeMaxHalf ||
  423. shapeIsLatitudeMaxOverHalf;
  424. const shapeIsLatitudeMinUnderHalf =
  425. shapeMinBounds.y > DefaultMinBounds.y + epsilonLatitude &&
  426. shapeMinBounds.y < -epsilonLatitudeFlat;
  427. const shapeIsLatitudeMinHalf =
  428. shapeMinBounds.y >= -epsilonLatitudeFlat &&
  429. shapeMinBounds.y <= +epsilonLatitudeFlat;
  430. const shapeIsLatitudeMinOverHalf = shapeMinBounds.y > +epsilonLatitudeFlat;
  431. const shapeHasLatitudeMin =
  432. shapeIsLatitudeMinUnderHalf ||
  433. shapeIsLatitudeMinHalf ||
  434. shapeIsLatitudeMinOverHalf;
  435. const shapeHasLatitude = shapeHasLatitudeMax || shapeHasLatitudeMin;
  436. const shaderUniforms = this._shaderUniforms;
  437. const shaderDefines = this._shaderDefines;
  438. // To keep things simple, clear the defines every time
  439. for (const key in shaderDefines) {
  440. if (shaderDefines.hasOwnProperty(key)) {
  441. shaderDefines[key] = undefined;
  442. }
  443. }
  444. shaderUniforms.ellipsoidRadii = Cartesian3.clone(
  445. shapeOuterExtent,
  446. shaderUniforms.ellipsoidRadii,
  447. );
  448. const { x: radiiX, z: radiiZ } = shaderUniforms.ellipsoidRadii;
  449. const axisRatio = radiiZ / radiiX;
  450. shaderUniforms.eccentricitySquared = 1.0 - axisRatio * axisRatio;
  451. shaderUniforms.evoluteScale = Cartesian2.fromElements(
  452. (radiiX * radiiX - radiiZ * radiiZ) / radiiX,
  453. (radiiZ * radiiZ - radiiX * radiiX) / radiiZ,
  454. shaderUniforms.evoluteScale,
  455. );
  456. // Used to compute geodetic surface normal.
  457. shaderUniforms.ellipsoidInverseRadiiSquared = Cartesian3.divideComponents(
  458. Cartesian3.ONE,
  459. Cartesian3.multiplyComponents(
  460. shaderUniforms.ellipsoidRadii,
  461. shaderUniforms.ellipsoidRadii,
  462. shaderUniforms.ellipsoidInverseRadiiSquared,
  463. ),
  464. shaderUniforms.ellipsoidInverseRadiiSquared,
  465. );
  466. // Keep track of how many intersections there are going to be.
  467. let intersectionCount = 0;
  468. // Intersects outer and inner ellipsoid for the max and min height.
  469. shaderDefines["ELLIPSOID_INTERSECTION_INDEX_HEIGHT_MAX"] = intersectionCount;
  470. intersectionCount += 1;
  471. shaderDefines["ELLIPSOID_INTERSECTION_INDEX_HEIGHT_MIN"] = intersectionCount;
  472. intersectionCount += 1;
  473. shaderUniforms.clipMinMaxHeight = Cartesian2.fromElements(
  474. renderMinBounds.z - shapeMaxBounds.z,
  475. renderMaxBounds.z - shapeMaxBounds.z,
  476. shaderUniforms.clipMinMaxHeight,
  477. );
  478. // The percent of space that is between the inner and outer ellipsoid.
  479. const thickness = shapeMaxBounds.z - shapeMinBounds.z;
  480. const heightScale = thickness === 0.0 ? 0.0 : 1.0 / thickness;
  481. // Intersects a wedge for the min and max longitude.
  482. if (renderHasLongitude) {
  483. shaderDefines["ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE"] = true;
  484. shaderDefines["ELLIPSOID_INTERSECTION_INDEX_LONGITUDE"] = intersectionCount;
  485. if (renderIsLongitudeRangeUnderHalf) {
  486. shaderDefines["ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_RANGE_UNDER_HALF"] =
  487. true;
  488. intersectionCount += 1;
  489. } else if (renderIsLongitudeRangeOverHalf) {
  490. shaderDefines["ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_RANGE_OVER_HALF"] =
  491. true;
  492. intersectionCount += 2;
  493. } else if (renderIsLongitudeRangeZero) {
  494. shaderDefines["ELLIPSOID_HAS_RENDER_BOUNDS_LONGITUDE_RANGE_EQUAL_ZERO"] =
  495. true;
  496. intersectionCount += 2;
  497. }
  498. shaderUniforms.ellipsoidRenderLongitudeMinMax = Cartesian2.fromElements(
  499. renderMinBounds.x,
  500. renderMaxBounds.x,
  501. shaderUniforms.ellipsoidRenderLongitudeMinMax,
  502. );
  503. }
  504. // Defaults are for the case where shapeLongitudeRange is zero, to avoid division by zero.
  505. let longitudeScale = 0.0;
  506. let longitudeOffset = 1.0;
  507. if (shapeHasLongitude) {
  508. shaderDefines["ELLIPSOID_HAS_SHAPE_BOUNDS_LONGITUDE"] = true;
  509. const uvShapeMinLongitude =
  510. (shapeMinBounds.x - DefaultMinBounds.x) / defaultLongitudeRange;
  511. const uvShapeMaxLongitude =
  512. (shapeMaxBounds.x - DefaultMinBounds.x) / defaultLongitudeRange;
  513. const uvLongitudeRangeZero =
  514. 1.0 - shapeLongitudeRange / defaultLongitudeRange;
  515. // Translate the origin of UV angles (in [0,1]) to the center of the unoccupied space
  516. const uvLongitudeRangeOrigin =
  517. (uvShapeMaxLongitude + 0.5 * uvLongitudeRangeZero) % 1.0;
  518. shaderUniforms.ellipsoidShapeUvLongitudeRangeOrigin =
  519. uvLongitudeRangeOrigin;
  520. if (shapeLongitudeRange > epsilonLongitude) {
  521. longitudeScale = defaultLongitudeRange / shapeLongitudeRange;
  522. const shiftedMinLongitude = uvShapeMinLongitude - uvLongitudeRangeOrigin;
  523. longitudeOffset =
  524. -longitudeScale *
  525. (shiftedMinLongitude - Math.floor(shiftedMinLongitude));
  526. }
  527. }
  528. if (renderHasLatitude) {
  529. // Intersects a cone for min latitude
  530. if (renderHasLatitudeMin) {
  531. shaderDefines["ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN"] = true;
  532. shaderDefines["ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MIN"] =
  533. intersectionCount;
  534. if (renderIsLatitudeMinUnderHalf) {
  535. shaderDefines["ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_UNDER_HALF"] =
  536. true;
  537. intersectionCount += 1;
  538. } else if (renderIsLatitudeMinHalf) {
  539. shaderDefines["ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_EQUAL_HALF"] =
  540. true;
  541. intersectionCount += 1;
  542. } else if (renderIsLatitudeMinOverHalf) {
  543. shaderDefines["ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MIN_OVER_HALF"] =
  544. true;
  545. intersectionCount += 2;
  546. }
  547. }
  548. // Intersects a cone for max latitude
  549. if (renderHasLatitudeMax) {
  550. shaderDefines["ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX"] = true;
  551. shaderDefines["ELLIPSOID_INTERSECTION_INDEX_LATITUDE_MAX"] =
  552. intersectionCount;
  553. if (renderIsLatitudeMaxUnderHalf) {
  554. shaderDefines["ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX_UNDER_HALF"] =
  555. true;
  556. intersectionCount += 2;
  557. } else if (renderIsLatitudeMaxHalf) {
  558. shaderDefines["ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX_EQUAL_HALF"] =
  559. true;
  560. intersectionCount += 1;
  561. } else if (renderIsLatitudeMaxOverHalf) {
  562. shaderDefines["ELLIPSOID_HAS_RENDER_BOUNDS_LATITUDE_MAX_OVER_HALF"] =
  563. true;
  564. intersectionCount += 1;
  565. }
  566. }
  567. shaderUniforms.ellipsoidRenderLatitudeSinMinMax = Cartesian2.fromElements(
  568. Math.sin(renderMinBounds.y),
  569. Math.sin(renderMaxBounds.y),
  570. shaderUniforms.ellipsoidRenderLatitudeSinMinMax,
  571. );
  572. }
  573. // Defaults are for the case where shapeLatitudeRange is zero, to avoid division by zero.
  574. let latitudeScale = 0.0;
  575. let latitudeOffset = 1.0;
  576. if (shapeHasLatitude) {
  577. shaderDefines["ELLIPSOID_HAS_SHAPE_BOUNDS_LATITUDE"] = true;
  578. if (shapeLatitudeRange > epsilonLatitude) {
  579. const defaultLatitudeRange = DefaultMaxBounds.y - DefaultMinBounds.y;
  580. latitudeScale = defaultLatitudeRange / shapeLatitudeRange;
  581. latitudeOffset =
  582. (DefaultMinBounds.y - shapeMinBounds.y) / shapeLatitudeRange;
  583. }
  584. }
  585. // Store scales in shader uniforms (GPU) and translates in private property (JS-only)
  586. shaderUniforms.ellipsoidLocalToShapeUvScale = Cartesian3.fromElements(
  587. longitudeScale,
  588. latitudeScale,
  589. heightScale,
  590. shaderUniforms.ellipsoidLocalToShapeUvScale,
  591. );
  592. this._localToShapeUvTranslate = Cartesian3.fromElements(
  593. longitudeOffset,
  594. latitudeOffset,
  595. 0.0, // Height translate not used (always 1.0 + height * scale)
  596. this._localToShapeUvTranslate,
  597. );
  598. this._shaderMaximumIntersectionsLength = intersectionCount;
  599. return true;
  600. };
  601. const scratchCameraPositionCartographic = new Cartographic();
  602. const surfacePositionScratch = new Cartesian3();
  603. const enuTransformScratch = new Matrix4();
  604. const enuRotationScratch = new Matrix3();
  605. /**
  606. * Update any view-dependent transforms.
  607. * @private
  608. * @param {FrameState} frameState The frame state.
  609. */
  610. VoxelEllipsoidShape.prototype.updateViewTransforms = function (frameState) {
  611. const shaderUniforms = this._shaderUniforms;
  612. const ellipsoid = this._ellipsoid;
  613. // TODO: incorporate modelMatrix or shapeTransform here?
  614. const cameraWC = frameState.camera.positionWC;
  615. const cameraPositionCartographic = ellipsoid.cartesianToCartographic(
  616. cameraWC,
  617. scratchCameraPositionCartographic,
  618. );
  619. Cartesian3.fromElements(
  620. cameraPositionCartographic.longitude,
  621. cameraPositionCartographic.latitude,
  622. cameraPositionCartographic.height,
  623. shaderUniforms.cameraPositionCartographic,
  624. );
  625. // TODO: incorporate modelMatrix here?
  626. const surfacePosition = Cartesian3.fromRadians(
  627. cameraPositionCartographic.longitude,
  628. cameraPositionCartographic.latitude,
  629. 0.0,
  630. ellipsoid,
  631. surfacePositionScratch,
  632. );
  633. shaderUniforms.ellipsoidCurvatureAtLatitude = ellipsoid.getLocalCurvature(
  634. surfacePosition,
  635. shaderUniforms.ellipsoidCurvatureAtLatitude,
  636. );
  637. const enuToWorld = Transforms.eastNorthUpToFixedFrame(
  638. surfacePosition,
  639. ellipsoid,
  640. enuTransformScratch,
  641. );
  642. const rotateEnuToWorld = Matrix4.getRotation(enuToWorld, enuRotationScratch);
  643. const rotateWorldToView = frameState.context.uniformState.viewRotation;
  644. const rotateEnuToView = Matrix3.multiply(
  645. rotateWorldToView,
  646. rotateEnuToWorld,
  647. enuRotationScratch,
  648. );
  649. // Inverse is the transpose since it's a pure rotation.
  650. shaderUniforms.ellipsoidEcToEastNorthUp = Matrix3.transpose(
  651. rotateEnuToView,
  652. shaderUniforms.ellipsoidEcToEastNorthUp,
  653. );
  654. };
  655. const scratchRectangle = new Rectangle();
  656. /**
  657. * Computes an oriented bounding box for a specified tile.
  658. * @private
  659. * @param {number} tileLevel The tile's level.
  660. * @param {number} tileX The tile's x coordinate.
  661. * @param {number} tileY The tile's y coordinate.
  662. * @param {number} tileZ The tile's z coordinate.
  663. * @param {OrientedBoundingBox} result The oriented bounding box that will be set to enclose the specified tile
  664. * @returns {OrientedBoundingBox} The oriented bounding box.
  665. */
  666. VoxelEllipsoidShape.prototype.computeOrientedBoundingBoxForTile = function (
  667. tileLevel,
  668. tileX,
  669. tileY,
  670. tileZ,
  671. result,
  672. ) {
  673. //>>includeStart('debug', pragmas.debug);
  674. Check.typeOf.number("tileLevel", tileLevel);
  675. Check.typeOf.number("tileX", tileX);
  676. Check.typeOf.number("tileY", tileY);
  677. Check.typeOf.number("tileZ", tileZ);
  678. Check.typeOf.object("result", result);
  679. //>>includeEnd('debug');
  680. const sizeAtLevel = 1.0 / Math.pow(2.0, tileLevel);
  681. const minLongitudeLerp = tileX * sizeAtLevel;
  682. const maxLongitudeLerp = (tileX + 1) * sizeAtLevel;
  683. const minLatitudeLerp = tileY * sizeAtLevel;
  684. const maxLatitudeLerp = (tileY + 1) * sizeAtLevel;
  685. const minHeightLerp = tileZ * sizeAtLevel;
  686. const maxHeightLerp = (tileZ + 1) * sizeAtLevel;
  687. const rectangle = Rectangle.subsection(
  688. this._rectangle,
  689. minLongitudeLerp,
  690. minLatitudeLerp,
  691. maxLongitudeLerp,
  692. maxLatitudeLerp,
  693. scratchRectangle,
  694. );
  695. const minHeight = CesiumMath.lerp(
  696. this._minimumHeight,
  697. this._maximumHeight,
  698. minHeightLerp,
  699. );
  700. const maxHeight = CesiumMath.lerp(
  701. this._minimumHeight,
  702. this._maximumHeight,
  703. maxHeightLerp,
  704. );
  705. return getEllipsoidChunkObb(
  706. rectangle,
  707. minHeight,
  708. maxHeight,
  709. this._ellipsoid,
  710. this._translation,
  711. this._rotation,
  712. result,
  713. );
  714. };
  715. const scratchQuadrantPosition = new Cartesian2();
  716. const scratchInverseRadii = new Cartesian2();
  717. const scratchEllipseTrigs = new Cartesian2();
  718. const scratchEllipseGuess = new Cartesian2();
  719. const scratchEvolute = new Cartesian2();
  720. const scratchQ = new Cartesian2();
  721. /**
  722. * Find the nearest point on an ellipse and its radius.
  723. * @param {Cartesian2} position
  724. * @param {Cartesian2} radii
  725. * @param {Cartesian2} evoluteScale
  726. * @param {Cartesian3} result The Cartesian3 to store the result in. .x and .y components contain the nearest point on the ellipse, .z contains the local radius of curvature.
  727. * @returns {Cartesian3} The nearest point on the ellipse and its radius.
  728. * @private
  729. */
  730. function nearestPointAndRadiusOnEllipse(position, radii, evoluteScale, result) {
  731. // Map to the first quadrant
  732. const p = Cartesian2.abs(position, scratchQuadrantPosition);
  733. const inverseRadii = Cartesian2.fromElements(
  734. 1.0 / radii.x,
  735. 1.0 / radii.y,
  736. scratchInverseRadii,
  737. );
  738. // We describe the ellipse parametrically: v = radii * vec2(cos(t), sin(t))
  739. // but store the cos and sin of t in a vec2 for efficiency.
  740. // Initial guess: t = pi/4
  741. let tTrigs = Cartesian2.fromElements(
  742. Math.SQRT1_2,
  743. Math.SQRT1_2,
  744. scratchEllipseTrigs,
  745. );
  746. // TODO: too much duplication. Move v and evolute declarations inside loop?
  747. // Initial guess of point on ellipsoid
  748. let v = Cartesian2.multiplyComponents(radii, tTrigs, scratchEllipseGuess);
  749. // Center of curvature of the ellipse at v
  750. let evolute = Cartesian2.fromElements(
  751. evoluteScale.x * tTrigs.x * tTrigs.x * tTrigs.x,
  752. evoluteScale.y * tTrigs.y * tTrigs.y * tTrigs.y,
  753. scratchEvolute,
  754. );
  755. for (let i = 0; i < 3; ++i) {
  756. // Find the (approximate) intersection of p - evolute with the ellipsoid.
  757. const distance = Cartesian2.magnitude(
  758. Cartesian2.subtract(v, evolute, scratchQ),
  759. );
  760. const direction = Cartesian2.normalize(
  761. Cartesian2.subtract(p, evolute, scratchQ),
  762. scratchQ,
  763. );
  764. const q = Cartesian2.multiplyByScalar(direction, distance, scratchQ);
  765. // Update the estimate of t
  766. tTrigs = Cartesian2.multiplyComponents(
  767. Cartesian2.add(q, evolute, scratchEllipseTrigs),
  768. inverseRadii,
  769. scratchEllipseTrigs,
  770. );
  771. tTrigs = Cartesian2.normalize(
  772. Cartesian2.clamp(
  773. tTrigs,
  774. Cartesian2.ZERO,
  775. Cartesian2.ONE,
  776. scratchEllipseTrigs,
  777. ),
  778. scratchEllipseTrigs,
  779. );
  780. v = Cartesian2.multiplyComponents(radii, tTrigs, scratchEllipseGuess);
  781. evolute = Cartesian2.fromElements(
  782. evoluteScale.x * tTrigs.x * tTrigs.x * tTrigs.x,
  783. evoluteScale.y * tTrigs.y * tTrigs.y * tTrigs.y,
  784. scratchEvolute,
  785. );
  786. }
  787. // Map back to the original quadrant
  788. return Cartesian3.fromElements(
  789. Math.sign(position.x) * v.x,
  790. Math.sign(position.y) * v.y,
  791. Cartesian2.magnitude(Cartesian2.subtract(v, evolute, scratchQ)),
  792. result,
  793. );
  794. }
  795. const scratchEllipseRadii = new Cartesian2();
  796. const scratchEllipsePosition = new Cartesian2();
  797. const scratchSurfacePointAndRadius = new Cartesian3();
  798. const scratchNormal2d = new Cartesian2();
  799. /**
  800. * Convert a UV coordinate to the shape's UV space.
  801. * @private
  802. * @param {Cartesian3} positionLocal The local position to convert.
  803. * @param {Cartesian3} result The Cartesian3 to store the result in.
  804. * @returns {Cartesian3} The converted UV coordinate.
  805. */
  806. VoxelEllipsoidShape.prototype.convertLocalToShapeUvSpace = function (
  807. positionLocal,
  808. result,
  809. ) {
  810. //>>includeStart('debug', pragmas.debug);
  811. Check.typeOf.object("positionLocal", positionLocal);
  812. Check.typeOf.object("result", result);
  813. //>>includeEnd('debug');
  814. let longitude = Math.atan2(positionLocal.y, positionLocal.x);
  815. const {
  816. ellipsoidRadii,
  817. evoluteScale,
  818. ellipsoidInverseRadiiSquared,
  819. ellipsoidShapeUvLongitudeRangeOrigin,
  820. ellipsoidLocalToShapeUvScale,
  821. } = this._shaderUniforms;
  822. const localToShapeUvTranslate = this._localToShapeUvTranslate;
  823. const distanceFromZAxis = Math.hypot(positionLocal.x, positionLocal.y);
  824. const posEllipse = Cartesian2.fromElements(
  825. distanceFromZAxis,
  826. positionLocal.z,
  827. scratchEllipsePosition,
  828. );
  829. const surfacePointAndRadius = nearestPointAndRadiusOnEllipse(
  830. posEllipse,
  831. Cartesian2.fromElements(
  832. ellipsoidRadii.x,
  833. ellipsoidRadii.z,
  834. scratchEllipseRadii,
  835. ),
  836. evoluteScale,
  837. scratchSurfacePointAndRadius,
  838. );
  839. const normal2d = Cartesian2.normalize(
  840. Cartesian2.fromElements(
  841. surfacePointAndRadius.x * ellipsoidInverseRadiiSquared.x,
  842. surfacePointAndRadius.y * ellipsoidInverseRadiiSquared.z,
  843. scratchNormal2d,
  844. ),
  845. scratchNormal2d,
  846. );
  847. let latitude = Math.atan2(normal2d.y, normal2d.x);
  848. const heightSign =
  849. Cartesian2.magnitude(posEllipse) <
  850. Cartesian2.magnitude(surfacePointAndRadius)
  851. ? -1.0
  852. : 1.0;
  853. const heightVector = Cartesian2.subtract(
  854. posEllipse,
  855. surfacePointAndRadius,
  856. scratchEllipsePosition,
  857. );
  858. let height = heightSign * Cartesian2.magnitude(heightVector);
  859. const {
  860. ELLIPSOID_HAS_SHAPE_BOUNDS_LONGITUDE,
  861. ELLIPSOID_HAS_SHAPE_BOUNDS_LATITUDE,
  862. } = this._shaderDefines;
  863. longitude = (longitude + Math.PI) / (2.0 * Math.PI);
  864. if (defined(ELLIPSOID_HAS_SHAPE_BOUNDS_LONGITUDE)) {
  865. longitude -= ellipsoidShapeUvLongitudeRangeOrigin;
  866. longitude = longitude - Math.floor(longitude);
  867. // Scale and shift so [0, 1] covers the occupied space.
  868. longitude =
  869. longitude * ellipsoidLocalToShapeUvScale.x + localToShapeUvTranslate.x;
  870. }
  871. latitude = (latitude + Math.PI / 2.0) / Math.PI;
  872. if (defined(ELLIPSOID_HAS_SHAPE_BOUNDS_LATITUDE)) {
  873. // Scale and shift so [0, 1] covers the occupied space.
  874. latitude =
  875. latitude * ellipsoidLocalToShapeUvScale.y + localToShapeUvTranslate.y;
  876. }
  877. height = 1.0 + height * ellipsoidLocalToShapeUvScale.z;
  878. return Cartesian3.fromElements(longitude, latitude, height, result);
  879. };
  880. const sampleSizeScratch = new Cartesian3();
  881. const scratchTileMinBounds = new Cartesian3();
  882. const scratchTileMaxBounds = new Cartesian3();
  883. /**
  884. * Computes an oriented bounding box for a specified sample within a specified tile.
  885. * @private
  886. * @param {SpatialNode} spatialNode The spatial node containing the sample
  887. * @param {Cartesian3} tileDimensions The size of the tile in number of samples, before padding
  888. * @param {Cartesian3} tileUv The sample coordinate within the tile
  889. * @param {OrientedBoundingBox} result The oriented bounding box that will be set to enclose the specified sample
  890. * @returns {OrientedBoundingBox} The oriented bounding box.
  891. */
  892. VoxelEllipsoidShape.prototype.computeOrientedBoundingBoxForSample = function (
  893. spatialNode,
  894. tileDimensions,
  895. tileUv,
  896. result,
  897. ) {
  898. //>>includeStart('debug', pragmas.debug);
  899. Check.typeOf.object("spatialNode", spatialNode);
  900. Check.typeOf.object("tileDimensions", tileDimensions);
  901. Check.typeOf.object("tileUv", tileUv);
  902. Check.typeOf.object("result", result);
  903. //>>includeEnd('debug');
  904. const tileSizeAtLevel = 1.0 / Math.pow(2.0, spatialNode.level);
  905. const sampleSize = Cartesian3.divideComponents(
  906. Cartesian3.ONE,
  907. tileDimensions,
  908. sampleSizeScratch,
  909. );
  910. const sampleSizeAtLevel = Cartesian3.multiplyByScalar(
  911. sampleSize,
  912. tileSizeAtLevel,
  913. sampleSizeScratch,
  914. );
  915. const minLerp = Cartesian3.multiplyByScalar(
  916. Cartesian3.fromElements(
  917. spatialNode.x + tileUv.x,
  918. spatialNode.y + tileUv.y,
  919. spatialNode.z + tileUv.z,
  920. scratchTileMinBounds,
  921. ),
  922. tileSizeAtLevel,
  923. scratchTileMinBounds,
  924. );
  925. const maxLerp = Cartesian3.add(
  926. minLerp,
  927. sampleSizeAtLevel,
  928. scratchTileMaxBounds,
  929. );
  930. const rectangle = Rectangle.subsection(
  931. this._rectangle,
  932. minLerp.x,
  933. minLerp.y,
  934. maxLerp.x,
  935. maxLerp.y,
  936. scratchRectangle,
  937. );
  938. const minHeight = CesiumMath.lerp(
  939. this._minimumHeight,
  940. this._maximumHeight,
  941. minLerp.z,
  942. );
  943. const maxHeight = CesiumMath.lerp(
  944. this._minimumHeight,
  945. this._maximumHeight,
  946. maxLerp.z,
  947. );
  948. return getEllipsoidChunkObb(
  949. rectangle,
  950. minHeight,
  951. maxHeight,
  952. this._ellipsoid,
  953. this._translation,
  954. this._rotation,
  955. result,
  956. );
  957. };
  958. /**
  959. * Computes an {@link OrientedBoundingBox} for a subregion of the shape.
  960. *
  961. * @function
  962. *
  963. * @param {Rectangle} rectangle The rectangle.
  964. * @param {number} minHeight The minimumZ.
  965. * @param {number} maxHeight The maximumZ.
  966. * @param {Ellipsoid} ellipsoid The ellipsoid.
  967. * @param {Cartesian3} translation The translation applied to the shape
  968. * @param {Matrix3} rotation The rotation applied to the shape
  969. * @param {OrientedBoundingBox} result The object onto which to store the result.
  970. * @returns {OrientedBoundingBox} The oriented bounding box that contains this subregion.
  971. *
  972. * @private
  973. */
  974. function getEllipsoidChunkObb(
  975. rectangle,
  976. minHeight,
  977. maxHeight,
  978. ellipsoid,
  979. translation,
  980. rotation,
  981. result,
  982. ) {
  983. result = OrientedBoundingBox.fromRectangle(
  984. rectangle,
  985. minHeight,
  986. maxHeight,
  987. ellipsoid,
  988. result,
  989. );
  990. result.center = Cartesian3.add(result.center, translation, result.center);
  991. result.halfAxes = Matrix3.multiply(
  992. result.halfAxes,
  993. rotation,
  994. result.halfAxes,
  995. );
  996. return result;
  997. }
  998. /**
  999. * Defines the minimum bounds of the shape. Corresponds to minimum longitude, latitude, height.
  1000. * @private
  1001. * @type {Cartesian3}
  1002. * @constant
  1003. * @readonly
  1004. */
  1005. VoxelEllipsoidShape.DefaultMinBounds = Object.freeze(
  1006. new Cartesian3(
  1007. -CesiumMath.PI,
  1008. -CesiumMath.PI_OVER_TWO,
  1009. -Ellipsoid.WGS84.minimumRadius,
  1010. ),
  1011. );
  1012. /**
  1013. * Defines the maximum bounds of the shape. Corresponds to maximum longitude, latitude, height.
  1014. * @private
  1015. * @type {Cartesian3}
  1016. * @constant
  1017. * @readonly
  1018. */
  1019. VoxelEllipsoidShape.DefaultMaxBounds = Object.freeze(
  1020. new Cartesian3(
  1021. CesiumMath.PI,
  1022. CesiumMath.PI_OVER_TWO,
  1023. 10.0 * Ellipsoid.WGS84.maximumRadius,
  1024. ),
  1025. );
  1026. export default VoxelEllipsoidShape;