本章主要学习知识点
- 学习如何操作摄像机运动
- 了解如何旋转相机进行渲染
- 了解管道漫游实现原理,并练习实操
相机动画
相机动画可以理解为「让3D场景的虚拟镜头动起来」,就像电影中的运镜效果。
通过移动摄像机位置或调整镜头参数,我们可以实现:
- 环绕观察:让镜头围绕物体旋转,类似无人机环绕拍摄
- 推拉镜头:从远处逐渐靠近物体(放大)或后退远离(缩小)
- 视角切换:从俯视切换到平视,展示不同角度的场景细节
修改相机动画的三种方式
1、直接修改相机参数 (适合简单的动画)
看看下面这个环绕运动
angle += 0.002;
// 在XOZ面上做圆周运动
camera.position.x = R * Math.cos(angle);
camera.position.z = R * Math.sin(angle);
camera.lookAt(0,0,0);
这种方式适合直线运动、匀速旋转等基础动画
2、使用Tween.js库 (适合复杂动画)
new TWEEN.Tween(camera.position)
.to({ x: 200 }, 3000)
.easing(TWEEN.Easing.Quadratic.InOut) // 缓动效果
.start(); // 循环更新Tween动画
function animate() {
TWEEN.update();
requestAnimationFrame(animate);
}
这种方式适合具有弹性、反弹等高级缓动效果动画
3、路径动画 (沿预定轨迹运动)
- 定义运动路径 (如贝塞尔曲线)
- 通过插值计算相机位置
const path = new THREE.CurvePath();
path.add(new THREE.LineCurve3(startPoint, endPoint)); // 添加路径段
const t = 0.5; // 路径进度(0~1)
const point = path.getPoint(t); // 获取中点坐标
camera.position.copy(point);
这种方式适合沿复杂轨迹飞行或环绕的动画
相机运动的使用场景
| 场景 | 实现方案 | 效果示例 |
|---|---|---|
| 产品展示 | 环绕动画 + 缓动 | 360°旋转查看商品细节 |
| 地图漫游 | 路径动画 + 键盘控制 | 第一人称视角游览3D城市 |
| 过场切换 | 相机位置插值 | 镜头从全景推近到特写 |
| 交互式教学 | 点击触发相机位移 | 点击按钮切换解剖模型视角 |
旋转渲染
你可以理解为现实中我们扭动我们头从不同的角度观看同一事物,而不是移动我们自身
在THREE.js中是通过调整camera.up来实现相机角度姿态改变的,默认是Y轴朝上(0,1,0)
为了能更好的查看,我们常见一个立方体,并为其每个面添加不同颜色的材质
const geometry = new THREE.BoxGeometry( 1, 1, 1 );
// 设置立方体的每个面为不同的颜色
const faceColors = [
new THREE.Color(0x00ff00), // 前
new THREE.Color(0x0000ff), // 后
new THREE.Color(0xff0000), // 上
new THREE.Color(0x00ffff), // 下
new THREE.Color(0xffff00), // 左
new THREE.Color(0xff00ff), // 右
];
// 创建材质数组
const materials = faceColors.map(color => new THREE.MeshBasicMaterial({ color: color }));
cube = new THREE.Mesh( geometry, materials );
scene.add( cube );
我们可以看到默认状态下,Y轴为绿色线条朝上,且我们看到的是红色面朝上,修改camera.up为(0,0,1),也就是蓝色线条朝上看看
camera.up.set(0,0,1)
可以看到此时蓝线朝上,相当于当前的Y轴被之前的Z轴替代了,反应在模型上就像是模型被翻转了一样。
管道漫游
「漫游管道」可以理解为「让相机像火车一样沿着3D管道内部移动」,创造出一种沉浸式的穿梭或飞行效果。
先看效果
要实现管道漫游,首先要创建一条管道路径,使用THREE.Curve或THREE.CatmullRomCurve3生成3D曲线
const path = new THREE.CatmullRomCurve3([
new THREE.Vector3(-5, 2, 9),
new THREE.Vector3(-1, 4, 4),
new THREE.Vector3(0, 0, 0),
new THREE.Vector3(6, -6, 0),
new THREE.Vector3(9, -4, 6),
new THREE.Vector3(12, 3, 3),
new THREE.Vector3(22, 3, 16),
new THREE.Vector3(4, 3, 18),
new THREE.Vector3(-5, 2, 12),
new THREE.Vector3(-5, 2, 9),
]);
const geometry = new THREE.TubeGeometry(path, 125, 0.5, 30 ,true)
const texLoader = new THREE.TextureLoader(loadingManager)
const texture = texLoader.load('texture/disturb.jpg')
这里为了能看见该管道,这里进行了贴图,调整相机位置我们能看到如下管道
这里可以发现管道呈闭环状态,最简单的闭环就是环状,这样容易实现无限循环漫游效果, 调整相机位置
const pointsArr = path.getSpacedPoints(3000)
let i = 0;
camera.position.copy(pointsArr[i]); // 管道中的第一个点坐标
camera.lookAt(pointsArr[i + 1]);
通过不断地改变相机位置,实现漫游效果
if(i < pointsArr.length - 1) {
camera.position.copy(pointsArr[i])
camera.lookAt(pointsArr[i + 1])
i += 1;
}else {
i = 0;
}
主要应用场景
| 场景 | 实现效果 | 技术要点 |
|---|---|---|
| 地铁隧道模拟 | 第一人称视角穿越隧道 | 透视相机 + 直线路径 |
| 工业管道监控 | 自动巡检管道内部 | 正投影相机 + 固定高度 |
| 科幻游戏过场 | 飞船在虫洞中穿梭 | 曲线路径 + 动态材质 |