cesium/Apps/Sandcastle/gallery/3D Tiles Clipping Planes.html

332 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 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="../../../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;
}
#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>
<input
type="checkbox"
value="false"
data-bind="checked: debugBoundingVolumesEnabled, valueUpdate: 'input'"
/>
Show bounding volume
<input
type="checkbox"
value="true"
data-bind="checked: edgeStylingEnabled, valueUpdate: 'input'"
/>
Enable edge styling
</div>
<script id="cesium_sandcastle_script">
window.startup = async function (Cesium) {
"use strict";
//Sandcastle_Begin
// Add a clipping plane, a plane geometry to show the representation of the
// plane, and control the magnitude of the plane distance with the mouse.
const viewer = new Cesium.Viewer("cesiumContainer", {
infoBox: false,
selectionIndicator: false,
});
const scene = viewer.scene;
viewer.clock.currentTime = Cesium.JulianDate.fromIso8601("2022-08-01T00:00:00Z");
const clipObjects = ["BIM", "Point Cloud", "Instanced", "Model"];
const viewModel = {
debugBoundingVolumesEnabled: false,
edgeStylingEnabled: true,
exampleTypes: clipObjects,
currentExampleType: clipObjects[0],
};
let targetY = 0.0;
let planeEntities = [];
let selectedPlane;
let clippingPlanes;
// Select plane when mouse down
const downHandler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
downHandler.setInputAction(function (movement) {
const pickedObject = scene.pick(movement.position);
if (
Cesium.defined(pickedObject) &&
Cesium.defined(pickedObject.id) &&
Cesium.defined(pickedObject.id.plane)
) {
selectedPlane = pickedObject.id.plane;
selectedPlane.material = Cesium.Color.WHITE.withAlpha(0.05);
selectedPlane.outlineColor = Cesium.Color.WHITE;
scene.screenSpaceCameraController.enableInputs = false;
}
}, Cesium.ScreenSpaceEventType.LEFT_DOWN);
// Release plane on mouse up
const upHandler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
upHandler.setInputAction(function () {
if (Cesium.defined(selectedPlane)) {
selectedPlane.material = Cesium.Color.WHITE.withAlpha(0.1);
selectedPlane.outlineColor = Cesium.Color.WHITE;
selectedPlane = undefined;
}
scene.screenSpaceCameraController.enableInputs = true;
}, Cesium.ScreenSpaceEventType.LEFT_UP);
// Update plane on mouse move
const moveHandler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
moveHandler.setInputAction(function (movement) {
if (Cesium.defined(selectedPlane)) {
const deltaY = movement.startPosition.y - movement.endPosition.y;
targetY += deltaY;
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
function createPlaneUpdateFunction(plane) {
return function () {
plane.distance = targetY;
return plane;
};
}
let tileset;
async function loadTileset(resource, modelMatrix) {
const currentExampleType = viewModel.currentExampleType;
clippingPlanes = new Cesium.ClippingPlaneCollection({
planes: [
new Cesium.ClippingPlane(new Cesium.Cartesian3(0.0, 0.0, -1.0), 0.0),
],
edgeWidth: viewModel.edgeStylingEnabled ? 1.0 : 0.0,
});
try {
const url = await Promise.resolve(resource);
tileset = await Cesium.Cesium3DTileset.fromUrl(url, {
clippingPlanes: clippingPlanes,
});
if (currentExampleType !== viewModel.currentExampleType) {
// Another tileset was loaded, discard the current result
return;
}
if (Cesium.defined(modelMatrix)) {
tileset.modelMatrix = modelMatrix;
}
viewer.scene.primitives.add(tileset);
tileset.debugShowBoundingVolume = viewModel.debugBoundingVolumesEnabled;
const boundingSphere = tileset.boundingSphere;
const radius = boundingSphere.radius;
viewer.zoomTo(tileset, new Cesium.HeadingPitchRange(0.5, -0.2, radius * 4.0));
if (!Cesium.Matrix4.equals(tileset.root.transform, Cesium.Matrix4.IDENTITY)) {
// The clipping plane is initially positioned at the tileset's root transform.
// Apply an additional matrix to center the clipping plane on the bounding sphere center.
const transformCenter = Cesium.Matrix4.getTranslation(
tileset.root.transform,
new Cesium.Cartesian3(),
);
const transformCartographic =
Cesium.Cartographic.fromCartesian(transformCenter);
const boundingSphereCartographic = Cesium.Cartographic.fromCartesian(
tileset.boundingSphere.center,
);
const height =
boundingSphereCartographic.height - transformCartographic.height;
clippingPlanes.modelMatrix = Cesium.Matrix4.fromTranslation(
new Cesium.Cartesian3(0.0, 0.0, height),
);
}
for (let i = 0; i < clippingPlanes.length; ++i) {
const plane = clippingPlanes.get(i);
const planeEntity = viewer.entities.add({
position: boundingSphere.center,
plane: {
dimensions: new Cesium.Cartesian2(radius * 2.5, radius * 2.5),
material: Cesium.Color.WHITE.withAlpha(0.1),
plane: new Cesium.CallbackProperty(
createPlaneUpdateFunction(plane),
false,
),
outline: true,
outlineColor: Cesium.Color.WHITE,
},
});
planeEntities.push(planeEntity);
}
return tileset;
} catch (error) {
console.log(`Error loading tileset: ${error}`);
}
}
function loadModel(url) {
clippingPlanes = new Cesium.ClippingPlaneCollection({
planes: [
new Cesium.ClippingPlane(new Cesium.Cartesian3(0.0, 0.0, -1.0), 0.0),
],
edgeWidth: viewModel.edgeStylingEnabled ? 1.0 : 0.0,
});
const position = Cesium.Cartesian3.fromDegrees(-123.0744619, 44.0503706, 300.0);
const heading = Cesium.Math.toRadians(135.0);
const pitch = 0.0;
const roll = 0.0;
const hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);
const orientation = Cesium.Transforms.headingPitchRollQuaternion(position, hpr);
const entity = viewer.entities.add({
name: url,
position: position,
orientation: orientation,
model: {
uri: url,
scale: 8,
minimumPixelSize: 100.0,
clippingPlanes: clippingPlanes,
},
});
viewer.trackedEntity = entity;
for (let i = 0; i < clippingPlanes.length; ++i) {
const plane = clippingPlanes.get(i);
const planeEntity = viewer.entities.add({
position: position,
plane: {
dimensions: new Cesium.Cartesian2(300.0, 300.0),
material: Cesium.Color.WHITE.withAlpha(0.1),
plane: new Cesium.CallbackProperty(
createPlaneUpdateFunction(plane),
false,
),
outline: true,
outlineColor: Cesium.Color.WHITE,
},
});
planeEntities.push(planeEntity);
}
}
// Power Plant design model provided by Bentley Systems
const bimUrl = Cesium.IonResource.fromAssetId(2464651);
const pointCloudUrl = Cesium.IonResource.fromAssetId(16421);
const instancedUrl =
"../../SampleData/Cesium3DTiles/Instanced/InstancedOrientation/tileset.json";
const modelUrl = "../../SampleData/models/CesiumAir/Cesium_Air.glb";
loadTileset(bimUrl);
// Track and create the bindings for the view model
const toolbar = document.getElementById("toolbar");
Cesium.knockout.track(viewModel);
Cesium.knockout.applyBindings(viewModel, toolbar);
Cesium.knockout
.getObservable(viewModel, "currentExampleType")
.subscribe(function (newValue) {
reset();
if (newValue === clipObjects[0]) {
loadTileset(bimUrl);
} else if (newValue === clipObjects[1]) {
loadTileset(pointCloudUrl);
} else if (newValue === clipObjects[2]) {
// Position the instanced tileset above terrain
loadTileset(
instancedUrl,
Cesium.Matrix4.fromTranslation(
new Cesium.Cartesian3(15.0, -58.6, 50.825),
),
);
} else {
loadModel(modelUrl);
}
});
Cesium.knockout
.getObservable(viewModel, "debugBoundingVolumesEnabled")
.subscribe(function (value) {
if (Cesium.defined(tileset)) {
tileset.debugShowBoundingVolume = value;
}
});
Cesium.knockout
.getObservable(viewModel, "edgeStylingEnabled")
.subscribe(function (value) {
const edgeWidth = value ? 1.0 : 0.0;
clippingPlanes.edgeWidth = edgeWidth;
});
function reset() {
viewer.entities.removeAll();
if (Cesium.defined(tileset)) {
viewer.scene.primitives.remove(tileset);
}
planeEntities = [];
targetY = 0.0;
tileset = undefined;
}
//Sandcastle_End
};
if (typeof Cesium !== "undefined") {
window.startupCalled = true;
window.startup(Cesium).catch((error) => {
"use strict";
console.error(error);
});
Sandcastle.finishedLoading();
}
</script>
</body>
</html>