需求:屏幕上点击两点划线对场景进行剖切(相机作为第三个点),常见场景如切西瓜。
针对glb模型
针对tileset
核心思想:
1.viewer.camera.getPickRay函数不受相机位置的影响。
2.剖面是以物体(origin)为原点的物体坐标系形成的。
3.基于上述两点,相机到划线两点的两方向向量需要进行转换,从全局坐标转到物体东北上坐标系。且此时“相机”坐标也需要转换为物体坐标,通过两方向向量确定平面的法向量,再根据平面上的一点来生成对应的平面即可。
4.第3点中的相机坐标打引号了,是因为当viewer.trackedEntity=entity之后,相机坐标此时为东北上的物体坐标系,且带有一定偏移。经测试发现可能和glb模型的建模原点与包围体中心点不一致导致,但经过计算比较也合不上。 所以第3点中的相机坐标来源于第1点提到的函数,该函数可以得到方向向量的起点(即相机实际位置)和方向。
5.坐标转换从全局坐标到物体坐标由eastNorthUpToFixedFrame实现,position为物体(glb)放置的位置
const transform = Cesium.Transforms.eastNorthUpToFixedFrame(position);
const inverse = new Cesium.Matrix4();
Cesium.Matrix4.inverse(transform,
inverse
);
6.若是3dtiles格式则需要看其transform矩阵,如果没有,则第5点提到的position即为包围球的中心
function getInverseTransform (tileSet) {
let transform;
let tmp = tileSet.root.transform;
let tempPos1=tileSet.boundingSphere.center;
if ((tmp && tmp.equals(Cesium.Matrix4.IDENTITY)) || !tmp) {
transform = Cesium.Transforms.eastNorthUpToFixedFrame(tileSet.boundingSphere.center);
} else {
transform = Cesium.Matrix4.fromArray(tileSet.root.transform);
tempPos1 = new Cesium.Cartesian3(tileset.root.transform[12],tileset.root.transform[13],tileset.root.transform[14]);
}
const inverse = new Cesium.Matrix4();
Cesium.Matrix4.inverse(transform,
inverse
);
return [transform,tempPos1,inverse];
}