整体思路
- 利用
CatmullRomCurve3创建一个三维样条曲线 - 在三位样条曲线上
等间距的取一系列点 相机位置按照第二步所取的点移动。
实现步骤
三位样条曲线
import * as THREE from 'three';
// 三维样条曲线
const path = new THREE.CatmullRomCurve3([
new THREE.Vector3(-50, 20, 90),
new THREE.Vector3(-10, 40, 40),
new THREE.Vector3(0, 0, 0),
new THREE.Vector3(60, -60, 0),
new THREE.Vector3(90, -40, 60),
new THREE.Vector3(120, 30, 30),
]);
// 样条曲线path作为TubeGeometry参数生成管道
const geometry = new THREE.TubeGeometry(path, 200, 5, 30);
//纹理加载器
const texLoader = new THREE.TextureLoader();
const texture = texLoader.load('./diffuse.jpg');//纹理贴图
//UV坐标U方向阵列模式
texture.wrapS = THREE.RepeatWrapping;
//纹理沿着管道方向阵列数(UV坐标U方向)
texture.repeat.x = 10;
//材质对象
const material = new THREE.MeshLambertMaterial({
map:texture, //纹理
side: THREE.DoubleSide, //双面显示看到管道内壁
});
const mesh = new THREE.Mesh(geometry, material);
// 从曲线轨迹线上等间距获取一定数量点坐标
const pointsArr = path.getSpacedPoints(500);
export {mesh,pointsArr};
效果:
调整相机位置,让相机看向管道内部
核心代码:
const i = 100;
// 相机位置设置在当前点位置
camera.position.copy(pointsArr[i]);
// 曲线上当前点pointsArr[i]和下一个点pointsArr[i+1]近似模拟当前点曲线切线
// 设置相机观察点为当前点的下一个点,相机视线和当前点曲线切线重合
camera.lookAt(pointsArr[i + 1]);
效果展示:
注意点:
因为这里要模拟人眼效果,所以使用的是透视投影相机.
让相机动起来,实现一种漫游效果
**核心代码: **
// 渲染循环
let i = 0; //在渲染循环中累加变化
function render() {
if (i < pointsArr.length - 1) {
// 相机位置设置在当前点位置
camera.position.copy(pointsArr[i]);
// 曲线上当前点pointsArr[i]和下一个点pointsArr[i+1]近似模拟当前点曲线切线
// 设置相机观察点为当前点的下一个点,相机视线和当前点曲线切线重合
camera.lookAt(pointsArr[i + 1]);
i += 1; //调节速度
} else {
i = 0
}
renderer.render(scene, camera);
//请求动画帧,重复执行。
requestAnimationFrame(render);
}
render();
效果:
总结
管道漫游的本质也是移动相机位置,但需要注意一些细节问题,例如:
- 如何让相机指向管道内部
- 使用正投影相机还是使用透视投影相机
- 相机位置改变的时候,相机lookAt 的改变
等等....