GeometryVisualizer.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. /*global define*/
  2. define([
  3. '../Core/AssociativeArray',
  4. '../Core/defined',
  5. '../Core/destroyObject',
  6. '../Core/DeveloperError',
  7. './ColorMaterialProperty',
  8. './StaticGeometryColorBatch',
  9. './StaticGeometryPerMaterialBatch',
  10. './StaticOutlineGeometryBatch'
  11. ], function(
  12. AssociativeArray,
  13. defined,
  14. destroyObject,
  15. DeveloperError,
  16. ColorMaterialProperty,
  17. StaticGeometryColorBatch,
  18. StaticGeometryPerMaterialBatch,
  19. StaticOutlineGeometryBatch) {
  20. "use strict";
  21. var emptyArray = [];
  22. var DynamicGeometryBatch = function(primitives) {
  23. this._primitives = primitives;
  24. this._dynamicUpdaters = new AssociativeArray();
  25. };
  26. DynamicGeometryBatch.prototype.add = function(time, updater) {
  27. this._dynamicUpdaters.set(updater.entity.id, updater.createDynamicUpdater(this._primitives));
  28. };
  29. DynamicGeometryBatch.prototype.remove = function(updater) {
  30. var id = updater.entity.id;
  31. var dynamicUpdater = this._dynamicUpdaters.get(id);
  32. if (defined(dynamicUpdater)) {
  33. this._dynamicUpdaters.remove(id);
  34. dynamicUpdater.destroy();
  35. }
  36. };
  37. DynamicGeometryBatch.prototype.update = function(time) {
  38. var geometries = this._dynamicUpdaters.values;
  39. for (var i = 0, len = geometries.length; i < len; i++) {
  40. geometries[i].update(time);
  41. }
  42. return true;
  43. };
  44. DynamicGeometryBatch.prototype.removeAllPrimitives = function() {
  45. var geometries = this._dynamicUpdaters.values;
  46. for (var i = 0, len = geometries.length; i < len; i++) {
  47. geometries[i].destroy();
  48. }
  49. this._dynamicUpdaters.removeAll();
  50. };
  51. function removeUpdater(that, updater) {
  52. //We don't keep track of which batch an updater is in, so just remove it from all of them.
  53. that._outlineBatch.remove(updater);
  54. that._closedColorBatch.remove(updater);
  55. that._closedMaterialBatch.remove(updater);
  56. that._openColorBatch.remove(updater);
  57. that._openMaterialBatch.remove(updater);
  58. that._dynamicBatch.remove(updater);
  59. }
  60. function insertUpdaterIntoBatch(that, time, updater) {
  61. if (updater.isDynamic) {
  62. that._dynamicBatch.add(time, updater);
  63. return;
  64. }
  65. if (updater.outlineEnabled) {
  66. that._outlineBatch.add(time, updater);
  67. }
  68. if (updater.fillEnabled) {
  69. if (updater.isClosed) {
  70. if (updater.fillMaterialProperty instanceof ColorMaterialProperty) {
  71. that._closedColorBatch.add(time, updater);
  72. } else {
  73. that._closedMaterialBatch.add(time, updater);
  74. }
  75. } else {
  76. if (updater.fillMaterialProperty instanceof ColorMaterialProperty) {
  77. that._openColorBatch.add(time, updater);
  78. } else {
  79. that._openMaterialBatch.add(time, updater);
  80. }
  81. }
  82. }
  83. }
  84. /**
  85. * A general purpose visualizer for geometry represented by {@link Primitive} instances.
  86. * @alias GeometryVisualizer
  87. * @constructor
  88. *
  89. * @param {GeometryUpdater} type The updater to be used for creating the geometry.
  90. * @param {Scene} scene The scene the primitives will be rendered in.
  91. * @param {EntityCollection} entityCollection The entityCollection to visualize.
  92. */
  93. var GeometryVisualizer = function(type, scene, entityCollection) {
  94. //>>includeStart('debug', pragmas.debug);
  95. if (!defined(type)) {
  96. throw new DeveloperError('type is required.');
  97. }
  98. if (!defined(scene)) {
  99. throw new DeveloperError('scene is required.');
  100. }
  101. if (!defined(entityCollection)) {
  102. throw new DeveloperError('entityCollection is required.');
  103. }
  104. //>>includeEnd('debug');
  105. this._type = type;
  106. var primitives = scene.primitives;
  107. this._scene = scene;
  108. this._primitives = primitives;
  109. this._entityCollection = undefined;
  110. this._addedObjects = new AssociativeArray();
  111. this._removedObjects = new AssociativeArray();
  112. this._changedObjects = new AssociativeArray();
  113. this._outlineBatch = new StaticOutlineGeometryBatch(primitives, scene);
  114. this._closedColorBatch = new StaticGeometryColorBatch(primitives, type.perInstanceColorAppearanceType, true);
  115. this._closedMaterialBatch = new StaticGeometryPerMaterialBatch(primitives, type.materialAppearanceType, true);
  116. this._openColorBatch = new StaticGeometryColorBatch(primitives, type.perInstanceColorAppearanceType, false);
  117. this._openMaterialBatch = new StaticGeometryPerMaterialBatch(primitives, type.materialAppearanceType, false);
  118. this._dynamicBatch = new DynamicGeometryBatch(primitives);
  119. this._subscriptions = new AssociativeArray();
  120. this._updaters = new AssociativeArray();
  121. this._entityCollection = entityCollection;
  122. entityCollection.collectionChanged.addEventListener(GeometryVisualizer.prototype._onCollectionChanged, this);
  123. this._onCollectionChanged(entityCollection, entityCollection.entities, emptyArray);
  124. };
  125. /**
  126. * Updates all of the primitives created by this visualizer to match their
  127. * Entity counterpart at the given time.
  128. *
  129. * @param {JulianDate} time The time to update to.
  130. * @returns {Boolean} True if the visualizer successfully updated to the provided time,
  131. * false if the visualizer is waiting for asynchronous primitives to be created.
  132. */
  133. GeometryVisualizer.prototype.update = function(time) {
  134. //>>includeStart('debug', pragmas.debug);
  135. if (!defined(time)) {
  136. throw new DeveloperError('time is required.');
  137. }
  138. //>>includeEnd('debug');
  139. var addedObjects = this._addedObjects;
  140. var added = addedObjects.values;
  141. var removedObjects = this._removedObjects;
  142. var removed = removedObjects.values;
  143. var changedObjects = this._changedObjects;
  144. var changed = changedObjects.values;
  145. var i;
  146. var entity;
  147. var id;
  148. var updater;
  149. for (i = removed.length - 1; i > -1; i--) {
  150. entity = removed[i];
  151. id = entity.id;
  152. updater = this._updaters.get(id);
  153. removeUpdater(this, updater);
  154. updater.destroy();
  155. this._updaters.remove(id);
  156. this._subscriptions.get(id)();
  157. this._subscriptions.remove(id);
  158. }
  159. for (i = added.length - 1; i > -1; i--) {
  160. entity = added[i];
  161. id = entity.id;
  162. updater = new this._type(entity, this._scene);
  163. this._updaters.set(id, updater);
  164. insertUpdaterIntoBatch(this, time, updater);
  165. this._subscriptions.set(id, updater.geometryChanged.addEventListener(GeometryVisualizer._onGeometryChanged, this));
  166. }
  167. for (i = changed.length - 1; i > -1; i--) {
  168. entity = changed[i];
  169. id = entity.id;
  170. updater = this._updaters.get(id);
  171. removeUpdater(this, updater);
  172. insertUpdaterIntoBatch(this, time, updater);
  173. }
  174. addedObjects.removeAll();
  175. removedObjects.removeAll();
  176. changedObjects.removeAll();
  177. var isUpdated = this._closedColorBatch.update(time);
  178. isUpdated = this._closedMaterialBatch.update(time) && isUpdated;
  179. isUpdated = this._openColorBatch.update(time) && isUpdated;
  180. isUpdated = this._openMaterialBatch.update(time) && isUpdated;
  181. isUpdated = this._dynamicBatch.update(time) && isUpdated;
  182. isUpdated = this._outlineBatch.update(time) && isUpdated;
  183. return isUpdated;
  184. };
  185. /**
  186. * Returns true if this object was destroyed; otherwise, false.
  187. *
  188. * @returns {Boolean} True if this object was destroyed; otherwise, false.
  189. */
  190. GeometryVisualizer.prototype.isDestroyed = function() {
  191. return false;
  192. };
  193. /**
  194. * Removes and destroys all primitives created by this instance.
  195. */
  196. GeometryVisualizer.prototype.destroy = function() {
  197. this._entityCollection.collectionChanged.removeEventListener(GeometryVisualizer.prototype._onCollectionChanged, this);
  198. this._addedObjects.removeAll();
  199. this._removedObjects.removeAll();
  200. this._outlineBatch.removeAllPrimitives();
  201. this._closedColorBatch.removeAllPrimitives();
  202. this._closedMaterialBatch.removeAllPrimitives();
  203. this._openColorBatch.removeAllPrimitives();
  204. this._openMaterialBatch.removeAllPrimitives();
  205. this._dynamicBatch.removeAllPrimitives();
  206. var subscriptions = this._subscriptions.values;
  207. var len = subscriptions.length;
  208. for (var i = 0; i < len; i++) {
  209. subscriptions[i]();
  210. }
  211. this._subscriptions.removeAll();
  212. return destroyObject(this);
  213. };
  214. /**
  215. * @private
  216. */
  217. GeometryVisualizer._onGeometryChanged = function(updater) {
  218. var removedObjects = this._removedObjects;
  219. var changedObjects = this._changedObjects;
  220. var entity = updater.entity;
  221. var id = entity.id;
  222. if (!defined(removedObjects.get(id)) && !defined(changedObjects.get(id))) {
  223. changedObjects.set(id, entity);
  224. }
  225. };
  226. /**
  227. * @private
  228. */
  229. GeometryVisualizer.prototype._onCollectionChanged = function(entityCollection, added, removed) {
  230. var addedObjects = this._addedObjects;
  231. var removedObjects = this._removedObjects;
  232. var changedObjects = this._changedObjects;
  233. var i;
  234. var id;
  235. var entity;
  236. for (i = removed.length - 1; i > -1; i--) {
  237. entity = removed[i];
  238. id = entity.id;
  239. if (!addedObjects.remove(id)) {
  240. removedObjects.set(id, entity);
  241. changedObjects.remove(id);
  242. }
  243. }
  244. for (i = added.length - 1; i > -1; i--) {
  245. entity = added[i];
  246. id = entity.id;
  247. if (removedObjects.remove(id)) {
  248. changedObjects.set(id, entity);
  249. } else {
  250. addedObjects.set(id, entity);
  251. }
  252. }
  253. };
  254. return GeometryVisualizer;
  255. });