useGLTF.ts 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. import type { AnimationClip, Material, Scene } from 'three'
  2. import type { GLTF } from 'three-stdlib'
  3. import { type TresLoader, type TresObject3D, useLoader } from '@tresjs/core'
  4. import { DRACOLoader, GLTFLoader } from 'three-stdlib'
  5. export interface GLTFLoaderOptions {
  6. /**
  7. * Whether to use Draco compression.
  8. *
  9. * @type {boolean}
  10. * @memberof GLTFLoaderOptions
  11. */
  12. draco?: boolean
  13. /**
  14. * The path to the Draco decoder.
  15. *
  16. * @type {string}
  17. * @memberof GLTFLoaderOptions
  18. */
  19. decoderPath?: string
  20. }
  21. export interface GLTFResult {
  22. animations: Array<AnimationClip>
  23. nodes: Record<string, TresObject3D>
  24. materials: Record<string, Material>
  25. scene: Scene
  26. }
  27. let dracoLoader: DRACOLoader | null = null
  28. export interface TresGLTFLoader extends TresLoader<GLTF> {
  29. setDRACOLoader?: (dracoLoader: DRACOLoader) => void
  30. }
  31. /**
  32. * Sets the extensions for the GLTFLoader.
  33. *
  34. * @param {GLTFLoaderOptions} options
  35. * @param {(loader: TresGLTFLoader) => void} [extendLoader]
  36. * @return {*}
  37. */
  38. function setExtensions(options: GLTFLoaderOptions, extendLoader?: (loader: TresGLTFLoader) => void) {
  39. return (loader: TresGLTFLoader) => {
  40. if (extendLoader) {
  41. extendLoader(loader)
  42. }
  43. if (options.draco) {
  44. if (!dracoLoader) {
  45. dracoLoader = new DRACOLoader()
  46. }
  47. dracoLoader.setDecoderPath(options.decoderPath || 'https://www.gstatic.com/draco/versioned/decoders/1.4.3/')
  48. if (loader.setDRACOLoader) {
  49. loader.setDRACOLoader(dracoLoader)
  50. }
  51. }
  52. }
  53. }
  54. /**
  55. * Loads a GLTF file and returns a THREE.Object3D.
  56. *
  57. * @export
  58. * @param {(string | string[])} path
  59. * @param {GLTFLoaderOptions} [options]
  60. *
  61. *
  62. * @param {(loader: GLTFLoader) => void} [extendLoader]
  63. * @return {*} {Promise<GLTFResult>}
  64. */
  65. export async function useGLTF<T extends string | string[]>(
  66. path: T,
  67. options: GLTFLoaderOptions = {
  68. draco: false,
  69. },
  70. extendLoader?: (loader: TresGLTFLoader) => void,
  71. ): Promise<T extends string[] ? GLTFResult[] : GLTFResult> {
  72. const gltfModel = (await useLoader<GLTF>(GLTFLoader, path, setExtensions(options, extendLoader))) as unknown as GLTFResult
  73. dracoLoader?.dispose()
  74. dracoLoader = null
  75. return gltfModel as T extends string[] ? GLTFResult[] : GLTFResult
  76. }