CylinderGeometryUpdater.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609
  1. /*global define*/
  2. define([
  3. '../Core/Cartesian3',
  4. '../Core/Color',
  5. '../Core/ColorGeometryInstanceAttribute',
  6. '../Core/CylinderGeometry',
  7. '../Core/CylinderOutlineGeometry',
  8. '../Core/defaultValue',
  9. '../Core/defined',
  10. '../Core/defineProperties',
  11. '../Core/destroyObject',
  12. '../Core/DeveloperError',
  13. '../Core/Event',
  14. '../Core/GeometryInstance',
  15. '../Core/Iso8601',
  16. '../Core/ShowGeometryInstanceAttribute',
  17. '../Scene/MaterialAppearance',
  18. '../Scene/PerInstanceColorAppearance',
  19. '../Scene/Primitive',
  20. './ColorMaterialProperty',
  21. './ConstantProperty',
  22. './MaterialProperty',
  23. './Property'
  24. ], function(
  25. Cartesian3,
  26. Color,
  27. ColorGeometryInstanceAttribute,
  28. CylinderGeometry,
  29. CylinderOutlineGeometry,
  30. defaultValue,
  31. defined,
  32. defineProperties,
  33. destroyObject,
  34. DeveloperError,
  35. Event,
  36. GeometryInstance,
  37. Iso8601,
  38. ShowGeometryInstanceAttribute,
  39. MaterialAppearance,
  40. PerInstanceColorAppearance,
  41. Primitive,
  42. ColorMaterialProperty,
  43. ConstantProperty,
  44. MaterialProperty,
  45. Property) {
  46. "use strict";
  47. var defaultMaterial = ColorMaterialProperty.fromColor(Color.WHITE);
  48. var defaultShow = new ConstantProperty(true);
  49. var defaultFill = new ConstantProperty(true);
  50. var defaultOutline = new ConstantProperty(false);
  51. var defaultOutlineColor = new ConstantProperty(Color.BLACK);
  52. var scratchColor = new Color();
  53. var GeometryOptions = function(entity) {
  54. this.id = entity;
  55. this.vertexFormat = undefined;
  56. this.length = undefined;
  57. this.topRadius = undefined;
  58. this.bottomRadius = undefined;
  59. this.slices = undefined;
  60. this.numberOfVerticalLines = undefined;
  61. };
  62. /**
  63. * A {@link GeometryUpdater} for cylinders.
  64. * Clients do not normally create this class directly, but instead rely on {@link DataSourceDisplay}.
  65. * @alias CylinderGeometryUpdater
  66. * @constructor
  67. *
  68. * @param {Entity} entity The entity containing the geometry to be visualized.
  69. * @param {Scene} scene The scene where visualization is taking place.
  70. */
  71. var CylinderGeometryUpdater = function(entity, scene) {
  72. //>>includeStart('debug', pragmas.debug);
  73. if (!defined(entity)) {
  74. throw new DeveloperError('entity is required');
  75. }
  76. if (!defined(scene)) {
  77. throw new DeveloperError('scene is required');
  78. }
  79. //>>includeEnd('debug');
  80. this._entity = entity;
  81. this._scene = scene;
  82. this._entitySubscription = entity.definitionChanged.addEventListener(CylinderGeometryUpdater.prototype._onEntityPropertyChanged, this);
  83. this._fillEnabled = false;
  84. this._dynamic = false;
  85. this._outlineEnabled = false;
  86. this._geometryChanged = new Event();
  87. this._showProperty = undefined;
  88. this._materialProperty = undefined;
  89. this._hasConstantOutline = true;
  90. this._showOutlineProperty = undefined;
  91. this._outlineColorProperty = undefined;
  92. this._outlineWidth = 1.0;
  93. this._options = new GeometryOptions(entity);
  94. this._onEntityPropertyChanged(entity, 'cylinder', entity.cylinder, undefined);
  95. };
  96. defineProperties(CylinderGeometryUpdater, {
  97. /**
  98. * Gets the type of Appearance to use for simple color-based geometry.
  99. * @memberof CylinderGeometryUpdater
  100. * @type {Appearance}
  101. */
  102. perInstanceColorAppearanceType : {
  103. value : PerInstanceColorAppearance
  104. },
  105. /**
  106. * Gets the type of Appearance to use for material-based geometry.
  107. * @memberof CylinderGeometryUpdater
  108. * @type {Appearance}
  109. */
  110. materialAppearanceType : {
  111. value : MaterialAppearance
  112. }
  113. });
  114. defineProperties(CylinderGeometryUpdater.prototype, {
  115. /**
  116. * Gets the entity associated with this geometry.
  117. * @memberof CylinderGeometryUpdater.prototype
  118. *
  119. * @type {Entity}
  120. * @readonly
  121. */
  122. entity : {
  123. get : function() {
  124. return this._entity;
  125. }
  126. },
  127. /**
  128. * Gets a value indicating if the geometry has a fill component.
  129. * @memberof CylinderGeometryUpdater.prototype
  130. *
  131. * @type {Boolean}
  132. * @readonly
  133. */
  134. fillEnabled : {
  135. get : function() {
  136. return this._fillEnabled;
  137. }
  138. },
  139. /**
  140. * Gets a value indicating if fill visibility varies with simulation time.
  141. * @memberof CylinderGeometryUpdater.prototype
  142. *
  143. * @type {Boolean}
  144. * @readonly
  145. */
  146. hasConstantFill : {
  147. get : function() {
  148. return !this._fillEnabled ||
  149. (!defined(this._entity.availability) &&
  150. Property.isConstant(this._showProperty) &&
  151. Property.isConstant(this._fillProperty));
  152. }
  153. },
  154. /**
  155. * Gets the material property used to fill the geometry.
  156. * @memberof CylinderGeometryUpdater.prototype
  157. *
  158. * @type {MaterialProperty}
  159. * @readonly
  160. */
  161. fillMaterialProperty : {
  162. get : function() {
  163. return this._materialProperty;
  164. }
  165. },
  166. /**
  167. * Gets a value indicating if the geometry has an outline component.
  168. * @memberof CylinderGeometryUpdater.prototype
  169. *
  170. * @type {Boolean}
  171. * @readonly
  172. */
  173. outlineEnabled : {
  174. get : function() {
  175. return this._outlineEnabled;
  176. }
  177. },
  178. /**
  179. * Gets a value indicating if outline visibility varies with simulation time.
  180. * @memberof CylinderGeometryUpdater.prototype
  181. *
  182. * @type {Boolean}
  183. * @readonly
  184. */
  185. hasConstantOutline : {
  186. get : function() {
  187. return !this._outlineEnabled ||
  188. (!defined(this._entity.availability) &&
  189. Property.isConstant(this._showProperty) &&
  190. Property.isConstant(this._showOutlineProperty));
  191. }
  192. },
  193. /**
  194. * Gets the {@link Color} property for the geometry outline.
  195. * @memberof CylinderGeometryUpdater.prototype
  196. *
  197. * @type {Property}
  198. * @readonly
  199. */
  200. outlineColorProperty : {
  201. get : function() {
  202. return this._outlineColorProperty;
  203. }
  204. },
  205. /**
  206. * Gets the constant with of the geometry outline, in pixels.
  207. * This value is only valid if isDynamic is false.
  208. * @memberof CylinderGeometryUpdater.prototype
  209. *
  210. * @type {Number}
  211. * @readonly
  212. */
  213. outlineWidth : {
  214. get : function() {
  215. return this._outlineWidth;
  216. }
  217. },
  218. /**
  219. * Gets a value indicating if the geometry is time-varying.
  220. * If true, all visualization is delegated to the {@link DynamicGeometryUpdater}
  221. * returned by GeometryUpdater#createDynamicUpdater.
  222. * @memberof CylinderGeometryUpdater.prototype
  223. *
  224. * @type {Boolean}
  225. * @readonly
  226. */
  227. isDynamic : {
  228. get : function() {
  229. return this._dynamic;
  230. }
  231. },
  232. /**
  233. * Gets a value indicating if the geometry is closed.
  234. * This property is only valid for static geometry.
  235. * @memberof CylinderGeometryUpdater.prototype
  236. *
  237. * @type {Boolean}
  238. * @readonly
  239. */
  240. isClosed : {
  241. value : true
  242. },
  243. /**
  244. * Gets an event that is raised whenever the public properties
  245. * of this updater change.
  246. * @memberof CylinderGeometryUpdater.prototype
  247. *
  248. * @type {Boolean}
  249. * @readonly
  250. */
  251. geometryChanged : {
  252. get : function() {
  253. return this._geometryChanged;
  254. }
  255. }
  256. });
  257. /**
  258. * Checks if the geometry is outlined at the provided time.
  259. *
  260. * @param {JulianDate} time The time for which to retrieve visibility.
  261. * @returns {Boolean} true if geometry is outlined at the provided time, false otherwise.
  262. */
  263. CylinderGeometryUpdater.prototype.isOutlineVisible = function(time) {
  264. var entity = this._entity;
  265. return this._outlineEnabled && entity.isAvailable(time) && this._showProperty.getValue(time) && this._showOutlineProperty.getValue(time);
  266. };
  267. /**
  268. * Checks if the geometry is filled at the provided time.
  269. *
  270. * @param {JulianDate} time The time for which to retrieve visibility.
  271. * @returns {Boolean} true if geometry is filled at the provided time, false otherwise.
  272. */
  273. CylinderGeometryUpdater.prototype.isFilled = function(time) {
  274. var entity = this._entity;
  275. return this._fillEnabled && entity.isAvailable(time) && this._showProperty.getValue(time) && this._fillProperty.getValue(time);
  276. };
  277. /**
  278. * Creates the geometry instance which represents the fill of the geometry.
  279. *
  280. * @param {JulianDate} time The time to use when retrieving initial attribute values.
  281. * @returns {GeometryInstance} The geometry instance representing the filled portion of the geometry.
  282. *
  283. * @exception {DeveloperError} This instance does not represent a filled geometry.
  284. */
  285. CylinderGeometryUpdater.prototype.createFillGeometryInstance = function(time) {
  286. //>>includeStart('debug', pragmas.debug);
  287. if (!defined(time)) {
  288. throw new DeveloperError('time is required.');
  289. }
  290. if (!this._fillEnabled) {
  291. throw new DeveloperError('This instance does not represent a filled geometry.');
  292. }
  293. //>>includeEnd('debug');
  294. var entity = this._entity;
  295. var isAvailable = entity.isAvailable(time);
  296. var attributes;
  297. var color;
  298. var show = new ShowGeometryInstanceAttribute(isAvailable && this._showProperty.getValue(time) && this._fillProperty.getValue(time));
  299. if (this._materialProperty instanceof ColorMaterialProperty) {
  300. var currentColor = Color.WHITE;
  301. if (defined(this._materialProperty.color) && (this._materialProperty.color.isConstant || isAvailable)) {
  302. currentColor = this._materialProperty.color.getValue(time);
  303. }
  304. color = ColorGeometryInstanceAttribute.fromColor(currentColor);
  305. attributes = {
  306. show : show,
  307. color : color
  308. };
  309. } else {
  310. attributes = {
  311. show : show
  312. };
  313. }
  314. return new GeometryInstance({
  315. id : entity,
  316. geometry : new CylinderGeometry(this._options),
  317. modelMatrix : entity._getModelMatrix(Iso8601.MINIMUM_VALUE),
  318. attributes : attributes
  319. });
  320. };
  321. /**
  322. * Creates the geometry instance which represents the outline of the geometry.
  323. *
  324. * @param {JulianDate} time The time to use when retrieving initial attribute values.
  325. * @returns {GeometryInstance} The geometry instance representing the outline portion of the geometry.
  326. *
  327. * @exception {DeveloperError} This instance does not represent an outlined geometry.
  328. */
  329. CylinderGeometryUpdater.prototype.createOutlineGeometryInstance = function(time) {
  330. //>>includeStart('debug', pragmas.debug);
  331. if (!defined(time)) {
  332. throw new DeveloperError('time is required.');
  333. }
  334. if (!this._outlineEnabled) {
  335. throw new DeveloperError('This instance does not represent an outlined geometry.');
  336. }
  337. //>>includeEnd('debug');
  338. var entity = this._entity;
  339. var isAvailable = entity.isAvailable(time);
  340. var outlineColor = Property.getValueOrDefault(this._outlineColorProperty, time, Color.BLACK);
  341. return new GeometryInstance({
  342. id : entity,
  343. geometry : new CylinderOutlineGeometry(this._options),
  344. modelMatrix : entity._getModelMatrix(Iso8601.MINIMUM_VALUE),
  345. attributes : {
  346. show : new ShowGeometryInstanceAttribute(isAvailable && this._showProperty.getValue(time) && this._showOutlineProperty.getValue(time)),
  347. color : ColorGeometryInstanceAttribute.fromColor(outlineColor)
  348. }
  349. });
  350. };
  351. /**
  352. * Returns true if this object was destroyed; otherwise, false.
  353. *
  354. * @returns {Boolean} True if this object was destroyed; otherwise, false.
  355. */
  356. CylinderGeometryUpdater.prototype.isDestroyed = function() {
  357. return false;
  358. };
  359. /**
  360. * Destroys and resources used by the object. Once an object is destroyed, it should not be used.
  361. *
  362. * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
  363. */
  364. CylinderGeometryUpdater.prototype.destroy = function() {
  365. this._entitySubscription();
  366. destroyObject(this);
  367. };
  368. CylinderGeometryUpdater.prototype._onEntityPropertyChanged = function(entity, propertyName, newValue, oldValue) {
  369. if (!(propertyName === 'availability' || propertyName === 'position' || propertyName === 'orientation' || propertyName === 'cylinder')) {
  370. return;
  371. }
  372. var cylinder = entity.cylinder;
  373. if (!defined(cylinder)) {
  374. if (this._fillEnabled || this._outlineEnabled) {
  375. this._fillEnabled = false;
  376. this._outlineEnabled = false;
  377. this._geometryChanged.raiseEvent(this);
  378. }
  379. return;
  380. }
  381. var fillProperty = cylinder.fill;
  382. var fillEnabled = defined(fillProperty) && fillProperty.isConstant ? fillProperty.getValue(Iso8601.MINIMUM_VALUE) : true;
  383. var outlineProperty = cylinder.outline;
  384. var outlineEnabled = defined(outlineProperty);
  385. if (outlineEnabled && outlineProperty.isConstant) {
  386. outlineEnabled = outlineProperty.getValue(Iso8601.MINIMUM_VALUE);
  387. }
  388. if (!fillEnabled && !outlineEnabled) {
  389. if (this._fillEnabled || this._outlineEnabled) {
  390. this._fillEnabled = false;
  391. this._outlineEnabled = false;
  392. this._geometryChanged.raiseEvent(this);
  393. }
  394. return;
  395. }
  396. var position = entity.position;
  397. var length = cylinder.length;
  398. var topRadius = cylinder.topRadius;
  399. var bottomRadius = cylinder.bottomRadius;
  400. var show = cylinder.show;
  401. if ((defined(show) && show.isConstant && !show.getValue(Iso8601.MINIMUM_VALUE)) || //
  402. (!defined(position) || !defined(length) || !defined(topRadius) || !defined(bottomRadius))) {
  403. if (this._fillEnabled || this._outlineEnabled) {
  404. this._fillEnabled = false;
  405. this._outlineEnabled = false;
  406. this._geometryChanged.raiseEvent(this);
  407. }
  408. return;
  409. }
  410. var material = defaultValue(cylinder.material, defaultMaterial);
  411. var isColorMaterial = material instanceof ColorMaterialProperty;
  412. this._materialProperty = material;
  413. this._fillProperty = defaultValue(fillProperty, defaultFill);
  414. this._showProperty = defaultValue(show, defaultShow);
  415. this._showOutlineProperty = defaultValue(cylinder.outline, defaultOutline);
  416. this._outlineColorProperty = outlineEnabled ? defaultValue(cylinder.outlineColor, defaultOutlineColor) : undefined;
  417. var slices = cylinder.slices;
  418. var outlineWidth = cylinder.outlineWidth;
  419. var numberOfVerticalLines = cylinder.numberOfVerticalLines;
  420. this._fillEnabled = fillEnabled;
  421. this._outlineEnabled = outlineEnabled;
  422. if (!position.isConstant || //
  423. !Property.isConstant(entity.orientation) || //
  424. !length.isConstant || //
  425. !topRadius.isConstant || //
  426. !bottomRadius.isConstant || //
  427. !Property.isConstant(slices) || //
  428. !Property.isConstant(outlineWidth) || //
  429. !Property.isConstant(numberOfVerticalLines)) {
  430. if (!this._dynamic) {
  431. this._dynamic = true;
  432. this._geometryChanged.raiseEvent(this);
  433. }
  434. } else {
  435. var options = this._options;
  436. options.vertexFormat = isColorMaterial ? PerInstanceColorAppearance.VERTEX_FORMAT : MaterialAppearance.MaterialSupport.TEXTURED.vertexFormat;
  437. options.length = length.getValue(Iso8601.MINIMUM_VALUE);
  438. options.topRadius = topRadius.getValue(Iso8601.MINIMUM_VALUE);
  439. options.bottomRadius = bottomRadius.getValue(Iso8601.MINIMUM_VALUE);
  440. options.slices = defined(slices) ? slices.getValue(Iso8601.MINIMUM_VALUE) : undefined;
  441. options.numberOfVerticalLines = defined(numberOfVerticalLines) ? numberOfVerticalLines.getValue(Iso8601.MINIMUM_VALUE) : undefined;
  442. this._outlineWidth = defined(outlineWidth) ? outlineWidth.getValue(Iso8601.MINIMUM_VALUE) : 1.0;
  443. this._dynamic = false;
  444. this._geometryChanged.raiseEvent(this);
  445. }
  446. };
  447. /**
  448. * Creates the dynamic updater to be used when GeometryUpdater#isDynamic is true.
  449. *
  450. * @param {PrimitiveCollection} primitives The primitive collection to use.
  451. * @returns {DynamicGeometryUpdater} The dynamic updater used to update the geometry each frame.
  452. *
  453. * @exception {DeveloperError} This instance does not represent dynamic geometry.
  454. */
  455. CylinderGeometryUpdater.prototype.createDynamicUpdater = function(primitives) {
  456. //>>includeStart('debug', pragmas.debug);
  457. if (!this._dynamic) {
  458. throw new DeveloperError('This instance does not represent dynamic geometry.');
  459. }
  460. if (!defined(primitives)) {
  461. throw new DeveloperError('primitives is required.');
  462. }
  463. //>>includeEnd('debug');
  464. return new DynamicGeometryUpdater(primitives, this);
  465. };
  466. /**
  467. * @private
  468. */
  469. var DynamicGeometryUpdater = function(primitives, geometryUpdater) {
  470. this._primitives = primitives;
  471. this._primitive = undefined;
  472. this._outlinePrimitive = undefined;
  473. this._geometryUpdater = geometryUpdater;
  474. this._options = new GeometryOptions(geometryUpdater._entity);
  475. };
  476. DynamicGeometryUpdater.prototype.update = function(time) {
  477. //>>includeStart('debug', pragmas.debug);
  478. if (!defined(time)) {
  479. throw new DeveloperError('time is required.');
  480. }
  481. //>>includeEnd('debug');
  482. var primitives = this._primitives;
  483. primitives.removeAndDestroy(this._primitive);
  484. primitives.removeAndDestroy(this._outlinePrimitive);
  485. var geometryUpdater = this._geometryUpdater;
  486. var entity = geometryUpdater._entity;
  487. var cylinder = entity.cylinder;
  488. if (!entity.isAvailable(time) || !Property.getValueOrDefault(cylinder.show, time, true)) {
  489. return;
  490. }
  491. var options = this._options;
  492. var modelMatrix = entity._getModelMatrix(time);
  493. var length = Property.getValueOrUndefined(cylinder.length, time);
  494. var topRadius = Property.getValueOrUndefined(cylinder.topRadius, time);
  495. var bottomRadius = Property.getValueOrUndefined(cylinder.bottomRadius, time);
  496. if (!defined(modelMatrix) || !defined(length) || !defined(topRadius) || !defined(bottomRadius)) {
  497. return;
  498. }
  499. options.length = length;
  500. options.topRadius = topRadius;
  501. options.bottomRadius = bottomRadius;
  502. options.slices = Property.getValueOrUndefined(cylinder.slices, time);
  503. options.numberOfVerticalLines = Property.getValueOrUndefined(cylinder.numberOfVerticalLines, time);
  504. if (Property.getValueOrDefault(cylinder.fill, time, true)) {
  505. var material = MaterialProperty.getValue(time, geometryUpdater.fillMaterialProperty, this._material);
  506. this._material = material;
  507. var appearance = new MaterialAppearance({
  508. material : material,
  509. translucent : material.isTranslucent(),
  510. closed : true
  511. });
  512. options.vertexFormat = appearance.vertexFormat;
  513. this._primitive = primitives.add(new Primitive({
  514. geometryInstances : new GeometryInstance({
  515. id : entity,
  516. geometry : new CylinderGeometry(options),
  517. modelMatrix : modelMatrix
  518. }),
  519. appearance : appearance,
  520. asynchronous : false
  521. }));
  522. }
  523. if (Property.getValueOrDefault(cylinder.outline, time, false)) {
  524. options.vertexFormat = PerInstanceColorAppearance.VERTEX_FORMAT;
  525. var outlineColor = Property.getValueOrClonedDefault(cylinder.outlineColor, time, Color.BLACK, scratchColor);
  526. var outlineWidth = Property.getValueOrDefault(cylinder.outlineWidth, 1.0);
  527. var translucent = outlineColor.alpha !== 1.0;
  528. this._outlinePrimitive = primitives.add(new Primitive({
  529. geometryInstances : new GeometryInstance({
  530. id : entity,
  531. geometry : new CylinderOutlineGeometry(options),
  532. modelMatrix : modelMatrix,
  533. attributes : {
  534. color : ColorGeometryInstanceAttribute.fromColor(outlineColor)
  535. }
  536. }),
  537. appearance : new PerInstanceColorAppearance({
  538. flat : true,
  539. translucent : translucent,
  540. renderState : {
  541. lineWidth : geometryUpdater._scene.clampLineWidth(outlineWidth)
  542. }
  543. }),
  544. asynchronous : false
  545. }));
  546. }
  547. };
  548. DynamicGeometryUpdater.prototype.isDestroyed = function() {
  549. return false;
  550. };
  551. DynamicGeometryUpdater.prototype.destroy = function() {
  552. var primitives = this._primitives;
  553. primitives.removeAndDestroy(this._primitive);
  554. primitives.removeAndDestroy(this._outlinePrimitive);
  555. destroyObject(this);
  556. };
  557. return CylinderGeometryUpdater;
  558. });