Forge Viewer 2D模式下自定义几何体缩放时消失/抖动/裁切问题
问题分析
在Forge Viewer 2D模式下添加自定义几何体出现可见性不稳定、抖动裁切的核心原因:
- 2D模式采用正交相机,模型深度范围极小,你设置的
BoxGeometryz轴为0,极易与原有模型几何体的深度重叠,导致遮挡或裁切。 - 未适配Viewer 2D视图的渲染层级与深度规则,自定义Mesh的深度测试未做特殊处理。
BoxGeometry的固定尺寸未考虑Viewer缩放级别,缩放时易出现视觉上的尺寸偏差或抖动。
解决方案
1. 替换几何体为平面类型,适配2D场景
用THREE.PlaneBufferGeometry替代BoxGeometry,2D场景下平面更贴合需求,且BufferGeometry性能更优,减少精度问题:
// 替换原BoxGeometry创建代码 const planeSize = 0.02; // 根据需求调整大小 const geom = new THREE.PlaneBufferGeometry(planeSize, planeSize);
2. 调整Mesh的Z轴位置,避免深度冲突
将自定义Mesh放在模型的最上层,确保不会被原有模型遮挡:
// 获取模型的最大Z值,让自定义Mesh在其上方 const modelBounds = this.viewer.model.getBoundingBox(); const safeZ = modelBounds.max.z + 0.05; // 加一个小偏移量避免重叠 mesh.position.set(result.point.x, result.point.y, safeZ);
3. 配置材质禁用深度测试,确保始终可见
禁用深度测试可以让自定义Mesh始终渲染在所有模型内容之上,避免缩放时的层级错乱:
var material = new THREE.MeshBasicMaterial({ color: 0xff0000, depthTest: false, // 关键:禁用深度测试 transparent: false // 可选,根据需求调整 });
4. 强制更新Mesh矩阵,避免抖动
添加Mesh后强制更新矩阵,确保位置和尺寸的计算准确:
this.viewer.overlays.addMesh(mesh, 'custom-scene'); mesh.updateMatrixWorld(true); // 强制更新矩阵
5. 可选:根据缩放级别动态调整几何体尺寸
如果需要自定义几何体在不同缩放级别下保持一致的屏幕大小,可以根据Viewer的当前缩放因子调整平面尺寸:
// 获取当前Viewer的缩放因子 const zoomFactor = this.viewer.navigation.getZoomFactor(); // 计算适配缩放的平面尺寸(示例值,可根据需求调整) const adaptiveSize = 0.02 / zoomFactor; const geom = new THREE.PlaneBufferGeometry(adaptiveSize, adaptiveSize);
修改后的完整代码
handleSingleTap(event) { const canvasX = event.canvasX; const canvasY = event.canvasY; const result = this.viewer.clientToWorld(canvasX, canvasY); if (result) { // 根据缩放因子调整平面尺寸 const zoomFactor = this.viewer.navigation.getZoomFactor(); const adaptiveSize = 0.02 / zoomFactor; const geom = new THREE.PlaneBufferGeometry(adaptiveSize, adaptiveSize); var material = new THREE.MeshBasicMaterial({ color: 0xff0000, depthTest: false }); var mesh = new THREE.Mesh(geom, material); // 设置安全的Z轴位置,避免深度冲突 const modelBounds = this.viewer.model.getBoundingBox(); const safeZ = modelBounds.max.z + 0.05; mesh.position.set(result.point.x, result.point.y, safeZ); if (!this.viewer.overlays.hasScene('custom-scene')) { this.viewer.overlays.addScene('custom-scene'); } this.viewer.overlays.addMesh(mesh, 'custom-scene'); mesh.updateMatrixWorld(true); // 强制更新矩阵 } return true; }
额外注意事项
- 确保在Viewer完全加载完成后再绑定点击事件,避免
viewer.model未初始化导致的错误。 - 如果仍有裁切问题,可以检查Viewer的视口设置,或者尝试将自定义Mesh添加到
viewer.impl.sceneAfter(替代overlays场景),但overlays是官方推荐的自定义内容添加方式。
内容的提问来源于stack exchange,提问作者Kiran Kulkarni
相关产品推荐
相关产品推荐

