Skip to content

Commit

Permalink
Merge pull request #4932 from austinEng/frustum-debug
Browse files Browse the repository at this point in the history
Add multifrustum near/far planes to DebugCameraPrimitive
  • Loading branch information
lilleyse authored Feb 2, 2017
2 parents b6b3ad2 + 9d28ee1 commit b6afe7e
Show file tree
Hide file tree
Showing 6 changed files with 189 additions and 23 deletions.
2 changes: 1 addition & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Change Log
==========

### 1.31 - 2017-03-01

* Added support to `DebugCameraPrimitive` to draw multifrustum planes. The attribute `debugShowFrustumPlanes` of `Scene` and `frustumPlanes` of `CesiumInspector` toggles this. `FrameState` has been augmented to include `frustumSplits` which is a `Number[]` of the near/far planes of the camera frustums.
* Enable rendering `GroundPrimitives` on hardware without the `EXT_frag_depth` extension; however, this could cause artifacts for certain viewing angles.
* Added compressed texture support. [#4758](https://github.com/AnalyticalGraphicsInc/cesium/pull/4758)
* glTF models and imagery layers can now reference [KTX](https://www.khronos.org/opengles/sdk/tools/KTX/) textures and textures compressed with [crunch](https://github.com/BinomialLLC/crunch).
Expand Down
135 changes: 113 additions & 22 deletions Source/Scene/DebugCameraPrimitive.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,24 +92,20 @@ define([
this._planesPrimitive = undefined;
}

var frustumCornersNDC = new Array(8);
frustumCornersNDC[0] = new Cartesian4(-1.0, -1.0, -1.0, 1.0);
frustumCornersNDC[1] = new Cartesian4(1.0, -1.0, -1.0, 1.0);
frustumCornersNDC[2] = new Cartesian4(1.0, 1.0, -1.0, 1.0);
frustumCornersNDC[3] = new Cartesian4(-1.0, 1.0, -1.0, 1.0);
frustumCornersNDC[4] = new Cartesian4(-1.0, -1.0, 1.0, 1.0);
frustumCornersNDC[5] = new Cartesian4(1.0, -1.0, 1.0, 1.0);
frustumCornersNDC[6] = new Cartesian4(1.0, 1.0, 1.0, 1.0);
frustumCornersNDC[7] = new Cartesian4(-1.0, 1.0, 1.0, 1.0);
var frustumCornersNDC = new Array(4);
frustumCornersNDC[0] = new Cartesian4(-1.0, -1.0, 1.0, 1.0);
frustumCornersNDC[1] = new Cartesian4(1.0, -1.0, 1.0, 1.0);
frustumCornersNDC[2] = new Cartesian4(1.0, 1.0, 1.0, 1.0);
frustumCornersNDC[3] = new Cartesian4(-1.0, 1.0, 1.0, 1.0);

var scratchMatrix = new Matrix4();
var scratchFrustumCorners = new Array(8);
for (var i = 0; i < 8; ++i) {
var scratchFrustumCorners = new Array(4);
for (var i = 0; i < 4; ++i) {
scratchFrustumCorners[i] = new Cartesian4();
}

var scratchColor = new Color();

var scratchSplits = [1.0, 100000.0];
/**
* @private
*/
Expand All @@ -130,14 +126,34 @@ define([
var viewProjection = Matrix4.multiply(projection, view, scratchMatrix);
var inverseViewProjection = Matrix4.inverse(viewProjection, scratchMatrix);

var positions = new Float64Array(8 * 3);
for (var i = 0; i < 8; ++i) {
var corner = Cartesian4.clone(frustumCornersNDC[i], scratchFrustumCorners[i]);
Matrix4.multiplyByVector(inverseViewProjection, corner, corner);
Cartesian3.divideByScalar(corner, corner.w, corner); // Handle the perspective divide
positions[i * 3] = corner.x;
positions[i * 3 + 1] = corner.y;
positions[i * 3 + 2] = corner.z;
var frustumSplits = frameState.frustumSplits;
var numFrustums = frustumSplits.length - 1;
if (numFrustums <= 0) {
frustumSplits = scratchSplits; // Use near and far planes if no splits created
frustumSplits[0] = this._camera.frustum.near;
frustumSplits[1] = this._camera.frustum.far;
numFrustums = 1;
}

var positions = new Float64Array(3 * 4 * (numFrustums + 1));
var f;
for (f = 0; f < numFrustums + 1; ++f) {
for (var i = 0; i < 4; ++i) {
var corner = Cartesian4.clone(frustumCornersNDC[i], scratchFrustumCorners[i]);

Matrix4.multiplyByVector(inverseViewProjection, corner, corner);
Cartesian3.divideByScalar(corner, corner.w, corner); // Handle the perspective divide
Cartesian3.subtract(corner, this._camera.positionWC, corner);
Cartesian3.normalize(corner, corner);

var fac = Cartesian3.dot(this._camera.directionWC, corner);
Cartesian3.multiplyByScalar(corner, frustumSplits[f] / fac, corner);
Cartesian3.add(corner, this._camera.positionWC, corner);

positions[12 * f + i * 3] = corner.x;
positions[12 * f + i * 3 + 1] = corner.y;
positions[12 * f + i * 3 + 2] = corner.z;
}
}

var boundingSphere = new BoundingSphere.fromVertices(positions);
Expand All @@ -149,8 +165,38 @@ define([
values : positions
});

var offset, index;

// Create the outline primitive
var outlineIndices = new Uint16Array([0,1,1,2,2,3,3,0,0,4,4,7,7,3,7,6,6,2,2,1,1,5,5,4,5,6]);
var outlineIndices = new Uint16Array(8 * (2 * numFrustums + 1));
// Build the far planes
for (f = 0; f < numFrustums + 1; ++f) {
offset = f * 8;
index = f * 4;

outlineIndices[offset] = index;
outlineIndices[offset + 1] = index + 1;
outlineIndices[offset + 2] = index + 1;
outlineIndices[offset + 3] = index + 2;
outlineIndices[offset + 4] = index + 2;
outlineIndices[offset + 5] = index + 3;
outlineIndices[offset + 6] = index + 3;
outlineIndices[offset + 7] = index;
}
// Build the sides of the frustums
for (f = 0; f < numFrustums; ++f) {
offset = (numFrustums + 1 + f) * 8;
index = f * 4;

outlineIndices[offset] = index;
outlineIndices[offset + 1] = index + 4;
outlineIndices[offset + 2] = index + 1;
outlineIndices[offset + 3] = index + 5;
outlineIndices[offset + 4] = index + 2;
outlineIndices[offset + 5] = index + 6;
outlineIndices[offset + 6] = index + 3;
outlineIndices[offset + 7] = index + 7;
}

this._outlinePrimitive = new Primitive({
geometryInstances : new GeometryInstance({
Expand All @@ -174,7 +220,52 @@ define([
});

// Create the planes primitive
var planesIndices = new Uint16Array([4,5,6,4,6,7,5,1,2,5,2,6,7,6,2,7,2,3,0,1,5,0,5,4,0,4,7,0,7,3,1,0,3,1,3,2]);
var planesIndices = new Uint16Array(6 * (5 * numFrustums + 1));
// Build the far planes
for (f = 0; f < numFrustums + 1; ++f) {
offset = f * 6;
index = f * 4;

planesIndices[offset] = index;
planesIndices[offset + 1] = index + 1;
planesIndices[offset + 2] = index + 2;
planesIndices[offset + 3] = index;
planesIndices[offset + 4] = index + 2;
planesIndices[offset + 5] = index + 3;
}
// Build the sides of the frustums
for (f = 0; f < numFrustums; ++f) {
offset = (numFrustums + 1 + 4 * f) * 6;
index = f * 4;

planesIndices[offset] = index + 4;
planesIndices[offset + 1] = index;
planesIndices[offset + 2] = index + 3;
planesIndices[offset + 3] = index + 4;
planesIndices[offset + 4] = index + 3;
planesIndices[offset + 5] = index + 7;

planesIndices[offset + 6] = index + 4;
planesIndices[offset + 7] = index;
planesIndices[offset + 8] = index + 1;
planesIndices[offset + 9] = index + 4;
planesIndices[offset + 10] = index + 1;
planesIndices[offset + 11] = index + 5;

planesIndices[offset + 12] = index + 7;
planesIndices[offset + 13] = index + 3;
planesIndices[offset + 14] = index + 2;
planesIndices[offset + 15] = index + 7;
planesIndices[offset + 16] = index + 2;
planesIndices[offset + 17] = index + 6;

planesIndices[offset + 18] = index + 6;
planesIndices[offset + 19] = index + 2;
planesIndices[offset + 20] = index + 1;
planesIndices[offset + 21] = index + 6;
planesIndices[offset + 22] = index + 1;
planesIndices[offset + 23] = index + 5;
}

this._planesPrimitive = new Primitive({
geometryInstances : new GeometryInstance({
Expand Down
7 changes: 7 additions & 0 deletions Source/Scene/FrameState.js
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,13 @@ define([
* @default 0.0
*/
this.imagerySplitPosition = 0.0;

/**
* Distances to the near and far planes of the camera frustums
* @type {Number[]}
* @default []
*/
this.frustumSplits = [];
}

/**
Expand Down
46 changes: 46 additions & 0 deletions Source/Scene/Scene.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ define([
'./Camera',
'./CreditDisplay',
'./CullingVolume',
'./DebugCameraPrimitive',
'./DepthPlane',
'./DeviceOrientationCameraController',
'./Fog',
Expand Down Expand Up @@ -109,6 +110,7 @@ define([
Camera,
CreditDisplay,
CullingVolume,
DebugCameraPrimitive,
DepthPlane,
DeviceOrientationCameraController,
Fog,
Expand Down Expand Up @@ -515,6 +517,20 @@ define([
*/
this.debugShowDepthFrustum = 1;

/**
* This property is for debugging only; it is not for production use.
* <p>
* When <code>true</code>, draws outlines to show the boundaries of the camera frustums
* </p>
*
* @type Boolean
*
* @default false
*/
this.debugShowFrustumPlanes = false;
this._debugShowFrustumPlanes = false;
this._debugFrustumPlanes = undefined;

/**
* When <code>true</code>, enables Fast Approximate Anti-aliasing even when order independent translucency
* is unsupported.
Expand Down Expand Up @@ -1442,6 +1458,15 @@ define([
updateFrustums(near, far, farToNearRatio, numFrustums, frustumCommandsList, is2D, scene.nearToFarDistance2D);
createPotentiallyVisibleSet(scene);
}

var frustumSplits = frameState.frustumSplits;
frustumSplits.length = numFrustums + 1;
for (var j = 0; j < numFrustums; ++j) {
frustumSplits[j] = frustumCommandsList[j].near;
if (j === numFrustums - 1) {
frustumSplits[j + 1] = frustumCommandsList[j].far;
}
}
}

function getAttributeLocations(shaderProgram) {
Expand Down Expand Up @@ -2202,6 +2227,25 @@ define([
}
}

function updateDebugFrustumPlanes(scene) {
var frameState = scene._frameState;
if (scene.debugShowFrustumPlanes !== scene._debugShowFrustumPlanes) {
if (scene.debugShowFrustumPlanes) {
scene._debugFrustumPlanes = new DebugCameraPrimitive({
camera: scene.camera,
updateOnChange: false
});
} else {
scene._debugFrustumPlanes = scene._debugFrustumPlanes && scene._debugFrustumPlanes.destroy();
}
scene._debugShowFrustumPlanes = scene.debugShowFrustumPlanes;
}

if (defined(scene._debugFrustumPlanes)) {
scene._debugFrustumPlanes.update(frameState);
}
}

function updateShadowMaps(scene) {
var frameState = scene._frameState;
var shadowMaps = frameState.shadowMaps;
Expand Down Expand Up @@ -2253,6 +2297,7 @@ define([
scene._groundPrimitives.update(frameState);
scene._primitives.update(frameState);

updateDebugFrustumPlanes(scene);
updateShadowMaps(scene);

if (scene._globe) {
Expand Down Expand Up @@ -2908,6 +2953,7 @@ define([
this._sunPostProcess = this._sunPostProcess && this._sunPostProcess.destroy();
this._depthPlane = this._depthPlane && this._depthPlane.destroy();
this._transitioner.destroy();
this._debugFrustumPlanes = this._debugFrustumPlanes && this._debugFrustumPlanes.destroy();

if (defined(this._globeDepth)) {
this._globeDepth.destroy();
Expand Down
9 changes: 9 additions & 0 deletions Source/Widgets/CesiumInspector/CesiumInspector.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ define([
generalSection.className = 'cesium-cesiumInspector-section';
generalSection.setAttribute('data-bind', 'css: {"cesium-cesiumInspector-show" : generalVisible, "cesium-cesiumInspector-hide" : !generalVisible}');
panel.appendChild(generalSection);

var debugShowFrustums = document.createElement('div');
generalSection.appendChild(debugShowFrustums);
var frustumStats = document.createElement('div');
Expand All @@ -92,6 +93,14 @@ define([
debugShowFrustums.appendChild(document.createTextNode('Show Frustums'));
debugShowFrustums.appendChild(frustumStats);

var debugShowFrustumPlanes = document.createElement('div');
generalSection.appendChild(debugShowFrustumPlanes);
var frustumPlanesCheckbox = document.createElement('input');
frustumPlanesCheckbox.type = 'checkbox';
frustumPlanesCheckbox.setAttribute('data-bind', 'checked: frustumPlanes');
debugShowFrustumPlanes.appendChild(frustumPlanesCheckbox);
debugShowFrustumPlanes.appendChild(document.createTextNode('Show Frustum Planes'));

var performanceDisplay = document.createElement('div');
generalSection.appendChild(performanceDisplay);
var pdCheckbox = document.createElement('input');
Expand Down
13 changes: 13 additions & 0 deletions Source/Widgets/CesiumInspector/CesiumInspectorViewModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,13 @@ define([
*/
this.frustums = false;

/**
* Gets or sets the show frustum planes state. This property is observable.
* @type {Boolean}
* @default false
*/
this.frustumPlanes = false;

/**
* Gets or sets the show performance display state. This property is observable.
* @type {Boolean}
Expand Down Expand Up @@ -305,6 +312,7 @@ define([

knockout.track(this, [
'frustums',
'frustumPlanes',
'performance',
'shaderCacheText',
'primitiveBoundingSphere',
Expand Down Expand Up @@ -351,6 +359,10 @@ define([
that._scene.debugShowFrustums = val;
});

this._frustumPlanesSubscription = knockout.getObservable(this, 'frustumPlanes').subscribe(function(val) {
that._scene.debugShowFrustumPlanes = val;
});

this._performanceSubscription = knockout.getObservable(this, 'performance').subscribe(function(val) {
if (val) {
that._performanceDisplay = new PerformanceDisplay({
Expand Down Expand Up @@ -940,6 +952,7 @@ define([
CesiumInspectorViewModel.prototype.destroy = function() {
this._eventHandler.destroy();
this._frustumsSubscription.dispose();
this._frustumPlanesSubscription.dispose();
this._performanceSubscription.dispose();
this._primitiveBoundingSphereSubscription.dispose();
this._primitiveReferenceFrameSubscription.dispose();
Expand Down

0 comments on commit b6afe7e

Please sign in to comment.