cesium模型压平(简易版)

摸索半天并未搜到有具体的实现方式,但从众多文章里边找到了一条小路。大家都知道思路就是修改顶点着色器的高度值,但是怎么去修改?

下边是我参考的两篇文章,感谢岭南灯火、百年内必成大牛

https://www.cnblogs.com/webglblog#/c/subject/p/17093810.html

https://www.cnblogs.com/onsummer/p/14212009.html

cesium模型压平(简易版)_第1张图片

 

customShader中修改vertexShaderText,vsOutput.positionMC就是最后输出的模型内部顶点坐标,可以在官方沙盒测试一下,大家都说修改高度,那就直接让它的z等于0,有变化了,模型变平了,哎怎么是斜的,修改xy也是斜的。

这个时候你可能会问是不是少了什么?难道还要变换矩阵吗?这可就费劲了,上学时候线性代数我都是60多分啊,其实不是我们只需换个自己的数据再试一下就会看到正常的变化,而且3dtiles的坐标轴不一样,更改的参数也不一样,需要试一下,一般是修改y。

 

 vertexShaderText: `
  void vertexMain(VertexInput vsInput, inout czm_modelVertexOutput vsOutput) {
    vsOutput.positionMC.y = 0.;
  }
  `,

 找了自己的数据试了以后又出来了一个新的问题,不同瓦片并不是在同一个平面,根据以往经验应该还是包围盒中心点不在一个高度,所以不能直接想当然的等于0,让它贴地。

由于这里我已经把范围点传进来了,就试了下等于传进来点的y,效果是几乎在一个平面上,对是几乎。不同瓦片之间存在缝隙及闪面问题,闪面应该是重合的问题,缝隙是不同瓦片高度还是存在一点点差别。

cesium模型压平(简易版)_第2张图片

 

这里先不谈缝隙及闪面,暂未深究。

那么外部点是怎么传进去的呢,答案是uniforms,先来个四边形吧,实际上只需要对角线的1和3就行。

cesium模型压平(简易版)_第3张图片

 

      uniforms: {
        u_firstPWC: {
          type: Cesium.UniformType.VEC3,
          value: Cesium.Cartesian3.fromDegrees(
            113.84576776093665,34.70286868401709,25
          ),
        },
        u_first2PWC: {
          type: Cesium.UniformType.VEC3,
          value: Cesium.Cartesian3.fromDegrees(
            113.84676776093665,34.70286868401709, 25
          ),
        },
        u_first3PWC: {
          type: Cesium.UniformType.VEC3,
          value: Cesium.Cartesian3.fromDegrees(
            113.84676776093665,34.70186868401709, 25
          ),
        },
        u_first4PWC: {
          type: Cesium.UniformType.VEC3,
          value: Cesium.Cartesian3.fromDegrees(
            113.84576776093665,34.70186868401709, 25
          ),
        },
      },

 上边第二篇文章里有世界坐标转模型内部坐标的方法

cesium模型压平(简易版)_第4张图片

可以通过四边形范围的x和z来限制压平范围,(xz方向可能不同需要自己调整), 至于不规则多边形可以通过点是否在多边形内判断,网上一大堆可以去试试,然后加上交互把多边形点传进去就行了。一般项目里压平操作是为了放置或替换其他模型,比如挖掉倾斜然后放精模,矩形就够了。不压平裁剪掉也可以。

vertexShaderText: `
      void vertexMain(VertexInput vsInput, inout czm_modelVertexOutput vsOutput) {
        vec4 firstpMC = czm_inverseModel * vec4(u_firstPWC, 1);
        vec4 firstp3MC = czm_inverseModel * vec4(u_first3PWC, 1);
        if(vsOutput.positionMC.x>firstpMC.x && vsOutput.positionMC.xfirstp3MC.z && vsOutput.positionMC.z

总结一下,本文只是简易版,能凑合用,未测试更多数据,(大雁塔数据没有缝隙)具体效果因数据而异。目前大面积压平有闪面、缝隙、视锥裁剪问题,欢迎其他朋友分享解决方案。

cesium版本是103,最后CustomShader完整代码

    let customShader = new Cesium.CustomShader({
      lightingModel: Cesium.LightingModel.UNLIT,
      uniforms: {
        u_firstPWC: {
          type: Cesium.UniformType.VEC3,
          value: Cesium.Cartesian3.fromDegrees(
            113.84576776093665,34.70286868401709,25
          ),
        },
        u_first2PWC: {
          type: Cesium.UniformType.VEC3,
          value: Cesium.Cartesian3.fromDegrees(
            113.84676776093665,34.70286868401709, 25
          ),
        },
        u_first3PWC: {
          type: Cesium.UniformType.VEC3,
          value: Cesium.Cartesian3.fromDegrees(
            113.84676776093665,34.70186868401709, 25
          ),
        },
        u_first4PWC: {
          type: Cesium.UniformType.VEC3,
          value: Cesium.Cartesian3.fromDegrees(
            113.84576776093665,34.70186868401709, 25
          ),
        },
      },
      vertexShaderText: `
      void vertexMain(VertexInput vsInput, inout czm_modelVertexOutput vsOutput) {
        vec4 firstpMC = czm_inverseModel * vec4(u_firstPWC, 1);
        vec4 firstp3MC = czm_inverseModel * vec4(u_first3PWC, 1);
        if(vsOutput.positionMC.x>firstpMC.x && vsOutput.positionMC.xfirstp3MC.z && vsOutput.positionMC.z

写东西确实有点费劲~


你可能感兴趣的:(Cesium,开源)