计算框架和长宽比指南以匹配相机

yak*_*aku 0 three.js

我正在尝试在 Three.js 中可视化胶片相机裁剪和纵横比。请耐心等待,这是一道数学问题,我无法用更简短的语言来描述它......

我不只是使用 CameraHelper,而是为每个相机使用三个稍微修改过的 CameraHelper 对象。当查看相机(锥体)时,或者通过相机查看时,可以看到辅助线,辅助线有效地为当前相机创建引导线。

  • 框架助手(带有渲染侧面的蓝色)。考虑到焦距和传感器或胶片尺寸,这是经过配置的并且应该是实际相机所看到的。计算在getFOVFrame.

  • 监控助手(白色)。我们这里的帧长宽比是 1.5。例如,如果我们计划使用长宽比为 1.5 的相机拍摄长宽比为 2.35(电影院)的影片,则这将显示帧的裁剪区域。因此,它需要完全适合框架,上下或两侧都有额外的空间,但不能两者兼而有之。计算在getFOVMonitor.

  • 屏幕助手(紫色)。我们希望在浏览器中看到完整的东西,如果浏览器窗口尺寸/长宽比不同,我们会调整实际渲染的 Three.js 相机,使其适合浏览器窗口和尺寸。因此,这个助手始终具有当前浏览器窗口的宽高比和焦距,以便它适合框架和监视器助手。计算于getFOVScreen

因此,根据我们实际首选的相机(帧助手),我们需要计算监控相机并调整它的视场,使其完全适合帧相机内。然后我们还需要计算屏幕相机并调整它的视场,使帧相机完全适合内部。

我当前的解决方案看起来几乎是正确的,但有一些问题。对于长镜头(小视场,大焦距),这似乎是正确的:

  • 仔细一看,看起来是正确的:http://toppinen.net/projects/so/so_fov/Clipboard-6.png
  • 当前相机和前面的相机看起来都是正确的:在此输入图像描述
  • 仔细一看,看起来是正确的: 在此输入图像描述

但在广角镜头(大视场、小焦距)下,解决方案开始失效,白色监视器助手周围有额外的空间,例如:

  • 往里看,白色的盒子应该从侧面接触蓝色的盒子:在此输入图像描述
  • 当前相机和前面的相机看起来都是错误的,白色框应该接触蓝色框的侧面(两者都有很宽的镜头):在此输入图像描述
  • 通过(非常宽的镜头)看,看起来不对,白色盒子应该接触蓝色盒子,蓝色盒子应该接触紫色盒子:在此输入图像描述

所以我认为我对各种相机的计算是错误的,尽管结果看起来几乎“足够接近”。

下面的代码返回垂直 FOV、水平 HFOV 和纵横比,然后用于配置相机和助手:

// BLUE camera fov, based on physical camera settings (sensor dimensions and focal length)
var getFOVFrame = function() {
  var fov = 2 * Math.atan( sensor_height / ( focal_length * 2 ) ) * ( 180 / Math.PI );
  return fov;
}
var getHFOVFrame = function() {
  return getFOVFrame() * getAspectFrame();
}

// PURPLE screen fov, should be able to contain the frame
var getFOVScreen = function() {
  var fov = getFOVFrame();
  var hfov = fov * getAspectScreen();
  if (hfov < getHFOVFrame()) {
    hfov = getHFOVFrame();
    fov = hfov / getAspectScreen();
  }  
  return fov;
}
var getHFOVScreen = function() {
  return getFOVScreen() * getAspectScreen();
}

// WHITE crop area fov, should fit inside blue frame camera
var getFOVMonitor = function() {
  var fov = getFOVFrame();      
  var hfov = fov * getAspectMonitor();
  if (hfov > getHFOVFrame())   {
    hfov = getHFOVFrame();
    fov = hfov / getAspectMonitor();
  }
  return fov;
}
var getHFOVMonitor = function() {
  return getFOVMonitor() * getAspectMonitor();
}

var getAspectScreen = function() {
  return  screen_width / screen_height;
}

var getAspectFrame = function() {
  return  sensor_width / sensor_height;
}

var getAspectMonitor = function() {
  return monitor_aspect;
}
Run Code Online (Sandbox Code Playgroud)

为什么在使用大视场/宽镜头时会产生不正确的结果?getFOVScreen尤其getFOVMonitor是嫌疑人。

Wes*_*ley 5

你的等式var hfov = fov * getAspectScreen();不正确。

vFOV垂直FOV ( ) 和水平FOV ( )之间的关系hFOV由以下等式给出:

hFOV = 2 * Math.atan( Math.tan( vFOV / 2 ) * aspectRatio );
Run Code Online (Sandbox Code Playgroud)

同样,

vFOV = 2 * Math.atan( Math.tan( hFOV / 2 ) / aspectRatio );
Run Code Online (Sandbox Code Playgroud)

在这些方程中,vFOV和 的hFOV单位是弧度;aspectRatio = width / height

在 Three.js 中,PerspectiveCamera.fov是垂直的,单位是度。

三.js r.59