StaticOutlineGeometryBatch.js 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. /*global define*/
  2. define([
  3. '../Core/AssociativeArray',
  4. '../Core/Color',
  5. '../Core/ColorGeometryInstanceAttribute',
  6. '../Core/defined',
  7. '../Core/ShowGeometryInstanceAttribute',
  8. '../Scene/PerInstanceColorAppearance',
  9. '../Scene/Primitive'
  10. ], function(
  11. AssociativeArray,
  12. Color,
  13. ColorGeometryInstanceAttribute,
  14. defined,
  15. ShowGeometryInstanceAttribute,
  16. PerInstanceColorAppearance,
  17. Primitive) {
  18. "use strict";
  19. var Batch = function(primitives, translucent, width) {
  20. this.translucent = translucent;
  21. this.primitives = primitives;
  22. this.createPrimitive = false;
  23. this.primitive = undefined;
  24. this.oldPrimitive = undefined;
  25. this.geometry = new AssociativeArray();
  26. this.updaters = new AssociativeArray();
  27. this.updatersWithAttributes = new AssociativeArray();
  28. this.attributes = new AssociativeArray();
  29. this.itemsToRemove = [];
  30. this.width = width;
  31. };
  32. Batch.prototype.add = function(updater, instance) {
  33. var id = updater.entity.id;
  34. this.createPrimitive = true;
  35. this.geometry.set(id, instance);
  36. this.updaters.set(id, updater);
  37. if (!updater.hasConstantOutline || !updater.outlineColorProperty.isConstant) {
  38. this.updatersWithAttributes.set(id, updater);
  39. }
  40. };
  41. Batch.prototype.remove = function(updater) {
  42. var id = updater.entity.id;
  43. this.createPrimitive = this.geometry.remove(id) || this.createPrimitive;
  44. this.updaters.remove(id);
  45. this.updatersWithAttributes.remove(id);
  46. };
  47. var colorScratch = new Color();
  48. Batch.prototype.update = function(time) {
  49. var show = true;
  50. var isUpdated = true;
  51. var removedCount = 0;
  52. var primitive = this.primitive;
  53. var primitives = this.primitives;
  54. if (this.createPrimitive) {
  55. this.attributes.removeAll();
  56. if (defined(primitive)) {
  57. if (primitive.ready) {
  58. this.oldPrimitive = primitive;
  59. } else {
  60. primitives.remove(primitive);
  61. }
  62. show = false;
  63. }
  64. var geometry = this.geometry.values;
  65. if (geometry.length > 0) {
  66. primitive = new Primitive({
  67. asynchronous : true,
  68. geometryInstances : geometry,
  69. appearance : new PerInstanceColorAppearance({
  70. flat : true,
  71. translucent : this.translucent,
  72. renderState : {
  73. lineWidth : this.width
  74. }
  75. })
  76. });
  77. primitives.add(primitive);
  78. isUpdated = false;
  79. primitive.show = show;
  80. }
  81. this.primitive = primitive;
  82. this.createPrimitive = false;
  83. } else if (defined(primitive) && primitive.ready) {
  84. if (defined(this.oldPrimitive)) {
  85. primitives.remove(this.oldPrimitive);
  86. this.oldPrimitive = undefined;
  87. primitive.show = true;
  88. }
  89. var updatersWithAttributes = this.updatersWithAttributes.values;
  90. var length = updatersWithAttributes.length;
  91. for (var i = 0; i < length; i++) {
  92. var updater = updatersWithAttributes[i];
  93. var instance = this.geometry.get(updater.entity.id);
  94. var attributes = this.attributes.get(instance.id.id);
  95. if (!defined(attributes)) {
  96. attributes = primitive.getGeometryInstanceAttributes(instance.id);
  97. this.attributes.set(instance.id.id, attributes);
  98. }
  99. if (!updater.outlineColorProperty.isConstant) {
  100. var outlineColorProperty = updater.outlineColorProperty;
  101. outlineColorProperty.getValue(time, colorScratch);
  102. if (!Color.equals(attributes._lastColor, colorScratch)) {
  103. attributes._lastColor = Color.clone(colorScratch, attributes._lastColor);
  104. attributes.color = ColorGeometryInstanceAttribute.toValue(colorScratch, attributes.color);
  105. if ((this.translucent && attributes.color[3] === 255) || (!this.translucent && attributes.color[3] !== 255)) {
  106. this.itemsToRemove[removedCount++] = updater;
  107. }
  108. }
  109. }
  110. if (!updater.hasConstantOutline) {
  111. show = updater.isOutlineVisible(time);
  112. if (show !== attributes._lastShow) {
  113. attributes._lastShow = show;
  114. attributes.show = ShowGeometryInstanceAttribute.toValue(show, attributes.show);
  115. }
  116. }
  117. }
  118. } else if (defined(primitive) && !primitive.ready) {
  119. isUpdated = false;
  120. }
  121. this.itemsToRemove.length = removedCount;
  122. return isUpdated;
  123. };
  124. Batch.prototype.removeAllPrimitives = function() {
  125. var primitive = this.primitive;
  126. if (defined(primitive)) {
  127. this.primitives.remove(primitive);
  128. this.primitive = undefined;
  129. this.geometry.removeAll();
  130. this.updaters.removeAll();
  131. }
  132. };
  133. /**
  134. * @private
  135. */
  136. var StaticOutlineGeometryBatch = function(primitives, scene) {
  137. this._primitives = primitives;
  138. this._scene = scene;
  139. this._solidBatches = new AssociativeArray();
  140. this._translucentBatches = new AssociativeArray();
  141. };
  142. StaticOutlineGeometryBatch.prototype.add = function(time, updater) {
  143. var instance = updater.createOutlineGeometryInstance(time);
  144. var width = this._scene.clampLineWidth(updater.outlineWidth);
  145. var batches;
  146. var batch;
  147. if (instance.attributes.color.value[3] === 255) {
  148. batches = this._solidBatches;
  149. batch = batches.get(width);
  150. if (!defined(batch)) {
  151. batch = new Batch(this._primitives, false, width);
  152. batches.set(width, batch);
  153. }
  154. batch.add(updater, instance);
  155. } else {
  156. batches = this._translucentBatches;
  157. batch = batches.get(width);
  158. if (!defined(batch)) {
  159. batch = new Batch(this._primitives, true, width);
  160. batches.set(width, batch);
  161. }
  162. batch.add(updater, instance);
  163. }
  164. };
  165. StaticOutlineGeometryBatch.prototype.remove = function(updater) {
  166. var i;
  167. var solidBatches = this._solidBatches.values;
  168. var solidBatchesLength = solidBatches.length;
  169. for (i = 0; i < solidBatchesLength; i++) {
  170. if (solidBatches[i].remove(updater)) {
  171. return;
  172. }
  173. }
  174. var translucentBatches = this._translucentBatches.values;
  175. var translucentBatchesLength = translucentBatches.length;
  176. for (i = 0; i < translucentBatchesLength; i++) {
  177. if (translucentBatches.remove(updater)) {
  178. return;
  179. }
  180. }
  181. };
  182. StaticOutlineGeometryBatch.prototype.update = function(time) {
  183. var i;
  184. var x;
  185. var updater;
  186. var batch;
  187. var solidBatches = this._solidBatches.values;
  188. var solidBatchesLength = solidBatches.length;
  189. var translucentBatches = this._translucentBatches.values;
  190. var translucentBatchesLength = translucentBatches.length;
  191. var itemsToRemove;
  192. var isUpdated = true;
  193. var needUpdate = false;
  194. do {
  195. needUpdate = false;
  196. for (x = 0; x < solidBatchesLength; x++) {
  197. batch = solidBatches[x];
  198. //Perform initial update
  199. isUpdated = batch.update(time);
  200. //If any items swapped between solid/translucent, we need to
  201. //move them between batches
  202. itemsToRemove = batch.itemsToRemove;
  203. var solidsToMoveLength = itemsToRemove.length;
  204. if (solidsToMoveLength > 0) {
  205. needUpdate = true;
  206. for (i = 0; i < solidsToMoveLength; i++) {
  207. updater = itemsToRemove[i];
  208. batch.remove(updater);
  209. this.add(time, updater);
  210. }
  211. }
  212. }
  213. for (x = 0; x < translucentBatchesLength; x++) {
  214. batch = translucentBatches[x];
  215. //Perform initial update
  216. isUpdated = batch.update(time);
  217. //If any items swapped between solid/translucent, we need to
  218. //move them between batches
  219. itemsToRemove = batch.itemsToRemove;
  220. var translucentToMoveLength = itemsToRemove.length;
  221. if (translucentToMoveLength > 0) {
  222. needUpdate = true;
  223. for (i = 0; i < translucentToMoveLength; i++) {
  224. updater = itemsToRemove[i];
  225. batch.remove(updater);
  226. this.add(time, updater);
  227. }
  228. }
  229. }
  230. } while (needUpdate);
  231. return isUpdated;
  232. };
  233. StaticOutlineGeometryBatch.prototype.removeAllPrimitives = function() {
  234. var i;
  235. var solidBatches = this._solidBatches.values;
  236. var solidBatchesLength = solidBatches.length;
  237. for (i = 0; i < solidBatchesLength; i++) {
  238. solidBatches[i].removeAllPrimitives();
  239. }
  240. var translucentBatches = this._translucentBatches.values;
  241. var translucentBatchesLength = translucentBatches.length;
  242. for (i = 0; i < translucentBatchesLength; i++) {
  243. translucentBatches[i].removeAllPrimitives();
  244. }
  245. };
  246. return StaticOutlineGeometryBatch;
  247. });