Skip to content

相机基础

正投影相机

正投影

js
// 正投影相机
OrthographicCamera(left, right, top, bottom, near, far);
参数含义
left, right, top, bottom渲染左右上下边界
near距离相机开始渲染的位置,默认 0.1
far距离相机截止渲染的位置, 默认 2000

创建正投影相机

  1. 设置渲染范围

    js
    // 正投影相机
    const width = window.innerWidth; //canvas画布宽度
    const height = window.innerHeight; //canvas画布高度
    const k = width / height; //canvas画布宽高比
    const s = 600; //控制left, right, top, bottom范围大小
    const camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 8000);
  2. 相机位置和观察目标

    js
    camera.position.set(0, 2000, 0); //相机放在y轴上
    camera.lookAt(0, 0, 0); //指向坐标原点

更新 canvas 画布尺寸

js
// Canvas画布跟随窗口变化
window.onresize = function () {
  const width = window.innerWidth; //canvas画布宽度
  const height = window.innerHeight; //canvas画布高度
  // 1. WebGL渲染器渲染的Cnavas画布尺寸更新
  renderer.setSize(width, height);
  // 2.1.更新相机参数
  const k = width / height; //canvas画布宽高比
  camera.left = -s * k;
  camera.right = s * k;
  // 2.2.相机的left, right, top, bottom属性变化了,通知threejs系统
  camera.updateProjectionMatrix();
};

包围盒

把模型的所有顶点数据包围在一个最小的长方体空间中,这个最小长方体空间就是该模型的包围盒 Box3 包围盒

使用 min 和 max 两个属性来描述包围区域, 属性值都是三维向量对象 Vector3

计算模型最小包围盒.expandByObject()

可以查看模型的包围盒属性.min.max

js
const box3 = new THREE.Box3();
box3.expandByObject(mesh); // 计算模型包围盒
console.log("查看包围盒", box3);

包围盒尺寸.getSize()

可以获取包围盒的长宽高

js
const scale = new THREE.Vector3();
// getSize()计算包围盒尺寸
// 获得包围盒长宽高尺寸,结果保存在参数三维向量对象scale中
box3.getSize(scale);
console.log("模型包围盒尺寸", scale);

包围盒几何中心.getCenter()

js
// 计算包围盒中心坐标
const center = new THREE.Vector3();
box3.getCenter(center);
console.log("模型中心坐标", center);

相机动画

通过改变相机对象 Camera.position 属性和.lookAt()方法,实现一段相机动画

直线运动

js
// 渲染循环
function render() {
  camera.position.z -= 0.3; //相机直线运动动画
  renderer.render(scene, camera);
  requestAnimationFrame(render);
}
render();

圆周运动

js
// 渲染循环
let angle = 0; //用于圆周运动计算的角度值
const R = 100; //相机圆周运动的半径
function render() {
  angle += 0.01;
  // 相机y坐标不变,在XOZ平面上做圆周运动
  camera.position.x = R * Math.cos(angle);
  camera.position.z = R * Math.sin(angle);
  renderer.render(scene, camera);
  requestAnimationFrame(render);
}
render();

执行lookAt()计算相机视线方向

改变.position属性后,如果不执行.lookAt()方法,相机的观察方向默认不变

js
function render() {
  angle += 0.01;
  camera.position.x = R * Math.cos(angle);
  camera.position.z = R * Math.sin(angle);
  // .position改变,重新执行lookAt(0,0,0)计算相机视线方向
  camera.lookAt(0, 0, 0);
  requestAnimationFrame(render);
}
render();

旋转渲染结果

指定相机的方向属性.up, 使一个坐标轴方向朝上

js
// 你可以看到模型相比原来上下颠倒  y坐标轴朝下
camera.up.set(0, -1, 0);
//渲染效果:红色x轴向上
camera.up.set(1, 0, 0);
//渲染效果:蓝色z轴向上
camera.up.set(0, 0, 1);

执行顺序

.up属性和.position属性,如果在.lookAt()执行之后改变,需要重新执行.lookAt()

js
camera.lookAt(0, 0, 0);
camera.up.set(0, 0, 1); //改变up
camera.lookAt(0, 0, 0); //执行lookAt重新计算相机姿态

旋转缩放限制OrbitControls

限制属性

  • 禁止右键平移.enablePan

    js
    controls.enablePan = false;
  • 禁止缩放.enableZoom

    js
    controls.enableZoom = false;
  • 禁止旋转.enableRotate

    js
    controls.enableRotate = false;

OrbitControls.target属性

  • 对应的相机的.lookAt()观察目标
  • 执行controls.update();, 相机控件内部会执行camera.lookAt(controls.target)
js
// controls.target默认值是坐标原点
controls.target.set(x, y, z);
//update()函数内会执行camera.lookAt(x, y, z)
controls.update();

透视投影缩放范围

  • OrbitControls缩放,本质上就是改变相机的位置属性.position
  • 通过设置.minDistance.maxDistance, 约束相机位置.position的变化范围, 控制缩放范围
js
//相机位置与观察目标点最小值
controls.minDistance = 200;

//相机位置与观察目标点最大值
controls.maxDistance = 500;

正投影缩放范围

正投影的缩放范围, 通过相机控件OrbitControls.minZoom.maxZoom属性实现

js
// 缩放范围
controls.minZoom = 0.5;
controls.maxZoom = 2;

获取相机与目标观察点的距离.getDistance()

js
//相机位置与目标观察点距离
const dis = controls.getDistance();
console.log("dis", dis);

可视化设置相机缩放范围

实时打印相机与目标距离, 得到理想的minDistancemaxDistance

js
controls.addEventListener("change", function () {
  //相机位置与目标观察点距离
  const dis = controls.getDistance();
  console.log("dis", dis);
});

设置旋转范围

  • 通过.minPolarAngle.maxPolarAngle属性控制上下的旋转范围

    • 默认情况下 0 度,XOZ 平面平行 canvas 画布,y 轴垂直指向屏幕外
    • 90 度时候,渲染结果 y 轴竖直向上
    • 180 度,XOZ 平面平行 canvas 画布,y 轴垂直指向屏幕内
js
// 上下旋转范围
controls.minPolarAngle = 0; //默认值0
controls.maxPolarAngle = Math.PI; //默认值Math.PI

.maxPolarAngle属性设置为 90 度,这样不能看到模型底部:

js
controls.maxPolarAngle = Math.PI / 2;
  • 通过.minAzimuthAngle.maxAzimuthAngle属性控制左右的旋转范围。
js
// 左右旋转范围
controls.minAzimuthAngle = -Math.PI / 2;
controls.maxAzimuthAngle = Math.PI / 2;

相机控件MapControls

好像和OrbitControls功能差不多, 除了鼠标执行事件有所不同

引入

js
// 引入相机控件`MapControls`
import { MapControls } from "three/addons/controls/OrbitControls.js";
const controls = new MapControls(camera, renderer.domElement);

使用

同上OrbitControls