Aframe/Three 适合屏幕 - 计算缩放

Aframe/Three fit to screen - calculate zoom

我想放大相机 Three/Aframe 以便图像适合屏幕。

这是我正在使用的代码:

    this._camera = document.getElementById('camera').getAttribute('camera')
    this._ratio = this._assetWidth/this._assetHeight

    this._vFOV = window.THREE.Math.degToRad( this._camera?.fov || 80 )

    this._height = 2 * Math.tan( this._vFOV / 2 ) * this.data.distance
    this._width = this._height * this._ratio

    this._zoom = this._ratio > 1 ? this._width/window.innerWidth : this._height/window.innerHeight

    console.log(this._zoom,  this._ratio, this._width, window.innerWidth)

我已经到了需要计算缩放以使对象适合屏幕的部分,即,如果它的横向适合宽度,如果它的纵向适合高度。

我以为 this was the answer 但事实并非如此。那是计算相机位置而不是缩放值。

我对你计算缩放值的方法很困惑。

有什么线索吗?

通过以下方式使对象适合屏幕:

  • 更改相机 FoV
  • 正在缩放相机
  • 重新定位相机/物体

一旦您了解公式的来源,就会非常相似。
我们将使用这张简洁的图片 (),因为它涵盖了所有三个主题:

0。我们要达到什么目的

我们希望对象(其宽度或高度的较长边)覆盖 filmHeight - 因此适合屏幕。

1.重新计算 FoV

在这种情况下,我们确实知道 focalLength(相机与物体的距离)和 filmHeight(物体的宽度或高度)。我们可以计算 fov / 2 感谢我们的朋友 trigonometry:

Tan (fov / 2) = (filmHeight / 2) / focalLength
=> fov = 2 * ATan ((filmHeight / 2)) / focalLength * 180 / PI

<script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
<script>
  AFRAME.registerComponent("fit", {
    init: function() {
      const plane = document.querySelector("a-plane")
      const distance = this.el.object3D.position.distanceTo(plane.object3D.position)
      var height = plane.getAttribute("geometry").height
      var newFov = 2 * Math.atan((height / 2) / distance) * (180 / Math.PI); // in degrees
      this.el.sceneEl.camera.fov = newFov
    }
  })
</script>
<a-scene>
  <a-plane position="0 1.6 -2" material="src: https://i.imgur.com/wjobVTN.jpg"></a-plane>
  <a-camera position="0 1.6 0" fit></a-camera>
</a-scene>

2。重新定位物体/相机

同一个三角形不同的变量。现在我们想知道 focalLength:
Tan (fov / 2) = (filmHeight / 2) / focalLength
=> focalLength = (filmHeight / 2) / Tan (fov / 2)

<script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
<script>
  AFRAME.registerComponent("fit", {
    init: function() {
      const plane = document.querySelector("a-plane")
      const height = plane.getAttribute("geometry").height
      const fov = this.el.sceneEl.camera.fov * (Math.PI / 180);
      const newDistance = Math.abs((height / 2) / Math.tan(fov / 2))
      plane.object3D.position.z = -1 * newDistance;
    }
  })
</script>
<a-scene>
  <a-plane position="0 1.6 -2" material="src: https://i.imgur.com/wjobVTN.jpg"></a-plane>
  <a-camera position="0 1.6 0" fit></a-camera>
</a-scene>

3。变焦镜头

如果我们知道相机与物体的距离应该是多少才能填满屏幕 - 我们就知道当前距离与新距离之间的关系是什么:

zoom = currentDistance / necessaryDistance

<script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
<script>
  AFRAME.registerComponent("fit", {
    init: function() {
      const plane = document.querySelector("a-plane");
      const distance = this.el.object3D.position.distanceTo(plane.object3D.position);
      const height = plane.getAttribute("geometry").height;
      const fov = this.el.sceneEl.camera.fov * (Math.PI / 180);
      const newDistance = Math.abs((height / 2) / Math.tan(fov / 2));
      this.el.sceneEl.camera.zoom = distance / newDistance;
    }
  })
</script>
<a-scene>
  <a-plane position="0 1.6 -2" material="src: https://i.imgur.com/wjobVTN.jpg"></a-plane>
  <a-camera position="0 1.6 0" fit></a-camera>
</a-scene>