You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Three.js正交相机X轴旋转的视野计算与视口调整问题咨询

Three.js正交相机视野问题

正交相机旋转至-90°时

当相机绕x轴旋转至-90°(从正上方垂直向下俯视平面),此时相机仅能看到整个平面,无其他场景内容。

场景设置:场景设置-90°
相机视野:相机视野-90°


正交相机旋转至-40°时

当相机绕x轴旋转至-40°,相机不仅能看到整个平面,还会显示场景其他部分,相当于旋转导致相机“视野范围变大”。

场景设置:场景设置-40°
相机视野:相机视野-40°


我的疑问

  1. 如何计算相机因x轴旋转而扩大的视野范围?
  2. 如何调整相机的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 21:25:29