PointCloud3DTileContent.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. import Color from '../Core/Color.js';
  2. import combine from '../Core/combine.js';
  3. import defaultValue from '../Core/defaultValue.js';
  4. import defined from '../Core/defined.js';
  5. import defineProperties from '../Core/defineProperties.js';
  6. import destroyObject from '../Core/destroyObject.js';
  7. import DeveloperError from '../Core/DeveloperError.js';
  8. import CesiumMath from '../Core/Math.js';
  9. import Pass from '../Renderer/Pass.js';
  10. import Cesium3DTileBatchTable from './Cesium3DTileBatchTable.js';
  11. import Cesium3DTileFeature from './Cesium3DTileFeature.js';
  12. import Cesium3DTileRefine from './Cesium3DTileRefine.js';
  13. import PointCloud from './PointCloud.js';
  14. import PointCloudShading from './PointCloudShading.js';
  15. import SceneMode from './SceneMode.js';
  16. /**
  17. * Represents the contents of a
  18. * {@link https://github.com/AnalyticalGraphicsInc/3d-tiles/tree/master/specification/TileFormats/PointCloud|Point Cloud}
  19. * tile in a {@link https://github.com/AnalyticalGraphicsInc/3d-tiles/tree/master/specification|3D Tiles} tileset.
  20. * <p>
  21. * Implements the {@link Cesium3DTileContent} interface.
  22. * </p>
  23. *
  24. * @alias PointCloud3DTileContent
  25. * @constructor
  26. *
  27. * @private
  28. */
  29. function PointCloud3DTileContent(tileset, tile, resource, arrayBuffer, byteOffset) {
  30. this._tileset = tileset;
  31. this._tile = tile;
  32. this._resource = resource;
  33. this._pickId = undefined; // Only defined when batchTable is undefined
  34. this._batchTable = undefined; // Used when feature table contains BATCH_ID semantic
  35. this._styleDirty = false;
  36. this._features = undefined;
  37. /**
  38. * @inheritdoc Cesium3DTileContent#featurePropertiesDirty
  39. */
  40. this.featurePropertiesDirty = false;
  41. this._pointCloud = new PointCloud({
  42. arrayBuffer : arrayBuffer,
  43. byteOffset : byteOffset,
  44. cull : false,
  45. opaquePass : Pass.CESIUM_3D_TILE,
  46. vertexShaderLoaded : getVertexShaderLoaded(this),
  47. fragmentShaderLoaded : getFragmentShaderLoaded(this),
  48. uniformMapLoaded : getUniformMapLoaded(this),
  49. batchTableLoaded : getBatchTableLoaded(this),
  50. pickIdLoaded : getPickIdLoaded(this)
  51. });
  52. }
  53. defineProperties(PointCloud3DTileContent.prototype, {
  54. featuresLength : {
  55. get : function() {
  56. if (defined(this._batchTable)) {
  57. return this._batchTable.featuresLength;
  58. }
  59. return 0;
  60. }
  61. },
  62. pointsLength : {
  63. get : function() {
  64. return this._pointCloud.pointsLength;
  65. }
  66. },
  67. trianglesLength : {
  68. get : function() {
  69. return 0;
  70. }
  71. },
  72. geometryByteLength : {
  73. get : function() {
  74. return this._pointCloud.geometryByteLength;
  75. }
  76. },
  77. texturesByteLength : {
  78. get : function() {
  79. return 0;
  80. }
  81. },
  82. batchTableByteLength : {
  83. get : function() {
  84. if (defined(this._batchTable)) {
  85. return this._batchTable.memorySizeInBytes;
  86. }
  87. return 0;
  88. }
  89. },
  90. innerContents : {
  91. get : function() {
  92. return undefined;
  93. }
  94. },
  95. readyPromise : {
  96. get : function() {
  97. return this._pointCloud.readyPromise;
  98. }
  99. },
  100. tileset : {
  101. get : function() {
  102. return this._tileset;
  103. }
  104. },
  105. tile : {
  106. get : function() {
  107. return this._tile;
  108. }
  109. },
  110. url : {
  111. get : function() {
  112. return this._resource.getUrlComponent(true);
  113. }
  114. },
  115. batchTable : {
  116. get : function() {
  117. return this._batchTable;
  118. }
  119. }
  120. });
  121. function getVertexShaderLoaded(content) {
  122. return function(vs) {
  123. if (defined(content._batchTable)) {
  124. return content._batchTable.getVertexShaderCallback(false, 'a_batchId', undefined)(vs);
  125. }
  126. return vs;
  127. };
  128. }
  129. function getFragmentShaderLoaded(content) {
  130. return function(fs) {
  131. if (defined(content._batchTable)) {
  132. return content._batchTable.getFragmentShaderCallback(false, undefined)(fs);
  133. }
  134. return 'uniform vec4 czm_pickColor;\n' + fs;
  135. };
  136. }
  137. function getUniformMapLoaded(content) {
  138. return function(uniformMap) {
  139. if (defined(content._batchTable)) {
  140. return content._batchTable.getUniformMapCallback()(uniformMap);
  141. }
  142. return combine(uniformMap, {
  143. czm_pickColor : function() {
  144. return content._pickId.color;
  145. }
  146. });
  147. };
  148. }
  149. function getBatchTableLoaded(content) {
  150. return function(batchLength, batchTableJson, batchTableBinary) {
  151. content._batchTable = new Cesium3DTileBatchTable(content, batchLength, batchTableJson, batchTableBinary);
  152. };
  153. }
  154. function getPickIdLoaded(content) {
  155. return function() {
  156. return defined(content._batchTable) ? content._batchTable.getPickId() : 'czm_pickColor';
  157. };
  158. }
  159. function getGeometricError(content) {
  160. var pointCloudShading = content._tileset.pointCloudShading;
  161. var sphereVolume = content._tile.contentBoundingVolume.boundingSphere.volume();
  162. var baseResolutionApproximation = CesiumMath.cbrt(sphereVolume / content.pointsLength);
  163. var geometricError = content._tile.geometricError;
  164. if (geometricError === 0) {
  165. if (defined(pointCloudShading) && defined(pointCloudShading.baseResolution)) {
  166. geometricError = pointCloudShading.baseResolution;
  167. } else {
  168. geometricError = baseResolutionApproximation;
  169. }
  170. }
  171. return geometricError;
  172. }
  173. function createFeatures(content) {
  174. var featuresLength = content.featuresLength;
  175. if (!defined(content._features) && (featuresLength > 0)) {
  176. var features = new Array(featuresLength);
  177. for (var i = 0; i < featuresLength; ++i) {
  178. features[i] = new Cesium3DTileFeature(content, i);
  179. }
  180. content._features = features;
  181. }
  182. }
  183. PointCloud3DTileContent.prototype.hasProperty = function(batchId, name) {
  184. if (defined(this._batchTable)) {
  185. return this._batchTable.hasProperty(batchId, name);
  186. }
  187. return false;
  188. };
  189. /**
  190. * Part of the {@link Cesium3DTileContent} interface.
  191. *
  192. * In this context a feature refers to a group of points that share the same BATCH_ID.
  193. * For example all the points that represent a door in a house point cloud would be a feature.
  194. *
  195. * Features are backed by a batch table and can be colored, shown/hidden, picked, etc like features
  196. * in b3dm and i3dm.
  197. *
  198. * When the BATCH_ID semantic is omitted and the point cloud stores per-point properties, they
  199. * are not accessible by getFeature. They are only used for dynamic styling.
  200. */
  201. PointCloud3DTileContent.prototype.getFeature = function(batchId) {
  202. if (!defined(this._batchTable)) {
  203. return undefined;
  204. }
  205. var featuresLength = this.featuresLength;
  206. //>>includeStart('debug', pragmas.debug);
  207. if (!defined(batchId) || (batchId < 0) || (batchId >= featuresLength)) {
  208. throw new DeveloperError('batchId is required and between zero and featuresLength - 1 (' + (featuresLength - 1) + ').');
  209. }
  210. //>>includeEnd('debug');
  211. createFeatures(this);
  212. return this._features[batchId];
  213. };
  214. PointCloud3DTileContent.prototype.applyDebugSettings = function(enabled, color) {
  215. this._pointCloud.color = enabled ? color : Color.WHITE;
  216. };
  217. PointCloud3DTileContent.prototype.applyStyle = function(style) {
  218. if (defined(this._batchTable)) {
  219. this._batchTable.applyStyle(style);
  220. } else {
  221. this._styleDirty = true;
  222. }
  223. };
  224. var defaultShading = new PointCloudShading();
  225. PointCloud3DTileContent.prototype.update = function(tileset, frameState) {
  226. var pointCloud = this._pointCloud;
  227. var pointCloudShading = defaultValue(tileset.pointCloudShading, defaultShading);
  228. var tile = this._tile;
  229. var batchTable = this._batchTable;
  230. var mode = frameState.mode;
  231. var clippingPlanes = tileset.clippingPlanes;
  232. if (!defined(this._pickId) && !defined(batchTable)) {
  233. this._pickId = frameState.context.createPickId({
  234. primitive : tileset,
  235. content : this
  236. });
  237. }
  238. if (defined(batchTable)) {
  239. batchTable.update(tileset, frameState);
  240. }
  241. var boundingSphere;
  242. if (defined(tile._contentBoundingVolume)) {
  243. boundingSphere = mode === SceneMode.SCENE3D ? tile._contentBoundingVolume.boundingSphere : tile._contentBoundingVolume2D.boundingSphere;
  244. } else {
  245. boundingSphere = mode === SceneMode.SCENE3D ? tile._boundingVolume.boundingSphere : tile._boundingVolume2D.boundingSphere;
  246. }
  247. var styleDirty = this._styleDirty;
  248. this._styleDirty = false;
  249. pointCloud.clippingPlanesOriginMatrix = tileset.clippingPlanesOriginMatrix;
  250. pointCloud.style = defined(batchTable) ? undefined : tileset.style;
  251. pointCloud.styleDirty = styleDirty;
  252. pointCloud.modelMatrix = tile.computedTransform;
  253. pointCloud.time = tileset.timeSinceLoad;
  254. pointCloud.shadows = tileset.shadows;
  255. pointCloud.boundingSphere = boundingSphere;
  256. pointCloud.clippingPlanes = clippingPlanes;
  257. pointCloud.isClipped = defined(clippingPlanes) && clippingPlanes.enabled && tile._isClipped;
  258. pointCloud.clippingPlanesDirty = tile.clippingPlanesDirty;
  259. pointCloud.attenuation = pointCloudShading.attenuation;
  260. pointCloud.backFaceCulling = pointCloudShading.backFaceCulling;
  261. pointCloud.normalShading = pointCloudShading.normalShading;
  262. pointCloud.geometricError = getGeometricError(this);
  263. pointCloud.geometricErrorScale = pointCloudShading.geometricErrorScale;
  264. if (defined(pointCloudShading) && defined(pointCloudShading.maximumAttenuation)) {
  265. pointCloud.maximumAttenuation = pointCloudShading.maximumAttenuation;
  266. } else if (tile.refine === Cesium3DTileRefine.ADD) {
  267. pointCloud.maximumAttenuation = 5.0;
  268. } else {
  269. pointCloud.maximumAttenuation = tileset.maximumScreenSpaceError;
  270. }
  271. pointCloud.update(frameState);
  272. };
  273. PointCloud3DTileContent.prototype.isDestroyed = function() {
  274. return false;
  275. };
  276. PointCloud3DTileContent.prototype.destroy = function() {
  277. this._pickId = this._pickId && this._pickId.destroy();
  278. this._pointCloud = this._pointCloud && this._pointCloud.destroy();
  279. this._batchTable = this._batchTable && this._batchTable.destroy();
  280. return destroyObject(this);
  281. };
  282. export default PointCloud3DTileContent;