@lark-apaas/coding-steering 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,607 @@
1
+ # React Three Fiber Loaders
2
+
3
+ ## Quick Start
4
+
5
+ ```tsx
6
+ import { Canvas } from '@react-three/fiber'
7
+ import { useGLTF, OrbitControls } from '@react-three/drei'
8
+ import { Suspense } from 'react'
9
+
10
+ function Model() {
11
+ const { scene } = useGLTF('/models/robot.glb')
12
+ return <primitive object={scene} />
13
+ }
14
+
15
+ export default function App() {
16
+ return (
17
+ <Canvas>
18
+ <ambientLight />
19
+ <Suspense fallback={null}>
20
+ <Model />
21
+ </Suspense>
22
+ <OrbitControls />
23
+ </Canvas>
24
+ )
25
+ }
26
+ ```
27
+
28
+ ## useGLTF (Drei)
29
+
30
+ The recommended way to load GLTF/GLB models.
31
+
32
+ ### Basic Usage
33
+
34
+ ```tsx
35
+ import { useGLTF } from '@react-three/drei'
36
+
37
+ function Model() {
38
+ const gltf = useGLTF('/models/robot.glb')
39
+
40
+ // gltf contains:
41
+ // - scene: THREE.Group (the main scene)
42
+ // - nodes: Object of named meshes
43
+ // - materials: Object of named materials
44
+ // - animations: Array of AnimationClip
45
+
46
+ return <primitive object={gltf.scene} />
47
+ }
48
+ ```
49
+
50
+ ### Using Nodes and Materials
51
+
52
+ ```tsx
53
+ function Model() {
54
+ const { nodes, materials } = useGLTF('/models/robot.glb')
55
+
56
+ return (
57
+ <group>
58
+ {/* Use specific meshes */}
59
+ <mesh
60
+ geometry={nodes.Body.geometry}
61
+ material={materials.Metal}
62
+ position={[0, 0, 0]}
63
+ />
64
+ <mesh
65
+ geometry={nodes.Head.geometry}
66
+ material={materials.Plastic}
67
+ position={[0, 1, 0]}
68
+ />
69
+ </group>
70
+ )
71
+ }
72
+ ```
73
+
74
+ ### With TypeScript (gltfjsx)
75
+
76
+ Generate typed components using gltfjsx:
77
+
78
+ ```bash
79
+ npx gltfjsx model.glb --types
80
+ ```
81
+
82
+ ```tsx
83
+ // Generated component
84
+ import { useGLTF } from '@react-three/drei'
85
+ import { GLTF } from 'three-stdlib'
86
+
87
+ type GLTFResult = GLTF & {
88
+ nodes: {
89
+ Body: THREE.Mesh
90
+ Head: THREE.Mesh
91
+ }
92
+ materials: {
93
+ Metal: THREE.MeshStandardMaterial
94
+ Plastic: THREE.MeshStandardMaterial
95
+ }
96
+ }
97
+
98
+ export function Model(props: JSX.IntrinsicElements['group']) {
99
+ const { nodes, materials } = useGLTF('/model.glb') as GLTFResult
100
+
101
+ return (
102
+ <group {...props} dispose={null}>
103
+ <mesh geometry={nodes.Body.geometry} material={materials.Metal} />
104
+ <mesh geometry={nodes.Head.geometry} material={materials.Plastic} />
105
+ </group>
106
+ )
107
+ }
108
+
109
+ useGLTF.preload('/model.glb')
110
+ ```
111
+
112
+ ### Draco Compression
113
+
114
+ ```tsx
115
+ import { useGLTF } from '@react-three/drei'
116
+
117
+ function Model() {
118
+ // Drei automatically handles Draco if the file is Draco-compressed
119
+ const { scene } = useGLTF('/models/compressed.glb')
120
+ return <primitive object={scene} />
121
+ }
122
+
123
+ // Or specify Draco decoder path
124
+ useGLTF.setDecoderPath('https://www.gstatic.com/draco/versioned/decoders/1.5.6/')
125
+ ```
126
+
127
+ ### Preloading
128
+
129
+ ```tsx
130
+ import { useGLTF } from '@react-three/drei'
131
+
132
+ // Preload at module level
133
+ useGLTF.preload('/models/robot.glb')
134
+ useGLTF.preload(['/model1.glb', '/model2.glb'])
135
+
136
+ function Model() {
137
+ // Will be instant if preloaded
138
+ const { scene } = useGLTF('/models/robot.glb')
139
+ return <primitive object={scene} />
140
+ }
141
+ ```
142
+
143
+ ### Processing Loaded Model
144
+
145
+ ```tsx
146
+ function Model() {
147
+ const { scene } = useGLTF('/models/robot.glb')
148
+
149
+ useEffect(() => {
150
+ // Enable shadows on all meshes
151
+ scene.traverse((child) => {
152
+ if (child.isMesh) {
153
+ child.castShadow = true
154
+ child.receiveShadow = true
155
+ }
156
+ })
157
+ }, [scene])
158
+
159
+ return <primitive object={scene} />
160
+ }
161
+ ```
162
+
163
+ ## useLoader (Core R3F)
164
+
165
+ For loading any Three.js asset.
166
+
167
+ ### Basic Texture Loading
168
+
169
+ ```tsx
170
+ import { useLoader } from '@react-three/fiber'
171
+ import { TextureLoader } from 'three'
172
+
173
+ function TexturedMesh() {
174
+ const texture = useLoader(TextureLoader, '/textures/color.jpg')
175
+
176
+ return (
177
+ <mesh>
178
+ <boxGeometry />
179
+ <meshStandardMaterial map={texture} />
180
+ </mesh>
181
+ )
182
+ }
183
+ ```
184
+
185
+ ### Multiple Assets
186
+
187
+ ```tsx
188
+ function MultiTexture() {
189
+ const [colorMap, normalMap, roughnessMap] = useLoader(TextureLoader, [
190
+ '/textures/color.jpg',
191
+ '/textures/normal.jpg',
192
+ '/textures/roughness.jpg',
193
+ ])
194
+
195
+ return (
196
+ <mesh>
197
+ <sphereGeometry args={[1, 64, 64]} />
198
+ <meshStandardMaterial
199
+ map={colorMap}
200
+ normalMap={normalMap}
201
+ roughnessMap={roughnessMap}
202
+ />
203
+ </mesh>
204
+ )
205
+ }
206
+ ```
207
+
208
+ ### With Extensions (Draco)
209
+
210
+ ```tsx
211
+ import { useLoader } from '@react-three/fiber'
212
+ import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
213
+ import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'
214
+
215
+ function Model() {
216
+ const gltf = useLoader(GLTFLoader, '/model.glb', (loader) => {
217
+ const dracoLoader = new DRACOLoader()
218
+ dracoLoader.setDecoderPath('https://www.gstatic.com/draco/v1/decoders/')
219
+ loader.setDRACOLoader(dracoLoader)
220
+ })
221
+
222
+ return <primitive object={gltf.scene} />
223
+ }
224
+ ```
225
+
226
+ ### Progress Callback
227
+
228
+ ```tsx
229
+ function Model() {
230
+ const gltf = useLoader(
231
+ GLTFLoader,
232
+ '/model.glb',
233
+ undefined, // extensions
234
+ (progress) => {
235
+ console.log(`Loading: ${(progress.loaded / progress.total) * 100}%`)
236
+ }
237
+ )
238
+
239
+ return <primitive object={gltf.scene} />
240
+ }
241
+ ```
242
+
243
+ ### Preloading (useLoader)
244
+
245
+ ```tsx
246
+ import { useLoader } from '@react-three/fiber'
247
+ import { TextureLoader } from 'three'
248
+
249
+ // Preload
250
+ useLoader.preload(TextureLoader, '/textures/color.jpg')
251
+ useLoader.preload(TextureLoader, ['/tex1.jpg', '/tex2.jpg'])
252
+
253
+ // Clear cache
254
+ useLoader.clear(TextureLoader, '/textures/color.jpg')
255
+ ```
256
+
257
+ ## Drei Loader Hooks
258
+
259
+ ### useTexture
260
+
261
+ ```tsx
262
+ import { useTexture } from '@react-three/drei'
263
+
264
+ // Single
265
+ const texture = useTexture('/texture.jpg')
266
+
267
+ // Array
268
+ const [color, normal] = useTexture(['/color.jpg', '/normal.jpg'])
269
+
270
+ // Named object (spreads directly to material)
271
+ const textures = useTexture({
272
+ map: '/color.jpg',
273
+ normalMap: '/normal.jpg',
274
+ roughnessMap: '/roughness.jpg',
275
+ })
276
+ <meshStandardMaterial {...textures} />
277
+
278
+ // With callback for configuration
279
+ const texture = useTexture('/texture.jpg', (tex) => {
280
+ tex.wrapS = tex.wrapT = THREE.RepeatWrapping
281
+ tex.repeat.set(4, 4)
282
+ })
283
+
284
+ // Preload
285
+ useTexture.preload('/texture.jpg')
286
+ ```
287
+
288
+ ### useCubeTexture
289
+
290
+ ```tsx
291
+ import { useCubeTexture } from '@react-three/drei'
292
+
293
+ function EnvMap() {
294
+ const envMap = useCubeTexture(
295
+ ['px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg'],
296
+ { path: '/textures/cube/' }
297
+ )
298
+
299
+ return (
300
+ <mesh>
301
+ <sphereGeometry />
302
+ <meshStandardMaterial envMap={envMap} metalness={1} roughness={0} />
303
+ </mesh>
304
+ )
305
+ }
306
+ ```
307
+
308
+ ### useEnvironment
309
+
310
+ ```tsx
311
+ import { useEnvironment } from '@react-three/drei'
312
+
313
+ // Preset
314
+ const envMap = useEnvironment({ preset: 'sunset' })
315
+ // Presets: apartment, city, dawn, forest, lobby, night, park, studio, sunset, warehouse
316
+
317
+ // Custom HDR file
318
+ const envMap = useEnvironment({ files: '/hdri/studio.hdr' })
319
+
320
+ // Cube map
321
+ const envMap = useEnvironment({
322
+ files: ['px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg'],
323
+ path: '/textures/',
324
+ })
325
+ ```
326
+
327
+ ### useVideoTexture
328
+
329
+ ```tsx
330
+ import { useVideoTexture } from '@react-three/drei'
331
+
332
+ function VideoPlane() {
333
+ const texture = useVideoTexture('/video.mp4', {
334
+ start: true,
335
+ loop: true,
336
+ muted: true,
337
+ crossOrigin: 'anonymous',
338
+ })
339
+
340
+ return (
341
+ <mesh>
342
+ <planeGeometry args={[16/9 * 2, 2]} />
343
+ <meshBasicMaterial map={texture} toneMapped={false} />
344
+ </mesh>
345
+ )
346
+ }
347
+ ```
348
+
349
+ ### useFont
350
+
351
+ ```tsx
352
+ import { useFont, Text3D } from '@react-three/drei'
353
+
354
+ // Preload font
355
+ useFont.preload('/fonts/helvetiker.json')
356
+
357
+ function Text() {
358
+ return (
359
+ <Text3D font="/fonts/helvetiker.json" size={1} height={0.2}>
360
+ Hello
361
+ <meshStandardMaterial color="gold" />
362
+ </Text3D>
363
+ )
364
+ }
365
+ ```
366
+
367
+ ## Suspense Patterns
368
+
369
+ ### Basic Suspense
370
+
371
+ ```tsx
372
+ import { Suspense } from 'react'
373
+
374
+ function Scene() {
375
+ return (
376
+ <Canvas>
377
+ <Suspense fallback={<Loader />}>
378
+ <Model />
379
+ </Suspense>
380
+ </Canvas>
381
+ )
382
+ }
383
+
384
+ function Loader() {
385
+ return (
386
+ <mesh>
387
+ <boxGeometry />
388
+ <meshBasicMaterial color="gray" wireframe />
389
+ </mesh>
390
+ )
391
+ }
392
+ ```
393
+
394
+ ### Loading Progress UI
395
+
396
+ ```tsx
397
+ import { useProgress, Html } from '@react-three/drei'
398
+
399
+ function Loader() {
400
+ const { active, progress, errors, item, loaded, total } = useProgress()
401
+
402
+ return (
403
+ <Html center>
404
+ <div className="loader">
405
+ <div className="progress-bar">
406
+ <div style={{ width: `${progress}%` }} />
407
+ </div>
408
+ <p>{Math.round(progress)}% loaded</p>
409
+ <p>Loading: {item}</p>
410
+ </div>
411
+ </Html>
412
+ )
413
+ }
414
+
415
+ function App() {
416
+ return (
417
+ <Canvas>
418
+ <Suspense fallback={<Loader />}>
419
+ <Scene />
420
+ </Suspense>
421
+ </Canvas>
422
+ )
423
+ }
424
+ ```
425
+
426
+ ### Drei Loader Component
427
+
428
+ ```tsx
429
+ import { Loader } from '@react-three/drei'
430
+
431
+ function App() {
432
+ return (
433
+ <>
434
+ <Canvas>
435
+ <Suspense fallback={null}>
436
+ <Scene />
437
+ </Suspense>
438
+ </Canvas>
439
+ {/* HTML loading overlay */}
440
+ <Loader />
441
+ </>
442
+ )
443
+ }
444
+ ```
445
+
446
+ ## Other Model Formats
447
+
448
+ ### OBJ + MTL
449
+
450
+ ```tsx
451
+ import { useLoader } from '@react-three/fiber'
452
+ import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader'
453
+ import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader'
454
+
455
+ function OBJModel() {
456
+ const materials = useLoader(MTLLoader, '/model.mtl')
457
+ const obj = useLoader(OBJLoader, '/model.obj', (loader) => {
458
+ materials.preload()
459
+ loader.setMaterials(materials)
460
+ })
461
+
462
+ return <primitive object={obj} />
463
+ }
464
+ ```
465
+
466
+ ### FBX
467
+
468
+ ```tsx
469
+ import { useFBX } from '@react-three/drei'
470
+
471
+ function FBXModel() {
472
+ const fbx = useFBX('/model.fbx')
473
+
474
+ return <primitive object={fbx} scale={0.01} />
475
+ }
476
+
477
+ // Preload
478
+ useFBX.preload('/model.fbx')
479
+ ```
480
+
481
+ ### STL
482
+
483
+ ```tsx
484
+ import { useLoader } from '@react-three/fiber'
485
+ import { STLLoader } from 'three/examples/jsm/loaders/STLLoader'
486
+
487
+ function STLModel() {
488
+ const geometry = useLoader(STLLoader, '/model.stl')
489
+
490
+ return (
491
+ <mesh geometry={geometry}>
492
+ <meshStandardMaterial color="gray" />
493
+ </mesh>
494
+ )
495
+ }
496
+ ```
497
+
498
+ ### PLY
499
+
500
+ ```tsx
501
+ import { useLoader } from '@react-three/fiber'
502
+ import { PLYLoader } from 'three/examples/jsm/loaders/PLYLoader'
503
+
504
+ function PLYModel() {
505
+ const geometry = useLoader(PLYLoader, '/model.ply')
506
+
507
+ useEffect(() => {
508
+ geometry.computeVertexNormals()
509
+ }, [geometry])
510
+
511
+ return (
512
+ <mesh geometry={geometry}>
513
+ <meshStandardMaterial vertexColors />
514
+ </mesh>
515
+ )
516
+ }
517
+ ```
518
+
519
+ ## Clone for Multiple Instances
520
+
521
+ ```tsx
522
+ import { useGLTF, Clone } from '@react-three/drei'
523
+
524
+ function Trees() {
525
+ const { scene } = useGLTF('/models/tree.glb')
526
+
527
+ return (
528
+ <>
529
+ <Clone object={scene} position={[0, 0, 0]} />
530
+ <Clone object={scene} position={[5, 0, 0]} />
531
+ <Clone object={scene} position={[-5, 0, 0]} />
532
+ <Clone object={scene} position={[0, 0, 5]} scale={1.5} />
533
+ </>
534
+ )
535
+ }
536
+ ```
537
+
538
+ ## Error Handling
539
+
540
+ ```tsx
541
+ import { useGLTF } from '@react-three/drei'
542
+ import { ErrorBoundary } from 'react-error-boundary'
543
+
544
+ function ModelWithErrorHandling() {
545
+ return (
546
+ <ErrorBoundary fallback={<FallbackModel />}>
547
+ <Suspense fallback={<Loader />}>
548
+ <Model />
549
+ </Suspense>
550
+ </ErrorBoundary>
551
+ )
552
+ }
553
+
554
+ function FallbackModel() {
555
+ return (
556
+ <mesh>
557
+ <boxGeometry />
558
+ <meshBasicMaterial color="red" wireframe />
559
+ </mesh>
560
+ )
561
+ }
562
+ ```
563
+
564
+ ## Asset Caching
565
+
566
+ ```tsx
567
+ import { useGLTF, useTexture } from '@react-three/drei'
568
+
569
+ // Assets are automatically cached by URL
570
+ // Same URL = same asset instance
571
+
572
+ function Scene() {
573
+ // These all reference the same cached asset
574
+ const model1 = useGLTF('/model.glb')
575
+ const model2 = useGLTF('/model.glb')
576
+ const model3 = useGLTF('/model.glb')
577
+
578
+ // Clear cache if needed
579
+ useGLTF.clear('/model.glb')
580
+ }
581
+ ```
582
+
583
+ ## Performance Tips
584
+
585
+ 1. **Preload critical assets**: Avoid loading during interaction
586
+ 2. **Use Draco compression**: Smaller file sizes
587
+ 3. **Use LOD models**: Different detail levels for distance
588
+ 4. **Clone instead of reload**: For multiple instances
589
+ 5. **Lazy load non-critical**: Load on demand
590
+
591
+ ```tsx
592
+ // Preload strategy
593
+ useGLTF.preload('/models/hero.glb') // Critical
594
+ useTexture.preload('/textures/main.jpg') // Critical
595
+
596
+ function LazyModel({ visible }) {
597
+ // Only load when visible
598
+ const { scene } = useGLTF(visible ? '/models/detail.glb' : null)
599
+ return scene ? <primitive object={scene} /> : null
600
+ }
601
+ ```
602
+
603
+ ## See Also
604
+
605
+ - `r3f-animation` - Playing loaded animations
606
+ - `r3f-textures` - Texture configuration
607
+ - `r3f-materials` - Materials from loaded models