Cesium3DTilesetMostDetailedTraversal.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. import Intersect from "../Core/Intersect.js";
  2. import ManagedArray from "../Core/ManagedArray.js";
  3. import Cesium3DTileRefine from "./Cesium3DTileRefine.js";
  4. import Cesium3DTilesetTraversal from "./Cesium3DTilesetTraversal.js";
  5. /**
  6. * Traversal that loads all leaves that intersect the camera frustum.
  7. * Used to determine ray-tileset intersections during a pickFromRayMostDetailed call.
  8. *
  9. * @alias Cesium3DTilesetMostDetailedTraversal
  10. * @constructor
  11. *
  12. * @private
  13. */
  14. function Cesium3DTilesetMostDetailedTraversal() {}
  15. const traversal = {
  16. stack: new ManagedArray(),
  17. stackMaximumLength: 0,
  18. };
  19. /**
  20. * Traverses a {@link Cesium3DTileset} to determine which tiles to load and render.
  21. *
  22. * @private
  23. * @param {Cesium3DTileset} tileset
  24. * @param {FrameState} frameState
  25. * @returns {boolean} Whether the appropriate tile is ready for picking
  26. */
  27. Cesium3DTilesetMostDetailedTraversal.selectTiles = function (
  28. tileset,
  29. frameState
  30. ) {
  31. tileset._selectedTiles.length = 0;
  32. tileset._requestedTiles.length = 0;
  33. tileset.hasMixedContent = false;
  34. let ready = true;
  35. const root = tileset.root;
  36. root.updateVisibility(frameState);
  37. if (!root.isVisible) {
  38. return ready;
  39. }
  40. const { touchTile, visitTile } = Cesium3DTilesetTraversal;
  41. const stack = traversal.stack;
  42. stack.push(root);
  43. while (stack.length > 0) {
  44. traversal.stackMaximumLength = Math.max(
  45. traversal.stackMaximumLength,
  46. stack.length
  47. );
  48. const tile = stack.pop();
  49. const add = tile.refine === Cesium3DTileRefine.ADD;
  50. const replace = tile.refine === Cesium3DTileRefine.REPLACE;
  51. const traverse = canTraverse(tile);
  52. if (traverse) {
  53. updateAndPushChildren(tile, stack, frameState);
  54. }
  55. if (add || (replace && !traverse)) {
  56. loadTile(tileset, tile);
  57. touchTile(tile, frameState);
  58. selectDesiredTile(tile, frameState);
  59. if (tile.hasRenderableContent && !tile.contentAvailable) {
  60. ready = false;
  61. }
  62. }
  63. visitTile(tile, frameState);
  64. }
  65. traversal.stack.trim(traversal.stackMaximumLength);
  66. return ready;
  67. };
  68. function canTraverse(tile) {
  69. if (tile.children.length === 0) {
  70. return false;
  71. }
  72. if (tile.hasTilesetContent || tile.hasImplicitContent) {
  73. // Traverse external tileset to visit its root tile
  74. // Don't traverse if the subtree is expired because it will be destroyed
  75. return !tile.contentExpired;
  76. }
  77. if (tile.hasEmptyContent) {
  78. return true;
  79. }
  80. return true; // Keep traversing until a leaf is hit
  81. }
  82. function updateAndPushChildren(tile, stack, frameState) {
  83. const { children } = tile;
  84. for (let i = 0; i < children.length; ++i) {
  85. const child = children[i];
  86. child.updateVisibility(frameState);
  87. if (child.isVisible) {
  88. stack.push(child);
  89. }
  90. }
  91. }
  92. function loadTile(tileset, tile) {
  93. if (tile.hasUnloadedRenderableContent || tile.contentExpired) {
  94. tile._priority = 0.0; // Highest priority
  95. tileset._requestedTiles.push(tile);
  96. }
  97. }
  98. function selectDesiredTile(tile, frameState) {
  99. if (
  100. tile.contentAvailable &&
  101. tile.contentVisibility(frameState) !== Intersect.OUTSIDE
  102. ) {
  103. tile.tileset._selectedTiles.push(tile);
  104. }
  105. }
  106. export default Cesium3DTilesetMostDetailedTraversal;