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

Add multifrustum near/far planes to DebugCameraPrimitive #4932

Merged
merged 13 commits into from
Feb 2, 2017
Merged
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