Hello everyone,
I’m trying to rotate a clipping plane, from the clipping plane editor (SDK object).
I end up with this function, called each time my variable “orient” changes (it is binded to a slider, representing orientation in degrees 0-360), which reconstruct clippingPlanes and editor :
Function
function updateRotation(orient) {
var angleRadians = Cesium.Math.toRadians(orient);
var dist = tileset.clippingPlanes.get(0).distance;
var rotatedPlane = new Cesium.Plane(new Cesium.Cartesian3(Math.cos(angleRadians), Math.sin(angleRadians), 0.0), dist);
//get the translation in local frame between the rotated plane and the origin
var translate = new Cesium.Cartesian3(Math.cos(angleRadians)*dist, Math.sin(angleRadians)*dist, 0.0);
clippingPlanes = new Cesium.ClippingPlaneCollection({
planes : [Cesium.ClippingPlane.fromPlane(rotatedPlane)],
edgeWidth : 1.0
});
if (Cesium.defined(clippingPlanesEditor)) {
clippingPlanesEditor.destroy();
clippingPlanesEditor = undefined;
}
tileset.clippingPlanes = clippingPlanes;
clippingPlanesEditor = new Cesium.ClippingPlanesEditor({
scene : viewer.scene,
clippingPlanes : clippingPlanes,
movePlanesToOrigin : false,
//origin : ?,
maximumSizeInMeters : new Cesium.Cartesian2(500, 500),
pixelSize : new Cesium.Cartesian2(150, 150)
});
clippingPlanesEditor.activate();
}
With this function my plane is rotating over the tileset center when its distance is not zero.
For it to rotate around itself I figured out that I need to rotate the editor’s origin around the plane (not the tileset.center otherwise my tileset would also rotate).
Or maybe something more efficient, translate the editor’s origin to the plane (the inverse of moving the plane to its origin) and setting the plane’s distance to zero (so that it would rotate over the new origin, “itself”)
Maybe there is a simpler way to achieve this effect, working with the clipping plane editor from the SDK.
I tried a lot of different approaches, like getting the translation vector between the previous plane and the new plane (rotated), then applying that translation to the new plane so that it would “stay in place”.
Or getting the translation from the origin to the plane (normal*distance).
Or playing with clippingPlanes.modelMatrix.
I tried to use Cesium.Transforms.eastNorthUpToFixedFrame to get a 4x4 transform matrix at the tileset’s center or editor’s origin, but I don’t really know what to do with it then.
Here is the complete sandcastle code (SDK required) :
Javascript
/////////////////////
////////INIT/////////
/////////////////////
var viewer = new Cesium.Viewer('cesiumContainer', {
scene3DOnly : true,
terrainProvider : Cesium.createWorldTerrain()
});
var globe = viewer.scene.globe;
globe.depthTestAgainstTerrain = true;
var viewModel = {
orientation: 0
};
Cesium.knockout.track(viewModel);
var toolbar = document.getElementById('toolbar');
Cesium.knockout.applyBindings(viewModel, toolbar);
var clippingPlanes;
var clippingPlanesEditor;
var tileset;
clippingPlanes = new Cesium.ClippingPlaneCollection({
planes : [
new Cesium.ClippingPlane(new Cesium.Cartesian3(1, 0, 0), 0),
],
unionClippingRegions : true,
edgeWidth : 1.0
});
tileset = new Cesium.Cesium3DTileset({
url : Cesium.IonResource.fromAssetId(40866),
clippingPlanes : clippingPlanes
});
tileset.readyPromise.then(function(tileset) {
viewer.scene.primitives.add(tileset);
viewer.zoomTo(tileset);
});
clippingPlanesEditor = new Cesium.ClippingPlanesEditor({
scene : viewer.scene,
clippingPlanes : tileset.clippingPlanes,
movePlanesToOrigin : true,
maximumSizeInMeters : new Cesium.Cartesian2(500, 500),
pixelSize : new Cesium.Cartesian2(150, 150)
});
clippingPlanesEditor.activate();
/////////////////////
//////END INIT///////
/////////////////////
function updateRotation(orient) {
var m4 = Cesium.Transforms.eastNorthUpToFixedFrame(clippingPlanesEditor._origin);// or tilest.boundingSphere.center ? but what for ?
var angleRadians = Cesium.Math.toRadians(orient);
var dist = tileset.clippingPlanes.get(0).distance;
//create a new plane, with rotation from the slider
var rotatedPlane = new Cesium.Plane(new Cesium.Cartesian3(Math.cos(angleRadians), Math.sin(angleRadians), 0.0), dist);
//the point in local frame where the editor's origin would be moved to
var rotatedPlaneOrigin = new Cesium.Cartesian3(Math.cos(angleRadians)*dist, Math.sin(angleRadians)*dist, 0.0);
//var newEditorOrigin = Cesium.Matrix4.multiplyByPoint(m4, rotatedPlaneOrigin);//incorrect it seems
clippingPlanes = new Cesium.ClippingPlaneCollection({
planes : [Cesium.ClippingPlane.fromPlane(rotatedPlane)],
unionClippingRegions : true,
edgeWidth : 1.0
});
if (Cesium.defined(clippingPlanesEditor)) {
clippingPlanesEditor.destroy();
clippingPlanesEditor = undefined;
}
tileset.clippingPlanes = clippingPlanes;
clippingPlanesEditor = new Cesium.ClippingPlanesEditor({
scene : viewer.scene,
clippingPlanes : clippingPlanes,
movePlanesToOrigin : false,//need to be true when the origin is translated
//origin : ?,
maximumSizeInMeters : new Cesium.Cartesian2(500, 500),
pixelSize : new Cesium.Cartesian2(150, 150)
});
clippingPlanesEditor.activate();
}
Cesium.knockout.getObservable(viewModel, 'orientation').subscribe(function(orientation) {
orientation = Number(orientation);
if (isNaN(orientation)) {
return;
}
updateRotation(orientation);
});
HTML and CSS
<style>
@import url(../templates/bucket.css);
</style>
<div id="cesiumContainer" class="fullSize"></div>
<div id="loadingOverlay"><h1>Loading...</h1></div>
<div id="toolbar">
<div>Orientation</div>
<input type="range" min="-180.0" max="180.0" step="1" data-bind="value: orientation, valueUpdate: 'input'">
<input type="text" size="5" data-bind="value: orientation">
</div>
Any help or thought is welcomed !
cesium version : latest
browser : chrome