/
birds.js
84 lines (79 loc) · 2.36 KB
/
birds.js
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import React, { useRef, useState, useEffect, Suspense } from 'react'
import * as THREE from 'three'
import { Canvas, useFrame, useLoader } from 'react-three-fiber'
let GLTFLoader
const Bird = ({ speed, factor, url, ...props }) => {
const gltf = useLoader(GLTFLoader, url)
const group = useRef()
const [mixer] = useState(() => new THREE.AnimationMixer())
useEffect(
() => void mixer.clipAction(gltf.animations[0], group.current).play(),
[gltf.animations, mixer]
)
useFrame((state, delta) => {
group.current.rotation.y +=
Math.sin((delta * factor) / 2) * Math.cos((delta * factor) / 2) * 1.5
mixer.update(delta * speed)
})
return (
<group ref={group}>
<scene name="Scene" {...props}>
<mesh
name="Object_0"
morphTargetDictionary={gltf.__$[1].morphTargetDictionary}
morphTargetInfluences={gltf.__$[1].morphTargetInfluences}
rotation={[1.5707964611537577, 0, 0]}
>
<bufferGeometry attach="geometry" {...gltf.__$[1].geometry} />
<meshStandardMaterial
attach="material"
{...gltf.__$[1].material}
name="Material_0_COLOR_0"
/>
</mesh>
</scene>
</group>
)
}
const Birds = () => {
return new Array(5).fill().map((_, i) => {
const x = (15 + Math.random() * 30) * (Math.round(Math.random()) ? -1 : 1)
const y = -10 + Math.random() * 20
const z = -5 + Math.random() * 10
const bird = ['stork', 'parrot', 'flamingo'][Math.round(Math.random() * 2)]
let speed = bird === 'stork' ? 0.5 : bird === 'flamingo' ? 2 : 5
let factor =
bird === 'stork'
? 0.5 + Math.random()
: bird === 'flamingo'
? 0.25 + Math.random()
: 1 + Math.random() - 0.5
return (
<Bird
key={i}
position={[x, y, z]}
rotation={[0, x > 0 ? Math.PI : 0, 0]}
speed={speed}
factor={factor}
url={`/glb/${bird}.glb`}
/>
)
})
}
const BirdsPage = props => {
useEffect(() => {
GLTFLoader = require('three/examples/jsm/loaders/GLTFLoader').GLTFLoader
}, [])
return (
<>
<Canvas camera={{ position: [0, 0, 35] }}>
<ambientLight intensity={2} />
<pointLight position={[40, 40, 40]} />
<Suspense fallback={null}>
<Birds />
</Suspense>
</Canvas>
</>
)
}
export default BirdsPage