Source: DataSources/EllipsoidGeometryUpdater.js

  1. /*global define*/
  2. define([
  3. '../Core/Cartesian3',
  4. '../Core/Color',
  5. '../Core/ColorGeometryInstanceAttribute',
  6. '../Core/defaultValue',
  7. '../Core/defined',
  8. '../Core/defineProperties',
  9. '../Core/destroyObject',
  10. '../Core/DeveloperError',
  11. '../Core/DistanceDisplayCondition',
  12. '../Core/DistanceDisplayConditionGeometryInstanceAttribute',
  13. '../Core/EllipsoidGeometry',
  14. '../Core/EllipsoidOutlineGeometry',
  15. '../Core/Event',
  16. '../Core/GeometryInstance',
  17. '../Core/Iso8601',
  18. '../Core/Matrix4',
  19. '../Core/ShowGeometryInstanceAttribute',
  20. '../Scene/MaterialAppearance',
  21. '../Scene/PerInstanceColorAppearance',
  22. '../Scene/Primitive',
  23. '../Scene/SceneMode',
  24. '../Scene/ShadowMode',
  25. './ColorMaterialProperty',
  26. './ConstantProperty',
  27. './dynamicGeometryGetBoundingSphere',
  28. './MaterialProperty',
  29. './Property'
  30. ], function(
  31. Cartesian3,
  32. Color,
  33. ColorGeometryInstanceAttribute,
  34. defaultValue,
  35. defined,
  36. defineProperties,
  37. destroyObject,
  38. DeveloperError,
  39. DistanceDisplayCondition,
  40. DistanceDisplayConditionGeometryInstanceAttribute,
  41. EllipsoidGeometry,
  42. EllipsoidOutlineGeometry,
  43. Event,
  44. GeometryInstance,
  45. Iso8601,
  46. Matrix4,
  47. ShowGeometryInstanceAttribute,
  48. MaterialAppearance,
  49. PerInstanceColorAppearance,
  50. Primitive,
  51. SceneMode,
  52. ShadowMode,
  53. ColorMaterialProperty,
  54. ConstantProperty,
  55. dynamicGeometryGetBoundingSphere,
  56. MaterialProperty,
  57. Property) {
  58. 'use strict';
  59. var defaultMaterial = new ColorMaterialProperty(Color.WHITE);
  60. var defaultShow = new ConstantProperty(true);
  61. var defaultFill = new ConstantProperty(true);
  62. var defaultOutline = new ConstantProperty(false);
  63. var defaultOutlineColor = new ConstantProperty(Color.BLACK);
  64. var defaultShadows = new ConstantProperty(ShadowMode.DISABLED);
  65. var defaultDistanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition());
  66. var radiiScratch = new Cartesian3();
  67. var scratchColor = new Color();
  68. var unitSphere = new Cartesian3(1, 1, 1);
  69. function GeometryOptions(entity) {
  70. this.id = entity;
  71. this.vertexFormat = undefined;
  72. this.radii = undefined;
  73. this.stackPartitions = undefined;
  74. this.slicePartitions = undefined;
  75. this.subdivisions = undefined;
  76. }
  77. /**
  78. * A {@link GeometryUpdater} for ellipsoids.
  79. * Clients do not normally create this class directly, but instead rely on {@link DataSourceDisplay}.
  80. * @alias EllipsoidGeometryUpdater
  81. * @constructor
  82. *
  83. * @param {Entity} entity The entity containing the geometry to be visualized.
  84. * @param {Scene} scene The scene where visualization is taking place.
  85. */
  86. function EllipsoidGeometryUpdater(entity, scene) {
  87. //>>includeStart('debug', pragmas.debug);
  88. if (!defined(entity)) {
  89. throw new DeveloperError('entity is required');
  90. }
  91. if (!defined(scene)) {
  92. throw new DeveloperError('scene is required');
  93. }
  94. //>>includeEnd('debug');
  95. this._scene = scene;
  96. this._entity = entity;
  97. this._entitySubscription = entity.definitionChanged.addEventListener(EllipsoidGeometryUpdater.prototype._onEntityPropertyChanged, this);
  98. this._fillEnabled = false;
  99. this._dynamic = false;
  100. this._outlineEnabled = false;
  101. this._geometryChanged = new Event();
  102. this._showProperty = undefined;
  103. this._materialProperty = undefined;
  104. this._hasConstantOutline = true;
  105. this._showOutlineProperty = undefined;
  106. this._outlineColorProperty = undefined;
  107. this._outlineWidth = 1.0;
  108. this._shadowsProperty = undefined;
  109. this._distanceDisplayConditionProperty = undefined;
  110. this._options = new GeometryOptions(entity);
  111. this._onEntityPropertyChanged(entity, 'ellipsoid', entity.ellipsoid, undefined);
  112. }
  113. defineProperties(EllipsoidGeometryUpdater, {
  114. /**
  115. * Gets the type of Appearance to use for simple color-based geometry.
  116. * @memberof EllipsoidGeometryUpdater
  117. * @type {Appearance}
  118. */
  119. perInstanceColorAppearanceType : {
  120. value : PerInstanceColorAppearance
  121. },
  122. /**
  123. * Gets the type of Appearance to use for material-based geometry.
  124. * @memberof EllipsoidGeometryUpdater
  125. * @type {Appearance}
  126. */
  127. materialAppearanceType : {
  128. value : MaterialAppearance
  129. }
  130. });
  131. defineProperties(EllipsoidGeometryUpdater.prototype, {
  132. /**
  133. * Gets the entity associated with this geometry.
  134. * @memberof EllipsoidGeometryUpdater.prototype
  135. *
  136. * @type {Entity}
  137. * @readonly
  138. */
  139. entity : {
  140. get : function() {
  141. return this._entity;
  142. }
  143. },
  144. /**
  145. * Gets a value indicating if the geometry has a fill component.
  146. * @memberof EllipsoidGeometryUpdater.prototype
  147. *
  148. * @type {Boolean}
  149. * @readonly
  150. */
  151. fillEnabled : {
  152. get : function() {
  153. return this._fillEnabled;
  154. }
  155. },
  156. /**
  157. * Gets a value indicating if fill visibility varies with simulation time.
  158. * @memberof EllipsoidGeometryUpdater.prototype
  159. *
  160. * @type {Boolean}
  161. * @readonly
  162. */
  163. hasConstantFill : {
  164. get : function() {
  165. return !this._fillEnabled ||
  166. (!defined(this._entity.availability) &&
  167. Property.isConstant(this._showProperty) &&
  168. Property.isConstant(this._fillProperty));
  169. }
  170. },
  171. /**
  172. * Gets the material property used to fill the geometry.
  173. * @memberof EllipsoidGeometryUpdater.prototype
  174. *
  175. * @type {MaterialProperty}
  176. * @readonly
  177. */
  178. fillMaterialProperty : {
  179. get : function() {
  180. return this._materialProperty;
  181. }
  182. },
  183. /**
  184. * Gets a value indicating if the geometry has an outline component.
  185. * @memberof EllipsoidGeometryUpdater.prototype
  186. *
  187. * @type {Boolean}
  188. * @readonly
  189. */
  190. outlineEnabled : {
  191. get : function() {
  192. return this._outlineEnabled;
  193. }
  194. },
  195. /**
  196. * Gets a value indicating if outline visibility varies with simulation time.
  197. * @memberof EllipsoidGeometryUpdater.prototype
  198. *
  199. * @type {Boolean}
  200. * @readonly
  201. */
  202. hasConstantOutline : {
  203. get : function() {
  204. return !this._outlineEnabled ||
  205. (!defined(this._entity.availability) &&
  206. Property.isConstant(this._showProperty) &&
  207. Property.isConstant(this._showOutlineProperty));
  208. }
  209. },
  210. /**
  211. * Gets the {@link Color} property for the geometry outline.
  212. * @memberof EllipsoidGeometryUpdater.prototype
  213. *
  214. * @type {Property}
  215. * @readonly
  216. */
  217. outlineColorProperty : {
  218. get : function() {
  219. return this._outlineColorProperty;
  220. }
  221. },
  222. /**
  223. * Gets the constant with of the geometry outline, in pixels.
  224. * This value is only valid if isDynamic is false.
  225. * @memberof EllipsoidGeometryUpdater.prototype
  226. *
  227. * @type {Number}
  228. * @readonly
  229. */
  230. outlineWidth : {
  231. get : function() {
  232. return this._outlineWidth;
  233. }
  234. },
  235. /**
  236. * Gets the property specifying whether the geometry
  237. * casts or receives shadows from each light source.
  238. * @memberof EllipsoidGeometryUpdater.prototype
  239. *
  240. * @type {Property}
  241. * @readonly
  242. */
  243. shadowsProperty : {
  244. get : function() {
  245. return this._shadowsProperty;
  246. }
  247. },
  248. /**
  249. * Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this geometry will be displayed.
  250. * @memberof EllipsoidGeometryUpdater.prototype
  251. *
  252. * @type {Property}
  253. * @readonly
  254. */
  255. distanceDisplayConditionProperty : {
  256. get : function() {
  257. return this._distanceDisplayConditionProperty;
  258. }
  259. },
  260. /**
  261. * Gets a value indicating if the geometry is time-varying.
  262. * If true, all visualization is delegated to the {@link DynamicGeometryUpdater}
  263. * returned by GeometryUpdater#createDynamicUpdater.
  264. * @memberof EllipsoidGeometryUpdater.prototype
  265. *
  266. * @type {Boolean}
  267. * @readonly
  268. */
  269. isDynamic : {
  270. get : function() {
  271. return this._dynamic;
  272. }
  273. },
  274. /**
  275. * Gets a value indicating if the geometry is closed.
  276. * This property is only valid for static geometry.
  277. * @memberof EllipsoidGeometryUpdater.prototype
  278. *
  279. * @type {Boolean}
  280. * @readonly
  281. */
  282. isClosed : {
  283. value : true
  284. },
  285. /**
  286. * Gets an event that is raised whenever the public properties
  287. * of this updater change.
  288. * @memberof EllipsoidGeometryUpdater.prototype
  289. *
  290. * @type {Boolean}
  291. * @readonly
  292. */
  293. geometryChanged : {
  294. get : function() {
  295. return this._geometryChanged;
  296. }
  297. }
  298. });
  299. /**
  300. * Checks if the geometry is outlined at the provided time.
  301. *
  302. * @param {JulianDate} time The time for which to retrieve visibility.
  303. * @returns {Boolean} true if geometry is outlined at the provided time, false otherwise.
  304. */
  305. EllipsoidGeometryUpdater.prototype.isOutlineVisible = function(time) {
  306. var entity = this._entity;
  307. return this._outlineEnabled && entity.isAvailable(time) && this._showProperty.getValue(time) && this._showOutlineProperty.getValue(time);
  308. };
  309. /**
  310. * Checks if the geometry is filled at the provided time.
  311. *
  312. * @param {JulianDate} time The time for which to retrieve visibility.
  313. * @returns {Boolean} true if geometry is filled at the provided time, false otherwise.
  314. */
  315. EllipsoidGeometryUpdater.prototype.isFilled = function(time) {
  316. var entity = this._entity;
  317. return this._fillEnabled && entity.isAvailable(time) && this._showProperty.getValue(time) && this._fillProperty.getValue(time);
  318. };
  319. /**
  320. * Creates the geometry instance which represents the fill of the geometry.
  321. *
  322. * @param {JulianDate} time The time to use when retrieving initial attribute values.
  323. * @returns {GeometryInstance} The geometry instance representing the filled portion of the geometry.
  324. *
  325. * @exception {DeveloperError} This instance does not represent a filled geometry.
  326. */
  327. EllipsoidGeometryUpdater.prototype.createFillGeometryInstance = function(time) {
  328. //>>includeStart('debug', pragmas.debug);
  329. if (!defined(time)) {
  330. throw new DeveloperError('time is required.');
  331. }
  332. if (!this._fillEnabled) {
  333. throw new DeveloperError('This instance does not represent a filled geometry.');
  334. }
  335. //>>includeEnd('debug');
  336. var entity = this._entity;
  337. var isAvailable = entity.isAvailable(time);
  338. var attributes;
  339. var color;
  340. var show = new ShowGeometryInstanceAttribute(isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._fillProperty.getValue(time));
  341. var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(time);
  342. var distanceDisplayConditionAttribute = DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(distanceDisplayCondition);
  343. if (this._materialProperty instanceof ColorMaterialProperty) {
  344. var currentColor = Color.WHITE;
  345. if (defined(this._materialProperty.color) && (this._materialProperty.color.isConstant || isAvailable)) {
  346. currentColor = this._materialProperty.color.getValue(time);
  347. }
  348. color = ColorGeometryInstanceAttribute.fromColor(currentColor);
  349. attributes = {
  350. show : show,
  351. distanceDisplayCondition : distanceDisplayConditionAttribute,
  352. color : color
  353. };
  354. } else {
  355. attributes = {
  356. show : show,
  357. distanceDisplayCondition : distanceDisplayConditionAttribute
  358. };
  359. }
  360. return new GeometryInstance({
  361. id : entity,
  362. geometry : new EllipsoidGeometry(this._options),
  363. modelMatrix : entity._getModelMatrix(Iso8601.MINIMUM_VALUE),
  364. attributes : attributes
  365. });
  366. };
  367. /**
  368. * Creates the geometry instance which represents the outline of the geometry.
  369. *
  370. * @param {JulianDate} time The time to use when retrieving initial attribute values.
  371. * @returns {GeometryInstance} The geometry instance representing the outline portion of the geometry.
  372. *
  373. * @exception {DeveloperError} This instance does not represent an outlined geometry.
  374. */
  375. EllipsoidGeometryUpdater.prototype.createOutlineGeometryInstance = function(time) {
  376. //>>includeStart('debug', pragmas.debug);
  377. if (!defined(time)) {
  378. throw new DeveloperError('time is required.');
  379. }
  380. if (!this._outlineEnabled) {
  381. throw new DeveloperError('This instance does not represent an outlined geometry.');
  382. }
  383. //>>includeEnd('debug');
  384. var entity = this._entity;
  385. var isAvailable = entity.isAvailable(time);
  386. var outlineColor = Property.getValueOrDefault(this._outlineColorProperty, time, Color.BLACK);
  387. var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(time);
  388. return new GeometryInstance({
  389. id : entity,
  390. geometry : new EllipsoidOutlineGeometry(this._options),
  391. modelMatrix : entity._getModelMatrix(Iso8601.MINIMUM_VALUE),
  392. attributes : {
  393. show : new ShowGeometryInstanceAttribute(isAvailable && entity.isShowing && this._showProperty.getValue(time) && this._showOutlineProperty.getValue(time)),
  394. color : ColorGeometryInstanceAttribute.fromColor(outlineColor),
  395. distanceDisplayCondition : DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(distanceDisplayCondition)
  396. }
  397. });
  398. };
  399. /**
  400. * Returns true if this object was destroyed; otherwise, false.
  401. *
  402. * @returns {Boolean} True if this object was destroyed; otherwise, false.
  403. */
  404. EllipsoidGeometryUpdater.prototype.isDestroyed = function() {
  405. return false;
  406. };
  407. /**
  408. * Destroys and resources used by the object. Once an object is destroyed, it should not be used.
  409. *
  410. * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
  411. */
  412. EllipsoidGeometryUpdater.prototype.destroy = function() {
  413. this._entitySubscription();
  414. destroyObject(this);
  415. };
  416. EllipsoidGeometryUpdater.prototype._onEntityPropertyChanged = function(entity, propertyName, newValue, oldValue) {
  417. if (!(propertyName === 'availability' || propertyName === 'position' || propertyName === 'orientation' || propertyName === 'ellipsoid')) {
  418. return;
  419. }
  420. var ellipsoid = entity.ellipsoid;
  421. if (!defined(ellipsoid)) {
  422. if (this._fillEnabled || this._outlineEnabled) {
  423. this._fillEnabled = false;
  424. this._outlineEnabled = false;
  425. this._geometryChanged.raiseEvent(this);
  426. }
  427. return;
  428. }
  429. var fillProperty = ellipsoid.fill;
  430. var fillEnabled = defined(fillProperty) && fillProperty.isConstant ? fillProperty.getValue(Iso8601.MINIMUM_VALUE) : true;
  431. var outlineProperty = ellipsoid.outline;
  432. var outlineEnabled = defined(outlineProperty);
  433. if (outlineEnabled && outlineProperty.isConstant) {
  434. outlineEnabled = outlineProperty.getValue(Iso8601.MINIMUM_VALUE);
  435. }
  436. if (!fillEnabled && !outlineEnabled) {
  437. if (this._fillEnabled || this._outlineEnabled) {
  438. this._fillEnabled = false;
  439. this._outlineEnabled = false;
  440. this._geometryChanged.raiseEvent(this);
  441. }
  442. return;
  443. }
  444. var position = entity.position;
  445. var radii = ellipsoid.radii;
  446. var show = ellipsoid.show;
  447. if ((defined(show) && show.isConstant && !show.getValue(Iso8601.MINIMUM_VALUE)) || //
  448. (!defined(position) || !defined(radii))) {
  449. if (this._fillEnabled || this._outlineEnabled) {
  450. this._fillEnabled = false;
  451. this._outlineEnabled = false;
  452. this._geometryChanged.raiseEvent(this);
  453. }
  454. return;
  455. }
  456. var material = defaultValue(ellipsoid.material, defaultMaterial);
  457. var isColorMaterial = material instanceof ColorMaterialProperty;
  458. this._materialProperty = material;
  459. this._fillProperty = defaultValue(fillProperty, defaultFill);
  460. this._showProperty = defaultValue(show, defaultShow);
  461. this._showOutlineProperty = defaultValue(ellipsoid.outline, defaultOutline);
  462. this._outlineColorProperty = outlineEnabled ? defaultValue(ellipsoid.outlineColor, defaultOutlineColor) : undefined;
  463. this._shadowsProperty = defaultValue(ellipsoid.shadows, defaultShadows);
  464. this._distanceDisplayConditionProperty = defaultValue(ellipsoid.distanceDisplayCondition, defaultDistanceDisplayCondition);
  465. this._fillEnabled = fillEnabled;
  466. this._outlineEnabled = outlineEnabled;
  467. var stackPartitions = ellipsoid.stackPartitions;
  468. var slicePartitions = ellipsoid.slicePartitions;
  469. var outlineWidth = ellipsoid.outlineWidth;
  470. var subdivisions = ellipsoid.subdivisions;
  471. if (!position.isConstant || //
  472. !Property.isConstant(entity.orientation) || //
  473. !radii.isConstant || //
  474. !Property.isConstant(stackPartitions) || //
  475. !Property.isConstant(slicePartitions) || //
  476. !Property.isConstant(outlineWidth) || //
  477. !Property.isConstant(subdivisions)) {
  478. if (!this._dynamic) {
  479. this._dynamic = true;
  480. this._geometryChanged.raiseEvent(this);
  481. }
  482. } else {
  483. var options = this._options;
  484. options.vertexFormat = isColorMaterial ? PerInstanceColorAppearance.VERTEX_FORMAT : MaterialAppearance.MaterialSupport.TEXTURED.vertexFormat;
  485. options.radii = radii.getValue(Iso8601.MINIMUM_VALUE, options.radii);
  486. options.stackPartitions = defined(stackPartitions) ? stackPartitions.getValue(Iso8601.MINIMUM_VALUE) : undefined;
  487. options.slicePartitions = defined(slicePartitions) ? slicePartitions.getValue(Iso8601.MINIMUM_VALUE) : undefined;
  488. options.subdivisions = defined(subdivisions) ? subdivisions.getValue(Iso8601.MINIMUM_VALUE) : undefined;
  489. this._outlineWidth = defined(outlineWidth) ? outlineWidth.getValue(Iso8601.MINIMUM_VALUE) : 1.0;
  490. this._dynamic = false;
  491. this._geometryChanged.raiseEvent(this);
  492. }
  493. };
  494. /**
  495. * Creates the dynamic updater to be used when GeometryUpdater#isDynamic is true.
  496. *
  497. * @param {PrimitiveCollection} primitives The primitive collection to use.
  498. * @returns {DynamicGeometryUpdater} The dynamic updater used to update the geometry each frame.
  499. *
  500. * @exception {DeveloperError} This instance does not represent dynamic geometry.
  501. */
  502. EllipsoidGeometryUpdater.prototype.createDynamicUpdater = function(primitives) {
  503. //>>includeStart('debug', pragmas.debug);
  504. if (!this._dynamic) {
  505. throw new DeveloperError('This instance does not represent dynamic geometry.');
  506. }
  507. if (!defined(primitives)) {
  508. throw new DeveloperError('primitives is required.');
  509. }
  510. //>>includeEnd('debug');
  511. return new DynamicGeometryUpdater(primitives, this);
  512. };
  513. /**
  514. * @private
  515. */
  516. function DynamicGeometryUpdater(primitives, geometryUpdater) {
  517. this._entity = geometryUpdater._entity;
  518. this._scene = geometryUpdater._scene;
  519. this._primitives = primitives;
  520. this._primitive = undefined;
  521. this._outlinePrimitive = undefined;
  522. this._geometryUpdater = geometryUpdater;
  523. this._options = new GeometryOptions(geometryUpdater._entity);
  524. this._modelMatrix = new Matrix4();
  525. this._material = undefined;
  526. this._attributes = undefined;
  527. this._outlineAttributes = undefined;
  528. this._lastSceneMode = undefined;
  529. this._lastShow = undefined;
  530. this._lastOutlineShow = undefined;
  531. this._lastOutlineWidth = undefined;
  532. this._lastOutlineColor = undefined;
  533. }
  534. DynamicGeometryUpdater.prototype.update = function(time) {
  535. //>>includeStart('debug', pragmas.debug);
  536. if (!defined(time)) {
  537. throw new DeveloperError('time is required.');
  538. }
  539. //>>includeEnd('debug');
  540. var entity = this._entity;
  541. var ellipsoid = entity.ellipsoid;
  542. if (!entity.isShowing || !entity.isAvailable(time) || !Property.getValueOrDefault(ellipsoid.show, time, true)) {
  543. if (defined(this._primitive)) {
  544. this._primitive.show = false;
  545. }
  546. if (defined(this._outlinePrimitive)) {
  547. this._outlinePrimitive.show = false;
  548. }
  549. return;
  550. }
  551. var radii = Property.getValueOrUndefined(ellipsoid.radii, time, radiiScratch);
  552. var modelMatrix = entity._getModelMatrix(time, this._modelMatrix);
  553. if (!defined(modelMatrix) || !defined(radii)) {
  554. if (defined(this._primitive)) {
  555. this._primitive.show = false;
  556. }
  557. if (defined(this._outlinePrimitive)) {
  558. this._outlinePrimitive.show = false;
  559. }
  560. return;
  561. }
  562. //Compute attributes and material.
  563. var appearance;
  564. var showFill = Property.getValueOrDefault(ellipsoid.fill, time, true);
  565. var showOutline = Property.getValueOrDefault(ellipsoid.outline, time, false);
  566. var outlineColor = Property.getValueOrClonedDefault(ellipsoid.outlineColor, time, Color.BLACK, scratchColor);
  567. var material = MaterialProperty.getValue(time, defaultValue(ellipsoid.material, defaultMaterial), this._material);
  568. this._material = material;
  569. // Check properties that could trigger a primitive rebuild.
  570. var stackPartitions = Property.getValueOrUndefined(ellipsoid.stackPartitions, time);
  571. var slicePartitions = Property.getValueOrUndefined(ellipsoid.slicePartitions, time);
  572. var subdivisions = Property.getValueOrUndefined(ellipsoid.subdivisions, time);
  573. var outlineWidth = Property.getValueOrDefault(ellipsoid.outlineWidth, time, 1.0);
  574. //In 3D we use a fast path by modifying Primitive.modelMatrix instead of regenerating the primitive every frame.
  575. var sceneMode = this._scene.mode;
  576. var in3D = sceneMode === SceneMode.SCENE3D;
  577. var options = this._options;
  578. var shadows = this._geometryUpdater.shadowsProperty.getValue(time);
  579. var distanceDisplayConditionProperty = this._geometryUpdater.distanceDisplayConditionProperty;
  580. var distanceDisplayCondition = distanceDisplayConditionProperty.getValue(time);
  581. var distanceDisplayConditionAttribute = DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(distanceDisplayCondition);
  582. //We only rebuild the primitive if something other than the radii has changed
  583. //For the radii, we use unit sphere and then deform it with a scale matrix.
  584. var rebuildPrimitives = !in3D || this._lastSceneMode !== sceneMode || !defined(this._primitive) || //
  585. options.stackPartitions !== stackPartitions || options.slicePartitions !== slicePartitions || //
  586. options.subdivisions !== subdivisions || this._lastOutlineWidth !== outlineWidth;
  587. if (rebuildPrimitives) {
  588. var primitives = this._primitives;
  589. primitives.removeAndDestroy(this._primitive);
  590. primitives.removeAndDestroy(this._outlinePrimitive);
  591. this._primitive = undefined;
  592. this._outlinePrimitive = undefined;
  593. this._lastSceneMode = sceneMode;
  594. this._lastOutlineWidth = outlineWidth;
  595. options.stackPartitions = stackPartitions;
  596. options.slicePartitions = slicePartitions;
  597. options.subdivisions = subdivisions;
  598. options.radii = in3D ? unitSphere : radii;
  599. appearance = new MaterialAppearance({
  600. material : material,
  601. translucent : material.isTranslucent(),
  602. closed : true
  603. });
  604. options.vertexFormat = appearance.vertexFormat;
  605. this._primitive = primitives.add(new Primitive({
  606. geometryInstances : new GeometryInstance({
  607. id : entity,
  608. geometry : new EllipsoidGeometry(options),
  609. modelMatrix : !in3D ? modelMatrix : undefined,
  610. attributes : {
  611. show : new ShowGeometryInstanceAttribute(showFill),
  612. distanceDisplayCondition : distanceDisplayConditionAttribute
  613. }
  614. }),
  615. appearance : appearance,
  616. asynchronous : false,
  617. shadows : shadows
  618. }));
  619. options.vertexFormat = PerInstanceColorAppearance.VERTEX_FORMAT;
  620. this._outlinePrimitive = primitives.add(new Primitive({
  621. geometryInstances : new GeometryInstance({
  622. id : entity,
  623. geometry : new EllipsoidOutlineGeometry(options),
  624. modelMatrix : !in3D ? modelMatrix : undefined,
  625. attributes : {
  626. show : new ShowGeometryInstanceAttribute(showOutline),
  627. color : ColorGeometryInstanceAttribute.fromColor(outlineColor),
  628. distanceDisplayCondition : distanceDisplayConditionAttribute
  629. }
  630. }),
  631. appearance : new PerInstanceColorAppearance({
  632. flat : true,
  633. translucent : outlineColor.alpha !== 1.0,
  634. renderState : {
  635. lineWidth : this._geometryUpdater._scene.clampLineWidth(outlineWidth)
  636. }
  637. }),
  638. asynchronous : false,
  639. shadows : shadows
  640. }));
  641. this._lastShow = showFill;
  642. this._lastOutlineShow = showOutline;
  643. this._lastOutlineColor = Color.clone(outlineColor, this._lastOutlineColor);
  644. this._lastDistanceDisplayCondition = distanceDisplayCondition;
  645. } else if (this._primitive.ready) {
  646. //Update attributes only.
  647. var primitive = this._primitive;
  648. var outlinePrimitive = this._outlinePrimitive;
  649. primitive.show = true;
  650. outlinePrimitive.show = true;
  651. appearance = primitive.appearance;
  652. appearance.material = material;
  653. var attributes = this._attributes;
  654. if (!defined(attributes)) {
  655. attributes = primitive.getGeometryInstanceAttributes(entity);
  656. this._attributes = attributes;
  657. }
  658. if (showFill !== this._lastShow) {
  659. attributes.show = ShowGeometryInstanceAttribute.toValue(showFill, attributes.show);
  660. this._lastShow = showFill;
  661. }
  662. var outlineAttributes = this._outlineAttributes;
  663. if (!defined(outlineAttributes)) {
  664. outlineAttributes = outlinePrimitive.getGeometryInstanceAttributes(entity);
  665. this._outlineAttributes = outlineAttributes;
  666. }
  667. if (showOutline !== this._lastOutlineShow) {
  668. outlineAttributes.show = ShowGeometryInstanceAttribute.toValue(showOutline, outlineAttributes.show);
  669. this._lastOutlineShow = showOutline;
  670. }
  671. if (!Color.equals(outlineColor, this._lastOutlineColor)) {
  672. outlineAttributes.color = ColorGeometryInstanceAttribute.toValue(outlineColor, outlineAttributes.color);
  673. Color.clone(outlineColor, this._lastOutlineColor);
  674. }
  675. if (!DistanceDisplayCondition.equals(distanceDisplayCondition, this._lastDistanceDisplayCondition)) {
  676. attributes.distanceDisplayCondition = DistanceDisplayConditionGeometryInstanceAttribute.toValue(distanceDisplayCondition, attributes.distanceDisplayCondition);
  677. outlineAttributes.distanceDisplayCondition = DistanceDisplayConditionGeometryInstanceAttribute.toValue(distanceDisplayCondition, outlineAttributes.distanceDisplayCondition);
  678. DistanceDisplayCondition.clone(distanceDisplayCondition, this._lastDistanceDisplayCondition);
  679. }
  680. }
  681. if (in3D) {
  682. //Since we are scaling a unit sphere, we can't let any of the values go to zero.
  683. //Instead we clamp them to a small value. To the naked eye, this produces the same results
  684. //that you get passing EllipsoidGeometry a radii with a zero component.
  685. radii.x = Math.max(radii.x, 0.001);
  686. radii.y = Math.max(radii.y, 0.001);
  687. radii.z = Math.max(radii.z, 0.001);
  688. modelMatrix = Matrix4.multiplyByScale(modelMatrix, radii, modelMatrix);
  689. this._primitive.modelMatrix = modelMatrix;
  690. this._outlinePrimitive.modelMatrix = modelMatrix;
  691. }
  692. };
  693. DynamicGeometryUpdater.prototype.getBoundingSphere = function(entity, result) {
  694. return dynamicGeometryGetBoundingSphere(entity, this._primitive, this._outlinePrimitive, result);
  695. };
  696. DynamicGeometryUpdater.prototype.isDestroyed = function() {
  697. return false;
  698. };
  699. DynamicGeometryUpdater.prototype.destroy = function() {
  700. var primitives = this._primitives;
  701. primitives.removeAndDestroy(this._primitive);
  702. primitives.removeAndDestroy(this._outlinePrimitive);
  703. destroyObject(this);
  704. };
  705. return EllipsoidGeometryUpdater;
  706. });