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
183 changes: 146 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,160 @@
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 demos = ['Cesium Man', 'St. Helens'];
Copy link
Contributor

Choose a reason for hiding this comment

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

For consistency rename to exampleTypes.

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

// For tracking state when switching demos
var clippingPlanesEnabled = true;
Copy link
Contributor

Choose a reason for hiding this comment

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

This one isn't being used.

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
});

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 pointCount = points.length;

// Create centerpoints for each clipping plane
Copy link
Contributor

Choose a reason for hiding this comment

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

Change centerpoints to center points.

var clippingPlanes = [];
for (var i = 0; i < pointCount; i++) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Style: rename pointCount to pointsLength.
Change i++ to ++i

var nextIndex = (i + 1) % pointCount;
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
});

// 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 === demos[0]) {
loadCesiumMan();
} else if (newValue === demos[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
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ Change Log
* Added a `ClippingPlane` object to be used with `ClippingPlaneCollection`.
* 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 a multi-part CZML example to Sandcastle. [#6320](https://github.com/AnalyticalGraphicsInc/cesium/pull/6320)
* Added `AttributeCompression.octEncodeToCartesian4` and `AttributeCompression.octDecodeFromCartesian4` which will encode and decode unit-length normal vectors using 4 `uint8` components in a `Cartesian4`.
Copy link
Contributor

Choose a reason for hiding this comment

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

This shouldn't be mentioned in CHANGES.md because the class is private.

* Added 3D Tiles use-case to Terrain Clipping Planes Sandcastle
Copy link
Contributor

Choose a reason for hiding this comment

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

This one can go under the

  • ClippingPlaneCollection updates #6201

heading.


##### Fixes :wrench:
* Fixed support of glTF-supplied tangent vectors. [#6302](https://github.com/AnalyticalGraphicsInc/cesium/pull/6302)
Expand Down
59 changes: 57 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 2 byte 'oct' encoding.
Copy link
Contributor

Choose a reason for hiding this comment

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

Change 2 byte to 4 byte

* @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,33 @@ 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 {Number} x The x component of the oct-encoded unit length vector.
* @param {Number} y The y component of the oct-encoded unit length vector.
* @param {Number} z The z component of the oct-encoded unit length vector.
* @param {Number} w The w component of 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(x, y, z, w, result) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think a Cartesian4 argument would be cleaner. Since this is based on octDecode, I wonder if that should take a Cartesian2 instead of x and y.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I wonder if that should take a Cartesian2 instead of x and y.

It looks like majority of the (few) use cases for octDecode do something to the components separately, so I'm in favor of leaving that as-is.

Having octDecodeFromCartesian4 take Cartesian4 makes sense though, it's in the name after all...

//>>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