计算帧和宽高比指南以匹配相机

时间:2013-07-24 14:55:18

标签: three.js

我正在尝试在Three.js中可视化胶片相机裁剪和宽高比。请耐心等待,这是一个数学问题,我无法用较少的词语来描述......

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

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

  • 计算
  • 监控助手(白色)。我们的帧长宽比为1.5。例如,如果我们计划使用宽高比为1.5的相机拍摄2.35(电影放映机)宽高比胶片,则会显示画面的裁剪区域。所以它需要精确地适合框架,在上下两侧或两侧都有额外的空间,但不是两者都有。以getFOVMonitor

  • 计算
  • 屏幕助手(紫色)。我们希望浏览器中显示完整的内容,如果浏览器窗口的尺寸/宽高比不同,我们会调整实际渲染的Three.js相机,使其适合浏览器窗口和尺寸。所以这个帮助器总是具有当前浏览器窗口的长宽比和焦距,以便它适合框架和监视器帮助器。以getFOVScreen

  • 计算

因此,基于我们实际首选的相机(帧辅助器),我们需要计算监视器摄像头并调整它的fov,使其完全适合帧内摄像机。然后我们还需要计算屏幕摄像头并调整帧摄像头完全适合内部的fov。

我当前的解决方案看起来几乎是正确的,但有一些错误。使用长镜头(小fov,大焦距)似乎是正确的:

  • 仔细观察,看起来正确:http://toppinen.net/projects/so/so_fov/Clipboard-6.png
  • 当前相机和前面的相机都看起来正确:enter image description here
  • 仔细观察,看起来正确: enter image description here

但是在宽镜头(大光圈,小焦距)下,解决方案开始破裂,白色显示器助手周围有额外的空间,例如:

  • 仔细观察,白色方框应该触摸两侧的蓝色方框:enter image description here
  • 当前相机和前面的相机都看错了,白框应该触摸蓝框的两侧(两者都有非常宽的镜头):enter image description here
  • 透过(非常宽的镜头),看起来不对,白框应该触摸蓝框,蓝框应该触摸紫框:enter image description here

所以我认为我正在计算各种相机的错误,虽然结果看起来几乎“足够接近”。

这是返回垂直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;
}

使用大型FOV /宽镜头时,为什么会产生不正确的结果? getFOVScreen,特别是getFOVMonitor是嫌疑人。

1 个答案:

答案 0 :(得分:2)

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

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

hFOV = 2 * Math.atan( Math.tan( vFOV / 2 ) * aspectRatio );

同样,

vFOV = 2 * Math.atan( Math.tan( hFOV / 2 ) / aspectRatio );

在这些等式中,vFOVhFOV以弧度为单位; aspectRatio = width / height

在three.js中,PerspectiveCamera.fov是垂直的,并且是度数。

three.js r.59