106 lines
5.5 KiB
JavaScript
106 lines
5.5 KiB
JavaScript
define([
|
|
'../Core/Cartesian3',
|
|
'../Core/Check',
|
|
'./Cesium3DTileOptimizationHint',
|
|
'./TileBoundingRegion',
|
|
'./TileOrientedBoundingBox'
|
|
], function(
|
|
Cartesian3,
|
|
Check,
|
|
Cesium3DTileOptimizationHint,
|
|
TileBoundingRegion,
|
|
TileOrientedBoundingBox) {
|
|
'use strict';
|
|
|
|
/**
|
|
* Utility functions for computing optimization hints for a {@link Cesium3DTileset}.
|
|
*
|
|
* @exports Cesium3DTileOptimizations
|
|
*
|
|
* @private
|
|
*/
|
|
var Cesium3DTileOptimizations = {};
|
|
|
|
var 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');
|
|
|
|
var children = tile.children;
|
|
var length = children.length;
|
|
|
|
// Check if the parent has an oriented bounding box.
|
|
var boundingVolume = tile.boundingVolume;
|
|
if (boundingVolume instanceof TileOrientedBoundingBox || boundingVolume instanceof TileBoundingRegion) {
|
|
var orientedBoundingBox = boundingVolume._orientedBoundingBox;
|
|
tile._optimChildrenWithinParent = Cesium3DTileOptimizationHint.USE_OPTIMIZATION;
|
|
for (var i = 0; i < length; ++i) {
|
|
var child = children[i];
|
|
|
|
// Check if the child has an oriented bounding box.
|
|
var 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;
|
|
}
|
|
|
|
var childOrientedBoundingBox = childBoundingVolume._orientedBoundingBox;
|
|
|
|
// Compute the axis from the parent to the child.
|
|
var axis = Cartesian3.subtract(childOrientedBoundingBox.center, orientedBoundingBox.center, scratchAxis);
|
|
var 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).
|
|
var 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.
|
|
var 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;
|
|
};
|
|
|
|
return Cesium3DTileOptimizations;
|
|
});
|