Skip to content

Commit

Permalink
Merge pull request #2782 from kainino0x/oriented-bounding-box
Browse files Browse the repository at this point in the history
Oriented bounding box & frustum culling optimizations
  • Loading branch information
pjcozzi committed Jun 25, 2015
2 parents e0f1a72 + 37ae29a commit 22f7dfc
Show file tree
Hide file tree
Showing 32 changed files with 1,655 additions and 79 deletions.
14 changes: 14 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ Change Log
==========

### 1.11 - 2015-07-01

* Deprecated
* The STK World Terrain url `cesiumjs.org/stk-terrain/world` has been deprecated, use `assets.agi.com/stk-terrain/world` instead. A redirect will be in place until 1.14.
* Deprecated `AxisAlignedBoundingBox.intersect` and `BoundingSphere.intersect`. These will be removed in 1.13. Use `.intersectPlane` and, if necessary, `Plane.fromCartesian4`.
* Deprecated the `ObjectOrientedBoundingBox` class. It will be removed in 1.12. Use `OrientedBoundingBox` instead.
* Improved the algorithm that `Camera.viewRectangle` uses to select the position of the camera, so that the specified rectangle is now better centered on the screen [#2764](https://github.com/AnalyticalGraphicsInc/cesium/issues/2764).
* The performance statistics displayed by setting `scene.debugShowFramesPerSecond` to `true` can now be styled using the `cesium-performanceDisplay` CSS classes in `shared.css` [#2779](https://github.com/AnalyticalGraphicsInc/cesium/issues/2779).
* Fixed a crash when `viewer.zoomTo` or `viewer.flyTo` were called immediately before or during a scene morph [#2775](https://github.com/AnalyticalGraphicsInc/cesium/issues/2775).
Expand All @@ -14,6 +17,17 @@ Change Log
* The camera now zooms to the point under the mouse cursor.
* Fixed a bug in `ImageryLayer` that could cause an exception and the render loop to stop when the base layer did not cover the entire globe.
* Fixed flash/streak rendering artifacts when picking [#2790](https://github.com/AnalyticalGraphicsInc/cesium/issues/2790), [#2811](https://github.com/AnalyticalGraphicsInc/cesium/issues/2811).
* Added `Plane.fromCartesian4` to convert old `Cartesian4` plane representations to the new `Plane` format.
* Added `Plane.ORIGIN_XY_PLANE`/`ORIGIN_YZ_PLANE`/`ORIGIN_ZX_PLANE` constants for commonly-used planes.
* Added `Matrix2`/`Matrix3`/`Matrix4.ZERO` constants for zero matrices.
* Added `Matrix2`/`Matrix3.multiplyByScale` for multiplying against non-uniform scales.
* Added `projectPointToNearestOnPlane` and `projectPointsToNearestOnPlane` to `EllipsoidTangentPlane` to project 3D points to the nearest 2D point on an `EllipsoidTangentPlane`.
* Added `OrientedBoundingBox` class.
* Added `EllipsoidTangentPlane.plane` property to get the `Plane` for the tangent plane.
* Added `EllipsoidTangentPlane.xAxis`/`yAxis`/`zAxis` properties to get the local coordinate system of the tangent plane.
* Add `QuantizedMeshTerrainData` constructor argument `orientedBoundingBox`.
* Add `TerrainMesh.orientedBoundingBox` which holds the `OrientedBoundingBox` for the mesh for a single terrain tile.
* Use `OrientedBoundingBox` when rendering terrain and imagery to improve performance of rendering and loading (by up to 50% of terrain/imagery tiles, depending on camera view).

### 1.10 - 2015-06-01

Expand Down
53 changes: 45 additions & 8 deletions Source/Core/AxisAlignedBoundingBox.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@ define([
'./Cartesian3',
'./defaultValue',
'./defined',
'./deprecationWarning',
'./DeveloperError',
'./Intersect'
'./Intersect',
'./Plane'
], function(
Cartesian3,
defaultValue,
defined,
deprecationWarning,
DeveloperError,
Intersect) {
Intersect,
Plane) {
"use strict";

/**
Expand Down Expand Up @@ -162,15 +166,13 @@ define([
* Determines which side of a plane a box is located.
*
* @param {AxisAlignedBoundingBox} box The bounding box to test.
* @param {Cartesian4} plane The coefficients of the plane in the form <code>ax + by + cz + d = 0</code>
* where the coefficients a, b, c, and d are the components x, y, z, and w
* of the {@link Cartesian4}, respectively.
* @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.
*/
AxisAlignedBoundingBox.intersect = function(box, plane) {
AxisAlignedBoundingBox.intersectPlane = function(box, plane) {
//>>includeStart('debug', pragmas.debug);
if (!defined(box)) {
throw new DeveloperError('box is required.');
Expand All @@ -182,8 +184,9 @@ define([

intersectScratch = Cartesian3.subtract(box.maximum, box.minimum, intersectScratch);
var h = Cartesian3.multiplyByScalar(intersectScratch, 0.5, intersectScratch); //The positive half diagonal
var e = h.x * Math.abs(plane.x) + h.y * Math.abs(plane.y) + h.z * Math.abs(plane.z);
var s = Cartesian3.dot(box.center, plane) + plane.w; //signed distance from center
var normal = plane.normal;
var e = h.x * Math.abs(normal.x) + h.y * Math.abs(normal.y) + h.z * Math.abs(normal.z);
var s = Cartesian3.dot(box.center, normal) + plane.distance; //signed distance from center

if (s - e > 0) {
return Intersect.INSIDE;
Expand All @@ -197,6 +200,26 @@ define([
return Intersect.INTERSECTING;
};

var scratchPlane = new Plane(new Cartesian3(), 0.0);
/**
* Determines which side of a plane a box is located.
*
* @deprecated
* @param {AxisAlignedBoundingBox} box The bounding box to test.
* @param {Cartesian4} plane The coefficients of the plane in the form <code>ax + by + cz + d = 0</code>
* where the coefficients a, b, c, and d are the components x, y, z, and w
* of the {@link Cartesian4}, respectively.
* @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.
*/
AxisAlignedBoundingBox.intersect = function(box, plane) {
deprecationWarning('AxisAlignedBoundingBox.intersect', 'AxisAlignedBoundingBox.intersect() was deprecated in Cesium 1.11. It will be removed in 1.12. Use AxisAlignedBoundingBox.intersectPlane() instead.');
var p = Plane.fromCartesian4(plane, scratchPlane);
return AxisAlignedBoundingBox.intersectPlane(box, p);
};

/**
* Duplicates this AxisAlignedBoundingBox instance.
*
Expand All @@ -210,6 +233,20 @@ define([
/**
* 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.
*/
AxisAlignedBoundingBox.prototype.intersectPlane = function(plane) {
return AxisAlignedBoundingBox.intersectPlane(this, plane);
};

/**
* Determines which side of a plane this box is located.
*
* @deprecated
* @param {Cartesian4} plane The coefficients of the plane in the form <code>ax + by + cz + d = 0</code>
* where the coefficients a, b, c, and d are the components x, y, z, and w
* of the {@link Cartesian4}, respectively.
Expand Down
49 changes: 43 additions & 6 deletions Source/Core/BoundingSphere.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,28 @@ define([
'./Cartographic',
'./defaultValue',
'./defined',
'./deprecationWarning',
'./DeveloperError',
'./Ellipsoid',
'./GeographicProjection',
'./Intersect',
'./Interval',
'./Matrix4',
'./Plane',
'./Rectangle'
], function(
Cartesian3,
Cartographic,
defaultValue,
defined,
deprecationWarning,
DeveloperError,
Ellipsoid,
GeographicProjection,
Intersect,
Interval,
Matrix4,
Plane,
Rectangle) {
"use strict";

Expand Down Expand Up @@ -742,16 +746,13 @@ define([
* Determines which side of a plane a sphere is located.
*
* @param {BoundingSphere} sphere The bounding sphere to test.
* @param {Cartesian4} plane The coefficients of the plane in Hessian Normal Form, as `ax + by + cz + d = 0`,
* where (a, b, c) must be a unit normal vector.
* The coefficients a, b, c, and d are the components x, y, z,
* and w of the {@link Cartesian4}, respectively.
* @param {Plane} plane The plane to test against.
* @returns {Intersect} {@link Intersect.INSIDE} if the entire sphere is on the side of the plane
* the normal is pointing, {@link Intersect.OUTSIDE} if the entire sphere is
* on the opposite side, and {@link Intersect.INTERSECTING} if the sphere
* intersects the plane.
*/
BoundingSphere.intersect = function(sphere, plane) {
BoundingSphere.intersectPlane = function(sphere, plane) {
//>>includeStart('debug', pragmas.debug);
if (!defined(sphere)) {
throw new DeveloperError('sphere is required.');
Expand All @@ -764,7 +765,8 @@ define([

var center = sphere.center;
var radius = sphere.radius;
var distanceToPlane = Cartesian3.dot(plane, center) + plane.w;
var normal = plane.normal;
var distanceToPlane = Cartesian3.dot(normal, center) + plane.distance;

if (distanceToPlane < -radius) {
// The center point is negative side of the plane normal
Expand All @@ -776,6 +778,27 @@ define([
return Intersect.INSIDE;
};

var scratchPlane = new Plane(new Cartesian3(), 0.0);
/**
* Determines which side of a plane a sphere is located.
*
* @deprecated
* @param {BoundingSphere} sphere The bounding sphere to test.
* @param {Cartesian4} plane The coefficients of the plane in Hessian Normal Form, as `ax + by + cz + d = 0`,
* where (a, b, c) must be a unit normal vector.
* The coefficients a, b, c, and d are the components x, y, z,
* and w of the {@link Cartesian4}, respectively.
* @returns {Intersect} {@link Intersect.INSIDE} if the entire sphere is on the side of the plane
* the normal is pointing, {@link Intersect.OUTSIDE} if the entire sphere is
* on the opposite side, and {@link Intersect.INTERSECTING} if the sphere
* intersects the plane.
*/
BoundingSphere.intersect = function(sphere, plane) {
deprecationWarning('BoundingSphere.intersect', 'BoundingSphere.intersect() was deprecated in Cesium 1.11. It will be removed in 1.12. Use BoundingSphere.intersectPlane() instead.');
var p = Plane.fromCartesian4(plane, scratchPlane);
return BoundingSphere.intersectPlane(sphere, p);
};

/**
* Applies a 4x4 affine transformation matrix to a bounding sphere.
*
Expand Down Expand Up @@ -1042,6 +1065,20 @@ define([
/**
* Determines which side of a plane the sphere is located.
*
* @param {Plane} plane The plane to test against.
* @returns {Intersect} {@link Intersect.INSIDE} if the entire sphere is on the side of the plane
* the normal is pointing, {@link Intersect.OUTSIDE} if the entire sphere is
* on the opposite side, and {@link Intersect.INTERSECTING} if the sphere
* intersects the plane.
*/
BoundingSphere.prototype.intersectPlane = function(plane) {
return BoundingSphere.intersectPlane(this, plane);
};

/**
* Determines which side of a plane the sphere is located.
*
* @deprecated
* @param {Cartesian4} plane The coefficients of the plane in the for ax + by + cz + d = 0
* where the coefficients a, b, c, and d are the components x, y, z,
* and w of the {@link Cartesian4}, respectively.
Expand Down
23 changes: 22 additions & 1 deletion Source/Core/CesiumTerrainProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ define([
'./IndexDatatype',
'./loadArrayBuffer',
'./loadJson',
'./Math',
'./Matrix3',
'./OrientedBoundingBox',
'./QuantizedMeshTerrainData',
'./RuntimeError',
'./TerrainProvider',
Expand All @@ -38,6 +41,9 @@ define([
IndexDatatype,
loadArrayBuffer,
loadJson,
CesiumMath,
Matrix3,
OrientedBoundingBox,
QuantizedMeshTerrainData,
RuntimeError,
TerrainProvider,
Expand Down Expand Up @@ -417,11 +423,26 @@ define([

var skirtHeight = provider.getLevelMaximumGeometricError(level) * 5.0;

var rectangle = provider._tilingScheme.tileXYToRectangle(x, y, level);
var orientedBoundingBox;
if (rectangle.width < CesiumMath.PI_OVER_TWO + CesiumMath.EPSILON5) {
// Here, rectangle.width < pi/2, and rectangle.height < pi
// (though it would still work with rectangle.width up to pi)

// The skirt is not included in the OBB computation. If this ever
// causes any rendering artifacts (cracks), they are expected to be
// minor and in the corners of the screen. It's possible that this
// might need to be changed - just change to `minimumHeight - skirtHeight`
// A similar change might also be needed in `upsampleQuantizedTerrainMesh.js`.
orientedBoundingBox = OrientedBoundingBox.fromRectangle(rectangle, minimumHeight, maximumHeight, provider._tilingScheme.ellipsoid);
}

return new QuantizedMeshTerrainData({
center : center,
minimumHeight : minimumHeight,
maximumHeight : maximumHeight,
boundingSphere : boundingSphere,
orientedBoundingBox : orientedBoundingBox,
horizonOcclusionPoint : horizonOcclusionPoint,
quantizedVertices : encodedVertexBuffer,
encodedNormals : encodedNormalBuffer,
Expand Down Expand Up @@ -713,4 +734,4 @@ define([
};

return CesiumTerrainProvider;
});
});
Loading

0 comments on commit 22f7dfc

Please sign in to comment.