-
Notifications
You must be signed in to change notification settings - Fork 708
/
Gltf.tsx
72 lines (60 loc) · 2.35 KB
/
Gltf.tsx
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
import * as React from 'react'
import { Clone } from './Clone'
import { type Loader } from 'three'
import { type GLTF, GLTFLoader, DRACOLoader, MeshoptDecoder } from 'three-stdlib'
import { type ObjectMap, useLoader } from '@react-three/fiber'
let dracoLoader: DRACOLoader | null = null
let decoderPath: string = 'https://www.gstatic.com/draco/versioned/decoders/1.5.5/'
function extensions(useDraco: boolean | string, useMeshopt: boolean, extendLoader?: (loader: GLTFLoader) => void) {
return (loader: Loader) => {
if (extendLoader) {
extendLoader(loader as GLTFLoader)
}
if (useDraco) {
if (!dracoLoader) {
dracoLoader = new DRACOLoader()
}
dracoLoader.setDecoderPath(typeof useDraco === 'string' ? useDraco : decoderPath)
;(loader as GLTFLoader).setDRACOLoader(dracoLoader)
}
if (useMeshopt) {
;(loader as GLTFLoader).setMeshoptDecoder(
typeof MeshoptDecoder === 'function' ? MeshoptDecoder() : MeshoptDecoder
)
}
}
}
export function useGLTF<T extends string | string[]>(
path: T,
useDraco: boolean | string = true,
useMeshOpt: boolean = true,
extendLoader?: (loader: GLTFLoader) => void
): T extends any[] ? (GLTF & ObjectMap)[] : GLTF & ObjectMap {
return useLoader(GLTFLoader, path, extensions(useDraco, useMeshOpt, extendLoader))
}
useGLTF.preload = (
path: string | string[],
useDraco: boolean | string = true,
useMeshOpt: boolean = true,
extendLoader?: (loader: GLTFLoader) => void
) => useLoader.preload(GLTFLoader, path, extensions(useDraco, useMeshOpt, extendLoader))
useGLTF.clear = (input: string | string[]) => useLoader.clear(GLTFLoader, input)
useGLTF.setDecoderPath = (path: string) => {
decoderPath = path
}
//
type UseGLTF = Parameters<typeof useGLTF>
type CloneProps = React.ComponentProps<typeof Clone>
type GltfRef = React.ElementRef<typeof Clone>
type GltfProps = Omit<CloneProps, 'object'> & {
src: string // simple string, not a string[] as useGLTF supports (otherwise we should render multiple <Clone>s?)
useDraco?: UseGLTF[1]
useMeshOpt?: UseGLTF[2]
extendLoader?: UseGLTF[3]
}
export const Gltf = /* @__PURE__ */ React.forwardRef<GltfRef, GltfProps>(
({ src, useDraco, useMeshOpt, extendLoader, ...props }, ref) => {
const { scene } = useGLTF(src, useDraco, useMeshOpt, extendLoader)
return <Clone ref={ref} {...props} object={scene} />
}
)