调整相机以查看 Three.js 形状

6

我有一个CubeGeometry,相机正在观察它,我希望相机缩放以使立方体完全可见,但不要更大。

我的初始尝试是将立方体顶点转换为相机坐标系,

function toScreenXY(position, camera) {
  var pos = position.clone();
  var projScreenMat = new THREE.Matrix4();
  projScreenMat.multiply(camera.projectionMatrix, camera.matrixWorldInverse);
  projScreenMat.multiplyVector3( pos );

  return pos;
}
function ScaleInView() {
  camera.fov = 0.0;
  for (var i=0; i<8; i++) {
    proj2d = toScreenXY(cube.geometry.vertices[i],camera);
    angle = 57.296 * Math.max(Math.atan(proj2d.x/proj2d.z), Math.atan(proj2d.y/proj2d.z));
    camera.fov = Math.max(camera.fov,angle);
  }
  camera.updateProjectionMatrix();
}

我原以为这个方法可以奏效,但有时候它太小了,而有时候又太大了(取决于相机的位置)。

我还需要在正交相机中实现此功能。

编辑: 当立方体面对着相机时,我知道如何实现此操作,但是我正在寻找一种在相机移动到某个任意(r, theta, phi)位置时(球坐标系;r 对于我的目的实际上是恒定的)实现它的方法。

2个回答

4

透视相机。如果相机位于正中央,以头戴方式查看立方体,则定义:

dist = 相机到立方体前面(非常重要!)的距离。

height = 立方体的高度。

如果将相机的视野设置如下:

fov = 2 * Math.atan( height / ( 2 * dist ) ) * ( 180 / Math.PI );

然后立方体的高度将与可见高度相匹配。

正交相机。如果相机位于中心并且正对着立方体,则定义

aspect = 窗口的宽高比(即,宽度/高度)

height = 立方体的高度。

然后按照以下方式构建您的相机:

camera = new THREE.OrthographicCamera( -aspect * height/2, aspect * height/2, height/2, -height/2, near, far );

立方体的高度将与可视高度匹配。
在任何情况下,如果相机没有居中,或者以其他方式以角度查看立方体,则问题就更加复杂。
此外,如果窗口比高宽,那么宽度是限制因素,问题就更加复杂。

我在最初的问题中应该更清楚一些。我的意图是在相机围绕立方体旋转时自动缩放。也就是说,当相机以某个角度查看立方体时。我已经编辑了问题以澄清这一点。 - sn6uv
你将如何找到立方体的高度?是通过计算边界框吗?在相机初始化后,我们将获得模型的边界框。 - Aasha joney

3

通过相机的matrixWorldInverse乘以向量可以得到相机坐标系下的向量,但重要的是不应用透视效果。

function toCameraCoords(position) {
  return camera.matrixWorldInverse.multiplyVector3(position.clone());
}

我们可以找到适合场景中所有盒子角落的最小角度。arctan(D.x / D.z) 给出了角度 BCD,其中 B 是相机所看的位置,C 是相机的位置,D 是您想在相机坐标系中可见的对象的位置。
在我的情况下,以下操作确保立方体边界框完全可见。
function ScaleInView() {
  var tmp_fov = 0.0;

  for (var i=0; i<8; i++) {
    proj2d = toCameraCoords(boundbox.geometry.vertices[i]);

    angle = 114.59 * Math.max( // 2 * (Pi / 180)
      Math.abs(Math.atan(proj2d.x/proj2d.z) / camera.aspect),
      Math.abs(Math.atan(proj2d.y/proj2d.z))
    );
    tmp_fov = Math.max(tmp_fov, angle);
 }

 camera.fov = tmp_fov + 5; // An extra 5 degrees keeps all lines visible
 camera.updateProjectionMatrix();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接