You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
216 lines
6.8 KiB
JavaScript
216 lines
6.8 KiB
JavaScript
import BoundingSphere from "../Core/BoundingSphere.js";
|
|
import BoxOutlineGeometry from "../Core/BoxOutlineGeometry.js";
|
|
import Cartesian3 from "../Core/Cartesian3.js";
|
|
import Check from "../Core/Check.js";
|
|
import ColorGeometryInstanceAttribute from "../Core/ColorGeometryInstanceAttribute.js";
|
|
import GeometryInstance from "../Core/GeometryInstance.js";
|
|
import Matrix3 from "../Core/Matrix3.js";
|
|
import Matrix4 from "../Core/Matrix4.js";
|
|
import CesiumMath from "../Core/Math.js";
|
|
import OrientedBoundingBox from "../Core/OrientedBoundingBox.js";
|
|
import PerInstanceColorAppearance from "./PerInstanceColorAppearance.js";
|
|
import Primitive from "./Primitive.js";
|
|
|
|
var scratchU = new Cartesian3();
|
|
var scratchV = new Cartesian3();
|
|
var scratchW = new Cartesian3();
|
|
var scratchCartesian = new Cartesian3();
|
|
|
|
function computeMissingVector(a, b, result) {
|
|
result = Cartesian3.cross(a, b, result);
|
|
var magnitude = Cartesian3.magnitude(result);
|
|
return Cartesian3.multiplyByScalar(
|
|
result,
|
|
CesiumMath.EPSILON7 / magnitude,
|
|
result
|
|
);
|
|
}
|
|
|
|
function findOrthogonalVector(a, result) {
|
|
var temp = Cartesian3.normalize(a, scratchCartesian);
|
|
var b = Cartesian3.equalsEpsilon(temp, Cartesian3.UNIT_X, CesiumMath.EPSILON6)
|
|
? Cartesian3.UNIT_Y
|
|
: Cartesian3.UNIT_X;
|
|
return computeMissingVector(a, b, result);
|
|
}
|
|
|
|
function checkHalfAxes(halfAxes) {
|
|
var u = Matrix3.getColumn(halfAxes, 0, scratchU);
|
|
var v = Matrix3.getColumn(halfAxes, 1, scratchV);
|
|
var w = Matrix3.getColumn(halfAxes, 2, scratchW);
|
|
|
|
var uZero = Cartesian3.equals(u, Cartesian3.ZERO);
|
|
var vZero = Cartesian3.equals(v, Cartesian3.ZERO);
|
|
var wZero = Cartesian3.equals(w, Cartesian3.ZERO);
|
|
|
|
if (!uZero && !vZero && !wZero) {
|
|
return halfAxes;
|
|
}
|
|
if (uZero && vZero && wZero) {
|
|
halfAxes[0] = CesiumMath.EPSILON7;
|
|
halfAxes[4] = CesiumMath.EPSILON7;
|
|
halfAxes[8] = CesiumMath.EPSILON7;
|
|
return halfAxes;
|
|
}
|
|
if (uZero && !vZero && !wZero) {
|
|
u = computeMissingVector(v, w, u);
|
|
} else if (!uZero && vZero && !wZero) {
|
|
v = computeMissingVector(u, w, v);
|
|
} else if (!uZero && !vZero && wZero) {
|
|
w = computeMissingVector(v, u, w);
|
|
} else if (!uZero) {
|
|
v = findOrthogonalVector(u, v);
|
|
w = computeMissingVector(v, u, w);
|
|
} else if (!vZero) {
|
|
u = findOrthogonalVector(v, u);
|
|
w = computeMissingVector(v, u, w);
|
|
} else if (!wZero) {
|
|
u = findOrthogonalVector(w, u);
|
|
v = computeMissingVector(w, u, v);
|
|
}
|
|
|
|
Matrix3.setColumn(halfAxes, 0, u, halfAxes);
|
|
Matrix3.setColumn(halfAxes, 1, v, halfAxes);
|
|
Matrix3.setColumn(halfAxes, 2, w, halfAxes);
|
|
|
|
return halfAxes;
|
|
}
|
|
|
|
/**
|
|
* A tile bounding volume specified as an oriented bounding box.
|
|
* @alias TileOrientedBoundingBox
|
|
* @constructor
|
|
*
|
|
* @param {Cartesian3} [center=Cartesian3.ZERO] The center of the box.
|
|
* @param {Matrix3} [halfAxes=Matrix3.ZERO] The three orthogonal half-axes of the bounding box.
|
|
* Equivalently, the transformation matrix, to rotate and scale a 2x2x2
|
|
* cube centered at the origin.
|
|
*
|
|
* @private
|
|
*/
|
|
function TileOrientedBoundingBox(center, halfAxes) {
|
|
halfAxes = checkHalfAxes(halfAxes);
|
|
this._orientedBoundingBox = new OrientedBoundingBox(center, halfAxes);
|
|
this._boundingSphere = BoundingSphere.fromOrientedBoundingBox(
|
|
this._orientedBoundingBox
|
|
);
|
|
}
|
|
|
|
Object.defineProperties(TileOrientedBoundingBox.prototype, {
|
|
/**
|
|
* The underlying bounding volume.
|
|
*
|
|
* @memberof TileOrientedBoundingBox.prototype
|
|
*
|
|
* @type {Object}
|
|
* @readonly
|
|
*/
|
|
boundingVolume: {
|
|
get: function () {
|
|
return this._orientedBoundingBox;
|
|
},
|
|
},
|
|
/**
|
|
* The underlying bounding sphere.
|
|
*
|
|
* @memberof TileOrientedBoundingBox.prototype
|
|
*
|
|
* @type {BoundingSphere}
|
|
* @readonly
|
|
*/
|
|
boundingSphere: {
|
|
get: function () {
|
|
return this._boundingSphere;
|
|
},
|
|
},
|
|
});
|
|
|
|
/**
|
|
* Computes the distance between this bounding box and the camera attached to frameState.
|
|
*
|
|
* @param {FrameState} frameState The frameState to which the camera is attached.
|
|
* @returns {Number} The distance between the camera and the bounding box in meters. Returns 0 if the camera is inside the bounding volume.
|
|
*/
|
|
TileOrientedBoundingBox.prototype.distanceToCamera = function (frameState) {
|
|
//>>includeStart('debug', pragmas.debug);
|
|
Check.defined("frameState", frameState);
|
|
//>>includeEnd('debug');
|
|
return Math.sqrt(
|
|
this._orientedBoundingBox.distanceSquaredTo(frameState.camera.positionWC)
|
|
);
|
|
};
|
|
|
|
/**
|
|
* Determines which side of a plane this box is located.
|
|
*
|
|
* @param {Plane} plane The plane to test against.
|
|
* @returns {Intersect} {@link Intersect.INSIDE} if the entire box is on the side of the plane
|
|
* the normal is pointing, {@link Intersect.OUTSIDE} if the entire box is
|
|
* on the opposite side, and {@link Intersect.INTERSECTING} if the box
|
|
* intersects the plane.
|
|
*/
|
|
TileOrientedBoundingBox.prototype.intersectPlane = function (plane) {
|
|
//>>includeStart('debug', pragmas.debug);
|
|
Check.defined("plane", plane);
|
|
//>>includeEnd('debug');
|
|
return this._orientedBoundingBox.intersectPlane(plane);
|
|
};
|
|
|
|
/**
|
|
* Update the bounding box after the tile is transformed.
|
|
*
|
|
* @param {Cartesian3} center The center of the box.
|
|
* @param {Matrix3} halfAxes The three orthogonal half-axes of the bounding box.
|
|
* Equivalently, the transformation matrix, to rotate and scale a 2x2x2
|
|
* cube centered at the origin.
|
|
*/
|
|
TileOrientedBoundingBox.prototype.update = function (center, halfAxes) {
|
|
Cartesian3.clone(center, this._orientedBoundingBox.center);
|
|
halfAxes = checkHalfAxes(halfAxes);
|
|
Matrix3.clone(halfAxes, this._orientedBoundingBox.halfAxes);
|
|
BoundingSphere.fromOrientedBoundingBox(
|
|
this._orientedBoundingBox,
|
|
this._boundingSphere
|
|
);
|
|
};
|
|
|
|
/**
|
|
* Creates a debug primitive that shows the outline of the box.
|
|
*
|
|
* @param {Color} color The desired color of the primitive's mesh
|
|
* @return {Primitive}
|
|
*/
|
|
TileOrientedBoundingBox.prototype.createDebugVolume = function (color) {
|
|
//>>includeStart('debug', pragmas.debug);
|
|
Check.defined("color", color);
|
|
//>>includeEnd('debug');
|
|
|
|
var geometry = new BoxOutlineGeometry({
|
|
// Make a 2x2x2 cube
|
|
minimum: new Cartesian3(-1.0, -1.0, -1.0),
|
|
maximum: new Cartesian3(1.0, 1.0, 1.0),
|
|
});
|
|
var modelMatrix = Matrix4.fromRotationTranslation(
|
|
this.boundingVolume.halfAxes,
|
|
this.boundingVolume.center
|
|
);
|
|
var instance = new GeometryInstance({
|
|
geometry: geometry,
|
|
id: "outline",
|
|
modelMatrix: modelMatrix,
|
|
attributes: {
|
|
color: ColorGeometryInstanceAttribute.fromColor(color),
|
|
},
|
|
});
|
|
|
|
return new Primitive({
|
|
geometryInstances: instance,
|
|
appearance: new PerInstanceColorAppearance({
|
|
translucent: false,
|
|
flat: true,
|
|
}),
|
|
asynchronous: false,
|
|
});
|
|
};
|
|
export default TileOrientedBoundingBox;
|