cesium/Apps/Sandcastle/gallery/Terrain Clipping Planes.html

364 lines
12 KiB
HTML

<!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="User-defined clipping planes applied to terrain." />
<meta name="cesium-sandcastle-labels" content="Showcases" />
<title>Cesium Demo</title>
<script type="text/javascript" src="../Sandcastle-header.js"></script>
<script
type="text/javascript"
src="../../../Build/CesiumUnminified/Cesium.js"
nomodule
></script>
<script type="module" src="../load-cesium-es6.js"></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;
}
</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>
<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">
window.startup = async function (Cesium) {
"use strict";
//Sandcastle_Begin
// Use clipping planes to selectively hide parts of the globe surface.
const viewer = new Cesium.Viewer("cesiumContainer", {
skyAtmosphere: false,
shouldAnimate: true,
terrain: Cesium.Terrain.fromWorldTerrain(),
scene3DOnly: true,
});
const globe = viewer.scene.globe;
const exampleTypes = ["Cesium Man", "St. Helens", "Grand Canyon Isolated"];
const viewModel = {
exampleTypes: exampleTypes,
currentExampleType: exampleTypes[0],
clippingPlanesEnabled: true,
edgeStylingEnabled: true,
};
const toolbar = document.getElementById("toolbar");
Cesium.knockout.track(viewModel);
Cesium.knockout.applyBindings(viewModel, toolbar);
// For tracking state when switching exampleTypes
let clippingPlanesEnabled = true;
let edgeStylingEnabled = true;
let tileset;
loadCesiumMan();
function reset() {
viewer.entities.removeAll();
viewer.scene.primitives.remove(tileset);
}
function loadCesiumMan() {
const position = Cesium.Cartesian3.fromRadians(
-2.0862979473351286,
0.6586620013036164,
1400.0,
);
const 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,
});
globe.backFaceCulling = true;
globe.showSkirts = true;
viewer.trackedEntity = entity;
}
async function loadStHelens() {
// Create clipping planes for polygon around area to be clipped.
const 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,
),
];
const pointsLength = points.length;
// Create center points for each clipping plane
const clippingPlanes = [];
for (let i = 0; i < pointsLength; ++i) {
const nextIndex = (i + 1) % pointsLength;
let midpoint = Cesium.Cartesian3.add(
points[i],
points[nextIndex],
new Cesium.Cartesian3(),
);
midpoint = Cesium.Cartesian3.multiplyByScalar(midpoint, 0.5, midpoint);
const up = Cesium.Cartesian3.normalize(midpoint, new Cesium.Cartesian3());
let right = Cesium.Cartesian3.subtract(
points[nextIndex],
midpoint,
new Cesium.Cartesian3(),
);
right = Cesium.Cartesian3.normalize(right, right);
let 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
const originCenteredPlane = new Cesium.Plane(normal, 0.0);
const 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,
});
globe.backFaceCulling = true;
globe.showSkirts = true;
try {
// Load tileset
tileset = await Cesium.Cesium3DTileset.fromIonAssetId(5713);
if (viewModel.currentExampleType !== exampleTypes[1]) {
// Scenario has changed. Discard the result.
return;
}
// Adjust height so tileset is in terrain
const cartographic = Cesium.Cartographic.fromCartesian(
tileset.boundingSphere.center,
);
const surface = Cesium.Cartesian3.fromRadians(
cartographic.longitude,
cartographic.latitude,
0.0,
);
const offset = Cesium.Cartesian3.fromRadians(
cartographic.longitude,
cartographic.latitude,
-20.0,
);
const 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);
const boundingSphere = tileset.boundingSphere;
const radius = boundingSphere.radius;
viewer.camera.viewBoundingSphere(
boundingSphere,
new Cesium.HeadingPitchRange(0.5, -0.2, radius * 4.0),
);
viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
} catch (error) {
console.log(`Error loading tileset: ${error}`);
}
}
function loadGrandCanyon() {
// Pick a position at the Grand Canyon
const position = Cesium.Cartographic.toCartesian(
new Cesium.Cartographic.fromDegrees(-113.2665534, 36.0939345, 100),
);
const distance = 3000.0;
const boundingSphere = new Cesium.BoundingSphere(position, distance);
globe.clippingPlanes = new Cesium.ClippingPlaneCollection({
modelMatrix: Cesium.Transforms.eastNorthUpToFixedFrame(position),
planes: [
new Cesium.ClippingPlane(new Cesium.Cartesian3(1.0, 0.0, 0.0), distance),
new Cesium.ClippingPlane(new Cesium.Cartesian3(-1.0, 0.0, 0.0), distance),
new Cesium.ClippingPlane(new Cesium.Cartesian3(0.0, 1.0, 0.0), distance),
new Cesium.ClippingPlane(new Cesium.Cartesian3(0.0, -1.0, 0.0), distance),
],
unionClippingRegions: true,
edgeWidth: edgeStylingEnabled ? 1.0 : 0.0,
edgeColor: Cesium.Color.WHITE,
enabled: clippingPlanesEnabled,
});
globe.backFaceCulling = false;
globe.showSkirts = false;
viewer.camera.viewBoundingSphere(
boundingSphere,
new Cesium.HeadingPitchRange(0.5, -0.5, boundingSphere.radius * 5.0),
);
viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
}
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();
} else if (newValue === exampleTypes[2]) {
loadGrandCanyon();
}
}); //Sandcastle_End
};
if (typeof Cesium !== "undefined") {
window.startupCalled = true;
window.startup(Cesium).catch((error) => {
"use strict";
console.error(error);
});
Sandcastle.finishedLoading();
}
</script>
</body>
</html>