0
# Asset Loading
1
2
Three.js provides a comprehensive asset loading system for 3D models, textures, audio, and other media with progress tracking, error handling, and caching capabilities. The loading system supports various file formats and provides both callback-based and Promise-based APIs.
3
4
## Capabilities
5
6
### Loading Manager
7
8
Central coordination system for managing multiple asset loads with global progress tracking and error handling.
9
10
```javascript { .api }
11
/**
12
* Manages loading of multiple assets with progress tracking and coordination
13
*/
14
class LoadingManager {
15
/**
16
* Create loading manager with optional callbacks
17
* @param onLoad - Called when all items finish loading
18
* @param onProgress - Called when any item reports progress
19
* @param onError - Called when any item fails to load
20
*/
21
constructor(
22
onLoad?: () => void,
23
onProgress?: (url: string, itemsLoaded: number, itemsTotal: number) => void,
24
onError?: (url: string) => void
25
);
26
27
/** Callback when all items finish loading */
28
onLoad: (() => void) | undefined;
29
30
/** Callback for progress updates */
31
onProgress: ((url: string, itemsLoaded: number, itemsTotal: number) => void) | undefined;
32
33
/** Callback for loading errors */
34
onError: ((url: string) => void) | undefined;
35
36
/** Callback when loading starts */
37
onStart: ((url: string, itemsLoaded: number, itemsTotal: number) => void) | undefined;
38
39
/**
40
* Register item as loading
41
* @param url - URL being loaded
42
*/
43
itemStart(url: string): void;
44
45
/**
46
* Register item as completed loading
47
* @param url - URL that finished loading
48
*/
49
itemEnd(url: string): void;
50
51
/**
52
* Handle loading error for item
53
* @param url - URL that failed to load
54
*/
55
itemError(url: string): void;
56
57
/**
58
* Resolve URL using URL resolver function
59
* @param url - URL to resolve
60
* @returns Resolved URL
61
*/
62
resolveURL(url: string): string;
63
64
/**
65
* Set URL modifier function for rewriting URLs
66
* @param callback - Function to modify URLs before loading
67
*/
68
setURLModifier(callback?: (url: string) => string): LoadingManager;
69
70
/**
71
* Add regex handler for transforming URLs
72
* @param regex - Pattern to match URLs
73
* @param callback - Function to transform matching URLs
74
*/
75
addHandler(regex: RegExp, loader: Loader): LoadingManager;
76
77
/**
78
* Remove URL handler
79
* @param regex - Pattern to remove handler for
80
*/
81
removeHandler(regex: RegExp): LoadingManager;
82
83
/**
84
* Get appropriate loader for URL
85
* @param file - URL to find loader for
86
* @returns Loader instance or null
87
*/
88
getHandler(file: string): Loader | null;
89
}
90
91
/** Default global loading manager instance */
92
declare const DefaultLoadingManager: LoadingManager;
93
```
94
95
**Usage Example:**
96
97
```javascript
98
import { LoadingManager, TextureLoader, GLTFLoader } from 'three';
99
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
100
101
// Create manager with progress tracking
102
const manager = new LoadingManager(
103
() => console.log('All assets loaded!'),
104
(url, loaded, total) => console.log(`Loading: ${loaded}/${total} - ${url}`),
105
(url) => console.error(`Failed to load: ${url}`)
106
);
107
108
// Use manager with loaders
109
const textureLoader = new TextureLoader(manager);
110
const gltfLoader = new GLTFLoader(manager);
111
112
// Load multiple assets
113
const texture = textureLoader.load('texture.jpg');
114
gltfLoader.load('model.gltf', (gltf) => {
115
scene.add(gltf.scene);
116
});
117
```
118
119
### Base Loader
120
121
Abstract base class providing common functionality for all asset loaders.
122
123
```javascript { .api }
124
/**
125
* Base class for all Three.js asset loaders
126
*/
127
abstract class Loader<TData = any> {
128
/**
129
* Create loader with optional loading manager
130
* @param manager - Loading manager to coordinate with
131
*/
132
constructor(manager?: LoadingManager);
133
134
/** Loading manager coordinating this loader */
135
manager: LoadingManager;
136
137
/** Base path for resolving relative URLs */
138
path: string;
139
140
/** Base resource path for resolving relative URLs */
141
resourcePath: string;
142
143
/** Request headers to send with load requests */
144
requestHeader: { [header: string]: string };
145
146
/** Credentials mode for cross-origin requests */
147
crossOrigin: string;
148
149
/** Whether to include credentials in requests */
150
withCredentials: boolean;
151
152
/**
153
* Load asset from URL
154
* @param url - Asset URL to load
155
* @param onLoad - Success callback with loaded data
156
* @param onProgress - Progress callback
157
* @param onError - Error callback
158
* @returns Loaded data or loading placeholder
159
*/
160
abstract load(
161
url: string,
162
onLoad?: (data: TData) => void,
163
onProgress?: (event: ProgressEvent) => void,
164
onError?: (event: ErrorEvent) => void
165
): TData;
166
167
/**
168
* Load multiple assets in parallel
169
* @param urls - Array of URLs to load
170
* @param onLoad - Success callback with array of loaded data
171
* @param onProgress - Progress callback
172
* @param onError - Error callback
173
*/
174
loadAsync(url: string): Promise<TData>;
175
176
/**
177
* Set base path for resolving relative URLs
178
* @param path - Base path to use
179
* @returns This loader for chaining
180
*/
181
setPath(path: string): this;
182
183
/**
184
* Set resource path for resolving resource URLs
185
* @param resourcePath - Resource path to use
186
* @returns This loader for chaining
187
*/
188
setResourcePath(resourcePath: string): this;
189
190
/**
191
* Set request headers for HTTP requests
192
* @param requestHeader - Headers object
193
* @returns This loader for chaining
194
*/
195
setRequestHeader(requestHeader: { [header: string]: string }): this;
196
}
197
```
198
199
### Texture Loader
200
201
Specialized loader for image textures with support for various image formats and texture configuration.
202
203
```javascript { .api }
204
/**
205
* Loads images as Three.js textures with automatic format detection
206
*/
207
class TextureLoader extends Loader<Texture> {
208
/**
209
* Create texture loader
210
* @param manager - Optional loading manager
211
*/
212
constructor(manager?: LoadingManager);
213
214
/**
215
* Load texture from image URL
216
* @param url - Image URL to load
217
* @param onLoad - Success callback with loaded texture
218
* @param onProgress - Progress callback
219
* @param onError - Error callback
220
* @returns Texture object (loads asynchronously)
221
*/
222
load(
223
url: string,
224
onLoad?: (texture: Texture) => void,
225
onProgress?: (event: ProgressEvent) => void,
226
onError?: (event: ErrorEvent) => void
227
): Texture;
228
229
/**
230
* Load texture asynchronously with Promise
231
* @param url - Image URL to load
232
* @returns Promise resolving to loaded texture
233
*/
234
loadAsync(url: string): Promise<Texture>;
235
}
236
```
237
238
**Usage Example:**
239
240
```javascript
241
import { TextureLoader, MeshBasicMaterial, PlaneGeometry, Mesh } from 'three';
242
243
const loader = new TextureLoader();
244
245
// Load texture with callbacks
246
const texture = loader.load(
247
'path/to/texture.jpg',
248
(texture) => {
249
console.log('Texture loaded:', texture);
250
// Texture is ready to use
251
},
252
(progress) => {
253
console.log('Loading progress:', progress.loaded / progress.total);
254
},
255
(error) => {
256
console.error('Loading failed:', error);
257
}
258
);
259
260
// Use texture immediately (will appear when loaded)
261
const material = new MeshBasicMaterial({ map: texture });
262
const geometry = new PlaneGeometry(1, 1);
263
const mesh = new Mesh(geometry, material);
264
265
// Or load with async/await
266
async function loadTexture() {
267
try {
268
const texture = await loader.loadAsync('path/to/texture.jpg');
269
const material = new MeshBasicMaterial({ map: texture });
270
// Use material...
271
} catch (error) {
272
console.error('Failed to load texture:', error);
273
}
274
}
275
```
276
277
### Cube Texture Loader
278
279
Loader for cube textures used in environment mapping and skyboxes.
280
281
```javascript { .api }
282
/**
283
* Loads six images as cube texture for environment mapping
284
*/
285
class CubeTextureLoader extends Loader<CubeTexture> {
286
/**
287
* Create cube texture loader
288
* @param manager - Optional loading manager
289
*/
290
constructor(manager?: LoadingManager);
291
292
/**
293
* Load cube texture from six image URLs
294
* @param urls - Array of 6 image URLs [+X, -X, +Y, -Y, +Z, -Z]
295
* @param onLoad - Success callback with loaded cube texture
296
* @param onProgress - Progress callback
297
* @param onError - Error callback
298
* @returns CubeTexture object (loads asynchronously)
299
*/
300
load(
301
urls: string[],
302
onLoad?: (texture: CubeTexture) => void,
303
onProgress?: (event: ProgressEvent) => void,
304
onError?: (event: ErrorEvent) => void
305
): CubeTexture;
306
307
/**
308
* Load cube texture asynchronously with Promise
309
* @param urls - Array of 6 image URLs
310
* @returns Promise resolving to loaded cube texture
311
*/
312
loadAsync(urls: string[]): Promise<CubeTexture>;
313
}
314
```
315
316
### File Loader
317
318
Low-level loader for arbitrary file types with configurable response types.
319
320
```javascript { .api }
321
/**
322
* Generic file loader supporting various response types
323
*/
324
class FileLoader extends Loader<string | ArrayBuffer> {
325
/**
326
* Create file loader
327
* @param manager - Optional loading manager
328
*/
329
constructor(manager?: LoadingManager);
330
331
/** MIME type for requests */
332
mimeType: string | undefined;
333
334
/** Response type for XMLHttpRequest */
335
responseType: string | undefined;
336
337
/**
338
* Load file from URL
339
* @param url - File URL to load
340
* @param onLoad - Success callback with file data
341
* @param onProgress - Progress callback
342
* @param onError - Error callback
343
* @returns File data (string or ArrayBuffer based on responseType)
344
*/
345
load(
346
url: string,
347
onLoad?: (data: string | ArrayBuffer) => void,
348
onProgress?: (event: ProgressEvent) => void,
349
onError?: (event: ErrorEvent) => void
350
): string | ArrayBuffer;
351
352
/**
353
* Set MIME type for requests
354
* @param mimeType - MIME type string
355
* @returns This loader for chaining
356
*/
357
setMimeType(mimeType: string): this;
358
359
/**
360
* Set response type for XMLHttpRequest
361
* @param responseType - Response type ('text', 'arraybuffer', 'blob', 'document', 'json')
362
* @returns This loader for chaining
363
*/
364
setResponseType(responseType: string): this;
365
}
366
```
367
368
### Image Loaders
369
370
Specialized loaders for different image loading scenarios.
371
372
```javascript { .api }
373
/**
374
* Loads images as HTML Image elements
375
*/
376
class ImageLoader extends Loader<HTMLImageElement> {
377
/**
378
* Create image loader
379
* @param manager - Optional loading manager
380
*/
381
constructor(manager?: LoadingManager);
382
383
/**
384
* Load image from URL
385
* @param url - Image URL to load
386
* @param onLoad - Success callback with loaded image
387
* @param onProgress - Progress callback (may not be supported)
388
* @param onError - Error callback
389
* @returns HTMLImageElement (loads asynchronously)
390
*/
391
load(
392
url: string,
393
onLoad?: (image: HTMLImageElement) => void,
394
onProgress?: (event: ProgressEvent) => void,
395
onError?: (event: ErrorEvent) => void
396
): HTMLImageElement;
397
}
398
399
/**
400
* Loads images as ImageBitmap objects for high-performance usage
401
*/
402
class ImageBitmapLoader extends Loader<ImageBitmap> {
403
/**
404
* Create ImageBitmap loader
405
* @param manager - Optional loading manager
406
*/
407
constructor(manager?: LoadingManager);
408
409
/** Options for createImageBitmap */
410
options: ImageBitmapOptions | undefined;
411
412
/**
413
* Load image as ImageBitmap
414
* @param url - Image URL to load
415
* @param onLoad - Success callback with ImageBitmap
416
* @param onProgress - Progress callback
417
* @param onError - Error callback
418
* @returns Promise-like object for ImageBitmap
419
*/
420
load(
421
url: string,
422
onLoad?: (imageBitmap: ImageBitmap) => void,
423
onProgress?: (event: ProgressEvent) => void,
424
onError?: (event: ErrorEvent) => void
425
): any;
426
427
/**
428
* Set options for ImageBitmap creation
429
* @param options - ImageBitmap creation options
430
* @returns This loader for chaining
431
*/
432
setOptions(options: ImageBitmapOptions): this;
433
}
434
```
435
436
### Data Texture Loader
437
438
Loader for raw texture data and specialized texture formats.
439
440
```javascript { .api }
441
/**
442
* Loads raw data as DataTexture objects
443
*/
444
class DataTextureLoader extends Loader<DataTexture> {
445
/**
446
* Create data texture loader
447
* @param manager - Optional loading manager
448
*/
449
constructor(manager?: LoadingManager);
450
451
/**
452
* Load raw data as texture
453
* @param url - Data URL to load
454
* @param onLoad - Success callback with DataTexture
455
* @param onProgress - Progress callback
456
* @param onError - Error callback
457
* @returns DataTexture object
458
*/
459
load(
460
url: string,
461
onLoad?: (dataTexture: DataTexture) => void,
462
onProgress?: (event: ProgressEvent) => void,
463
onError?: (event: ErrorEvent) => void
464
): DataTexture;
465
}
466
```
467
468
### Compressed Texture Loader
469
470
Loader for GPU-compressed texture formats for optimized memory usage and performance.
471
472
```javascript { .api }
473
/**
474
* Loads compressed texture formats (DXT, ETC, ASTC, etc.)
475
*/
476
class CompressedTextureLoader extends Loader<CompressedTexture> {
477
/**
478
* Create compressed texture loader
479
* @param manager - Optional loading manager
480
*/
481
constructor(manager?: LoadingManager);
482
483
/**
484
* Load compressed texture data
485
* @param url - Compressed texture URL
486
* @param onLoad - Success callback with CompressedTexture
487
* @param onProgress - Progress callback
488
* @param onError - Error callback
489
* @returns CompressedTexture object
490
*/
491
load(
492
url: string,
493
onLoad?: (texture: CompressedTexture) => void,
494
onProgress?: (event: ProgressEvent) => void,
495
onError?: (event: ErrorEvent) => void
496
): CompressedTexture;
497
}
498
```
499
500
### Object and Material Loaders
501
502
Loaders for Three.js-specific object and material formats.
503
504
```javascript { .api }
505
/**
506
* Loads Three.js Object3D hierarchies from JSON format
507
*/
508
class ObjectLoader extends Loader<Group> {
509
/**
510
* Create object loader
511
* @param manager - Optional loading manager
512
*/
513
constructor(manager?: LoadingManager);
514
515
/**
516
* Load Object3D hierarchy from JSON
517
* @param url - JSON file URL
518
* @param onLoad - Success callback with loaded object
519
* @param onProgress - Progress callback
520
* @param onError - Error callback
521
* @returns Group object containing loaded hierarchy
522
*/
523
load(
524
url: string,
525
onLoad?: (object: Group) => void,
526
onProgress?: (event: ProgressEvent) => void,
527
onError?: (event: ErrorEvent) => void
528
): Group;
529
530
/**
531
* Parse JSON data into Object3D hierarchy
532
* @param json - JSON object data
533
* @param onLoad - Success callback
534
* @returns Parsed Object3D
535
*/
536
parse<T extends Object3D>(json: any, onLoad?: (object: T) => void): T;
537
538
/**
539
* Parse geometries from JSON data
540
* @param json - JSON geometry data
541
* @returns Map of geometry instances
542
*/
543
parseGeometries(json: any): { [key: string]: BufferGeometry };
544
545
/**
546
* Parse materials from JSON data
547
* @param json - JSON material data
548
* @param textures - Map of loaded textures
549
* @returns Map of material instances
550
*/
551
parseMaterials(json: any, textures: { [key: string]: Texture }): { [key: string]: Material };
552
553
/**
554
* Parse animations from JSON data
555
* @param json - JSON animation data
556
* @returns Array of animation clips
557
*/
558
parseAnimations(json: any): AnimationClip[];
559
560
/**
561
* Parse images from JSON data
562
* @param json - JSON image data
563
* @param onLoad - Callback when all images loaded
564
* @returns Map of loaded textures
565
*/
566
parseImages(json: any, onLoad: () => void): { [key: string]: Texture };
567
568
/**
569
* Parse textures from JSON data
570
* @param json - JSON texture data
571
* @param images - Map of loaded images
572
* @returns Map of texture instances
573
*/
574
parseTextures(json: any, images: { [key: string]: Texture }): { [key: string]: Texture };
575
576
/**
577
* Parse objects from JSON data
578
* @param json - JSON object data
579
* @param geometries - Map of geometries
580
* @param materials - Map of materials
581
* @param animations - Array of animations
582
* @returns Parsed Object3D
583
*/
584
parseObject<T extends Object3D>(
585
json: any,
586
geometries: { [key: string]: BufferGeometry },
587
materials: { [key: string]: Material },
588
animations: AnimationClip[]
589
): T;
590
}
591
592
/**
593
* Loads Three.js materials from JSON format
594
*/
595
class MaterialLoader extends Loader<Material> {
596
/**
597
* Create material loader
598
* @param manager - Optional loading manager
599
*/
600
constructor(manager?: LoadingManager);
601
602
/** Map of loaded textures for material creation */
603
textures: { [key: string]: Texture };
604
605
/**
606
* Load material from JSON
607
* @param url - JSON file URL
608
* @param onLoad - Success callback with loaded material
609
* @param onProgress - Progress callback
610
* @param onError - Error callback
611
* @returns Material object
612
*/
613
load(
614
url: string,
615
onLoad?: (material: Material) => void,
616
onProgress?: (event: ProgressEvent) => void,
617
onError?: (event: ErrorEvent) => void
618
): Material;
619
620
/**
621
* Parse JSON data into material
622
* @param json - JSON material data
623
* @returns Parsed material instance
624
*/
625
parse(json: any): Material;
626
627
/**
628
* Set textures map for material parsing
629
* @param textures - Map of texture instances
630
* @returns This loader for chaining
631
*/
632
setTextures(textures: { [key: string]: Texture }): this;
633
}
634
635
/**
636
* Loads BufferGeometry from JSON format
637
*/
638
class BufferGeometryLoader extends Loader<BufferGeometry> {
639
/**
640
* Create buffer geometry loader
641
* @param manager - Optional loading manager
642
*/
643
constructor(manager?: LoadingManager);
644
645
/**
646
* Load geometry from JSON
647
* @param url - JSON file URL
648
* @param onLoad - Success callback with loaded geometry
649
* @param onProgress - Progress callback
650
* @param onError - Error callback
651
* @returns BufferGeometry object
652
*/
653
load(
654
url: string,
655
onLoad?: (geometry: BufferGeometry) => void,
656
onProgress?: (event: ProgressEvent) => void,
657
onError?: (event: ErrorEvent) => void
658
): BufferGeometry;
659
660
/**
661
* Parse JSON data into BufferGeometry
662
* @param json - JSON geometry data
663
* @returns Parsed BufferGeometry instance
664
*/
665
parse(json: any): BufferGeometry;
666
}
667
```
668
669
### Animation Loader
670
671
Loader for animation data in Three.js JSON format.
672
673
```javascript { .api }
674
/**
675
* Loads animation clips from JSON format
676
*/
677
class AnimationLoader extends Loader<AnimationClip[]> {
678
/**
679
* Create animation loader
680
* @param manager - Optional loading manager
681
*/
682
constructor(manager?: LoadingManager);
683
684
/**
685
* Load animations from JSON
686
* @param url - JSON file URL containing animation data
687
* @param onLoad - Success callback with loaded animation clips
688
* @param onProgress - Progress callback
689
* @param onError - Error callback
690
* @returns Array of AnimationClip objects
691
*/
692
load(
693
url: string,
694
onLoad?: (animations: AnimationClip[]) => void,
695
onProgress?: (event: ProgressEvent) => void,
696
onError?: (event: ErrorEvent) => void
697
): AnimationClip[];
698
699
/**
700
* Parse JSON data into animation clips
701
* @param json - JSON animation data
702
* @returns Array of parsed AnimationClip instances
703
*/
704
parse(json: any): AnimationClip[];
705
}
706
```
707
708
### Audio Loader
709
710
Loader for audio files with support for various audio formats.
711
712
```javascript { .api }
713
/**
714
* Loads audio files as AudioBuffer objects for use with Web Audio API
715
*/
716
class AudioLoader extends Loader<AudioBuffer> {
717
/**
718
* Create audio loader
719
* @param manager - Optional loading manager
720
*/
721
constructor(manager?: LoadingManager);
722
723
/**
724
* Load audio file
725
* @param url - Audio file URL
726
* @param onLoad - Success callback with decoded AudioBuffer
727
* @param onProgress - Progress callback
728
* @param onError - Error callback
729
* @returns AudioBuffer object (decoded asynchronously)
730
*/
731
load(
732
url: string,
733
onLoad?: (audioBuffer: AudioBuffer) => void,
734
onProgress?: (event: ProgressEvent) => void,
735
onError?: (event: ErrorEvent) => void
736
): AudioBuffer;
737
}
738
```
739
740
### Cache System
741
742
Global caching system for loaded assets to prevent duplicate requests and improve performance.
743
744
```javascript { .api }
745
/**
746
* Global cache for loaded assets to prevent duplicate requests
747
*/
748
class Cache {
749
/** Whether caching is enabled */
750
static enabled: boolean;
751
752
/** Map of cached files */
753
static files: { [key: string]: any };
754
755
/**
756
* Add item to cache
757
* @param key - Cache key (usually URL)
758
* @param file - Data to cache
759
*/
760
static add(key: string, file: any): void;
761
762
/**
763
* Get item from cache
764
* @param key - Cache key to retrieve
765
* @returns Cached data or undefined
766
*/
767
static get(key: string): any;
768
769
/**
770
* Remove item from cache
771
* @param key - Cache key to remove
772
*/
773
static remove(key: string): void;
774
775
/**
776
* Clear all cached items
777
*/
778
static clear(): void;
779
}
780
```
781
782
### Loader Utils
783
784
Utility functions for working with loaded data and extracting information.
785
786
```javascript { .api }
787
/**
788
* Utility functions for asset loading operations
789
*/
790
class LoaderUtils {
791
/**
792
* Extract URL base path for resolving relative URLs
793
* @param url - Full URL to extract base from
794
* @returns Base path portion of URL
795
*/
796
static extractUrlBase(url: string): string;
797
798
/**
799
* Decode text from array buffer with encoding detection
800
* @param array - Array buffer containing text data
801
* @returns Decoded text string
802
*/
803
static decodeText(array: Uint8Array): string;
804
}
805
```
806
807
## Types
808
809
```javascript { .api }
810
// Loading-related type definitions
811
interface ProgressEvent {
812
lengthComputable: boolean;
813
loaded: number;
814
total: number;
815
target?: any;
816
}
817
818
interface ErrorEvent {
819
message: string;
820
target?: any;
821
}
822
823
// ImageBitmap creation options
824
interface ImageBitmapOptions {
825
imageOrientation?: 'none' | 'flipY';
826
premultiplyAlpha?: 'none' | 'premultiply' | 'default';
827
colorSpaceConversion?: 'none' | 'default';
828
resizeWidth?: number;
829
resizeHeight?: number;
830
resizeQuality?: 'pixelated' | 'low' | 'medium' | 'high';
831
}
832
```
833
834
## Usage Examples
835
836
**Complete Asset Loading Pipeline:**
837
838
```javascript
839
import * as THREE from 'three';
840
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
841
import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js';
842
843
// Create loading manager with progress tracking
844
const loadingManager = new THREE.LoadingManager();
845
loadingManager.onStart = (url, itemsLoaded, itemsTotal) => {
846
console.log(`Started loading: ${url}`);
847
};
848
loadingManager.onProgress = (url, itemsLoaded, itemsTotal) => {
849
const progress = itemsLoaded / itemsTotal * 100;
850
console.log(`Loading progress: ${progress.toFixed(1)}%`);
851
updateProgressBar(progress);
852
};
853
loadingManager.onLoad = () => {
854
console.log('All assets loaded!');
855
hideLoadingScreen();
856
};
857
loadingManager.onError = (url) => {
858
console.error(`Failed to load: ${url}`);
859
};
860
861
// Set up loaders with manager
862
const textureLoader = new THREE.TextureLoader(loadingManager);
863
const gltfLoader = new GLTFLoader(loadingManager);
864
865
// Set up DRACO compression support
866
const dracoLoader = new DRACOLoader();
867
dracoLoader.setDecoderPath('/examples/js/libs/draco/');
868
gltfLoader.setDRACOLoader(dracoLoader);
869
870
// Load multiple assets
871
Promise.all([
872
textureLoader.loadAsync('textures/ground.jpg'),
873
textureLoader.loadAsync('textures/sky.jpg'),
874
gltfLoader.loadAsync('models/character.gltf')
875
]).then(([groundTexture, skyTexture, gltf]) => {
876
// All assets loaded, set up scene
877
groundTexture.wrapS = groundTexture.wrapT = THREE.RepeatWrapping;
878
groundTexture.repeat.set(10, 10);
879
880
const groundMaterial = new THREE.MeshLambertMaterial({ map: groundTexture });
881
const groundGeometry = new THREE.PlaneGeometry(50, 50);
882
const ground = new THREE.Mesh(groundGeometry, groundMaterial);
883
ground.rotation.x = -Math.PI / 2;
884
scene.add(ground);
885
886
scene.background = skyTexture;
887
scene.add(gltf.scene);
888
889
// Start animation if present
890
if (gltf.animations.length > 0) {
891
const mixer = new THREE.AnimationMixer(gltf.scene);
892
const action = mixer.clipAction(gltf.animations[0]);
893
action.play();
894
895
// Update mixer in render loop
896
const clock = new THREE.Clock();
897
function animate() {
898
const deltaTime = clock.getDelta();
899
mixer.update(deltaTime);
900
renderer.render(scene, camera);
901
requestAnimationFrame(animate);
902
}
903
animate();
904
}
905
}).catch((error) => {
906
console.error('Loading failed:', error);
907
});
908
```