Three.js正交相机X轴旋转的视野计算与视口调整问题咨询
Three.js正交相机视野问题
正交相机旋转至-90°时
当相机绕x轴旋转至-90°(从正上方垂直向下俯视平面),此时相机仅能看到整个平面,无其他场景内容。
场景设置:
相机视野:
正交相机旋转至-40°时
当相机绕x轴旋转至-40°,相机不仅能看到整个平面,还会显示场景其他部分,相当于旋转导致相机“视野范围变大”。
场景设置:
相机视野:
我的疑问
- 如何计算相机因x轴旋转而扩大的视野范围?
- 如何调整相机的
left、right、top、bottom属性及/或y轴位置,使相机仅显示平面(垂直方向视口被平面填满,水平方向允许平面部分超出视口)?
补充说明
此相机为正交相机,当前left、right、top、bottom参数为硬编码值,已考虑平面高度与屏幕宽高比;相机与平面的初始位置均为(0,0,0)。
代码示例:
camera = new THREE.OrthographicCamera( -planeZ * aspectRatio / 2, planeZ * aspectRatio / 2, planeZ / 2, -planeZ / 2, -100, 100 ); camera.position.set(0,0,0);
更新
我基于他人代码创建了示例,做了大量修改(如移除OrbitControls,采用角度计算方式)。
解决方案
1. 计算旋转后扩大的视野范围
正交相机旋转后,可视范围的变化可通过三角函数推导:
- 设相机绕x轴旋转角度为
θ(需转换为弧度,比如-40°对应-40 * Math.PI / 180) - 原垂直视野高度为
H(即top - bottom,对应示例中的planeZ) - 旋转后,垂直方向有效可视高度变为
H / Math.cos(θ)——旋转导致平面在视口中的投影被拉伸,视野扩大的比例为1 / Math.cos(θ) - 水平方向同理,若平面z轴长度为
W,旋转后有效可视宽度为W / Math.cos(θ)
角度越偏离-90°(余弦值越小),视野扩大的比例越高。
2. 调整相机参数实现垂直视口填满平面
以下两种方法可实现需求:
方法一:动态调整top和bottom
通过旋转角度的余弦值修正垂直视野范围,确保平面刚好填满视口垂直方向:
function updateCamera(rotationX) { const rad = THREE.MathUtils.degToRad(rotationX); const cosTheta = Math.abs(Math.cos(rad)); const aspectRatio = window.innerWidth / window.innerHeight; const planeZ = 10; // 替换为你的平面高度 // 修正垂直视野,让平面填满视口垂直方向 const adjustedHeight = planeZ * cosTheta; camera.top = adjustedHeight / 2; camera.bottom = -adjustedHeight / 2; // 水平方向保持原比例,允许平面超出视口 camera.left = -planeZ * aspectRatio / 2; camera.right = planeZ * aspectRatio / 2; camera.rotation.x = rad; camera.updateProjectionMatrix(); // 必须更新投影矩阵使参数生效 } // 调用示例:旋转至-40° updateCamera(-40);
方法二:调整相机y轴位置
若希望保持top、bottom参数不变,可通过移动相机y轴位置实现:
function updateCamera(rotationX) { const rad = THREE.MathUtils.degToRad(rotationX); const planeZ = 10; // 替换为你的平面高度 const aspectRatio = window.innerWidth / window.innerHeight; // 保持原视野参数,移动相机y轴位置对齐平面 camera.position.y = (planeZ / 2) * Math.tan(Math.abs(rad)); camera.left = -planeZ * aspectRatio / 2; camera.right = planeZ * aspectRatio / 2; camera.top = planeZ / 2; camera.bottom = -planeZ / 2; camera.rotation.x = rad; camera.updateProjectionMatrix(); }
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

