Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Oriented bounding box & frustum culling optimizations #2782

Merged
merged 31 commits into from
Jun 25, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
dfebc12
Replace .intersect(Cartesian4) with .intersectPlane(Plane)
kainino0x Jun 9, 2015
2e81e95
Fix for ObjectOrientedBoundingBox.equals
kainino0x Jun 3, 2015
f2800c4
Add Matrix2/3/4.ZERO for zero matrices
kainino0x Jun 3, 2015
4d686ee
Add Matrix2/3.multiplyByScale and a Matrix4.multiplyByScale test
kainino0x Jun 8, 2015
33a16c2
Add EllipsoidTangentPlane.projectPoint(s)ToNearestOnPlane
kainino0x Jun 10, 2015
0195ffa
Implement/test new OrientedBoundingBox
kainino0x Jun 3, 2015
69a9ab7
Deprecate ObjectOrientedBoundingBox
kainino0x Jun 3, 2015
3e68548
Add EllipsoidTangentPlane.extentsToOrientedBoundingBox
kainino0x Jun 10, 2015
09a847b
[WIP] Frustum-OBB culling on terrain - TODO: testing, benchmarks
kainino0x Jun 10, 2015
3f1a58e
Fixups for pull request
kainino0x Jun 10, 2015
931aa62
Move terrain bounding volume debug draw from Scene.js to GlobeSurface…
kainino0x Jun 13, 2015
d46b526
Additional OrientedBoundingBox.fromEllipsoidRectangle test
kainino0x Jun 13, 2015
4408e9f
fromEllipsoidRectangle fixup
kainino0x Jun 15, 2015
bc1c9e6
Rename fromEllipsoidRectangle to fromRectangle and reorder arguments
kainino0x Jun 15, 2015
c1c6a66
OBB intersectPlane: lower-level computation for perf
kainino0x Jun 15, 2015
1c23c4b
OBB fromRectangle: more invalid rectangle tests
kainino0x Jun 15, 2015
fc0ab82
OBB fromRectangle: require ellipsoid of revolution, at least for now
kainino0x Jun 16, 2015
3604485
OBB fromRectangle: change tangent plane for equator-spanning case, ad…
kainino0x Jun 16, 2015
d908de2
OBB fromRectangle: More similar tests
kainino0x Jun 16, 2015
58d06b9
OBB fromRectangle: more tests and fix another typo
kainino0x Jun 16, 2015
6510aff
Sync with master
kainino0x Jun 16, 2015
3da7263
Sync with master
kainino0x Jun 17, 2015
e183089
Hopefully-better debug volume render code
kainino0x Jun 17, 2015
8148cc1
Compute OrientedBoundingBoxes for upsampled terrain
kainino0x Jun 17, 2015
2f520c6
Fix crash for debug drawing code
kainino0x Jun 18, 2015
fb64614
Add a comment about excluding skirts from OBBs
kainino0x Jun 18, 2015
0a712f6
Possible minor optimization for OBB.intersectPlane
kainino0x Jun 19, 2015
1cd0747
Tile debug volume display: add comment and rename functions to clarif…
kainino0x Jun 19, 2015
85fc36c
Add OBB performance note to CHANGES.md
kainino0x Jun 19, 2015
d6a7389
Use bounding boxes for heightmap terrain (including no terrain).
kainino0x Jun 19, 2015
37ae29a
Merge branch 'master' into oriented-bounding-box
kainino0x Jun 24, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please submit an issue for this and another for the OOBB class (for example, see #2724).

* 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).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since it's new, add a line like "Added OrientedBoundingBox which ..." explaining what it's for.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same for any other new functions or objects you added.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I do that for .intersectPlane even though it's pretty much the same as .intersect?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If they are basically the same, (and you already mentioned it in the deprecated section) then it's probably just noise for less-used functions like this. If it were a popular part of the API, I would have said otherwise.

### 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) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use deprecationWarning. See https://github.com/AnalyticalGraphicsInc/cesium/wiki/Deprecation-Guide.

Same comment throughout for anything else that is deprecated.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, I forgot about that.

Since AABB.prototype.intersect calls AABB.intersect, should I only add it in AABB.intersect?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is fine for this case.

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) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On core math types, we usually only have prototype versions of functions for things like clone and equals.

Do we need this? Is this because intersectPlane is being used polymorphically? If so, this is fine.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, intersectPlane is being used polymorphically in the frustum plane tests.

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