3D瓦片的加载
(1)利用Cesium中Cesium3DTileset.fromUrl加载瓦片,参数是options,包括可见性、最大屏幕空间误差等,这个函数返回一个Promise,因此最好利用await关键字实现同步。
tileset = await Cesium.Cesium3DTileset.fromUrl(url, {
maximumScreenSpaceError: 2,
maximumNumberOfLoadedTiles: 1000,
debugShowBoundingVolume: false,
debugFreezeFrame: false,
refineToVisible: Cesium.defaultValue(false, !0),
...
})
(2)将瓦片通过Primitive的方式加载到视图中
viewer.scene.primitives.add(tileset)
(3)对瓦片进行从局部坐标系到世界坐标的转换
var position = tileset.boundingsphere.center;
var transform = Cesium.Transforms.eastNorthUpToFixedFrame(position);
tileset._root.transform = transform;
平移
在Cesium中实现平移有两种情况,第一种情况,假设你知道在世界坐标系下平移后的目标位置,我们设为b,从目标a到目标b的平移,通过矢量相减得到由a指向b的向量,这里得到的平移向量实际上是世界坐标系下的,因此当向量转为齐次坐标下的四维平移矩阵后,这个矩阵可以直接赋值给模型的modelmatrix。
const boundingSphere = titleset.boundingSphere;
const offset = Cesium.Cartesian3.fromDegrees(x, y, z);
const translation = Cesium.Cartesian3.subtract(offset, boundingSphere.center, new Cesium.Cartesian3());
tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation);
第二种情况,假设你不知道平移后的目标位置,你只知道模型朝着当前的东南西北哪个方向去移动。首先获取以当前模型位置为原点的局部坐标系到世界坐标系的转换矩阵,然后根据局部坐标系的xyz(东北天)进行移动,由于这里的平移是在局部坐标系下的,因此需要将平移量与坐标系转换矩阵进行左乘,得到在世界坐标系下的平移终点。现在已知在世界坐标系下平移后的目标位置,那么就又回到了第一种情况。
const tileset_center = tileset.boundingSphere.center;
const frompoint_to_world_matrix = Cesium.Transforms.eastNorthUpToFixedFrame(tileset_center);
//以模型中心为原点的局部坐标系下向东\北\天移动x,y,z的分量
const local_translation = new Cesium.Cartesian3(x, y, z);
const result = new Cesium.Cartesian3(0,0,0);
//局部坐标系到世界坐标系的转换矩阵左乘平移向量得到世界坐标系下的平移终点
Cesium.Matrix4.multiplyByPoint(frompoint_to_world_matrix, local_translation, result);
//问题回到了第一种情况
const translation = Cesium.Cartesian3.subtract(result, boundingSphere.center, new Cesium.Cartesian3());
tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation);
上述问题从下图看就是知道红色向量,和绿色向量,实现从红色到蓝色的平移
旋转
模型的旋转会根据旋转中心的不同而不同
(1)模型绕地心旋转
如果是绕地心旋转,不用考虑局部坐标系变换的问题,直接使用Cesium中Cesium.Matrix3.fromRotationX(),再通过Cesium.Matrix4.fromRotationTranslation或者Cesium.Matrix4.fromRotation构建齐次坐标系的旋转矩阵赋给modelmatrix,这就是绕世界坐标系下的xyz轴旋转。
//以绕x轴旋转为例
var x = Cesium.Matrix3.fromRotationX(Cesium.Math.toRadians(rotateX));
//三维矩阵转四维齐次矩阵
var rotationX = Cesium.Matrix4.fromRotation(mx);
tileset._root.transform = rotationX
在三维转四维的时候也可以用Cesium.Matrix4.fromRotationTranslation,这个函数既可以接受matrix3的旋转矩阵,还可以接受一个cartesian3的平移矩阵,不过平移参数是可选的(optional)。
(2)模型绕本身旋转
这里的本身通常是模型的几何中心点,对于三维瓦片而言就是瓦片的boundingsphere.center,旋转的方法和绕地心旋转类似,只是最后得到的旋转矩阵需要与坐标系转换矩阵相乘
//还是以绕x轴为例
var x = Cesium.Matrix3.fromRotationX(Cesium.Math.toRadians(0));
var rotationX = Cesium.Matrix4.fromRotation(mx);
var position = tileset.boundingSphere.center;
var transform = Cesium.Transforms.eastNorthUpToFixedFrame(position);
Cesium.Matrix4.multiply(transform, rotationX, transform);
tileset._root.transform = transform;