@cesium/engine
Version:
CesiumJS is a JavaScript library for creating 3D globes and 2D maps in a web browser without a plugin.
116 lines (103 loc) • 4.99 kB
JavaScript
import Cartesian3 from "../Core/Cartesian3.js";
import Check from "../Core/Check.js";
import Cesium3DTileOptimizationHint from "./Cesium3DTileOptimizationHint.js";
import TileBoundingRegion from "./TileBoundingRegion.js";
import TileOrientedBoundingBox from "./TileOrientedBoundingBox.js";
/**
* Utility functions for computing optimization hints for a {@link Cesium3DTileset}.
*
* @namespace Cesium3DTileOptimizations
*
* @private
*/
const Cesium3DTileOptimizations = {};
const scratchAxis = new Cartesian3();
/**
* Evaluates support for the childrenWithinParent optimization. This is used to more tightly cull tilesets if
* children bounds are fully contained within the parent. Currently, support for the optimization only works for
* oriented bounding boxes, so both the child and parent tile must be either a {@link TileOrientedBoundingBox} or
* {@link TileBoundingRegion}. The purpose of this check is to prevent use of a culling optimization when the child
* bounds exceed those of the parent. If the child bounds are greater, it is more likely that the optimization will
* waste CPU cycles. Bounding spheres are not supported for the reason that the child bounds can very often be
* partially outside of the parent bounds.
*
* @param {Cesium3DTile} tile The tile to check.
* @returns {boolean} Whether the childrenWithinParent optimization is supported.
*/
Cesium3DTileOptimizations.checkChildrenWithinParent = function (tile) {
//>>includeStart('debug', pragmas.debug);
Check.typeOf.object("tile", tile);
//>>includeEnd('debug');
const children = tile.children;
const length = children.length;
// Check if the parent has an oriented bounding box.
const boundingVolume = tile.boundingVolume;
if (
boundingVolume instanceof TileOrientedBoundingBox ||
boundingVolume instanceof TileBoundingRegion
) {
const orientedBoundingBox = boundingVolume._orientedBoundingBox;
tile._optimChildrenWithinParent =
Cesium3DTileOptimizationHint.USE_OPTIMIZATION;
for (let i = 0; i < length; ++i) {
const child = children[i];
// Check if the child has an oriented bounding box.
const childBoundingVolume = child.boundingVolume;
if (
!(
childBoundingVolume instanceof TileOrientedBoundingBox ||
childBoundingVolume instanceof TileBoundingRegion
)
) {
// Do not support if the parent and child both do not have oriented bounding boxes.
tile._optimChildrenWithinParent =
Cesium3DTileOptimizationHint.SKIP_OPTIMIZATION;
break;
}
const childOrientedBoundingBox = childBoundingVolume._orientedBoundingBox;
// Compute the axis from the parent to the child.
const axis = Cartesian3.subtract(
childOrientedBoundingBox.center,
orientedBoundingBox.center,
scratchAxis,
);
const axisLength = Cartesian3.magnitude(axis);
Cartesian3.divideByScalar(axis, axisLength, axis);
// Project the bounding box of the parent onto the axis. Because the axis is a ray from the parent
// to the child, the projection parameterized along the ray will be (+/- proj1).
const proj1 =
Math.abs(orientedBoundingBox.halfAxes[0] * axis.x) +
Math.abs(orientedBoundingBox.halfAxes[1] * axis.y) +
Math.abs(orientedBoundingBox.halfAxes[2] * axis.z) +
Math.abs(orientedBoundingBox.halfAxes[3] * axis.x) +
Math.abs(orientedBoundingBox.halfAxes[4] * axis.y) +
Math.abs(orientedBoundingBox.halfAxes[5] * axis.z) +
Math.abs(orientedBoundingBox.halfAxes[6] * axis.x) +
Math.abs(orientedBoundingBox.halfAxes[7] * axis.y) +
Math.abs(orientedBoundingBox.halfAxes[8] * axis.z);
// Project the bounding box of the child onto the axis. Because the axis is a ray from the parent
// to the child, the projection parameterized along the ray will be (+/- proj2) + axis.length.
const proj2 =
Math.abs(childOrientedBoundingBox.halfAxes[0] * axis.x) +
Math.abs(childOrientedBoundingBox.halfAxes[1] * axis.y) +
Math.abs(childOrientedBoundingBox.halfAxes[2] * axis.z) +
Math.abs(childOrientedBoundingBox.halfAxes[3] * axis.x) +
Math.abs(childOrientedBoundingBox.halfAxes[4] * axis.y) +
Math.abs(childOrientedBoundingBox.halfAxes[5] * axis.z) +
Math.abs(childOrientedBoundingBox.halfAxes[6] * axis.x) +
Math.abs(childOrientedBoundingBox.halfAxes[7] * axis.y) +
Math.abs(childOrientedBoundingBox.halfAxes[8] * axis.z);
// If the child extends the parent's bounds, the optimization is not valid and we skip it.
if (proj1 <= proj2 + axisLength) {
tile._optimChildrenWithinParent =
Cesium3DTileOptimizationHint.SKIP_OPTIMIZATION;
break;
}
}
}
return (
tile._optimChildrenWithinParent ===
Cesium3DTileOptimizationHint.USE_OPTIMIZATION
);
};
export default Cesium3DTileOptimizations;