1. 基本概念
    2. 使用方法
    3. 代码示例
    4. 总结
    5. 参考资料

基本概念

cone:锥体。

frustum: 截头锥体。也就是截掉头部的截体。如下图: 截头锥体1 截头锥体2

field of view(FOV): 视野,表示可视范围 。常用角度来表示。

Viewing frustum: 视锥体。视锥体只是截头锥体在透视相机系统中的具体表达。three.js中的视锥体又特指底面为四边形的截头锥体。锥体顶点被视作相机位置。如下图所示: Viewing frustum

使用方法

在three.js中,构建函数THREE.PerspectiveCamera,就是用来定义透视投影相机(Perspective Camera)的视锥体的。视锥体是空间物体的容器,物体位于视锥体内的部分才可能会显示出来,位于视锥体外的部分则会被剪切掉。

PerspectiveCamera的用法如下:

const camera = THREE.PerspectiveCamera(fov, aspect, near, far)

只有这几个参数的话,PerspectiveCamera就只是定义了一个形状。只有形状,没有位置,又怎么能知道某个物体是否在这个形状内呢?

其实,在three.js的坐标系(也称全球坐标系)中,所有三维物体,包括上面定义的camera,都被设置了一个默认位置的:(0, 0, 0),即原点。全球坐标系示意如下图: image

视锥体在坐标系中的位置,示意如下: image

如果不改变各个物体的默认位置,camera就会位于物体的内部,其定义的视锥体如果也正好在物体的外面的话,那就不会有任何的投影,屏幕会是一片空白。

所以,为了完整地投影三维物体,我们可以通过调整camera的位置或者视锥体的参数(fov/aspect/near/far),来确保三维物体位于视锥体的内部。

代码示例

下面举例说明。

单击此处在新窗口中打开

查看源码

首先,定义一个位于原点,尺寸为(1,1,1)的立方体。

const scene = new THREE.Scene();
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00, wireframe: true });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

定义一个z轴位于5的相机(立方体的z轴最大值为0.5)

const camera = new THREE.PerspectiveCamera(
  60,
  window.innerWidth / window.innerHeight,
  0.1,
  10
);
camera.position.set(0, 0, 5);

可以看到立方体完整投影,效果如下图。其中小正方形为立方体背面投影,大正方形为正面投影。近大远小。 image

调整相机位置,将其移到立方体后方

camera.position.set(0, 0, -0.5)

屏幕为空。

再调整相机方位置,让其只能看到立方体的背面,但看不到前方

camera.position.set(0, 0, 0.4);

效果如下图: image

总结

PerspectiveCamer定义了被称为视锥体的三维虚拟容器,位于其内部的物体会保留,位于外部的被剪切掉。留下的部分,和坐标系一起垂直于屏幕投影到二维平面如浏览器中,就是我们看到的最终效果。

参考资料