Cesium3DTileOptimizations.js 5.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  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. * @exports Cesium3DTileOptimizations
  10. *
  11. * @private
  12. */
  13. var Cesium3DTileOptimizations = {};
  14. var 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. var children = tile.children;
  32. var length = children.length;
  33. // Check if the parent has an oriented bounding box.
  34. var boundingVolume = tile.boundingVolume;
  35. if (boundingVolume instanceof TileOrientedBoundingBox || boundingVolume instanceof TileBoundingRegion) {
  36. var orientedBoundingBox = boundingVolume._orientedBoundingBox;
  37. tile._optimChildrenWithinParent = Cesium3DTileOptimizationHint.USE_OPTIMIZATION;
  38. for (var i = 0; i < length; ++i) {
  39. var child = children[i];
  40. // Check if the child has an oriented bounding box.
  41. var childBoundingVolume = child.boundingVolume;
  42. if (!(childBoundingVolume instanceof TileOrientedBoundingBox || childBoundingVolume instanceof TileBoundingRegion)) {
  43. // Do not support if the parent and child both do not have oriented bounding boxes.
  44. tile._optimChildrenWithinParent = Cesium3DTileOptimizationHint.SKIP_OPTIMIZATION;
  45. break;
  46. }
  47. var childOrientedBoundingBox = childBoundingVolume._orientedBoundingBox;
  48. // Compute the axis from the parent to the child.
  49. var axis = Cartesian3.subtract(childOrientedBoundingBox.center, orientedBoundingBox.center, scratchAxis);
  50. var axisLength = Cartesian3.magnitude(axis);
  51. Cartesian3.divideByScalar(axis, axisLength, axis);
  52. // Project the bounding box of the parent onto the axis. Because the axis is a ray from the parent
  53. // to the child, the projection parameterized along the ray will be (+/- proj1).
  54. var proj1 = Math.abs(orientedBoundingBox.halfAxes[0] * axis.x) +
  55. Math.abs(orientedBoundingBox.halfAxes[1] * axis.y) +
  56. Math.abs(orientedBoundingBox.halfAxes[2] * axis.z) +
  57. Math.abs(orientedBoundingBox.halfAxes[3] * axis.x) +
  58. Math.abs(orientedBoundingBox.halfAxes[4] * axis.y) +
  59. Math.abs(orientedBoundingBox.halfAxes[5] * axis.z) +
  60. Math.abs(orientedBoundingBox.halfAxes[6] * axis.x) +
  61. Math.abs(orientedBoundingBox.halfAxes[7] * axis.y) +
  62. Math.abs(orientedBoundingBox.halfAxes[8] * axis.z);
  63. // Project the bounding box of the child onto the axis. Because the axis is a ray from the parent
  64. // to the child, the projection parameterized along the ray will be (+/- proj2) + axis.length.
  65. var proj2 = Math.abs(childOrientedBoundingBox.halfAxes[0] * axis.x) +
  66. Math.abs(childOrientedBoundingBox.halfAxes[1] * axis.y) +
  67. Math.abs(childOrientedBoundingBox.halfAxes[2] * axis.z) +
  68. Math.abs(childOrientedBoundingBox.halfAxes[3] * axis.x) +
  69. Math.abs(childOrientedBoundingBox.halfAxes[4] * axis.y) +
  70. Math.abs(childOrientedBoundingBox.halfAxes[5] * axis.z) +
  71. Math.abs(childOrientedBoundingBox.halfAxes[6] * axis.x) +
  72. Math.abs(childOrientedBoundingBox.halfAxes[7] * axis.y) +
  73. Math.abs(childOrientedBoundingBox.halfAxes[8] * axis.z);
  74. // If the child extends the parent's bounds, the optimization is not valid and we skip it.
  75. if (proj1 <= proj2 + axisLength) {
  76. tile._optimChildrenWithinParent = Cesium3DTileOptimizationHint.SKIP_OPTIMIZATION;
  77. break;
  78. }
  79. }
  80. }
  81. return tile._optimChildrenWithinParent === Cesium3DTileOptimizationHint.USE_OPTIMIZATION;
  82. };
  83. export default Cesium3DTileOptimizations;