weixin_45881177 2025-08-12 11:05 采纳率: 0%
浏览 15

在加载Cesium.Geometry时,仰视视角(高于平视视角)对象消失不显示的问题怎么解决?

在加载Cesium.Geometry时,仰视视角(高于平视视角)对象消失不显示的问题怎么解决?

cesium里面我创建了一个Geometry->GeometryInstance->Primitive的对象,在我俯视的时候,即使高度低于对象也可以显示,但是一旦相机视角高于平视(仰视)的时候,对象就会消失不显示?
我在Primitive中已经关闭了背面剔除效果,但是还是会出现这种问题。
是因为我创建的对象的问题还是cesium本身不支持?如果这样的话,一般cesium是怎么将这种灰度图像加载上再三维显示的呀(不是作为高程加载)

附上代码:

const geometry = new Cesium.Geometry({
      attributes: {
        position: new Cesium.GeometryAttribute({
          componentDatatype: Cesium.ComponentDatatype.DOUBLE,
          componentsPerAttribute: 3,
          values: new Float64Array(
              Cesium.Cartesian3.packArray(Cesium.Cartesian3.fromDegreesArrayHeights(new Float64Array(positions)))
          ),
        }),
        normal: new Cesium.GeometryAttribute({
          componentDatatype: Cesium.ComponentDatatype.FLOAT,
          componentsPerAttribute: 3,
          values: new Float32Array(normals),
        }),
        color: new Cesium.GeometryAttribute({
          componentDatatype: Cesium.ComponentDatatype.FLOAT,
          componentsPerAttribute: 4,
          values: new Float32Array(colors),
        }),
      },
      primitiveType: Cesium.PrimitiveType.TRIANGLES,
      vertexFormat: Cesium.VertexFormat.POSITION_AND_COLOR,
      boundingSphere: Cesium.BoundingSphere.fromVertices(new Float64Array(positions)),
    });

    console.log('geometry created successfully:', geometry);

    const geometryInstance = new Cesium.GeometryInstance({
      geometry: geometry,
      modelMatrix: Cesium.Matrix4.IDENTITY,
      id: 'horizon',
    });

    const primitive = new Cesium.Primitive({
      geometryInstances: geometryInstance,
      // 修复视角问题的外观设置
      appearance: new Cesium.PerInstanceColorAppearance({
        translucent: false,
        closed: false, // 允许从内部看到几何体
        flat: true,
      }),
      asynchronous: false,
      cull: false, // 禁用背面剔除
      frustumCulled:false,
      show: true,
    });

俯视:

img

仰视:

img

  • 写回答

4条回答 默认 最新

  • 檀越@新空间 2025-08-12 11:06
    关注

    上午好☀️☀️☀️️
    本答案参考通义千问

    在使用 Cesium 创建 Geometry 对象并将其显示为 Primitive 时,仰视视角下对象消失不显示的问题,通常与 Cesium 的裁剪(Frustum Culling)机制光照和法线方向几何体的朝向有关。


    ✅ 问题分析

    你提到:

    • 俯视时可以正常显示
    • 仰视时对象消失
    • 已关闭了 背面剔除(cull: false)
    • 使用的是 PerInstanceColorAppearance,且设置了 closed: false

    可能原因总结如下:

    1. 几何体的法线方向不正确:Cesium 在渲染时依赖法线方向进行光照计算。如果法线方向与相机方向相反,可能会导致对象在某些视角下“不可见”。
    2. Frustum Culling 被误触发:虽然你设置了 frustumCulled: false,但可能由于其他配置或相机设置,仍然被裁剪。
    3. Geometry 本身存在错误:例如顶点顺序错误、面片方向不一致等。
    4. 光照/颜色计算问题:如果使用了光照相关外观(如 MaterialAppearance),可能会因光照方向导致颜色变暗或不可见。

    🛠️ 解决方案

    以下是针对上述问题的详细解决步骤:

    1. 检查 Geometry 法线方向是否正确

    Cesium 的 PerInstanceColorAppearance 默认会使用法线进行光照计算,如果你没有提供法线,Cesium 会自动计算,但可能导致光照方向不一致。

    重点:确保法线方向统一指向“外部”

    // 确保法线方向是正确的,比如面向外
    // 如果你的模型是向外的,那么法线应该指向模型外侧
    

    如果法线方向不对,建议手动指定法线,或者通过代码调整法线方向。


    2. 禁用 Frustum Culling 并验证

    你已经设置了 frustumCulled: false,但有时候 Cesium 的某些内部逻辑仍可能影响显示。

    重点:确保 Primitive 和 Scene 的 frustum culling 设置正确

    const primitive = new Cesium.Primitive({
      geometryInstances: geometryInstance,
      appearance: new Cesium.PerInstanceColorAppearance({
        translucent: false,
        closed: false,
        flat: true,
      }),
      asynchronous: false,
      cull: false, // 关闭背面剔除
      frustumCulled: false, // 强制关闭视锥体裁剪
      show: true,
    });
    

    3. 使用 MaterialAppearanceColorAppearance 替代 PerInstanceColorAppearance

    PerInstanceColorAppearance 会基于法线进行光照计算,可能导致某些视角下颜色变暗或不可见。

    重点:尝试使用 ColorAppearanceMaterialAppearance 来避免光照问题

    const appearance = new Cesium.ColorAppearance({
      translucent: false,
      material: Cesium.Material.fromType('Color'),
    });
    

    4. 检查 Geometry 的顶点顺序是否正确

    Cesium 渲染三角形时,依赖顶点顺序来判断面片的“正面”或“背面”。如果顶点顺序混乱,可能导致某些视角下无法渲染。

    重点:确保三角形顶点顺序是顺时针或逆时针一致

    你可以使用 Cesium.Geometry 构造器时,确认 primitiveTypeTRIANGLES,并且 positions 是正确顺序的数组。


    5. 使用 BoundingSphere 正确初始化

    确保 boundingSphere 是根据 positions 正确生成的。

    boundingSphere: Cesium.BoundingSphere.fromVertices(
      Cesium.Cartesian3.fromDegreesArrayHeights(positions)
    )
    

    ✅ 修改后的完整代码示例

    const positions = [
      [lon1, lat1, height1],
      [lon2, lat2, height2],
      [lon3, lat3, height3],
      // ...更多坐标
    ];
    
    const geometry = new Cesium.Geometry({
      attributes: {
        position: new Cesium.GeometryAttribute({
          componentDatatype: Cesium.ComponentDatatype.DOUBLE,
          componentsPerAttribute: 3,
          values: Cesium.Cartesian3.packArray(
            Cesium.Cartesian3.fromDegreesArrayHeights(positions)
          ),
        }),
        color: new Cesium.GeometryAttribute({
          componentDatatype: Cesium.ComponentDatatype.FLOAT,
          componentsPerAttribute: 4,
          values: new Float32Array([1.0, 0.0, 0.0, 1.0]), // 红色
        }),
      },
      primitiveType: Cesium.PrimitiveType.TRIANGLES,
      vertexFormat: Cesium.VertexFormat.POSITION_AND_COLOR,
      boundingSphere: Cesium.BoundingSphere.fromVertices(
        Cesium.Cartesian3.fromDegreesArrayHeights(positions)
      ),
    });
    
    const geometryInstance = new Cesium.GeometryInstance({
      geometry: geometry,
      modelMatrix: Cesium.Matrix4.IDENTITY,
      id: 'horizon',
    });
    
    const primitive = new Cesium.Primitive({
      geometryInstances: geometryInstance,
      appearance: new Cesium.ColorAppearance({
        translucent: false,
        material: Cesium.Material.fromType('Color'),
      }),
      asynchronous: false,
      cull: false,
      frustumCulled: false,
      show: true,
    });
    

    📌 其他建议

    • 如果你想将灰度图像作为三维表面显示,可以考虑使用 Cesium.GeoJsonDataSourceCesium.ImageMaterialProperty
    • 如果是高程数据,推荐使用 Cesium.HeightmapTerrainProviderCesium.EllipsoidTerrainProvider
    • 如果是自定义的 3D 模型,建议使用 Cesium.ModelCesium.GltfModel

    ✅ 总结

    | 问题 | 解决方案 | |------|----------| | 仰视视角下对象消失 | 确保法线方向正确,关闭 Frustum Culling | | 背面剔除已关闭但仍不可见 | 尝试使用 ColorAppearance 替代 PerInstanceColorAppearance | | 几何体未正确显示 | 检查顶点顺序和 boundingSphere 是否正确 |

    如需进一步调试,可以使用 Cesium 的 Scene.debugShowFramesPrimitive.debug 进行可视化分析。

    如还有疑问,欢迎继续提问!

    评论

报告相同问题?

问题事件

  • 创建了问题 8月12日