Better

Ethan的博客,欢迎访问交流

fitExtents in three.js

在 three.js 中实现聚焦某个物体,或整体内容自适应屏幕,在自身项目测试问题不大,但特殊情况估计还需要调整。

原理

在 three.js 中,控制视图的缩放、平移主要是通过控制镜头的参数和位置来实现。

计算物体的 max bounding box,从而计算出相关的相机参数,比如 top/bottom/left/right/center 等信息。

镜头类型

  • 正交相机:正交相机的成像原理比较简单
  • 透视相机:需要考虑视角,相对正交而言复杂些

正交相机实现

  • 求得物体的的 BoundingBox,得到 viewport 的相关信息(top/bottom/left/right/center)
  • 设置相机的 top/bottom/left/right 为 viewport 的值
  • 设置相机的 zoom 为 1
  • 镜头 lookAt(center)
  • 将相机的位置平移到 center 处即可
  • 如果应用了 controls,设置 controls.target 为 center

透视相机实现

  • 同正交相机一样,计算得到 viewport 信息
  • 由于透视相机不存在 top/bottom 等参数,大致有两种实现方式,一种是改变 fov 值,一种是改变相机的位置
  • 调整 fov(frame of view) 会改变视角的效果,感觉不是很好,排除(虽然社区也有人这样做)
  • 设置 zoom 值为 1
  • 通过 top 值,结合 fov 值计算出 distance
  • 镜头 lookAt(center)
  • 相机位置平移到 center,distance 作为 z 值
  • 如果应用了 controls,设置 controls.target 为 center

相机扩展

23D 切换:当相机的视线轴和场景的平面垂直时,使用平行投影,这样给人的感觉就是 2D 视图,所以需要根据透视的视锥体计算出平行投影的视景体

function fromPerspectiveToOrthographic() {
  const distance = this.cameraP.position.distanceTo(this.controls.target);
  const h = Math.tan(this.camera.fov / 2 * DEG2RAG) * distance;
  const r = h * this.cameraP.aspect;
  this.cameraO.zoom = 1;
  this.cameraO.top = h;
  this.cameraO.bottom = -h;
  this.cameraO.left = -r;
  this.cameraO.right = r;
  this.cameraO.updateProjectionMatrix();
}

function fromOrthographicToPerspective() {
  const zoom = this.cameraO.zoom;
  const distance = this.controls.target.distanceTo(this.cameraP.position);
  const eyeDirection = this.cameraP.position.clone().sub(this.controls.target).normalize();
  this.cameraP.position.copy(this.controls.target.clone().add(eyeDirection.multiplyScalar(distance / zoom)));
  this.cameraP.updateProjectionMatrix();
}

相关资料



留言