Three.js如何获取与相机远近裁剪面平行的当前平面的距离值
Three.js 透视相机视向距离计算方案
问题原因说明
你之前使用camera.position.z计算距离无效的核心原因是:该值是相机在世界坐标系下的Z轴坐标,和相机的实际视线方向没有绑定关系。当相机旋转后,视线方向不再沿世界坐标系Z轴,该值自然无法代表沿视线方向的深度。
你描述的与near/far平面平行的蓝色截面属于视锥体的平行截面,你需要的距离是沿相机视线方向的深度值,只要在相机局部坐标系下计算即可实现旋转无关的效果,你的理解是正确的:使用轨道控制器等工具缩放视角时,相机与目标截面的视向距离会同步变化。
具体实现方法
Three.js中透视相机的默认视线方向为自身局部坐标系的-Z轴,我们只需要将目标点的世界坐标转换到相机局部坐标系,取Z值的相反数即可得到不受旋转影响的视向距离,数值范围天然落在near和far之间(目标在视锥体内时)。
核心代码示例
// 1. 先获取目标点/物体的世界坐标,此处以场景中某个mesh为例 const targetWorldPos = new THREE.Vector3() mesh.getWorldPosition(targetWorldPos) // 2. 将世界坐标转换到相机的局部坐标系 const targetLocalPos = camera.worldToLocal(targetWorldPos.clone()) // 3. 计算沿视线方向的距离,结果为正数,不受相机旋转影响 const viewDistance = -targetLocalPos.z
最终需求实现(远近触发元素增减)
你可以在渲染帧循环中加入如下判断逻辑,自定义阈值即可实现距离触发逻辑:
// 自定义距离阈值,需要设置在相机的near和far参数范围内 const ADD_THRESHOLD = 5 // 距离小于5时添加元素 const REMOVE_THRESHOLD = 50 // 距离大于50时移除元素 const extraElement = 你要添加的Three.js对象 function renderLoop() { requestAnimationFrame(renderLoop) // 计算视向距离 const targetWorldPos = new THREE.Vector3() targetMesh.getWorldPosition(targetWorldPos) const viewDistance = -camera.worldToLocal(targetWorldPos.clone()).z // 执行元素增减逻辑 if (viewDistance < ADD_THRESHOLD && !extraElement.parent) { scene.add(extraElement) } else if (viewDistance > REMOVE_THRESHOLD && extraElement.parent) { scene.remove(extraElement) } renderer.render(scene, camera) }
注意事项
- 坐标转换时调用
clone()避免修改原对象的坐标属性,防止影响场景正常渲染 - 如果需要判断整个场景的整体距离,取多个关键场景节点的视向距离取平均值即可
- 阈值设置需要在相机初始化时的
near和far参数区间内,超出视锥体范围的物体已经被裁剪,判断无意义
内容的提问来源于stack exchange,提问作者Aenaon
相关产品推荐
相关产品推荐

