【问题标题】:Adjusting camera for visible Three.js shape为可见的 Three.js 形状调整相机
【发布时间】:2012-06-30 13:17:14
【问题描述】:

我有一个相机正在查看的 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 实际上是常数我的目的)。

【问题讨论】:

    标签: javascript three.js


    【解决方案1】:

    透视相机。如果相机居中并正面观察立方体,则定义

    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 );
    

    立方体高度将匹配可见高度。

    在任何一种情况下,如果相机未居中,或者以其他方式查看立方体,则问题会更加复杂。

    另外,如果窗口比高度窄,那么宽度就是制约因素,问题就比较复杂了。

    【讨论】:

    • 我应该在我原来的问题中更清楚。我要做的是在相机围绕立方体旋转时自动放大或缩小。也就是说,当它以一个角度查看立方体时。我已经编辑了问题以澄清这一点。
    • 如何找到立方体的高度。是通过计算bounding box吗?我们将在相机初始化后得到模型的bounding box。
    【解决方案2】:

    乘以 camera.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();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-17
      • 2016-10-18
      • 2013-01-18
      • 2014-04-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多