Cesium3DTileOptimizations.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. import Cartesian3 from "../Core/Cartesian3.js";
  2. import Check from "../Core/Check.js";
  3. import Cesium3DTileOptimizationHint from "./Cesium3DTileOptimizationHint.js";
  4. import TileBoundingRegion from "./TileBoundingRegion.js";
  5. import TileOrientedBoundingBox from "./TileOrientedBoundingBox.js";
  6. /**
  7. * Utility functions for computing optimization hints for a {@link Cesium3DTileset}.
  8. *
  9. * @namespace Cesium3DTileOptimizations
  10. *
  11. * @private
  12. */
  13. const Cesium3DTileOptimizations = {};
  14. const scratchAxis = new Cartesian3();
  15. /**
  16. * Evaluates support for the childrenWithinParent optimization. This is used to more tightly cull tilesets if
  17. * children bounds are fully contained within the parent. Currently, support for the optimization only works for
  18. * oriented bounding boxes, so both the child and parent tile must be either a {@link TileOrientedBoundingBox} or
  19. * {@link TileBoundingRegion}. The purpose of this check is to prevent use of a culling optimization when the child
  20. * bounds exceed those of the parent. If the child bounds are greater, it is more likely that the optimization will
  21. * waste CPU cycles. Bounding spheres are not supported for the reason that the child bounds can very often be
  22. * partially outside of the parent bounds.
  23. *
  24. * @param {Cesium3DTile} tile The tile to check.
  25. * @returns {boolean} Whether the childrenWithinParent optimization is supported.
  26. */
  27. Cesium3DTileOptimizations.checkChildrenWithinParent = function (tile) {
  28. //>>includeStart('debug', pragmas.debug);
  29. Check.typeOf.object("tile", tile);
  30. //>>includeEnd('debug');
  31. const children = tile.children;
  32. const length = children.length;
  33. // Check if the parent has an oriented bounding box.
  34. const boundingVolume = tile.boundingVolume;
  35. if (
  36. boundingVolume instanceof TileOrientedBoundingBox ||
  37. boundingVolume instanceof TileBoundingRegion
  38. ) {
  39. const orientedBoundingBox = boundingVolume._orientedBoundingBox;
  40. tile._optimChildrenWithinParent =
  41. Cesium3DTileOptimizationHint.USE_OPTIMIZATION;
  42. for (let i = 0; i < length; ++i) {
  43. const child = children[i];
  44. // Check if the child has an oriented bounding box.
  45. const childBoundingVolume = child.boundingVolume;
  46. if (
  47. !(
  48. childBoundingVolume instanceof TileOrientedBoundingBox ||
  49. childBoundingVolume instanceof TileBoundingRegion
  50. )
  51. ) {
  52. // Do not support if the parent and child both do not have oriented bounding boxes.
  53. tile._optimChildrenWithinParent =
  54. Cesium3DTileOptimizationHint.SKIP_OPTIMIZATION;
  55. break;
  56. }
  57. const childOrientedBoundingBox = childBoundingVolume._orientedBoundingBox;
  58. // Compute the axis from the parent to the child.
  59. const axis = Cartesian3.subtract(
  60. childOrientedBoundingBox.center,
  61. orientedBoundingBox.center,
  62. scratchAxis
  63. );
  64. const axisLength = Cartesian3.magnitude(axis);
  65. Cartesian3.divideByScalar(axis, axisLength, axis);
  66. // Project the bounding box of the parent onto the axis. Because the axis is a ray from the parent
  67. // to the child, the projection parameterized along the ray will be (+/- proj1).
  68. const proj1 =
  69. Math.abs(orientedBoundingBox.halfAxes[0] * axis.x) +
  70. Math.abs(orientedBoundingBox.halfAxes[1] * axis.y) +
  71. Math.abs(orientedBoundingBox.halfAxes[2] * axis.z) +
  72. Math.abs(orientedBoundingBox.halfAxes[3] * axis.x) +
  73. Math.abs(orientedBoundingBox.halfAxes[4] * axis.y) +
  74. Math.abs(orientedBoundingBox.halfAxes[5] * axis.z) +
  75. Math.abs(orientedBoundingBox.halfAxes[6] * axis.x) +
  76. Math.abs(orientedBoundingBox.halfAxes[7] * axis.y) +
  77. Math.abs(orientedBoundingBox.halfAxes[8] * axis.z);
  78. // Project the bounding box of the child onto the axis. Because the axis is a ray from the parent
  79. // to the child, the projection parameterized along the ray will be (+/- proj2) + axis.length.
  80. const proj2 =
  81. Math.abs(childOrientedBoundingBox.halfAxes[0] * axis.x) +
  82. Math.abs(childOrientedBoundingBox.halfAxes[1] * axis.y) +
  83. Math.abs(childOrientedBoundingBox.halfAxes[2] * axis.z) +
  84. Math.abs(childOrientedBoundingBox.halfAxes[3] * axis.x) +
  85. Math.abs(childOrientedBoundingBox.halfAxes[4] * axis.y) +
  86. Math.abs(childOrientedBoundingBox.halfAxes[5] * axis.z) +
  87. Math.abs(childOrientedBoundingBox.halfAxes[6] * axis.x) +
  88. Math.abs(childOrientedBoundingBox.halfAxes[7] * axis.y) +
  89. Math.abs(childOrientedBoundingBox.halfAxes[8] * axis.z);
  90. // If the child extends the parent's bounds, the optimization is not valid and we skip it.
  91. if (proj1 <= proj2 + axisLength) {
  92. tile._optimChildrenWithinParent =
  93. Cesium3DTileOptimizationHint.SKIP_OPTIMIZATION;
  94. break;
  95. }
  96. }
  97. }
  98. return (
  99. tile._optimChildrenWithinParent ===
  100. Cesium3DTileOptimizationHint.USE_OPTIMIZATION
  101. );
  102. };
  103. export default Cesium3DTileOptimizations;