-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
Geometric-error based point cloud attenuation and eye dome lighting #6069
Changes from 12 commits
501de27
095e152
dccefeb
aad2105
9659688
b77963d
d3367bf
e754963
9f9ebd1
4c7231b
0750c83
4e765ac
6041751
314355c
1484470
c4a3f6b
4400531
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,274 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<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="Point Cloud Attenuation and Eye Dome Lighting example."> | ||
<meta name="cesium-sandcastle-labels" content="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"> | ||
if(typeof require === "function") { | ||
require.config({ | ||
baseUrl : '../../../Source', | ||
waitSeconds : 120 | ||
}); | ||
} | ||
</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"> | ||
<select data-bind="options: exampleTypes, value: currentExampleType"></select> | ||
<table><tbody> | ||
<tr> | ||
<td>Maximum Screen Space Error</td> | ||
<td> | ||
<input type="range" min="0.0" max="64.0" step="0.1" data-bind="value: maximumScreenSpaceError, valueUpdate: 'input'"> | ||
<input type="text" size="5" data-bind="value: maximumScreenSpaceError"> | ||
</td> | ||
</tr> | ||
<tr><td class="header">Attenuation</td></tr> | ||
<tr> | ||
<td>Geometric Error Scale</td> | ||
<td> | ||
<input type="range" min="0.0" max="2.0" step="0.1" data-bind="value: geometricErrorScale, valueUpdate: 'input'"> | ||
<input type="text" size="5" data-bind="value: geometricErrorScale"> | ||
</td> | ||
</tr> | ||
<tr> | ||
<td>Maximum Attenuation</td> | ||
<td> | ||
<input type="range" min="0.0" max="32.0" step="1.0" data-bind="value: maximumAttenuation, valueUpdate: 'input'"> | ||
<input type="text" size="5" data-bind="value: maximumAttenuation"> | ||
</td> | ||
</tr> | ||
<tr> | ||
<td>Base Resolution</td> | ||
<td> | ||
<input type="range" min="0.0" max="10.0" step="0.01" data-bind="value: baseResolution, valueUpdate: 'input'"> | ||
<input type="text" size="5" data-bind="value: baseResolution"> | ||
</td> | ||
</tr> | ||
<tr><td class="header">Eye Dome Lighting</td></tr> | ||
<tr> | ||
<td>Eye Dome Lighting Strength</td> | ||
<td> | ||
<input type="range" min="0.0" max="10.0" step="0.1" data-bind="value: eyeDomeLightingStrength, valueUpdate: 'input'"> | ||
<input type="text" size="5" data-bind="value: eyeDomeLightingStrength"> | ||
</td> | ||
</tr> | ||
<tr> | ||
<td>Eye Dome Lighting Radius</td> | ||
<td> | ||
<input type="range" min="0.0" max="10.0" step="0.1" data-bind="value: eyeDomeLightingRadius, valueUpdate: 'input'"> | ||
<input type="text" size="5" data-bind="value: eyeDomeLightingRadius"> | ||
</td> | ||
</tr> | ||
</tbody></table> | ||
</div> | ||
<script id="cesium_sandcastle_script"> | ||
function startup(Cesium) { | ||
'use strict'; | ||
//Sandcastle_Begin | ||
var viewer = new Cesium.Viewer('cesiumContainer'); | ||
|
||
var scene = viewer.scene; | ||
var tileset; | ||
|
||
function reset() { | ||
viewer.entities.removeAll(); | ||
viewer.scene.primitives.removeAll(); | ||
tileset = undefined; | ||
} | ||
|
||
// The viewModel tracks the state of our mini application. | ||
var pointClouds = ['St. Helens', 'Church']; | ||
var viewModel = { | ||
exampleTypes : pointClouds, | ||
currentExampleType : pointClouds[0], | ||
maximumScreenSpaceError : 8.0, | ||
geometricErrorScale : 1.0, | ||
maximumAttenuation : 0, // Equivalent to undefined | ||
baseResolution : 0, // Equivalent to undefined | ||
eyeDomeLightingStrength : 1.0, | ||
eyeDomeLightingRadius : 1.0 | ||
}; | ||
|
||
function tilesetToViewModel(tileset) { | ||
var pointShading = tileset.pointShading; | ||
viewModel.maximumScreenSpaceError = tileset.maximumScreenSpaceError; | ||
viewModel.geometricErrorScale = pointShading.geometricErrorScale; | ||
viewModel.maximumAttenuation = pointShading.maximumAttenuation ? pointShading.maximumAttenuation : 0; | ||
viewModel.baseResolution = pointShading.baseResolution ? pointShading.baseResolution : 0; | ||
viewModel.eyeDomeLightingStrength = pointShading.eyeDomeLightingStrength; | ||
viewModel.eyeDomeLightingRadius = pointShading.eyeDomeLightingRadius; | ||
} | ||
|
||
function loadStHelens() { | ||
// Mt. St. Helens 3D Tileset generated from LAS provided by https://www.liblas.org/samples/ | ||
// This tileset uses replacement refinement and has geometric error approximately equal to | ||
// the average interpoint distance in each tile. | ||
var url = 'https://beta.cesium.com/api/assets/3742?access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIxOGZjMjlhZC03MDE1LTQ3ZTAtODEyNy05YTU3M2MwYzQ0YmEiLCJpZCI6NDQsImFzc2V0cyI6WzM3NDJdLCJpYXQiOjE1MTcyNDI3NDJ9.TJAJctFXC1UyFMpxkA3cyKVAmnh72cLtfY1yKbaQsyk'; | ||
tileset = scene.primitives.add(new Cesium.Cesium3DTileset({ | ||
url : url | ||
})); | ||
|
||
// Set the initial camera view to look at Mt. St. Helens | ||
var initialPosition = Cesium.Cartesian3.fromRadians(-2.1344873183780484, 0.8071380277370774, 5743.394497982162); | ||
var initialOrientation = new Cesium.HeadingPitchRoll.fromDegrees(112.99596671210358, -21.34390550872461, 0.0716951918898415); | ||
viewer.scene.camera.setView({ | ||
destination: initialPosition, | ||
orientation: initialOrientation, | ||
endTransform: Cesium.Matrix4.IDENTITY | ||
}); | ||
|
||
tileset.readyPromise.then(function() { | ||
tileset.maximumScreenSpaceError = 8.0; | ||
tileset.pointShading.maximumAttenuation = undefined; // Will be based on maximumScreenSpaceError instead | ||
tileset.pointShading.baseResolution = undefined; | ||
tileset.pointShading.geometricErrorScale = 1.0; | ||
tileset.pointShading.attenuation = true; | ||
tileset.pointShading.eyeDomeLighting = true; | ||
|
||
tilesetToViewModel(tileset); | ||
}); | ||
} | ||
|
||
function loadChurch() { | ||
// Point Cloud by Prof. Peter Allen, Columbia University Robotics Lab. Scanning by Alejandro Troccoli and Matei Ciocarlie. | ||
// This tileset uses additive refinement and has geometric error based on the bounding box size for each tile. | ||
var url = 'https://beta.cesium.com/api/assets/1460?access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIyMzk2YzJiOS1jZGFmLTRlZmYtYmQ4MS00NTA3NjEwMzViZTkiLCJpZCI6NDQsImFzc2V0cyI6WzE0NjBdLCJpYXQiOjE0OTkyNjQ3NTV9.oWjvN52CRQ-dk3xtvD4e8ZnOHZhoWSpJLlw115mbQJM'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use the new ion loading utilities - look at the other Sandcastle demos. |
||
tileset = scene.primitives.add(new Cesium.Cesium3DTileset({ | ||
url : url | ||
})); | ||
|
||
viewer.zoomTo(tileset).otherwise(function(error) { | ||
throw(error); | ||
}); | ||
|
||
tileset.readyPromise.then(function() { | ||
tileset.maximumScreenSpaceError = 1024.0; // For better performance, due to how this tileset treats geometric error. | ||
tileset.pointShading.maximumAttenuation = 8.0; // Don't allow points larger than 8 pixels. | ||
tileset.pointShading.baseResolution = 0.05; // Assume an original capture resolution of 5 centimeters between neighboring points. | ||
tileset.pointShading.geometricErrorScale = 1.0; // Applies to both geometric error and the base resolution. | ||
tileset.pointShading.attenuation = true; | ||
tileset.pointShading.eyeDomeLighting = true; | ||
|
||
tilesetToViewModel(tileset); | ||
}); | ||
} | ||
|
||
function checkZero(newValue) { | ||
var newValueFloat = parseFloat(newValue); | ||
return (newValueFloat === 0.0) ? undefined : newValueFloat; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just to be sure, does the code still work without this function? For example, if a developer sets There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All computations will be done with 0.0 instead of with the "defaults." For |
||
} | ||
|
||
loadStHelens(); | ||
|
||
// Convert the viewModel members into knockout observables. | ||
Cesium.knockout.track(viewModel); | ||
|
||
// Bind the viewModel to the DOM elements of the UI that call for it. | ||
var toolbar = document.getElementById('toolbar'); | ||
Cesium.knockout.applyBindings(viewModel, toolbar); | ||
|
||
Cesium.knockout.getObservable(viewModel, 'currentExampleType').subscribe(function(newValue) { | ||
reset(); | ||
if (newValue === pointClouds[0]) { | ||
loadStHelens(); | ||
} else if (newValue === pointClouds[1]) { | ||
loadChurch(); | ||
} | ||
}); | ||
|
||
Cesium.knockout.getObservable(viewModel, 'maximumScreenSpaceError').subscribe( | ||
function(newValue) { | ||
if (Cesium.defined(tileset)) { | ||
tileset.maximumScreenSpaceError = parseFloat(newValue); | ||
} | ||
} | ||
); | ||
|
||
Cesium.knockout.getObservable(viewModel, 'geometricErrorScale').subscribe( | ||
function(newValue) { | ||
if (Cesium.defined(tileset)) { | ||
tileset.pointShading.geometricErrorScale = parseFloat(newValue); | ||
} | ||
} | ||
); | ||
|
||
Cesium.knockout.getObservable(viewModel, 'maximumAttenuation').subscribe( | ||
function(newValue) { | ||
if (Cesium.defined(tileset)) { | ||
tileset.pointShading.maximumAttenuation = checkZero(newValue); | ||
} | ||
} | ||
); | ||
|
||
Cesium.knockout.getObservable(viewModel, 'baseResolution').subscribe( | ||
function(newValue) { | ||
if (Cesium.defined(tileset)) { | ||
tileset.pointShading.baseResolution = checkZero(newValue); | ||
} | ||
} | ||
); | ||
|
||
Cesium.knockout.getObservable(viewModel, 'eyeDomeLightingStrength').subscribe( | ||
function(newValue) { | ||
if (Cesium.defined(tileset)) { | ||
tileset.pointShading.eyeDomeLightingStrength = parseFloat(newValue); | ||
} | ||
} | ||
); | ||
|
||
Cesium.knockout.getObservable(viewModel, 'eyeDomeLightingRadius').subscribe( | ||
function(newValue) { | ||
if (Cesium.defined(tileset)) { | ||
tileset.pointShading.eyeDomeLightingRadius = parseFloat(newValue); | ||
} | ||
} | ||
); | ||
|
||
Sandcastle.addToggleButton('Enable Attenuation', true, function(checked) { | ||
if (Cesium.defined(tileset)) { | ||
tileset.pointShading.attenuation = checked; | ||
} | ||
}); | ||
|
||
Sandcastle.addToggleButton('Enable Eye Dome Lighting', true, function(checked) { | ||
if (Cesium.defined(tileset)) { | ||
tileset.pointShading.eyeDomeLighting = checked; | ||
} | ||
}); | ||
|
||
//Sandcastle_End | ||
Sandcastle.finishedLoading(); | ||
} | ||
if (typeof Cesium !== "undefined") { | ||
startup(Cesium); | ||
} else if (typeof require === "function") { | ||
require(["Cesium"], startup); | ||
} | ||
</script> | ||
</body> | ||
</html> |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -41,6 +41,8 @@ Change Log | |
* Fixed camera movement and look functions for 2D mode [#5884](https://github.com/AnalyticalGraphicsInc/cesium/issues/5884) | ||
* Fixed discrepancy between default value used and commented value for default value for halfAxes of OrientedBoundingBox. [#6147](https://github.com/AnalyticalGraphicsInc/cesium/pull/6147) | ||
* Added `Cartographic.toCartesian` to convert from Cartographic to Cartesian3. [#6163](https://github.com/AnalyticalGraphicsInc/cesium/pull/6163) | ||
* Added geometric-error-based point cloud attenuation and eye dome lighting for point clouds using additive refinement. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Include the PR number like the other entries. Same below. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Should this be |
||
* Added volume computation to `BoundingSphere`. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Better to say what the actual function is:
|
||
|
||
### 1.41 - 2018-01-02 | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
define([ | ||
'./Cartesian3', | ||
'./Cartographic', | ||
'./Math', | ||
'./Check', | ||
'./defaultValue', | ||
'./defined', | ||
|
@@ -14,6 +15,7 @@ define([ | |
], function( | ||
Cartesian3, | ||
Cartographic, | ||
CesiumMath, | ||
Check, | ||
defaultValue, | ||
defined, | ||
|
@@ -66,6 +68,7 @@ define([ | |
var fromPointsMinBoxPt = new Cartesian3(); | ||
var fromPointsMaxBoxPt = new Cartesian3(); | ||
var fromPointsNaiveCenterScratch = new Cartesian3(); | ||
var volumeConstant = (4.0 / 3.0) * CesiumMath.PI; | ||
|
||
/** | ||
* Computes a tight-fitting bounding sphere enclosing a list of 3D Cartesian points. | ||
|
@@ -1302,5 +1305,14 @@ define([ | |
return BoundingSphere.clone(this, result); | ||
}; | ||
|
||
/** | ||
* Computes the radius of the BoundingSphere. | ||
* @returns {Number} The radius of the BoundingSphere. | ||
*/ | ||
BoundingSphere.prototype.volume = function() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add this to CHANGES.md. |
||
var radius = this.radius; | ||
return volumeConstant * radius * radius * radius; | ||
}; | ||
|
||
return BoundingSphere; | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,6 +36,8 @@ define([ | |
'./Cesium3DTileStyleEngine', | ||
'./ClassificationType', | ||
'./LabelCollection', | ||
'./PointShading', | ||
'./PointCloudEyeDomeLighting', | ||
'./SceneMode', | ||
'./ShadowMode', | ||
'./TileBoundingRegion', | ||
|
@@ -79,6 +81,8 @@ define([ | |
Cesium3DTileStyleEngine, | ||
ClassificationType, | ||
LabelCollection, | ||
PointShading, | ||
PointCloudEyeDomeLighting, | ||
SceneMode, | ||
ShadowMode, | ||
TileBoundingRegion, | ||
|
@@ -124,6 +128,7 @@ define([ | |
* @param {Boolean} [options.debugShowRenderingStatistics=false] For debugging only. When true, draws labels to indicate the number of commands, points, triangles and features for each tile. | ||
* @param {Boolean} [options.debugShowMemoryUsage=false] For debugging only. When true, draws labels to indicate the texture and geometry memory in megabytes used by each tile. | ||
* @param {Boolean} [options.debugShowUrl=false] For debugging only. When true, draws labels to indicate the url of each tile. | ||
* @param {Object} [options.pointShading] Options for constructing a PointShading object to control point attenuation based on geometric error and lighting. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use |
||
* | ||
* @exception {DeveloperError} The tileset must be 3D Tiles version 0.0 or 1.0. See {@link https://github.com/AnalyticalGraphicsInc/3d-tiles#spec-status} | ||
* | ||
|
@@ -334,6 +339,14 @@ define([ | |
*/ | ||
this.colorBlendAmount = 0.5; | ||
|
||
/** | ||
* Options for controlling point size based on geometric error and eye dome lighting. | ||
* @type {PointShading} | ||
*/ | ||
this.pointShading = new PointShading(options.pointShading); | ||
|
||
this._pointCloudEyeDomeLighting = new PointCloudEyeDomeLighting(); | ||
|
||
/** | ||
* The event fired to indicate progress of loading new tiles. This event is fired when a new tile | ||
* is requested, when a requested tile is finished downloading, and when a downloaded tile has been | ||
|
@@ -1632,6 +1645,7 @@ define([ | |
} | ||
} | ||
var lengthAfterUpdate = commandList.length; | ||
var addedCommandsLength = lengthAfterUpdate - lengthBeforeUpdate; | ||
|
||
tileset._backfaceCommands.trim(); | ||
|
||
|
@@ -1661,7 +1675,6 @@ define([ | |
*/ | ||
|
||
var backfaceCommands = tileset._backfaceCommands.values; | ||
var addedCommandsLength = (lengthAfterUpdate - lengthBeforeUpdate); | ||
var backfaceCommandsLength = backfaceCommands.length; | ||
|
||
commandList.length += backfaceCommandsLength; | ||
|
@@ -1680,6 +1693,13 @@ define([ | |
// Number of commands added by each update above | ||
statistics.numberOfCommands = (commandList.length - numberOfInitialCommands); | ||
|
||
// Only run EDL if simple attenuation is on | ||
if (tileset.pointShading.attenuation && | ||
tileset.pointShading.eyeDomeLighting && | ||
(addedCommandsLength > 0)) { | ||
tileset._pointCloudEyeDomeLighting.update(frameState, numberOfInitialCommands, tileset); | ||
} | ||
|
||
if (tileset.debugShowGeometricError || tileset.debugShowRenderingStatistics || tileset.debugShowMemoryUsage || tileset.debugShowUrl) { | ||
if (!defined(tileset._tileDebugLabels)) { | ||
tileset._tileDebugLabels = new LabelCollection(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This demo might look better with terrain on.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I gave it a quick try, but it looks like Chappes church is below terrain, and the terrain also doesn't perfectly align with the Mt. St. Helens points, it punches through in some views.