Skip to content

Commit

Permalink
Merge pull request #5913 from ggetz/clipping-planes-models
Browse files Browse the repository at this point in the history
Clipping planes for models, tilesets, point clouds
  • Loading branch information
lilleyse authored Nov 2, 2017
2 parents 24cc60f + b01ffa9 commit 7567c0c
Show file tree
Hide file tree
Showing 11 changed files with 380 additions and 4 deletions.
191 changes: 191 additions & 0 deletions Apps/Sandcastle/gallery/Clipping Planes.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1"> <!-- Use Chrome Frame in IE -->
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<meta name="description" content="User-defined clipping planes applied to a batched 3D Tileset, point cloud, and model.">
<meta name="cesium-sandcastle-labels" content="Showcases, 3D Tiles">
<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>
<script type="text/javascript">
require.config({
baseUrl : '../../../Source',
waitSeconds : 60
});
</script>
</head>
<body class="sandcastle-loading" data-sandcastle-bucket="bucket-requirejs.html">
<style>
@import url(../templates/bucket.css);
#toolbar {
background: rgba(42, 42, 42, 0.8);
padding: 4px;
border-radius: 4px;
}
#toolbar input {
vertical-align: middle;
padding-top: 2px;
padding-bottom: 2px;
}
#toolbar .header {
font-weight: bold;
}
</style>
<div id="cesiumContainer" class="fullSize"></div>
<div id="loadingOverlay"><h1>Loading...</h1></div>
<div id="toolbar">
<table><tbody>
<tr>
<td>Type</td>
<td><select data-bind="options: exampleTypes, value: exampleType"></select></td>
</tr>
<tr>
<td>x</td>
<td>
<input type="range" min="-100" max="100" step="1" data-bind="value: xOffset, valueUpdate: 'input'">
<input type="text" size="2" data-bind="value: xOffset">
</td>
</tr>
<tr>
<td>y</td>
<td>
<input type="range" min="-100" max="100" step="1" data-bind="value: yOffset, valueUpdate: 'input'">
<input type="text" size="2" data-bind="value: yOffset">
</td>
</tr>
<tr>
<td>z</td>
<td>
<input type="range" min="-100" max="100" step="1" data-bind="value: zOffset, valueUpdate: 'input'">
<input type="text" size="2" data-bind="value: zOffset">
</td>
</tr>
</tbody></table>
</div>

<script id="cesium_sandcastle_script">
function startup(Cesium) {
'use strict';
//Sandcastle_Begin
var viewer = new Cesium.Viewer('cesiumContainer');

var defaultClippingPlanes = [
new Cesium.Plane(new Cesium.Cartesian3(-1, 0, 0), 0.0),
new Cesium.Plane(new Cesium.Cartesian3(0, -1, 0), 100.0),
new Cesium.Plane(new Cesium.Cartesian3(0, 0, 1), 100.0)
];

function loadTileset (url) {
reset();

var tileset = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
url : url
}));

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

tileset.clippingPlanes = defaultClippingPlanes;
return tileset.clippingPlanes;
}

function loadModel (url) {
reset();

var position = Cesium.Cartesian3.fromDegrees(-123.0744619, 44.0503706, 100.0);
var heading = Cesium.Math.toRadians(135);
var pitch = 0;
var roll = 0;
var hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);
var orientation = Cesium.Transforms.headingPitchRollQuaternion(position, hpr);

var entity = viewer.entities.add({
name : url,
position : position,
orientation : orientation,
model : {
uri : url,
scale: 8,
minimumPixelSize: 100.0
}
});

viewer.trackedEntity = entity;

entity.model.clippingPlanes = defaultClippingPlanes;
return entity.model.clippingPlanes.getValue();
}

// Power Plant design model provided by Bentley Systems
var bimUrl = 'https://beta.cesium.com/api/assets/1459?access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIzNjUyM2I5Yy01YmRhLTQ0MjktOGI0Zi02MDdmYzBjMmY0MjYiLCJpZCI6NDQsImFzc2V0cyI6WzE0NTldLCJpYXQiOjE0OTkyNjQ3ODF9.SW_rwY-ic0TwQBeiweXNqFyywoxnnUBtcVjeCmDGef4';
var pointCloudUrl = 'https://beta.cesium.com/api/assets/1460?access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIyMzk2YzJiOS1jZGFmLTRlZmYtYmQ4MS00NTA3NjEwMzViZTkiLCJpZCI6NDQsImFzc2V0cyI6WzE0NjBdLCJpYXQiOjE0OTkyNjQ3NTV9.oWjvN52CRQ-dk3xtvD4e8ZnOHZhoWSpJLlw115mbQJM';
var modelUrl = '../../SampleData/models/CesiumAir/Cesium_Air.glb';

var clippingPlanes = loadTileset(bimUrl);

// Track and create the bindings for the view model

var viewModel = {
exampleType : 'BIM',
exampleTypes : ['BIM', 'Model', 'Point Cloud'],
xOffset : 0.0,
yOffset: 100.0,
zOffset: 100.0
};
var toolbar = document.getElementById('toolbar');
Cesium.knockout.track(viewModel);
Cesium.knockout.applyBindings(viewModel, toolbar);

Cesium.knockout.getObservable(viewModel, 'xOffset').subscribe(function(newValue) {
clippingPlanes[0].distance = parseFloat(newValue);
});

Cesium.knockout.getObservable(viewModel, 'yOffset').subscribe(function(newValue) {
clippingPlanes[1].distance = parseFloat(newValue);
});

Cesium.knockout.getObservable(viewModel, 'zOffset').subscribe(function(newValue) {
clippingPlanes[2].distance = parseFloat(newValue);
});

Cesium.knockout.getObservable(viewModel, 'exampleType').subscribe(
function(newValue) {
if (newValue === 'BIM') {
clippingPlanes = loadTileset(bimUrl);
} else if (newValue === 'Point Cloud') {
clippingPlanes = loadTileset(pointCloudUrl);
} else {
clippingPlanes = loadModel(modelUrl);
}
}
);

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

if (Cesium.defined(viewModel)) {
viewModel.xOffset = 0.0;
viewModel.yOffset = 100.0;
viewModel.zOffset = 100.0;
}
}

//Sandcastle_End
Sandcastle.finishedLoading();
}
if (typeof Cesium !== "undefined") {
startup(Cesium);
} else if (typeof require === "function") {
require(["Cesium"], startup);
}
</script>
</body>
</html>
Binary file added Apps/Sandcastle/gallery/Clipping Planes.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Change Log
* Fixed a 3D Tiles point cloud bug causing a stray point to appear at the center of the screen on certain hardware. [#5599](https://github.com/AnalyticalGraphicsInc/cesium/issues/5599)
* Fixed removing multiple event listeners within event callbacks. [#5827](https://github.com/AnalyticalGraphicsInc/cesium/issues/5827)
* Running `buildApps` now creates a built version of Sandcastle which uses the built version of Cesium for better performance.
* Added `clippingPlanes` property to models and 3D Tilesets, which specify an array of planes to clip the object. [TODO]()
* Fixed a tileset traversal bug when the `skipLevelOfDetail` optimization is off. [#5869](https://github.com/AnalyticalGraphicsInc/cesium/issues/5869)

### 1.37 - 2017-09-01
Expand Down
15 changes: 14 additions & 1 deletion Source/DataSources/ModelGraphics.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ define([
* @param {Property} [options.color=Color.WHITE] A Property specifying the {@link Color} that blends with the model's rendered color.
* @param {Property} [options.colorBlendMode=ColorBlendMode.HIGHLIGHT] An enum Property specifying how the color blends with the model.
* @param {Property} [options.colorBlendAmount=0.5] A numeric Property specifying the color strength when the <code>colorBlendMode</code> is <code>MIX</code>. A value of 0.0 results in the model's rendered color while a value of 1.0 results in a solid color, with any value in-between resulting in a mix of the two.
* @param {Property} [options.clippingPlanes=[]] A property specifying an array of {@link Plane} used to clip the model.
*
* @see {@link http://cesiumjs.org/2014/03/03/Cesium-3D-Models-Tutorial/|3D Models Tutorial}
* @demo {@link http://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=3D%20Models.html|Cesium Sandcastle 3D Models Demo}
Expand Down Expand Up @@ -91,6 +92,8 @@ define([
this._colorBlendModeSubscription = undefined;
this._colorBlendAmount = undefined;
this._colorBlendAmountSubscription = undefined;
this._clippingPlanes = undefined;
this._clippingPlanesSubscription = undefined;
this._definitionChanged = new Event();

this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT));
Expand Down Expand Up @@ -242,7 +245,15 @@ define([
* @type {Property}
* @default 0.5
*/
colorBlendAmount : createPropertyDescriptor('colorBlendAmount')
colorBlendAmount : createPropertyDescriptor('colorBlendAmount'),

/**
* A property specifying an array of {@link Plane} used to clip the model.
* @memberof ModelGraphics.prototype
* @type {Property}
* @default []
*/
clippingPlanes: createPropertyDescriptor('clippingPlanes')
});

/**
Expand Down Expand Up @@ -271,6 +282,7 @@ define([
result.color = this.color;
result.colorBlendMode = this.colorBlendMode;
result.colorBlendAmount = this.colorBlendAmount;
result.clippingPlanes = this.clippingPlanes;

return result;
};
Expand Down Expand Up @@ -303,6 +315,7 @@ define([
this.color = defaultValue(this.color, source.color);
this.colorBlendMode = defaultValue(this.colorBlendMode, source.colorBlendMode);
this.colorBlendAmount = defaultValue(this.colorBlendAmount, source.colorBlendAmount);
this.clippingPlanes = defaultValue(this.clippingPlanes, source.clippingPlanes);

var sourceNodeTransformations = source.nodeTransformations;
if (defined(sourceNodeTransformations)) {
Expand Down
2 changes: 2 additions & 0 deletions Source/DataSources/ModelVisualizer.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ define([
var defaultColor = Color.WHITE;
var defaultColorBlendMode = ColorBlendMode.HIGHLIGHT;
var defaultColorBlendAmount = 0.5;
var defaultClippingPlanes = [];

var modelMatrixScratch = new Matrix4();
var nodeMatrixScratch = new Matrix4();
Expand Down Expand Up @@ -152,6 +153,7 @@ define([
model.color = Property.getValueOrDefault(modelGraphics._color, time, defaultColor, model._color);
model.colorBlendMode = Property.getValueOrDefault(modelGraphics._colorBlendMode, time, defaultColorBlendMode);
model.colorBlendAmount = Property.getValueOrDefault(modelGraphics._colorBlendAmount, time, defaultColorBlendAmount);
model.clippingPlanes = Property.getValueOrDefault(modelGraphics._clippingPlanes, time, defaultClippingPlanes);

if (model.ready) {
var runAnimations = Property.getValueOrDefault(modelGraphics._runAnimations, time, true);
Expand Down
4 changes: 3 additions & 1 deletion Source/Scene/Batched3DModel3DTileContent.js
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,8 @@ define([
pickFragmentShaderLoaded : batchTable.getPickFragmentShaderCallback(),
pickUniformMapLoaded : batchTable.getPickUniformMapCallback(),
addBatchIdToGeneratedShaders : (batchLength > 0), // If the batch table has values in it, generated shaders will need a batchId attribute
pickObject : pickObject
pickObject : pickObject,
clippingPlanes : tileset.clippingPlanes
});
}

Expand Down Expand Up @@ -447,6 +448,7 @@ define([
this._model.modelMatrix = this._tile.computedTransform;
this._model.shadows = this._tileset.shadows;
this._model.debugWireframe = this._tileset.debugWireframe;
this._model.clippingPlanes = this._tileset.clippingPlanes;
this._model.update(frameState);

// If any commands were pushed, add derived commands
Expand Down
9 changes: 9 additions & 0 deletions Source/Scene/Cesium3DTileset.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ define([
* @param {Number} [options.skipLevels=1] When <code>skipLevelOfDetail</code> is <code>true</code>, a constant defining the minimum number of levels to skip when loading tiles. When it is 0, no levels are skipped. Used in conjunction with <code>skipScreenSpaceErrorFactor</code> to determine which tiles to load.
* @param {Boolean} [options.immediatelyLoadDesiredLevelOfDetail=false] When <code>skipLevelOfDetail</code> is <code>true</code>, only tiles that meet the maximum screen space error will ever be downloaded. Skipping factors are ignored and just the desired tiles are loaded.
* @param {Boolean} [options.loadSiblings=false] When <code>skipLevelOfDetail</code> is <code>true</code>, determines whether siblings of visible tiles are always downloaded during traversal.
* @param {Plane[]} [options.clippingPlanes=[]] An array of {@link Plane} used to clip the tileset.
* @param {Boolean} [options.debugFreezeFrame=false] For debugging only. Determines if only the tiles from last frame should be used for rendering.
* @param {Boolean} [options.debugColorizeTiles=false] For debugging only. When true, assigns a random color to each tile.
* @param {Boolean} [options.debugWireframe=false] For debugging only. When true, render's each tile's content as a wireframe.
Expand Down Expand Up @@ -522,6 +523,14 @@ define([
*/
this.loadSiblings = defaultValue(options.loadSiblings, false);

/**
* An array of {@link Plane} used to clip the tileset.
*
* @type {Plane[]}
* @default []
*/
this.clippingPlanes = defaultValue(options.clippingPlanes, []);

/**
* This property is for debugging only; it is not optimized for production use.
* <p>
Expand Down
Loading

0 comments on commit 7567c0c

Please sign in to comment.