ModelExperimental3DTileContent.js 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. import Axis from "../Axis.js";
  2. import Color from "../../Core/Color.js";
  3. import combine from "../../Core/combine.js";
  4. import defined from "../../Core/defined.js";
  5. import destroyObject from "../../Core/destroyObject.js";
  6. import Pass from "../../Renderer/Pass.js";
  7. import ModelExperimental from "./ModelExperimental.js";
  8. /**
  9. * Represents the contents of a glTF, glb or
  10. * {@link https://github.com/CesiumGS/3d-tiles/tree/main/specification/TileFormats/Batched3DModel|Batched 3D Model}
  11. * tile in a {@link https://github.com/CesiumGS/3d-tiles/tree/main/specification|3D Tiles} tileset.
  12. * <p>
  13. * Implements the {@link Cesium3DTileContent} interface.
  14. * </p>
  15. * @alias ModelExperimental3DTileContent
  16. * @constructor
  17. * @private
  18. */
  19. export default function ModelExperimental3DTileContent(
  20. tileset,
  21. tile,
  22. resource
  23. ) {
  24. this._tileset = tileset;
  25. this._tile = tile;
  26. this._resource = resource;
  27. this._model = undefined;
  28. this._metadata = undefined;
  29. this._group = undefined;
  30. }
  31. Object.defineProperties(ModelExperimental3DTileContent.prototype, {
  32. featuresLength: {
  33. get: function () {
  34. const model = this._model;
  35. const featureTables = model.featureTables;
  36. const featureTableId = model.featureTableId;
  37. if (defined(featureTables) && defined(featureTables[featureTableId])) {
  38. return featureTables[featureTableId].featuresLength;
  39. }
  40. return 0;
  41. },
  42. },
  43. pointsLength: {
  44. get: function () {
  45. return 0;
  46. },
  47. },
  48. trianglesLength: {
  49. get: function () {
  50. return 0;
  51. },
  52. },
  53. geometryByteLength: {
  54. get: function () {
  55. return 0;
  56. },
  57. },
  58. texturesByteLength: {
  59. get: function () {
  60. return 0;
  61. },
  62. },
  63. batchTableByteLength: {
  64. get: function () {
  65. return 0;
  66. },
  67. },
  68. innerContents: {
  69. get: function () {
  70. return undefined;
  71. },
  72. },
  73. readyPromise: {
  74. get: function () {
  75. return this._model.readyPromise;
  76. },
  77. },
  78. tileset: {
  79. get: function () {
  80. return this._tileset;
  81. },
  82. },
  83. tile: {
  84. get: function () {
  85. return this._tile;
  86. },
  87. },
  88. url: {
  89. get: function () {
  90. return this._resource.getUrlComponent(true);
  91. },
  92. },
  93. batchTable: {
  94. get: function () {
  95. const model = this._model;
  96. const featureTables = model.featureTables;
  97. const featureTableId = model.featureTableId;
  98. if (defined(featureTables) && defined(featureTables[featureTableId])) {
  99. return featureTables[featureTableId];
  100. }
  101. return undefined;
  102. },
  103. },
  104. metadata: {
  105. get: function () {
  106. return this._metadata;
  107. },
  108. set: function (value) {
  109. this._metadata = value;
  110. },
  111. },
  112. group: {
  113. get: function () {
  114. return this._group;
  115. },
  116. set: function (value) {
  117. this._group = value;
  118. },
  119. },
  120. });
  121. ModelExperimental3DTileContent.prototype.getFeature = function (featureId) {
  122. const model = this._model;
  123. const featureTableId = model.featureTableId;
  124. if (!defined(featureTableId)) {
  125. return undefined;
  126. }
  127. const featureTable = model.featureTables[featureTableId];
  128. return featureTable.getFeature(featureId);
  129. };
  130. ModelExperimental3DTileContent.prototype.hasProperty = function (
  131. featureId,
  132. name
  133. ) {
  134. const model = this._model;
  135. const featureTableId = model.featureTableId;
  136. if (!defined(featureTableId)) {
  137. return false;
  138. }
  139. const featureTable = model.featureTables[featureTableId];
  140. return featureTable.hasProperty(featureId, name);
  141. };
  142. ModelExperimental3DTileContent.prototype.applyDebugSettings = function (
  143. enabled,
  144. color
  145. ) {
  146. color = enabled ? color : Color.WHITE;
  147. if (this.featuresLength === 0) {
  148. this._model.color = color;
  149. } else if (defined(this.batchTable)) {
  150. this.batchTable.setAllColor(color);
  151. }
  152. };
  153. ModelExperimental3DTileContent.prototype.applyStyle = function (style) {
  154. // the setter will call model.applyStyle()
  155. this._model.style = style;
  156. };
  157. ModelExperimental3DTileContent.prototype.update = function (
  158. tileset,
  159. frameState
  160. ) {
  161. const model = this._model;
  162. const tile = this._tile;
  163. model.colorBlendAmount = tileset.colorBlendAmount;
  164. model.colorBlendMode = tileset.colorBlendMode;
  165. model.modelMatrix = tile.computedTransform;
  166. model.customShader = tileset.customShader;
  167. model.pointCloudShading = tileset.pointCloudShading;
  168. model.featureIdLabel = tileset.featureIdLabel;
  169. model.instanceFeatureIdLabel = tileset.instanceFeatureIdLabel;
  170. model.lightColor = tileset.lightColor;
  171. model.imageBasedLighting = tileset.imageBasedLighting;
  172. model.backFaceCulling = tileset.backFaceCulling;
  173. model.shadows = tileset.shadows;
  174. model.showCreditsOnScreen = tileset.showCreditsOnScreen;
  175. model.splitDirection = tileset.splitDirection;
  176. model.debugWireframe = tileset.debugWireframe;
  177. // Updating clipping planes requires more effort because of ownership checks
  178. const tilesetClippingPlanes = tileset.clippingPlanes;
  179. model.referenceMatrix = tileset.clippingPlanesOriginMatrix;
  180. if (defined(tilesetClippingPlanes) && tile.clippingPlanesDirty) {
  181. // Dereference the clipping planes from the model if they are irrelevant.
  182. model._clippingPlanes =
  183. tilesetClippingPlanes.enabled && tile._isClipped
  184. ? tilesetClippingPlanes
  185. : undefined;
  186. }
  187. // If the model references a different ClippingPlaneCollection from the tileset,
  188. // update the model to use the new ClippingPlaneCollection.
  189. if (
  190. defined(tilesetClippingPlanes) &&
  191. defined(model._clippingPlanes) &&
  192. model._clippingPlanes !== tilesetClippingPlanes
  193. ) {
  194. model._clippingPlanes = tilesetClippingPlanes;
  195. }
  196. model.update(frameState);
  197. };
  198. ModelExperimental3DTileContent.prototype.isDestroyed = function () {
  199. return false;
  200. };
  201. ModelExperimental3DTileContent.prototype.destroy = function () {
  202. this._model = this._model && this._model.destroy();
  203. return destroyObject(this);
  204. };
  205. ModelExperimental3DTileContent.fromGltf = function (
  206. tileset,
  207. tile,
  208. resource,
  209. gltf
  210. ) {
  211. const content = new ModelExperimental3DTileContent(tileset, tile, resource);
  212. const additionalOptions = {
  213. gltf: gltf,
  214. basePath: resource,
  215. };
  216. const modelOptions = makeModelOptions(
  217. tileset,
  218. tile,
  219. content,
  220. additionalOptions
  221. );
  222. content._model = ModelExperimental.fromGltf(modelOptions);
  223. return content;
  224. };
  225. ModelExperimental3DTileContent.fromB3dm = function (
  226. tileset,
  227. tile,
  228. resource,
  229. arrayBuffer,
  230. byteOffset
  231. ) {
  232. const content = new ModelExperimental3DTileContent(tileset, tile, resource);
  233. const additionalOptions = {
  234. arrayBuffer: arrayBuffer,
  235. byteOffset: byteOffset,
  236. resource: resource,
  237. };
  238. const modelOptions = makeModelOptions(
  239. tileset,
  240. tile,
  241. content,
  242. additionalOptions
  243. );
  244. content._model = ModelExperimental.fromB3dm(modelOptions);
  245. return content;
  246. };
  247. ModelExperimental3DTileContent.fromI3dm = function (
  248. tileset,
  249. tile,
  250. resource,
  251. arrayBuffer,
  252. byteOffset
  253. ) {
  254. const content = new ModelExperimental3DTileContent(tileset, tile, resource);
  255. const additionalOptions = {
  256. arrayBuffer: arrayBuffer,
  257. byteOffset: byteOffset,
  258. resource: resource,
  259. };
  260. const modelOptions = makeModelOptions(
  261. tileset,
  262. tile,
  263. content,
  264. additionalOptions
  265. );
  266. content._model = ModelExperimental.fromI3dm(modelOptions);
  267. return content;
  268. };
  269. ModelExperimental3DTileContent.fromPnts = function (
  270. tileset,
  271. tile,
  272. resource,
  273. arrayBuffer,
  274. byteOffset
  275. ) {
  276. const content = new ModelExperimental3DTileContent(tileset, tile, resource);
  277. const additionalOptions = {
  278. arrayBuffer: arrayBuffer,
  279. byteOffset: byteOffset,
  280. resource: resource,
  281. };
  282. const modelOptions = makeModelOptions(
  283. tileset,
  284. tile,
  285. content,
  286. additionalOptions
  287. );
  288. content._model = ModelExperimental.fromPnts(modelOptions);
  289. return content;
  290. };
  291. function makeModelOptions(tileset, tile, content, additionalOptions) {
  292. const mainOptions = {
  293. cull: false, // The model is already culled by 3D Tiles
  294. releaseGltfJson: true, // Models are unique and will not benefit from caching so save memory
  295. opaquePass: Pass.CESIUM_3D_TILE, // Draw opaque portions of the model during the 3D Tiles pass
  296. modelMatrix: tile.computedTransform,
  297. upAxis: tileset._gltfUpAxis,
  298. forwardAxis: Axis.X,
  299. incrementallyLoadTextures: false,
  300. customShader: tileset.customShader,
  301. content: content,
  302. show: tileset.show,
  303. colorBlendMode: tileset.colorBlendMode,
  304. colorBlendAmount: tileset.colorBlendAmount,
  305. lightColor: tileset.lightColor,
  306. imageBasedLighting: tileset.imageBasedLighting,
  307. featureIdLabel: tileset.featureIdLabel,
  308. instanceFeatureIdLabel: tileset.instanceFeatureIdLabel,
  309. pointCloudShading: tileset.pointCloudShading,
  310. clippingPlanes: tileset.clippingPlanes,
  311. backFaceCulling: tileset.backFaceCulling,
  312. shadows: tileset.shadows,
  313. showCreditsOnScreen: tileset.showCreditsOnScreen,
  314. splitDirection: tileset.splitDirection,
  315. debugWireframe: tileset.debugWireframe,
  316. };
  317. return combine(additionalOptions, mainOptions);
  318. }