可能每个人的童年都有个时空穿梭梦,印象粗浅的是第一次看《机器猫》,配角康夫卧室的抽屉就是时空隧道的入口,跳进隧道的那一刻,工夫记忆犹新般从身边流过,好像进入了异世界。
这次咱们用 three.js 实现一个 3d 隧道穿梭成果,关上异世界的大门。它也能够是一个跑酷游戏原型,又或者是 3D 空间导航,具体怎么利用由你来决定,先来看下成果。
有限循环时空隧道
有限循环的隧道实际上是一个首尾无缝相连的管道,你能够将它的形态设想成一个甜甜圈。咱们只有将摄像机搁置在这个管道外部,并沿着管道门路静止就能实现这种穿梭成果。
实现有限循环隧道
首先要实现这样一个管道咱们能够借助 three.js 中 TubeGeometry 对象,TubeGeometry 可能沿着一条 3D 曲线创立管道。咱们要做的是先创立一条曲线,曲线是用坐标函数建设的,咱们先拿 TubeGeometry 的官网示例试一下。
CustomSinCurve.prototype.getPoint = function (t) {
var tx = t * 3 - 1.5
var ty = Math.sin(2 * Math.PI * t)
var tz = 0
return new THREE.Vector3(tx, ty, tz).multiplyScalar(this.scale)
}
官网示例的 getPoint 函数绘制了一个烟斗状的曲线管道,看起来平铺直叙,别着急咱们来逐步完善。
用官网示例绘制出的漏斗状曲线
扭转下 getPonit 函数中的公式,咱们马上失去了一个关闭的圆环管道。
CustomSinCurve.prototype.getPoint = function (t) {const tx = Math.cos(2 * Math.PI * t)
const ty = Math.sin(2 * Math.PI * t)
const tz = 0
return new THREE.Vector3(tx, ty, tz).multiplyScalar(this.scale)
}
关闭圆环
为隧道增加材质
贴图是这个成果的灵魂,筹备一张 1024×1024 尺寸的材质贴图,它会反复地显示在管道模型外表,留神贴图中明暗交替的线条,这是实现背景光线成果的要害。
隧道的材质贴图
设置材质的贴图形式和反复次数,使材质沿曲线方向反复延展,咱们失去了一个贴好图的隧道模型。
material.map.wrapS = THREE.RepeatWrapping
material.map.wrapT= THREE.RepeatWrapping
material.map.repeat.set(10, 1)
贴图后的隧道
设置摄像机门路
要实现穿梭成果,咱们要将摄像机放在模型外部,并沿着隧道门路静止。官网的案例中也有一个相机沿曲线运动的例子,但通过试验成果并不现实,所以这里应用另外一种办法,这种办法思考了隧道门路的法向量,使转弯处过渡成果更加天然。因为代码较长,就不贴在这里了,具体能够参考本篇教程的源文件。
沿门路增加物体
为了在隧道门路上增加物体,先要在管道门路上通过 getPointAt 办法上取得坐标点,而后将物体设置在坐标点处,这里的物体是一个个通明贴图的立体对象。
for(let i = 0; i < 20; i++) {const plane = mesh.clone()
const pos = this.tubeGeometry.parameters.path.getPointAt(i * 0.04)
plane.position.copy(pos)
this.scene.add(plane)
}
最初,将这些立体对象旋转朝向摄像机,能够通过设置四元数属性和相机雷同轻松搞定。四元数是 3D 空间旋转罕用的数学方法,能够防止应用矩阵旋转时产生的万向锁问题,因为它数学原理比较复杂,这里就不做介绍了,有趣味能够找相干材料学习。
this.planes.forEach(plane => {plane.quaternion.copy(this.camera.quaternion)
})
总结
咱们曾经把握了如何使相机沿着自定义曲线运动,并实现了一个炫酷的空间隧道成果。接下来请施展你的设想,做出更乏味的利用。
这里是一些倡议:能够用 three.js 的 postprocessing 退出前期成果,使它更有科技感;能够退出鼠标交互,使摄像机依据鼠标滚轮向前挪动;能够和 cannon.js 物理库联合,退出碰撞检测等等。
教程源文件:
https://github.com/imokya/threejs-tunnel-effect