cesium学习笔记01:加载3DTiles数据并调整模型(平移,缩放,旋转,透明)
一、基础知识
1.1 3dtitles
3D Tiles是一种开放的三维空间数据标准,其设计目的主要是为了提升大的三维场景中模型的加载和渲染速度。假如要在Web客户端渲染一个非常大的三维模型(如一个大城市的建筑模型),如果把模型全部下载到客户端并且进行渲染,这个过程所消耗的时间对于使用普通电脑的用户来说是不能接受的。然而,在绝大多数的用户交互式的三维场景中,都只需要渲染模型的一小部分,将三维模型全部加载并渲染是一种极大的资源浪费,3D Tiles为这个问题提供了一个很好的解决方案。将三维空间数据组织为3D Tiles格式,可以实现模型的按需加载和渲染,从而实现流畅的三维模型浏览体验。
具体详情:可查看以下链接所述
参考链接1:Cesium 3dTiles 简介
参考链接2:Cesium数据规范详解
1.2 矩阵变换
在Cesium和其他三维开发中中经常用到矩阵变换。比如将一个物体移动、缩放、平移都可以用变换矩阵来计算。
再比如将三维场景中的物体转换为屏幕上显示的二维图形,需要用到透视投影(perspective projection)矩阵。
变换(tansformation)是一个函数,实现将一个空间坐标映射为另一个空间坐标,矩阵(matrix)是这种计算的一种方式,在三维开发中用途广泛。
注:cesium中的变换最终要再世界坐标系下进行体现,这是cesium矩阵变换的关键,否则会出现偏移过大的情况
二、cesium加载3Dtiles
代码示例
viewer = new Cesium.Viewer("cesiumContainer", {
terrainProvider: Cesium.createWorldTerrain(),
});
// 加载3Dtiles文件
tileSet = new Cesium.Cesium3DTileset({
// 这里的地址可以是本地地址或者是网络地址。如果是网络地址,可能会出现跨域问题,建议使用nginx服务做跨域处理
url: "3DTiles/tileset/tileset.json",
//maximumScreenSpaceError: 2, //最大的屏幕空间误差
//maximumNumberOfLoadedTiles: 1000, //最大加载瓦片个数
});
tileSet.readyPromise.then((tileset) => {
viewer.scene.primitives.add(tileset);
boundingSphereCenter = tileset.boundingSphere.center // 后续的变换需要这个变量
// 定位到该模型
viewer.zoomTo(
tileset,
// cesium方位角,可以试着调节参数掌握api的使用
new Cesium.HeadingPitchRange(
0.0,
-0.5,
tileset.boundingSphere.radius * 4.0
)
);
})
三 :3DTiles平移变换
注:每次平移变换都是根据原始模型中心作为起始,因此加载3DTiles时,将原始模型和原始模型的中心坐标缓存至变量中:tileSet 和 boundingSphereCenter中 ,同样适用与旋转,缩放
代码示例
平移思路:首先平移的矩阵是属于局部坐标系下的矩阵,我们需要统一再世界坐标系进行矩阵变换。
首先获取模型中心世界坐标(即变换起始的坐标),在获取平移过后的世界坐标。相减即可得到平移坐标。
getTranslationMatrix(mdlParams) {
const cartographicCenter =
Cesium.Cartographic.fromCartesian(boundingSphereCenter);
const surface = Cesium.Cartesian3.fromRadians(
cartographicCenter.longitude,
cartographicCenter.latitude,
0.0
);
const offset = Cesium.Cartesian3.fromDegrees(
mdlParams.longitude,
mdlParams.latitude,
mdlParams.height
);
// 平移矩阵必须相减,才能得到贴面的模型
const translation = Cesium.Cartesian3.subtract(
offset,
surface,
new Cesium.Cartesian3()
);
const translationMatrix4 = Cesium.Matrix4.fromTranslation(translation);
return translationMatrix4
}
四:3DTiles旋转变换
旋转思路:先将模型平移到世界中心坐标,在进行旋转,最后在平移回来。
代码示例:
tileset
.readyPromise
.then(tileset => {
const tileset_center = tileset.boundingSphere.center; // Cartesian3
const frompoint_to_world_matrix = Cesium.Transforms.eastNorthUpToFixedFrame(tileset_center); // Matrix4
const local_translation = new Cesium.Cartesian3(310, -140, 10); // 向模型中心为原点,正北为y,正东为x,地心朝上为z分别平移 310、-140、10米
const result = new Cesium.Cartesian3(0,0,0);
Cesium.Matrix4.multiplyByPoint(frompoint_to_world_matrix, local_translation, result); // 转换矩阵左乘局部平移向量,结果存储在 result 中,结果是世界坐标下的平移终点向量
const targetpoint_to_world_matrix = Cesium.Transforms.eastNorthUpToFixedFrame(result);
const world_translation = new Cesium.Cartesian3(
targetpoint_to_world_matrix[12] - frompoint_to_world_matrix[12],
targetpoint_to_world_matrix[13] - frompoint_to_world_matrix[13],
targetpoint_to_world_matrix[14] - frompoint_to_world_matrix[14],
); // 向量相减,得到世界坐标下的平移向量
tileset.modelMatrix = Cesium.Matrix4.fromTranslation(world_translation); // 构造平移矩阵并赋值
viewer.zoomTo(tileset);
});
五:3DTiles 模型缩放
思路于模型旋转一样,下面是构造模型缩放矩阵的代码
代码示例:
getScaleMatrix4(scaleX, scaleY, scaleZ) {
// 构造局部缩放矩阵
const cartesianScale = new Cesium.Cartesian3(scaleX, scaleY, scaleZ);
const localScaleM = Cesium.Matrix4.fromScale(
cartesianScale,
new Cesium.Matrix4()
);
console.log("缩放本地矩阵:" + localScaleM);
// 构造世界坐标中心矩阵
const backto_Martix =
Cesium.Matrix4.fromTranslation(boundingSphereCenter);
// 构建返回的变换举证
const moveto_vec = Cesium.Cartesian3.multiplyByScalar(
boundingSphereCenter,
-1,
new Cesium.Cartesian3()
);
const moveto_Martix = Cesium.Matrix4.fromTranslation(moveto_vec);
// 矩阵计算,构建缩放矩阵
const temp = Cesium.Matrix4.multiply(
localScaleM,
moveto_Martix,
new Cesium.Matrix4()
);
const resultM = Cesium.Matrix4.multiply(
backto_Martix,
temp,
new Cesium.Matrix4()
);
return resultM;
},
六 地表透明
1、需开启地表透明
mdlScene.globe.translucency.enabled = true; // 开启地表透明
2、通过设置mdlScene.globe.translucency的属性来设置透明度,有远近之区分
mdlScene.globe.translucency.frontFaceAlphaByDistance =new Cesium.NearFarScalar(1000.0, 1, 1000000.0, 1);
3、 自己查看官网api,自行调式透明效果