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

Clipping planes tweaks #6327

Merged
merged 11 commits into from
Mar 15, 2018
1 change: 1 addition & 0 deletions Apps/Sandcastle/gallery/3D Tiles Clipping Planes.html
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@
viewer.scene.primitives.removeAll();
planeEntities = [];
targetY = 0.0;
tileset = undefined;
}

//Sandcastle_End
Expand Down
185 changes: 148 additions & 37 deletions Apps/Sandcastle/gallery/Terrain Clipping Planes.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@
<div id="cesiumContainer" class="fullSize"></div>
<div id="loadingOverlay"><h1>Loading...</h1></div>
<div id="toolbar">
<select data-bind="options: exampleTypes, value: currentExampleType"></select>
<input type="checkbox" value="false" data-bind="checked: clippingPlanesEnabled, valueUpdate: 'input'"> Globe clipping planes enabled
<input type="checkbox" value="false" data-bind="checked: edgeStylingEnabled, valueUpdate: 'input'"> Edge styling enabled
</div>
<script id="cesium_sandcastle_script">
function startup(Cesium) {
Expand All @@ -46,53 +48,162 @@
shouldAnimate : true,
terrainProvider: Cesium.createWorldTerrain()
});

var position = Cesium.Cartesian3.fromRadians(-2.0862979473351286, 0.6586620013036164, 1400.0);

var entity = viewer.entities.add({
position : position,
box : {
dimensions : new Cesium.Cartesian3(1400.0, 1400.0, 2800.0),
material : Cesium.Color.WHITE.withAlpha(0.3),
outline : true,
outlineColor : Cesium.Color.WHITE
}
});

viewer.entities.add({
position : position,
model : {
uri : '../../SampleData/models/CesiumMan/Cesium_Man.glb',
minimumPixelSize : 128,
maximumScale : 800
}
});

var globe = viewer.scene.globe;
globe.depthTestAgainstTerrain = true;
globe.clippingPlanes = new Cesium.ClippingPlaneCollection({
modelMatrix : entity.computeModelMatrix(Cesium.JulianDate.now()),
planes : [
new Cesium.ClippingPlane(new Cesium.Cartesian3( 1.0, 0.0, 0.0), -700.0),
new Cesium.ClippingPlane(new Cesium.Cartesian3(-1.0, 0.0, 0.0), -700.0),
new Cesium.ClippingPlane(new Cesium.Cartesian3( 0.0, 1.0, 0.0), -700.0),
new Cesium.ClippingPlane(new Cesium.Cartesian3( 0.0, -1.0, 0.0), -700.0)
],
edgeWidth: 1.0,
edgeColor: Cesium.Color.WHITE
});

viewer.trackedEntity = entity;

var exampleTypes = ['Cesium Man', 'St. Helens'];
var viewModel = {
clippingPlanesEnabled : true
exampleTypes : exampleTypes,
currentExampleType : exampleTypes[0],
clippingPlanesEnabled : true,
edgeStylingEnabled : true
};
var toolbar = document.getElementById('toolbar');
Cesium.knockout.track(viewModel);
Cesium.knockout.applyBindings(viewModel, toolbar);

// For tracking state when switching exampleTypes
var clippingPlanesEnabled = true;
var edgeStylingEnabled = true;

loadCesiumMan();

function reset() {
viewer.entities.removeAll();
viewer.scene.primitives.removeAll();
}

function loadCesiumMan() {
var position = Cesium.Cartesian3.fromRadians(-2.0862979473351286, 0.6586620013036164, 1400.0);

var entity = viewer.entities.add({
position : position,
box : {
dimensions : new Cesium.Cartesian3(1400.0, 1400.0, 2800.0),
material : Cesium.Color.WHITE.withAlpha(0.3),
outline : true,
outlineColor : Cesium.Color.WHITE
}
});

viewer.entities.add({
position : position,
model : {
uri : '../../SampleData/models/CesiumMan/Cesium_Man.glb',
minimumPixelSize : 128,
maximumScale : 800
}
});

globe.depthTestAgainstTerrain = true;
globe.clippingPlanes = new Cesium.ClippingPlaneCollection({
modelMatrix : entity.computeModelMatrix(Cesium.JulianDate.now()),
planes : [
new Cesium.ClippingPlane(new Cesium.Cartesian3( 1.0, 0.0, 0.0), -700.0),
new Cesium.ClippingPlane(new Cesium.Cartesian3(-1.0, 0.0, 0.0), -700.0),
new Cesium.ClippingPlane(new Cesium.Cartesian3( 0.0, 1.0, 0.0), -700.0),
new Cesium.ClippingPlane(new Cesium.Cartesian3( 0.0, -1.0, 0.0), -700.0)
],
edgeWidth: edgeStylingEnabled ? 1.0 : 0.0,
edgeColor: Cesium.Color.WHITE,
enabled : clippingPlanesEnabled
});

viewer.trackedEntity = entity;
}

function loadStHelens() {
// Create clipping planes for polygon around area to be clipped.
var points = [
new Cesium.Cartesian3(-2358434.3501556474, -3743554.5012105294, 4581080.771684084),
new Cesium.Cartesian3(-2357886.4482675144, -3744467.562778789, 4581020.9199767085),
new Cesium.Cartesian3(-2357299.84353055, -3744954.0879047974, 4581080.992360969),
new Cesium.Cartesian3(-2356412.05169956, -3745385.3013702347, 4580893.4737207815),
new Cesium.Cartesian3(-2355472.889436636, -3745256.5725702164, 4581252.3128526565),
new Cesium.Cartesian3(-2354385.7458722834, -3744319.3823686405, 4582372.770031389),
new Cesium.Cartesian3(-2353758.788158616, -3743051.0128084184, 4583356.453176038),
new Cesium.Cartesian3(-2353663.8128999653, -3741847.9126874236, 4584079.428665509),
new Cesium.Cartesian3(-2354213.667592133, -3740784.50946316, 4584502.428203525),
new Cesium.Cartesian3(-2355596.239450013, -3739901.0226732804, 4584515.9652557485),
new Cesium.Cartesian3(-2356942.4170108805, -3740342.454698685, 4583686.690694482),
new Cesium.Cartesian3(-2357529.554838029, -3740766.995076834, 4583145.055348843),
new Cesium.Cartesian3(-2358106.017822064, -3741439.438418052, 4582452.293605261),
new Cesium.Cartesian3(-2358539.5426236596, -3742680.720902901, 4581692.0260975715)
];

var pointsLength = points.length;

// Create center points for each clipping plane
var clippingPlanes = [];
for (var i = 0; i < pointsLength; ++i) {
var nextIndex = (i + 1) % pointsLength;
var midpoint = Cesium.Cartesian3.add(points[i], points[nextIndex], new Cesium.Cartesian3());
midpoint = Cesium.Cartesian3.multiplyByScalar(midpoint, 0.5, midpoint);

var up = Cesium.Cartesian3.normalize(midpoint, new Cesium.Cartesian3());
var right = Cesium.Cartesian3.subtract(points[nextIndex], midpoint, new Cesium.Cartesian3());
right = Cesium.Cartesian3.normalize(right, right);

var normal = Cesium.Cartesian3.cross(right, up, new Cesium.Cartesian3());
normal = Cesium.Cartesian3.normalize(normal, normal);

// Compute distance by pretending the plane is at the origin
var originCenteredPlane = new Cesium.Plane(normal, 0.0);
var distance = Cesium.Plane.getPointDistance(originCenteredPlane, midpoint);

clippingPlanes.push(new Cesium.ClippingPlane(normal, distance));
}
globe.clippingPlanes = new Cesium.ClippingPlaneCollection({
planes : clippingPlanes,
edgeWidth: edgeStylingEnabled ? 1.0 : 0.0,
edgeColor: Cesium.Color.WHITE,
enabled : clippingPlanesEnabled
});

// Load tileset
var tileset = new Cesium.Cesium3DTileset({ url: Cesium.IonResource.fromAssetId(3844) });
return tileset.readyPromise.then(function() {
tileset.pointCloudShading.attenuation = true;

// Adjust height so tileset is in terrain
var cartographic = Cesium.Cartographic.fromCartesian(tileset.boundingSphere.center);
var surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0);
var offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, -20.0);
var translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3());
tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation);

tileset.style = new Cesium.Cesium3DTileStyle({
color : "rgb(207, 255, 207)"
});

viewer.scene.primitives.add(tileset);

var boundingSphere = tileset.boundingSphere;

var radius = boundingSphere.radius;
viewer.camera.viewBoundingSphere(boundingSphere, new Cesium.HeadingPitchRange(0.5, -0.2, radius * 4.0));
viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
}).otherwise(function(error) {
throw(error);
});
}

Cesium.knockout.getObservable(viewModel, 'clippingPlanesEnabled').subscribe(function(value) {
globe.clippingPlanes.enabled = value;
clippingPlanesEnabled = value;
});

Cesium.knockout.getObservable(viewModel, 'edgeStylingEnabled').subscribe(function(value) {
edgeStylingEnabled = value;
globe.clippingPlanes.edgeWidth = edgeStylingEnabled ? 1.0 : 0.0;
});

Cesium.knockout.getObservable(viewModel, 'currentExampleType').subscribe(function(newValue) {
reset();
if (newValue === exampleTypes[0]) {
loadCesiumMan();
} else if (newValue === exampleTypes[1]) {
loadStHelens();
}
});

//Sandcastle_End
Expand Down
21 changes: 8 additions & 13 deletions Apps/Sandcastle/gallery/development/Many Clipping Planes.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<meta name="description" content="Use Viewer to start building new applications or easily embed Cesium into existing applications.">
<meta name="cesium-sandcastle-labels" content="Beginner, Showcases">
<meta name="description" content="Demonstration of large numbers of clipping planes.">
<meta name="cesium-sandcastle-labels" content="Development">
<title>Cesium Demo</title>
<script type="text/javascript" src="../Sandcastle-header.js"></script>
<script type="text/javascript" src="../../../ThirdParty/requirejs-2.1.20/require.js"></script>
Expand Down Expand Up @@ -49,14 +49,10 @@
infoBox: false,
selectionIndicator: false,
shouldAnimate : true,
projectionPicker : true
projectionPicker : true,
terrainProvider: Cesium.createWorldTerrain()
});

viewer.terrainProvider = new Cesium.CesiumTerrainProvider({
url : 'https://assets.agi.com/stk-terrain/v1/tilesets/world/tiles',
requestWaterMask : true,
requestVertexNormals : true
});
viewer.extend(Cesium.viewerCesium3DTilesInspectorMixin);

var globe = viewer.scene.globe;
Expand Down Expand Up @@ -114,23 +110,22 @@
}

function computePlanes() {
var stepDegrees = 6.28319 / steps;
var stepDegrees = Cesium.Math.TWO_PI / steps;
clippingPlanes = [];

for (var i = 0; i < steps; i++) {
var angle = i * stepDegrees;
var dir = new Cesium.Cartesian3();
dir.x = 1.0;
dir.y = Math.tan(angle);
if (angle > 1.57079632679) {
if (angle > Cesium.Math.PI_OVER_TWO) {
dir.x = -1.0;
dir.y *= -1.0;
}
if (angle > 3.14159265359) {
if (angle > Cesium.Math.PI) {
dir.x = -1.0;
dir.y = dir.y;
}
if (angle > 4.71238898038) {
if (angle > (Cesium.Math.PI_OVER_TWO * 3)) {
dir.x = 1.0;
dir.y = -dir.y;
}
Expand Down
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Change Log
* Removed the 6-clipping-plane limit.
* Added support for Internet Explorer.
* Added a `ClippingPlane` object to be used with `ClippingPlaneCollection`.
* Added 3D Tiles use-case to Terrain Clipping Planes Sandcastle
* Updated `WebMapServiceImageryProvider` so it can take an srs or crs string to pass to the resource query parameters based on the WMS version. [#6223](https://github.com/AnalyticalGraphicsInc/cesium/issues/6223)
* Added additional query parameter options to the CesiumViewer demo application:
* sourceType specifies the type of data source if the URL doesn't have a known file extension.
Expand Down
64 changes: 62 additions & 2 deletions Source/Core/AttributeCompression.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ define([
CesiumMath) {
'use strict';

var RIGHT_SHIFT = 1.0 / 256.0;
var LEFT_SHIFT = 256.0;

/**
* Attribute compression and decompression functions.
*
Expand Down Expand Up @@ -80,6 +83,31 @@ define([
return AttributeCompression.octEncodeInRange(vector, 255, result);
};

var octEncodeScratch = new Cartesian2();
var uint8ForceArray = new Uint8Array(1);
function forceUint8(value) {
uint8ForceArray[0] = value;
return uint8ForceArray[0];
}
/**
* @param {Cartesian3} vector The normalized vector to be compressed into 4 byte 'oct' encoding.
* @param {Cartesian4} result The 4 byte oct-encoded unit length vector.
* @returns {Cartesian4} The 4 byte oct-encoded unit length vector.
*
* @exception {DeveloperError} vector must be normalized.
*
* @see AttributeCompression.octEncodeInRange
* @see AttributeCompression.octDecodeFromCartesian4
*/
AttributeCompression.octEncodeToCartesian4 = function(vector, result) {
AttributeCompression.octEncodeInRange(vector, 65535, octEncodeScratch);
result.x = forceUint8(octEncodeScratch.x * RIGHT_SHIFT);
result.y = forceUint8(octEncodeScratch.x);
result.z = forceUint8(octEncodeScratch.y * RIGHT_SHIFT);
result.w = forceUint8(octEncodeScratch.y);
return result;
};

/**
* Decodes a unit-length vector in 'oct' encoding to a normalized 3-component vector.
*
Expand All @@ -89,15 +117,15 @@ define([
* @param {Cartesian3} result The decoded and normalized vector
* @returns {Cartesian3} The decoded and normalized vector.
*
* @exception {DeveloperError} x and y must be an unsigned normalized integer between 0 and rangeMax.
* @exception {DeveloperError} x and y must be unsigned normalized integers between 0 and rangeMax.
*
* @see AttributeCompression.octEncodeInRange
*/
AttributeCompression.octDecodeInRange = function(x, y, rangeMax, result) {
//>>includeStart('debug', pragmas.debug);
Check.defined('result', result);
if (x < 0 || x > rangeMax || y < 0 || y > rangeMax) {
throw new DeveloperError('x and y must be a signed normalized integer between 0 and ' + rangeMax);
throw new DeveloperError('x and y must be unsigned normalized integers between 0 and ' + rangeMax);
}
//>>includeEnd('debug');

Expand Down Expand Up @@ -131,6 +159,38 @@ define([
return AttributeCompression.octDecodeInRange(x, y, 255, result);
};

/**
* Decodes a unit-length vector in 4 byte 'oct' encoding to a normalized 3-component vector.
*
* @param {Cartesian4} encoded The oct-encoded unit length vector.
* @param {Cartesian3} result The decoded and normalized vector.
* @returns {Cartesian3} The decoded and normalized vector.
*
* @exception {DeveloperError} x, y, z, and w must be unsigned normalized integers between 0 and 255.
*
* @see AttributeCompression.octDecodeInRange
* @see AttributeCompression.octEncodeToCartesian4
*/
AttributeCompression.octDecodeFromCartesian4 = function(encoded, result) {
//>>includeStart('debug', pragmas.debug);
Check.typeOf.object('encoded', encoded);
Check.typeOf.object('result', result);
//>>includeEnd('debug');
var x = encoded.x;
var y = encoded.y;
var z = encoded.z;
var w = encoded.w;
//>>includeStart('debug', pragmas.debug);
if (x < 0 || x > 255 || y < 0 || y > 255 || z < 0 || z > 255 || w < 0 || w > 255) {
throw new DeveloperError('x, y, z, and w must be unsigned normalized integers between 0 and 255');
}
//>>includeEnd('debug');

var xOct16 = x * LEFT_SHIFT + y;
var yOct16 = z * LEFT_SHIFT + w;
return AttributeCompression.octDecodeInRange(xOct16, yOct16, 65535, result);
};

/**
* Packs an oct encoded vector into a single floating-point number.
*
Expand Down
1 change: 1 addition & 0 deletions Source/Core/Cartesian4.js
Original file line number Diff line number Diff line change
Expand Up @@ -880,6 +880,7 @@ define([
*
* @param {Cartesian4} packedFloat A Cartesian4 containing a float packed to 4 values representable using uint8.
* @returns {Number} The unpacked float.
* @private
*/
Cartesian4.unpackFloat = function(packedFloat) {
//>>includeStart('debug', pragmas.debug);
Expand Down
Loading