Instanced3DModel3DTileContent.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  1. import AttributeCompression from "../Core/AttributeCompression.js";
  2. import Cartesian3 from "../Core/Cartesian3.js";
  3. import Color from "../Core/Color.js";
  4. import ComponentDatatype from "../Core/ComponentDatatype.js";
  5. import defaultValue from "../Core/defaultValue.js";
  6. import defined from "../Core/defined.js";
  7. import deprecationWarning from "../Core/deprecationWarning.js";
  8. import destroyObject from "../Core/destroyObject.js";
  9. import DeveloperError from "../Core/DeveloperError.js";
  10. import Ellipsoid from "../Core/Ellipsoid.js";
  11. import getStringFromTypedArray from "../Core/getStringFromTypedArray.js";
  12. import Matrix3 from "../Core/Matrix3.js";
  13. import Matrix4 from "../Core/Matrix4.js";
  14. import Quaternion from "../Core/Quaternion.js";
  15. import RequestType from "../Core/RequestType.js";
  16. import RuntimeError from "../Core/RuntimeError.js";
  17. import Transforms from "../Core/Transforms.js";
  18. import TranslationRotationScale from "../Core/TranslationRotationScale.js";
  19. import Pass from "../Renderer/Pass.js";
  20. import Axis from "./Axis.js";
  21. import Cesium3DTileBatchTable from "./Cesium3DTileBatchTable.js";
  22. import Cesium3DTileFeature from "./Cesium3DTileFeature.js";
  23. import Cesium3DTileFeatureTable from "./Cesium3DTileFeatureTable.js";
  24. import ModelInstanceCollection from "./ModelInstanceCollection.js";
  25. import ModelAnimationLoop from "./ModelAnimationLoop.js";
  26. /**
  27. * Represents the contents of a
  28. * {@link https://github.com/CesiumGS/3d-tiles/tree/master/specification/TileFormats/Instanced3DModel|Instanced 3D Model}
  29. * tile in a {@link https://github.com/CesiumGS/3d-tiles/tree/master/specification|3D Tiles} tileset.
  30. * <p>
  31. * Implements the {@link Cesium3DTileContent} interface.
  32. * </p>
  33. *
  34. * @alias Instanced3DModel3DTileContent
  35. * @constructor
  36. *
  37. * @private
  38. */
  39. function Instanced3DModel3DTileContent(
  40. tileset,
  41. tile,
  42. resource,
  43. arrayBuffer,
  44. byteOffset
  45. ) {
  46. this._tileset = tileset;
  47. this._tile = tile;
  48. this._resource = resource;
  49. this._modelInstanceCollection = undefined;
  50. this._batchTable = undefined;
  51. this._features = undefined;
  52. this.featurePropertiesDirty = false;
  53. initialize(this, arrayBuffer, byteOffset);
  54. }
  55. // This can be overridden for testing purposes
  56. Instanced3DModel3DTileContent._deprecationWarning = deprecationWarning;
  57. Object.defineProperties(Instanced3DModel3DTileContent.prototype, {
  58. featuresLength: {
  59. get: function () {
  60. return this._batchTable.featuresLength;
  61. },
  62. },
  63. pointsLength: {
  64. get: function () {
  65. return 0;
  66. },
  67. },
  68. trianglesLength: {
  69. get: function () {
  70. var model = this._modelInstanceCollection._model;
  71. if (defined(model)) {
  72. return model.trianglesLength;
  73. }
  74. return 0;
  75. },
  76. },
  77. geometryByteLength: {
  78. get: function () {
  79. var model = this._modelInstanceCollection._model;
  80. if (defined(model)) {
  81. return model.geometryByteLength;
  82. }
  83. return 0;
  84. },
  85. },
  86. texturesByteLength: {
  87. get: function () {
  88. var model = this._modelInstanceCollection._model;
  89. if (defined(model)) {
  90. return model.texturesByteLength;
  91. }
  92. return 0;
  93. },
  94. },
  95. batchTableByteLength: {
  96. get: function () {
  97. return this._batchTable.memorySizeInBytes;
  98. },
  99. },
  100. innerContents: {
  101. get: function () {
  102. return undefined;
  103. },
  104. },
  105. readyPromise: {
  106. get: function () {
  107. return this._modelInstanceCollection.readyPromise;
  108. },
  109. },
  110. tileset: {
  111. get: function () {
  112. return this._tileset;
  113. },
  114. },
  115. tile: {
  116. get: function () {
  117. return this._tile;
  118. },
  119. },
  120. url: {
  121. get: function () {
  122. return this._resource.getUrlComponent(true);
  123. },
  124. },
  125. batchTable: {
  126. get: function () {
  127. return this._batchTable;
  128. },
  129. },
  130. });
  131. function getPickIdCallback(content) {
  132. return function () {
  133. return content._batchTable.getPickId();
  134. };
  135. }
  136. var sizeOfUint32 = Uint32Array.BYTES_PER_ELEMENT;
  137. var propertyScratch1 = new Array(4);
  138. var propertyScratch2 = new Array(4);
  139. function initialize(content, arrayBuffer, byteOffset) {
  140. var byteStart = defaultValue(byteOffset, 0);
  141. byteOffset = byteStart;
  142. var uint8Array = new Uint8Array(arrayBuffer);
  143. var view = new DataView(arrayBuffer);
  144. byteOffset += sizeOfUint32; // Skip magic
  145. var version = view.getUint32(byteOffset, true);
  146. if (version !== 1) {
  147. throw new RuntimeError(
  148. "Only Instanced 3D Model version 1 is supported. Version " +
  149. version +
  150. " is not."
  151. );
  152. }
  153. byteOffset += sizeOfUint32;
  154. var byteLength = view.getUint32(byteOffset, true);
  155. byteOffset += sizeOfUint32;
  156. var featureTableJsonByteLength = view.getUint32(byteOffset, true);
  157. if (featureTableJsonByteLength === 0) {
  158. throw new RuntimeError(
  159. "featureTableJsonByteLength is zero, the feature table must be defined."
  160. );
  161. }
  162. byteOffset += sizeOfUint32;
  163. var featureTableBinaryByteLength = view.getUint32(byteOffset, true);
  164. byteOffset += sizeOfUint32;
  165. var batchTableJsonByteLength = view.getUint32(byteOffset, true);
  166. byteOffset += sizeOfUint32;
  167. var batchTableBinaryByteLength = view.getUint32(byteOffset, true);
  168. byteOffset += sizeOfUint32;
  169. var gltfFormat = view.getUint32(byteOffset, true);
  170. if (gltfFormat !== 1 && gltfFormat !== 0) {
  171. throw new RuntimeError(
  172. "Only glTF format 0 (uri) or 1 (embedded) are supported. Format " +
  173. gltfFormat +
  174. " is not."
  175. );
  176. }
  177. byteOffset += sizeOfUint32;
  178. var featureTableString = getStringFromTypedArray(
  179. uint8Array,
  180. byteOffset,
  181. featureTableJsonByteLength
  182. );
  183. var featureTableJson = JSON.parse(featureTableString);
  184. byteOffset += featureTableJsonByteLength;
  185. var featureTableBinary = new Uint8Array(
  186. arrayBuffer,
  187. byteOffset,
  188. featureTableBinaryByteLength
  189. );
  190. byteOffset += featureTableBinaryByteLength;
  191. var featureTable = new Cesium3DTileFeatureTable(
  192. featureTableJson,
  193. featureTableBinary
  194. );
  195. var instancesLength = featureTable.getGlobalProperty("INSTANCES_LENGTH");
  196. featureTable.featuresLength = instancesLength;
  197. if (!defined(instancesLength)) {
  198. throw new RuntimeError(
  199. "Feature table global property: INSTANCES_LENGTH must be defined"
  200. );
  201. }
  202. var batchTableJson;
  203. var batchTableBinary;
  204. if (batchTableJsonByteLength > 0) {
  205. var batchTableString = getStringFromTypedArray(
  206. uint8Array,
  207. byteOffset,
  208. batchTableJsonByteLength
  209. );
  210. batchTableJson = JSON.parse(batchTableString);
  211. byteOffset += batchTableJsonByteLength;
  212. if (batchTableBinaryByteLength > 0) {
  213. // Has a batch table binary
  214. batchTableBinary = new Uint8Array(
  215. arrayBuffer,
  216. byteOffset,
  217. batchTableBinaryByteLength
  218. );
  219. // Copy the batchTableBinary section and let the underlying ArrayBuffer be freed
  220. batchTableBinary = new Uint8Array(batchTableBinary);
  221. byteOffset += batchTableBinaryByteLength;
  222. }
  223. }
  224. content._batchTable = new Cesium3DTileBatchTable(
  225. content,
  226. instancesLength,
  227. batchTableJson,
  228. batchTableBinary
  229. );
  230. var gltfByteLength = byteStart + byteLength - byteOffset;
  231. if (gltfByteLength === 0) {
  232. throw new RuntimeError(
  233. "glTF byte length is zero, i3dm must have a glTF to instance."
  234. );
  235. }
  236. var gltfView;
  237. if (byteOffset % 4 === 0) {
  238. gltfView = new Uint8Array(arrayBuffer, byteOffset, gltfByteLength);
  239. } else {
  240. // Create a copy of the glb so that it is 4-byte aligned
  241. Instanced3DModel3DTileContent._deprecationWarning(
  242. "i3dm-glb-unaligned",
  243. "The embedded glb is not aligned to a 4-byte boundary."
  244. );
  245. gltfView = new Uint8Array(
  246. uint8Array.subarray(byteOffset, byteOffset + gltfByteLength)
  247. );
  248. }
  249. var tileset = content._tileset;
  250. // Create model instance collection
  251. var collectionOptions = {
  252. instances: new Array(instancesLength),
  253. batchTable: content._batchTable,
  254. cull: false, // Already culled by 3D Tiles
  255. url: undefined,
  256. requestType: RequestType.TILES3D,
  257. gltf: undefined,
  258. basePath: undefined,
  259. incrementallyLoadTextures: false,
  260. upAxis: tileset._gltfUpAxis,
  261. forwardAxis: Axis.X,
  262. opaquePass: Pass.CESIUM_3D_TILE, // Draw opaque portions during the 3D Tiles pass
  263. pickIdLoaded: getPickIdCallback(content),
  264. imageBasedLightingFactor: tileset.imageBasedLightingFactor,
  265. lightColor: tileset.lightColor,
  266. luminanceAtZenith: tileset.luminanceAtZenith,
  267. sphericalHarmonicCoefficients: tileset.sphericalHarmonicCoefficients,
  268. specularEnvironmentMaps: tileset.specularEnvironmentMaps,
  269. backFaceCulling: tileset.backFaceCulling,
  270. };
  271. if (gltfFormat === 0) {
  272. var gltfUrl = getStringFromTypedArray(gltfView);
  273. // We need to remove padding from the end of the model URL in case this tile was part of a composite tile.
  274. // This removes all white space and null characters from the end of the string.
  275. gltfUrl = gltfUrl.replace(/[\s\0]+$/, "");
  276. collectionOptions.url = content._resource.getDerivedResource({
  277. url: gltfUrl,
  278. });
  279. } else {
  280. collectionOptions.gltf = gltfView;
  281. collectionOptions.basePath = content._resource.clone();
  282. }
  283. var eastNorthUp = featureTable.getGlobalProperty("EAST_NORTH_UP");
  284. var rtcCenter;
  285. var rtcCenterArray = featureTable.getGlobalProperty(
  286. "RTC_CENTER",
  287. ComponentDatatype.FLOAT,
  288. 3
  289. );
  290. if (defined(rtcCenterArray)) {
  291. rtcCenter = Cartesian3.unpack(rtcCenterArray);
  292. }
  293. var instances = collectionOptions.instances;
  294. var instancePosition = new Cartesian3();
  295. var instancePositionArray = new Array(3);
  296. var instanceNormalRight = new Cartesian3();
  297. var instanceNormalUp = new Cartesian3();
  298. var instanceNormalForward = new Cartesian3();
  299. var instanceRotation = new Matrix3();
  300. var instanceQuaternion = new Quaternion();
  301. var instanceScale = new Cartesian3();
  302. var instanceTranslationRotationScale = new TranslationRotationScale();
  303. var instanceTransform = new Matrix4();
  304. for (var i = 0; i < instancesLength; i++) {
  305. // Get the instance position
  306. var position = featureTable.getProperty(
  307. "POSITION",
  308. ComponentDatatype.FLOAT,
  309. 3,
  310. i,
  311. propertyScratch1
  312. );
  313. if (!defined(position)) {
  314. position = instancePositionArray;
  315. var positionQuantized = featureTable.getProperty(
  316. "POSITION_QUANTIZED",
  317. ComponentDatatype.UNSIGNED_SHORT,
  318. 3,
  319. i,
  320. propertyScratch1
  321. );
  322. if (!defined(positionQuantized)) {
  323. throw new RuntimeError(
  324. "Either POSITION or POSITION_QUANTIZED must be defined for each instance."
  325. );
  326. }
  327. var quantizedVolumeOffset = featureTable.getGlobalProperty(
  328. "QUANTIZED_VOLUME_OFFSET",
  329. ComponentDatatype.FLOAT,
  330. 3
  331. );
  332. if (!defined(quantizedVolumeOffset)) {
  333. throw new RuntimeError(
  334. "Global property: QUANTIZED_VOLUME_OFFSET must be defined for quantized positions."
  335. );
  336. }
  337. var quantizedVolumeScale = featureTable.getGlobalProperty(
  338. "QUANTIZED_VOLUME_SCALE",
  339. ComponentDatatype.FLOAT,
  340. 3
  341. );
  342. if (!defined(quantizedVolumeScale)) {
  343. throw new RuntimeError(
  344. "Global property: QUANTIZED_VOLUME_SCALE must be defined for quantized positions."
  345. );
  346. }
  347. for (var j = 0; j < 3; j++) {
  348. position[j] =
  349. (positionQuantized[j] / 65535.0) * quantizedVolumeScale[j] +
  350. quantizedVolumeOffset[j];
  351. }
  352. }
  353. Cartesian3.unpack(position, 0, instancePosition);
  354. if (defined(rtcCenter)) {
  355. Cartesian3.add(instancePosition, rtcCenter, instancePosition);
  356. }
  357. instanceTranslationRotationScale.translation = instancePosition;
  358. // Get the instance rotation
  359. var normalUp = featureTable.getProperty(
  360. "NORMAL_UP",
  361. ComponentDatatype.FLOAT,
  362. 3,
  363. i,
  364. propertyScratch1
  365. );
  366. var normalRight = featureTable.getProperty(
  367. "NORMAL_RIGHT",
  368. ComponentDatatype.FLOAT,
  369. 3,
  370. i,
  371. propertyScratch2
  372. );
  373. var hasCustomOrientation = false;
  374. if (defined(normalUp)) {
  375. if (!defined(normalRight)) {
  376. throw new RuntimeError(
  377. "To define a custom orientation, both NORMAL_UP and NORMAL_RIGHT must be defined."
  378. );
  379. }
  380. Cartesian3.unpack(normalUp, 0, instanceNormalUp);
  381. Cartesian3.unpack(normalRight, 0, instanceNormalRight);
  382. hasCustomOrientation = true;
  383. } else {
  384. var octNormalUp = featureTable.getProperty(
  385. "NORMAL_UP_OCT32P",
  386. ComponentDatatype.UNSIGNED_SHORT,
  387. 2,
  388. i,
  389. propertyScratch1
  390. );
  391. var octNormalRight = featureTable.getProperty(
  392. "NORMAL_RIGHT_OCT32P",
  393. ComponentDatatype.UNSIGNED_SHORT,
  394. 2,
  395. i,
  396. propertyScratch2
  397. );
  398. if (defined(octNormalUp)) {
  399. if (!defined(octNormalRight)) {
  400. throw new RuntimeError(
  401. "To define a custom orientation with oct-encoded vectors, both NORMAL_UP_OCT32P and NORMAL_RIGHT_OCT32P must be defined."
  402. );
  403. }
  404. AttributeCompression.octDecodeInRange(
  405. octNormalUp[0],
  406. octNormalUp[1],
  407. 65535,
  408. instanceNormalUp
  409. );
  410. AttributeCompression.octDecodeInRange(
  411. octNormalRight[0],
  412. octNormalRight[1],
  413. 65535,
  414. instanceNormalRight
  415. );
  416. hasCustomOrientation = true;
  417. } else if (eastNorthUp) {
  418. Transforms.eastNorthUpToFixedFrame(
  419. instancePosition,
  420. Ellipsoid.WGS84,
  421. instanceTransform
  422. );
  423. Matrix4.getMatrix3(instanceTransform, instanceRotation);
  424. } else {
  425. Matrix3.clone(Matrix3.IDENTITY, instanceRotation);
  426. }
  427. }
  428. if (hasCustomOrientation) {
  429. Cartesian3.cross(
  430. instanceNormalRight,
  431. instanceNormalUp,
  432. instanceNormalForward
  433. );
  434. Cartesian3.normalize(instanceNormalForward, instanceNormalForward);
  435. Matrix3.setColumn(
  436. instanceRotation,
  437. 0,
  438. instanceNormalRight,
  439. instanceRotation
  440. );
  441. Matrix3.setColumn(
  442. instanceRotation,
  443. 1,
  444. instanceNormalUp,
  445. instanceRotation
  446. );
  447. Matrix3.setColumn(
  448. instanceRotation,
  449. 2,
  450. instanceNormalForward,
  451. instanceRotation
  452. );
  453. }
  454. Quaternion.fromRotationMatrix(instanceRotation, instanceQuaternion);
  455. instanceTranslationRotationScale.rotation = instanceQuaternion;
  456. // Get the instance scale
  457. instanceScale = Cartesian3.fromElements(1.0, 1.0, 1.0, instanceScale);
  458. var scale = featureTable.getProperty(
  459. "SCALE",
  460. ComponentDatatype.FLOAT,
  461. 1,
  462. i
  463. );
  464. if (defined(scale)) {
  465. Cartesian3.multiplyByScalar(instanceScale, scale, instanceScale);
  466. }
  467. var nonUniformScale = featureTable.getProperty(
  468. "SCALE_NON_UNIFORM",
  469. ComponentDatatype.FLOAT,
  470. 3,
  471. i,
  472. propertyScratch1
  473. );
  474. if (defined(nonUniformScale)) {
  475. instanceScale.x *= nonUniformScale[0];
  476. instanceScale.y *= nonUniformScale[1];
  477. instanceScale.z *= nonUniformScale[2];
  478. }
  479. instanceTranslationRotationScale.scale = instanceScale;
  480. // Get the batchId
  481. var batchId = featureTable.getProperty(
  482. "BATCH_ID",
  483. ComponentDatatype.UNSIGNED_SHORT,
  484. 1,
  485. i
  486. );
  487. if (!defined(batchId)) {
  488. // If BATCH_ID semantic is undefined, batchId is just the instance number
  489. batchId = i;
  490. }
  491. // Create the model matrix and the instance
  492. Matrix4.fromTranslationRotationScale(
  493. instanceTranslationRotationScale,
  494. instanceTransform
  495. );
  496. var modelMatrix = instanceTransform.clone();
  497. instances[i] = {
  498. modelMatrix: modelMatrix,
  499. batchId: batchId,
  500. };
  501. }
  502. content._modelInstanceCollection = new ModelInstanceCollection(
  503. collectionOptions
  504. );
  505. content._modelInstanceCollection.readyPromise.then(function (collection) {
  506. collection.activeAnimations.addAll({
  507. loop: ModelAnimationLoop.REPEAT,
  508. });
  509. });
  510. }
  511. function createFeatures(content) {
  512. var featuresLength = content.featuresLength;
  513. if (!defined(content._features) && featuresLength > 0) {
  514. var features = new Array(featuresLength);
  515. for (var i = 0; i < featuresLength; ++i) {
  516. features[i] = new Cesium3DTileFeature(content, i);
  517. }
  518. content._features = features;
  519. }
  520. }
  521. Instanced3DModel3DTileContent.prototype.hasProperty = function (batchId, name) {
  522. return this._batchTable.hasProperty(batchId, name);
  523. };
  524. Instanced3DModel3DTileContent.prototype.getFeature = function (batchId) {
  525. var featuresLength = this.featuresLength;
  526. //>>includeStart('debug', pragmas.debug);
  527. if (!defined(batchId) || batchId < 0 || batchId >= featuresLength) {
  528. throw new DeveloperError(
  529. "batchId is required and between zero and featuresLength - 1 (" +
  530. (featuresLength - 1) +
  531. ")."
  532. );
  533. }
  534. //>>includeEnd('debug');
  535. createFeatures(this);
  536. return this._features[batchId];
  537. };
  538. Instanced3DModel3DTileContent.prototype.applyDebugSettings = function (
  539. enabled,
  540. color
  541. ) {
  542. color = enabled ? color : Color.WHITE;
  543. this._batchTable.setAllColor(color);
  544. };
  545. Instanced3DModel3DTileContent.prototype.applyStyle = function (style) {
  546. this._batchTable.applyStyle(style);
  547. };
  548. Instanced3DModel3DTileContent.prototype.update = function (
  549. tileset,
  550. frameState
  551. ) {
  552. var commandStart = frameState.commandList.length;
  553. // In the PROCESSING state we may be calling update() to move forward
  554. // the content's resource loading. In the READY state, it will
  555. // actually generate commands.
  556. this._batchTable.update(tileset, frameState);
  557. this._modelInstanceCollection.modelMatrix = this._tile.computedTransform;
  558. this._modelInstanceCollection.shadows = this._tileset.shadows;
  559. this._modelInstanceCollection.lightColor = this._tileset.lightColor;
  560. this._modelInstanceCollection.luminanceAtZenith = this._tileset.luminanceAtZenith;
  561. this._modelInstanceCollection.sphericalHarmonicCoefficients = this._tileset.sphericalHarmonicCoefficients;
  562. this._modelInstanceCollection.specularEnvironmentMaps = this._tileset.specularEnvironmentMaps;
  563. this._modelInstanceCollection.backFaceCulling = this._tileset.backFaceCulling;
  564. this._modelInstanceCollection.debugWireframe = this._tileset.debugWireframe;
  565. var model = this._modelInstanceCollection._model;
  566. if (defined(model)) {
  567. // Update for clipping planes
  568. var tilesetClippingPlanes = this._tileset.clippingPlanes;
  569. model.clippingPlanesOriginMatrix = this._tileset.clippingPlanesOriginMatrix;
  570. if (defined(tilesetClippingPlanes) && this._tile.clippingPlanesDirty) {
  571. // Dereference the clipping planes from the model if they are irrelevant - saves on shading
  572. // Link/Dereference directly to avoid ownership checks.
  573. model._clippingPlanes =
  574. tilesetClippingPlanes.enabled && this._tile._isClipped
  575. ? tilesetClippingPlanes
  576. : undefined;
  577. }
  578. // If the model references a different ClippingPlaneCollection due to the tileset's collection being replaced with a
  579. // ClippingPlaneCollection that gives this tile the same clipping status, update the model to use the new ClippingPlaneCollection.
  580. if (
  581. defined(tilesetClippingPlanes) &&
  582. defined(model._clippingPlanes) &&
  583. model._clippingPlanes !== tilesetClippingPlanes
  584. ) {
  585. model._clippingPlanes = tilesetClippingPlanes;
  586. }
  587. }
  588. this._modelInstanceCollection.update(frameState);
  589. // If any commands were pushed, add derived commands
  590. var commandEnd = frameState.commandList.length;
  591. if (
  592. commandStart < commandEnd &&
  593. (frameState.passes.render || frameState.passes.pick)
  594. ) {
  595. this._batchTable.addDerivedCommands(frameState, commandStart, false);
  596. }
  597. };
  598. Instanced3DModel3DTileContent.prototype.isDestroyed = function () {
  599. return false;
  600. };
  601. Instanced3DModel3DTileContent.prototype.destroy = function () {
  602. this._modelInstanceCollection =
  603. this._modelInstanceCollection && this._modelInstanceCollection.destroy();
  604. this._batchTable = this._batchTable && this._batchTable.destroy();
  605. return destroyObject(this);
  606. };
  607. export default Instanced3DModel3DTileContent;