EllipsoidGeometryUpdater.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710
  1. import Cartesian3 from "../Core/Cartesian3.js";
  2. import Check from "../Core/Check.js";
  3. import Color from "../Core/Color.js";
  4. import ColorGeometryInstanceAttribute from "../Core/ColorGeometryInstanceAttribute.js";
  5. import defaultValue from "../Core/defaultValue.js";
  6. import defined from "../Core/defined.js";
  7. import DistanceDisplayCondition from "../Core/DistanceDisplayCondition.js";
  8. import DistanceDisplayConditionGeometryInstanceAttribute from "../Core/DistanceDisplayConditionGeometryInstanceAttribute.js";
  9. import EllipsoidGeometry from "../Core/EllipsoidGeometry.js";
  10. import EllipsoidOutlineGeometry from "../Core/EllipsoidOutlineGeometry.js";
  11. import GeometryInstance from "../Core/GeometryInstance.js";
  12. import GeometryOffsetAttribute from "../Core/GeometryOffsetAttribute.js";
  13. import Iso8601 from "../Core/Iso8601.js";
  14. import Matrix4 from "../Core/Matrix4.js";
  15. import OffsetGeometryInstanceAttribute from "../Core/OffsetGeometryInstanceAttribute.js";
  16. import ShowGeometryInstanceAttribute from "../Core/ShowGeometryInstanceAttribute.js";
  17. import HeightReference from "../Scene/HeightReference.js";
  18. import MaterialAppearance from "../Scene/MaterialAppearance.js";
  19. import PerInstanceColorAppearance from "../Scene/PerInstanceColorAppearance.js";
  20. import Primitive from "../Scene/Primitive.js";
  21. import SceneMode from "../Scene/SceneMode.js";
  22. import ColorMaterialProperty from "./ColorMaterialProperty.js";
  23. import DynamicGeometryUpdater from "./DynamicGeometryUpdater.js";
  24. import GeometryUpdater from "./GeometryUpdater.js";
  25. import heightReferenceOnEntityPropertyChanged from "./heightReferenceOnEntityPropertyChanged.js";
  26. import MaterialProperty from "./MaterialProperty.js";
  27. import Property from "./Property.js";
  28. const defaultMaterial = new ColorMaterialProperty(Color.WHITE);
  29. const defaultOffset = Cartesian3.ZERO;
  30. const offsetScratch = new Cartesian3();
  31. const radiiScratch = new Cartesian3();
  32. const innerRadiiScratch = new Cartesian3();
  33. const scratchColor = new Color();
  34. const unitSphere = new Cartesian3(1, 1, 1);
  35. function EllipsoidGeometryOptions(entity) {
  36. this.id = entity;
  37. this.vertexFormat = undefined;
  38. this.radii = undefined;
  39. this.innerRadii = undefined;
  40. this.minimumClock = undefined;
  41. this.maximumClock = undefined;
  42. this.minimumCone = undefined;
  43. this.maximumCone = undefined;
  44. this.stackPartitions = undefined;
  45. this.slicePartitions = undefined;
  46. this.subdivisions = undefined;
  47. this.offsetAttribute = undefined;
  48. }
  49. /**
  50. * A {@link GeometryUpdater} for ellipsoids.
  51. * Clients do not normally create this class directly, but instead rely on {@link DataSourceDisplay}.
  52. * @alias EllipsoidGeometryUpdater
  53. * @constructor
  54. *
  55. * @param {Entity} entity The entity containing the geometry to be visualized.
  56. * @param {Scene} scene The scene where visualization is taking place.
  57. */
  58. function EllipsoidGeometryUpdater(entity, scene) {
  59. GeometryUpdater.call(this, {
  60. entity: entity,
  61. scene: scene,
  62. geometryOptions: new EllipsoidGeometryOptions(entity),
  63. geometryPropertyName: "ellipsoid",
  64. observedPropertyNames: [
  65. "availability",
  66. "position",
  67. "orientation",
  68. "ellipsoid",
  69. ],
  70. });
  71. this._onEntityPropertyChanged(
  72. entity,
  73. "ellipsoid",
  74. entity.ellipsoid,
  75. undefined
  76. );
  77. }
  78. if (defined(Object.create)) {
  79. EllipsoidGeometryUpdater.prototype = Object.create(GeometryUpdater.prototype);
  80. EllipsoidGeometryUpdater.prototype.constructor = EllipsoidGeometryUpdater;
  81. }
  82. Object.defineProperties(EllipsoidGeometryUpdater.prototype, {
  83. /**
  84. * Gets the terrain offset property
  85. * @type {TerrainOffsetProperty}
  86. * @memberof EllipsoidGeometryUpdater.prototype
  87. * @readonly
  88. * @private
  89. */
  90. terrainOffsetProperty: {
  91. get: function () {
  92. return this._terrainOffsetProperty;
  93. },
  94. },
  95. });
  96. /**
  97. * Creates the geometry instance which represents the fill of the geometry.
  98. *
  99. * @param {JulianDate} time The time to use when retrieving initial attribute values.
  100. * @param {boolean} [skipModelMatrix=false] Whether to compute a model matrix for the geometry instance
  101. * @param {Matrix4} [modelMatrixResult] Used to store the result of the model matrix calculation
  102. * @returns {GeometryInstance} The geometry instance representing the filled portion of the geometry.
  103. *
  104. * @exception {DeveloperError} This instance does not represent a filled geometry.
  105. */
  106. EllipsoidGeometryUpdater.prototype.createFillGeometryInstance = function (
  107. time,
  108. skipModelMatrix,
  109. modelMatrixResult
  110. ) {
  111. //>>includeStart('debug', pragmas.debug);
  112. Check.defined("time", time);
  113. //>>includeEnd('debug');
  114. const entity = this._entity;
  115. const isAvailable = entity.isAvailable(time);
  116. let color;
  117. const show = new ShowGeometryInstanceAttribute(
  118. isAvailable &&
  119. entity.isShowing &&
  120. this._showProperty.getValue(time) &&
  121. this._fillProperty.getValue(time)
  122. );
  123. const distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(
  124. time
  125. );
  126. const distanceDisplayConditionAttribute = DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(
  127. distanceDisplayCondition
  128. );
  129. const attributes = {
  130. show: show,
  131. distanceDisplayCondition: distanceDisplayConditionAttribute,
  132. color: undefined,
  133. offset: undefined,
  134. };
  135. if (this._materialProperty instanceof ColorMaterialProperty) {
  136. let currentColor;
  137. if (
  138. defined(this._materialProperty.color) &&
  139. (this._materialProperty.color.isConstant || isAvailable)
  140. ) {
  141. currentColor = this._materialProperty.color.getValue(time, scratchColor);
  142. }
  143. if (!defined(currentColor)) {
  144. currentColor = Color.WHITE;
  145. }
  146. color = ColorGeometryInstanceAttribute.fromColor(currentColor);
  147. attributes.color = color;
  148. }
  149. if (defined(this._options.offsetAttribute)) {
  150. attributes.offset = OffsetGeometryInstanceAttribute.fromCartesian3(
  151. Property.getValueOrDefault(
  152. this._terrainOffsetProperty,
  153. time,
  154. defaultOffset,
  155. offsetScratch
  156. )
  157. );
  158. }
  159. return new GeometryInstance({
  160. id: entity,
  161. geometry: new EllipsoidGeometry(this._options),
  162. modelMatrix: skipModelMatrix
  163. ? undefined
  164. : entity.computeModelMatrixForHeightReference(
  165. time,
  166. entity.ellipsoid.heightReference,
  167. this._options.radii.z * 0.5,
  168. this._scene.mapProjection.ellipsoid,
  169. modelMatrixResult
  170. ),
  171. attributes: attributes,
  172. });
  173. };
  174. /**
  175. * Creates the geometry instance which represents the outline of the geometry.
  176. *
  177. * @param {JulianDate} time The time to use when retrieving initial attribute values.
  178. * @param {boolean} [skipModelMatrix=false] Whether to compute a model matrix for the geometry instance
  179. * @param {Matrix4} [modelMatrixResult] Used to store the result of the model matrix calculation
  180. * @returns {GeometryInstance} The geometry instance representing the outline portion of the geometry.
  181. *
  182. * @exception {DeveloperError} This instance does not represent an outlined geometry.
  183. */
  184. EllipsoidGeometryUpdater.prototype.createOutlineGeometryInstance = function (
  185. time,
  186. skipModelMatrix,
  187. modelMatrixResult
  188. ) {
  189. //>>includeStart('debug', pragmas.debug);
  190. Check.defined("time", time);
  191. //>>includeEnd('debug');
  192. const entity = this._entity;
  193. const isAvailable = entity.isAvailable(time);
  194. const outlineColor = Property.getValueOrDefault(
  195. this._outlineColorProperty,
  196. time,
  197. Color.BLACK,
  198. scratchColor
  199. );
  200. const distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(
  201. time
  202. );
  203. const attributes = {
  204. show: new ShowGeometryInstanceAttribute(
  205. isAvailable &&
  206. entity.isShowing &&
  207. this._showProperty.getValue(time) &&
  208. this._showOutlineProperty.getValue(time)
  209. ),
  210. color: ColorGeometryInstanceAttribute.fromColor(outlineColor),
  211. distanceDisplayCondition: DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(
  212. distanceDisplayCondition
  213. ),
  214. offset: undefined,
  215. };
  216. if (defined(this._options.offsetAttribute)) {
  217. attributes.offset = OffsetGeometryInstanceAttribute.fromCartesian3(
  218. Property.getValueOrDefault(
  219. this._terrainOffsetProperty,
  220. time,
  221. defaultOffset,
  222. offsetScratch
  223. )
  224. );
  225. }
  226. return new GeometryInstance({
  227. id: entity,
  228. geometry: new EllipsoidOutlineGeometry(this._options),
  229. modelMatrix: skipModelMatrix
  230. ? undefined
  231. : entity.computeModelMatrixForHeightReference(
  232. time,
  233. entity.ellipsoid.heightReference,
  234. this._options.radii.z * 0.5,
  235. this._scene.mapProjection.ellipsoid,
  236. modelMatrixResult
  237. ),
  238. attributes: attributes,
  239. });
  240. };
  241. EllipsoidGeometryUpdater.prototype._computeCenter = function (time, result) {
  242. return Property.getValueOrUndefined(this._entity.position, time, result);
  243. };
  244. EllipsoidGeometryUpdater.prototype._isHidden = function (entity, ellipsoid) {
  245. return (
  246. !defined(entity.position) ||
  247. !defined(ellipsoid.radii) ||
  248. GeometryUpdater.prototype._isHidden.call(this, entity, ellipsoid)
  249. );
  250. };
  251. EllipsoidGeometryUpdater.prototype._isDynamic = function (entity, ellipsoid) {
  252. return (
  253. !entity.position.isConstant || //
  254. !Property.isConstant(entity.orientation) || //
  255. !ellipsoid.radii.isConstant || //
  256. !Property.isConstant(ellipsoid.innerRadii) || //
  257. !Property.isConstant(ellipsoid.stackPartitions) || //
  258. !Property.isConstant(ellipsoid.slicePartitions) || //
  259. !Property.isConstant(ellipsoid.outlineWidth) || //
  260. !Property.isConstant(ellipsoid.minimumClock) || //
  261. !Property.isConstant(ellipsoid.maximumClock) || //
  262. !Property.isConstant(ellipsoid.minimumCone) || //
  263. !Property.isConstant(ellipsoid.maximumCone) || //
  264. !Property.isConstant(ellipsoid.subdivisions)
  265. );
  266. };
  267. EllipsoidGeometryUpdater.prototype._setStaticOptions = function (
  268. entity,
  269. ellipsoid
  270. ) {
  271. const heightReference = Property.getValueOrDefault(
  272. ellipsoid.heightReference,
  273. Iso8601.MINIMUM_VALUE,
  274. HeightReference.NONE
  275. );
  276. const options = this._options;
  277. options.vertexFormat =
  278. this._materialProperty instanceof ColorMaterialProperty
  279. ? PerInstanceColorAppearance.VERTEX_FORMAT
  280. : MaterialAppearance.MaterialSupport.TEXTURED.vertexFormat;
  281. options.radii = ellipsoid.radii.getValue(
  282. Iso8601.MINIMUM_VALUE,
  283. options.radii
  284. );
  285. options.innerRadii = Property.getValueOrUndefined(
  286. ellipsoid.innerRadii,
  287. options.radii
  288. );
  289. options.minimumClock = Property.getValueOrUndefined(
  290. ellipsoid.minimumClock,
  291. Iso8601.MINIMUM_VALUE
  292. );
  293. options.maximumClock = Property.getValueOrUndefined(
  294. ellipsoid.maximumClock,
  295. Iso8601.MINIMUM_VALUE
  296. );
  297. options.minimumCone = Property.getValueOrUndefined(
  298. ellipsoid.minimumCone,
  299. Iso8601.MINIMUM_VALUE
  300. );
  301. options.maximumCone = Property.getValueOrUndefined(
  302. ellipsoid.maximumCone,
  303. Iso8601.MINIMUM_VALUE
  304. );
  305. options.stackPartitions = Property.getValueOrUndefined(
  306. ellipsoid.stackPartitions,
  307. Iso8601.MINIMUM_VALUE
  308. );
  309. options.slicePartitions = Property.getValueOrUndefined(
  310. ellipsoid.slicePartitions,
  311. Iso8601.MINIMUM_VALUE
  312. );
  313. options.subdivisions = Property.getValueOrUndefined(
  314. ellipsoid.subdivisions,
  315. Iso8601.MINIMUM_VALUE
  316. );
  317. options.offsetAttribute =
  318. heightReference !== HeightReference.NONE
  319. ? GeometryOffsetAttribute.ALL
  320. : undefined;
  321. };
  322. EllipsoidGeometryUpdater.prototype._onEntityPropertyChanged = heightReferenceOnEntityPropertyChanged;
  323. EllipsoidGeometryUpdater.DynamicGeometryUpdater = DynamicEllipsoidGeometryUpdater;
  324. /**
  325. * @private
  326. */
  327. function DynamicEllipsoidGeometryUpdater(
  328. geometryUpdater,
  329. primitives,
  330. groundPrimitives
  331. ) {
  332. DynamicGeometryUpdater.call(
  333. this,
  334. geometryUpdater,
  335. primitives,
  336. groundPrimitives
  337. );
  338. this._scene = geometryUpdater._scene;
  339. this._modelMatrix = new Matrix4();
  340. this._attributes = undefined;
  341. this._outlineAttributes = undefined;
  342. this._lastSceneMode = undefined;
  343. this._lastShow = undefined;
  344. this._lastOutlineShow = undefined;
  345. this._lastOutlineWidth = undefined;
  346. this._lastOutlineColor = undefined;
  347. this._lastOffset = new Cartesian3();
  348. this._material = {};
  349. }
  350. if (defined(Object.create)) {
  351. DynamicEllipsoidGeometryUpdater.prototype = Object.create(
  352. DynamicGeometryUpdater.prototype
  353. );
  354. DynamicEllipsoidGeometryUpdater.prototype.constructor = DynamicEllipsoidGeometryUpdater;
  355. }
  356. DynamicEllipsoidGeometryUpdater.prototype.update = function (time) {
  357. //>>includeStart('debug', pragmas.debug);
  358. Check.defined("time", time);
  359. //>>includeEnd('debug');
  360. const entity = this._entity;
  361. const ellipsoid = entity.ellipsoid;
  362. if (
  363. !entity.isShowing ||
  364. !entity.isAvailable(time) ||
  365. !Property.getValueOrDefault(ellipsoid.show, time, true)
  366. ) {
  367. if (defined(this._primitive)) {
  368. this._primitive.show = false;
  369. }
  370. if (defined(this._outlinePrimitive)) {
  371. this._outlinePrimitive.show = false;
  372. }
  373. return;
  374. }
  375. const radii = Property.getValueOrUndefined(
  376. ellipsoid.radii,
  377. time,
  378. radiiScratch
  379. );
  380. let modelMatrix = defined(radii)
  381. ? entity.computeModelMatrixForHeightReference(
  382. time,
  383. ellipsoid.heightReference,
  384. radii.z * 0.5,
  385. this._scene.mapProjection.ellipsoid,
  386. this._modelMatrix
  387. )
  388. : undefined;
  389. if (!defined(modelMatrix) || !defined(radii)) {
  390. if (defined(this._primitive)) {
  391. this._primitive.show = false;
  392. }
  393. if (defined(this._outlinePrimitive)) {
  394. this._outlinePrimitive.show = false;
  395. }
  396. return;
  397. }
  398. //Compute attributes and material.
  399. const showFill = Property.getValueOrDefault(ellipsoid.fill, time, true);
  400. const showOutline = Property.getValueOrDefault(
  401. ellipsoid.outline,
  402. time,
  403. false
  404. );
  405. const outlineColor = Property.getValueOrClonedDefault(
  406. ellipsoid.outlineColor,
  407. time,
  408. Color.BLACK,
  409. scratchColor
  410. );
  411. const material = MaterialProperty.getValue(
  412. time,
  413. defaultValue(ellipsoid.material, defaultMaterial),
  414. this._material
  415. );
  416. // Check properties that could trigger a primitive rebuild.
  417. const innerRadii = Property.getValueOrUndefined(
  418. ellipsoid.innerRadii,
  419. time,
  420. innerRadiiScratch
  421. );
  422. const minimumClock = Property.getValueOrUndefined(
  423. ellipsoid.minimumClock,
  424. time
  425. );
  426. const maximumClock = Property.getValueOrUndefined(
  427. ellipsoid.maximumClock,
  428. time
  429. );
  430. const minimumCone = Property.getValueOrUndefined(ellipsoid.minimumCone, time);
  431. const maximumCone = Property.getValueOrUndefined(ellipsoid.maximumCone, time);
  432. const stackPartitions = Property.getValueOrUndefined(
  433. ellipsoid.stackPartitions,
  434. time
  435. );
  436. const slicePartitions = Property.getValueOrUndefined(
  437. ellipsoid.slicePartitions,
  438. time
  439. );
  440. const subdivisions = Property.getValueOrUndefined(
  441. ellipsoid.subdivisions,
  442. time
  443. );
  444. const outlineWidth = Property.getValueOrDefault(
  445. ellipsoid.outlineWidth,
  446. time,
  447. 1.0
  448. );
  449. const heightReference = Property.getValueOrDefault(
  450. ellipsoid.heightReference,
  451. time,
  452. HeightReference.NONE
  453. );
  454. const offsetAttribute =
  455. heightReference !== HeightReference.NONE
  456. ? GeometryOffsetAttribute.ALL
  457. : undefined;
  458. //In 3D we use a fast path by modifying Primitive.modelMatrix instead of regenerating the primitive every frame.
  459. //Also check for height reference because this method doesn't work when the height is relative to terrain.
  460. const sceneMode = this._scene.mode;
  461. const in3D =
  462. sceneMode === SceneMode.SCENE3D && heightReference === HeightReference.NONE;
  463. const options = this._options;
  464. const shadows = this._geometryUpdater.shadowsProperty.getValue(time);
  465. const distanceDisplayConditionProperty = this._geometryUpdater
  466. .distanceDisplayConditionProperty;
  467. const distanceDisplayCondition = distanceDisplayConditionProperty.getValue(
  468. time
  469. );
  470. const offset = Property.getValueOrDefault(
  471. this._geometryUpdater.terrainOffsetProperty,
  472. time,
  473. defaultOffset,
  474. offsetScratch
  475. );
  476. //We only rebuild the primitive if something other than the radii has changed
  477. //For the radii, we use unit sphere and then deform it with a scale matrix.
  478. const rebuildPrimitives =
  479. !in3D ||
  480. this._lastSceneMode !== sceneMode ||
  481. !defined(this._primitive) || //
  482. options.stackPartitions !== stackPartitions ||
  483. options.slicePartitions !== slicePartitions || //
  484. (defined(innerRadii) &&
  485. !Cartesian3.equals(options.innerRadii !== innerRadii)) ||
  486. options.minimumClock !== minimumClock || //
  487. options.maximumClock !== maximumClock ||
  488. options.minimumCone !== minimumCone || //
  489. options.maximumCone !== maximumCone ||
  490. options.subdivisions !== subdivisions || //
  491. this._lastOutlineWidth !== outlineWidth ||
  492. options.offsetAttribute !== offsetAttribute;
  493. if (rebuildPrimitives) {
  494. const primitives = this._primitives;
  495. primitives.removeAndDestroy(this._primitive);
  496. primitives.removeAndDestroy(this._outlinePrimitive);
  497. this._primitive = undefined;
  498. this._outlinePrimitive = undefined;
  499. this._lastSceneMode = sceneMode;
  500. this._lastOutlineWidth = outlineWidth;
  501. options.stackPartitions = stackPartitions;
  502. options.slicePartitions = slicePartitions;
  503. options.subdivisions = subdivisions;
  504. options.offsetAttribute = offsetAttribute;
  505. options.radii = Cartesian3.clone(in3D ? unitSphere : radii, options.radii);
  506. if (defined(innerRadii)) {
  507. if (in3D) {
  508. const mag = Cartesian3.magnitude(radii);
  509. options.innerRadii = Cartesian3.fromElements(
  510. innerRadii.x / mag,
  511. innerRadii.y / mag,
  512. innerRadii.z / mag,
  513. options.innerRadii
  514. );
  515. } else {
  516. options.innerRadii = Cartesian3.clone(innerRadii, options.innerRadii);
  517. }
  518. } else {
  519. options.innerRadii = undefined;
  520. }
  521. options.minimumClock = minimumClock;
  522. options.maximumClock = maximumClock;
  523. options.minimumCone = minimumCone;
  524. options.maximumCone = maximumCone;
  525. const appearance = new MaterialAppearance({
  526. material: material,
  527. translucent: material.isTranslucent(),
  528. closed: true,
  529. });
  530. options.vertexFormat = appearance.vertexFormat;
  531. const fillInstance = this._geometryUpdater.createFillGeometryInstance(
  532. time,
  533. in3D,
  534. this._modelMatrix
  535. );
  536. this._primitive = primitives.add(
  537. new Primitive({
  538. geometryInstances: fillInstance,
  539. appearance: appearance,
  540. asynchronous: false,
  541. shadows: shadows,
  542. })
  543. );
  544. const outlineInstance = this._geometryUpdater.createOutlineGeometryInstance(
  545. time,
  546. in3D,
  547. this._modelMatrix
  548. );
  549. this._outlinePrimitive = primitives.add(
  550. new Primitive({
  551. geometryInstances: outlineInstance,
  552. appearance: new PerInstanceColorAppearance({
  553. flat: true,
  554. translucent: outlineInstance.attributes.color.value[3] !== 255,
  555. renderState: {
  556. lineWidth: this._geometryUpdater._scene.clampLineWidth(
  557. outlineWidth
  558. ),
  559. },
  560. }),
  561. asynchronous: false,
  562. shadows: shadows,
  563. })
  564. );
  565. this._lastShow = showFill;
  566. this._lastOutlineShow = showOutline;
  567. this._lastOutlineColor = Color.clone(outlineColor, this._lastOutlineColor);
  568. this._lastDistanceDisplayCondition = distanceDisplayCondition;
  569. this._lastOffset = Cartesian3.clone(offset, this._lastOffset);
  570. } else if (this._primitive.ready) {
  571. //Update attributes only.
  572. const primitive = this._primitive;
  573. const outlinePrimitive = this._outlinePrimitive;
  574. primitive.show = true;
  575. outlinePrimitive.show = true;
  576. primitive.appearance.material = material;
  577. let attributes = this._attributes;
  578. if (!defined(attributes)) {
  579. attributes = primitive.getGeometryInstanceAttributes(entity);
  580. this._attributes = attributes;
  581. }
  582. if (showFill !== this._lastShow) {
  583. attributes.show = ShowGeometryInstanceAttribute.toValue(
  584. showFill,
  585. attributes.show
  586. );
  587. this._lastShow = showFill;
  588. }
  589. let outlineAttributes = this._outlineAttributes;
  590. if (!defined(outlineAttributes)) {
  591. outlineAttributes = outlinePrimitive.getGeometryInstanceAttributes(
  592. entity
  593. );
  594. this._outlineAttributes = outlineAttributes;
  595. }
  596. if (showOutline !== this._lastOutlineShow) {
  597. outlineAttributes.show = ShowGeometryInstanceAttribute.toValue(
  598. showOutline,
  599. outlineAttributes.show
  600. );
  601. this._lastOutlineShow = showOutline;
  602. }
  603. if (!Color.equals(outlineColor, this._lastOutlineColor)) {
  604. outlineAttributes.color = ColorGeometryInstanceAttribute.toValue(
  605. outlineColor,
  606. outlineAttributes.color
  607. );
  608. Color.clone(outlineColor, this._lastOutlineColor);
  609. }
  610. if (
  611. !DistanceDisplayCondition.equals(
  612. distanceDisplayCondition,
  613. this._lastDistanceDisplayCondition
  614. )
  615. ) {
  616. attributes.distanceDisplayCondition = DistanceDisplayConditionGeometryInstanceAttribute.toValue(
  617. distanceDisplayCondition,
  618. attributes.distanceDisplayCondition
  619. );
  620. outlineAttributes.distanceDisplayCondition = DistanceDisplayConditionGeometryInstanceAttribute.toValue(
  621. distanceDisplayCondition,
  622. outlineAttributes.distanceDisplayCondition
  623. );
  624. DistanceDisplayCondition.clone(
  625. distanceDisplayCondition,
  626. this._lastDistanceDisplayCondition
  627. );
  628. }
  629. if (!Cartesian3.equals(offset, this._lastOffset)) {
  630. attributes.offset = OffsetGeometryInstanceAttribute.toValue(
  631. offset,
  632. attributes.offset
  633. );
  634. outlineAttributes.offset = OffsetGeometryInstanceAttribute.toValue(
  635. offset,
  636. attributes.offset
  637. );
  638. Cartesian3.clone(offset, this._lastOffset);
  639. }
  640. }
  641. if (in3D) {
  642. //Since we are scaling a unit sphere, we can't let any of the values go to zero.
  643. //Instead we clamp them to a small value. To the naked eye, this produces the same results
  644. //that you get passing EllipsoidGeometry a radii with a zero component.
  645. radii.x = Math.max(radii.x, 0.001);
  646. radii.y = Math.max(radii.y, 0.001);
  647. radii.z = Math.max(radii.z, 0.001);
  648. modelMatrix = Matrix4.multiplyByScale(modelMatrix, radii, modelMatrix);
  649. this._primitive.modelMatrix = modelMatrix;
  650. this._outlinePrimitive.modelMatrix = modelMatrix;
  651. }
  652. };
  653. export default EllipsoidGeometryUpdater;