0%

18 管道漫游 - Threejs入门

创建一个 3D 管道,并让相机沿着管道路径移动,模拟穿过管道的动画效果。 [ 练一练 ] [ 看一看 ]

创建管道和纹理: 使用 Catmull-Rom 曲线定义管道路径,并加载砖墙纹理贴图。
相机沿路径移动: 沿着管道路径创建一系列点,相机在动画循环中依次移动到这些点,并朝向下一个点。
渲染动画: 在每一帧中,更新相机位置和朝向,并渲染场景,从而实现相机穿过管道的动画效果。

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import * as THREE from 'three'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'

const scene = new THREE.Scene()

const camera = new THREE.PerspectiveCamera(
90,
window.innerWidth / window.innerHeight,
0.1,
100
)
camera.position.set(0, 0, 30)

const renderer = new THREE.WebGLRenderer()
renderer.setSize(window.innerWidth, window.innerHeight)
app.appendChild(renderer.domElement)

const ambLight = new THREE.AmbientLight()
const dirLight = new THREE.DirectionalLight()
dirLight.position.set(5, 5, 5)
scene.add(ambLight, dirLight)

// code start
const path = new THREE.CatmullRomCurve3([
new THREE.Vector3(-5, 2, 9),
new THREE.Vector3(-10, 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),
])
const geometry = new THREE.TubeGeometry(path, 100, 0.5, 30)
const texLoader = new THREE.TextureLoader()

const texture = texLoader.load('./imgs/砖墙.jpg')
texture.wrapS = THREE.RepeatWrapping
texture.repeat.x = 20

const material = new THREE.MeshLambertMaterial({
map: texture,
side: THREE.DoubleSide, //双面显示看到管道内壁
})
const mesh = new THREE.Mesh(geometry, material)

scene.add(mesh)

const pointsArr = path.getSpacedPoints(5000)

let i = 0
renderer.setAnimationLoop(() => {
if (i < pointsArr.length - 1) {
camera.position.copy(pointsArr[i])
camera.lookAt(pointsArr[i + 1])
i += 1
} else {
i = 0
}
renderer.render(scene, camera)
})
// code end

const controls = new OrbitControls(camera, app)

演示效果