加载3DTiles数据并调整模型

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,自行调式透明效果

七 综合效果

综合效果

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值