@haiyue/extensions 0.1.0 → 0.2.0

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.
Files changed (269) hide show
  1. package/README.md +25 -0
  2. package/dist/animation/Animation2DComponent.d.ts +18 -0
  3. package/dist/animation/Animation2DExtensionRegistry.d.ts +7 -0
  4. package/dist/animation/Animation2DRenderSystem.d.ts +6 -0
  5. package/dist/animation/Animation2DRuntime.d.ts +6 -2
  6. package/dist/animation/AnimationTextRasterizer.d.ts +4 -0
  7. package/dist/animation/AnimationVisual2D.d.ts +58 -2
  8. package/dist/animation/interaction/InteractionRuntime.d.ts +83 -0
  9. package/dist/animation/interaction/runtime-types.d.ts +257 -0
  10. package/dist/animation.d.ts +3 -1
  11. package/dist/animation.js +551 -59
  12. package/dist/animation3d.js +1 -1
  13. package/dist/canvas-text.js +1 -1
  14. package/dist/chunks/2d-ui-animation-2d.generated-FpziAeGJ.js +4 -0
  15. package/dist/chunks/2d-ui-indexed-sprite.generated-DmKR0CC3.js +4 -0
  16. package/dist/chunks/Animation2DStateMachine-BHcA6Cu3.js +18212 -0
  17. package/dist/chunks/{AnimationStateMachineController-BIcAh-sT.js → AnimationStateMachineController-4sKaqh9E.js} +2 -2
  18. package/dist/chunks/AnimationVisual2D-8y3qp0_U.js +230 -0
  19. package/dist/chunks/{RenderSystem2DBase-DDT61dAu.js → RenderSystem2DBase-CF2s00vg.js} +2 -2
  20. package/dist/controls/VirtualJoystickControls.d.ts +46 -0
  21. package/dist/controls/contracts.d.ts +91 -0
  22. package/dist/controls.d.ts +2 -0
  23. package/dist/controls.js +358 -0
  24. package/dist/deformable-animation/runtime/DeformableMesh2DRuntimeExtension.d.ts +11 -0
  25. package/dist/deformable-animation/runtime/DeformableMesh2DSampler.d.ts +11 -0
  26. package/dist/deformable-animation.d.ts +5 -0
  27. package/dist/deformable-animation.js +316 -0
  28. package/dist/experimental-indexed-sprite.d.ts +5 -0
  29. package/dist/experimental-indexed-sprite.js +482 -0
  30. package/dist/gltf-worker-runtime.js +9 -9
  31. package/dist/hya-state-machine.js +3 -2
  32. package/dist/index.js +1 -1
  33. package/dist/indexed-sprite/AtlasLayout.d.ts +2 -0
  34. package/dist/indexed-sprite/IndexedSpriteRenderer.d.ts +23 -0
  35. package/dist/indexed-sprite/contracts.d.ts +89 -0
  36. package/dist/internal/2d-ui-shader-artifact.js +232 -23
  37. package/dist/ray-tracing/acceleration/bvh.d.ts +37 -0
  38. package/dist/ray-tracing/acceleration/index.d.ts +6 -0
  39. package/dist/ray-tracing/acceleration/pack.d.ts +152 -0
  40. package/dist/ray-tracing/acceleration/query.d.ts +4 -0
  41. package/dist/ray-tracing/acceleration/runtime.d.ts +30 -0
  42. package/dist/ray-tracing/acceleration/tlas.d.ts +4 -0
  43. package/dist/ray-tracing/acceleration/types.d.ts +165 -0
  44. package/dist/ray-tracing/denoise/index.d.ts +3 -0
  45. package/dist/ray-tracing/denoise/layout.d.ts +9 -0
  46. package/dist/ray-tracing/denoise/runtime.d.ts +23 -0
  47. package/dist/ray-tracing/denoise/types.d.ts +28 -0
  48. package/dist/ray-tracing/hybrid/contract.d.ts +2 -0
  49. package/dist/ray-tracing/hybrid/index.d.ts +5 -0
  50. package/dist/ray-tracing/hybrid/layout.d.ts +17 -0
  51. package/dist/ray-tracing/hybrid/plan.d.ts +2 -0
  52. package/dist/ray-tracing/hybrid/runtime.d.ts +31 -0
  53. package/dist/ray-tracing/hybrid/shaders/hybrid-artifact.generated.d.ts +625 -0
  54. package/dist/ray-tracing/hybrid/types.d.ts +144 -0
  55. package/dist/ray-tracing/lifecycle/device-recovery.d.ts +31 -0
  56. package/dist/ray-tracing/lifecycle/index.d.ts +2 -0
  57. package/dist/ray-tracing/lifecycle/types.d.ts +37 -0
  58. package/dist/ray-tracing/material/index.d.ts +2 -0
  59. package/dist/ray-tracing/material/pack.d.ts +5 -0
  60. package/dist/ray-tracing/material/types.d.ts +63 -0
  61. package/dist/ray-tracing/reference/index.d.ts +122 -0
  62. package/dist/ray-tracing/renderer/index.d.ts +7 -0
  63. package/dist/ray-tracing/renderer/layout.d.ts +20 -0
  64. package/dist/ray-tracing/renderer/plan.d.ts +2 -0
  65. package/dist/ray-tracing/renderer/reference.d.ts +17 -0
  66. package/dist/ray-tracing/renderer/runtime.d.ts +39 -0
  67. package/dist/ray-tracing/renderer/scene.d.ts +4 -0
  68. package/dist/ray-tracing/renderer/types.d.ts +115 -0
  69. package/dist/ray-tracing/sampling/index.d.ts +8 -0
  70. package/dist/ray-tracing/sampling/layout.d.ts +12 -0
  71. package/dist/ray-tracing/sampling/plan.d.ts +5 -0
  72. package/dist/ray-tracing/sampling/revision.d.ts +15 -0
  73. package/dist/ray-tracing/sampling/runtime.d.ts +44 -0
  74. package/dist/ray-tracing/sampling/sequence.d.ts +2 -0
  75. package/dist/ray-tracing/sampling/types.d.ts +96 -0
  76. package/dist/ray-tracing/scene/index.d.ts +41 -0
  77. package/dist/ray-tracing/traversal/index.d.ts +4 -0
  78. package/dist/ray-tracing/traversal/layout.d.ts +16 -0
  79. package/dist/ray-tracing/traversal/plan.d.ts +2 -0
  80. package/dist/ray-tracing/traversal/runtime.d.ts +25 -0
  81. package/dist/ray-tracing/traversal/types.d.ts +79 -0
  82. package/dist/ray-tracing/worker/client.d.ts +25 -0
  83. package/dist/ray-tracing/worker/index.d.ts +5 -0
  84. package/dist/ray-tracing/worker/runtime.d.ts +11 -0
  85. package/dist/ray-tracing/worker/serialization.d.ts +16 -0
  86. package/dist/ray-tracing/worker/source.d.ts +1 -0
  87. package/dist/ray-tracing/worker/types.d.ts +91 -0
  88. package/dist/ray-tracing.d.ts +17 -0
  89. package/dist/ray-tracing.js +7666 -0
  90. package/dist/spine.js +1 -1
  91. package/dist/tilemap.js +1 -1
  92. package/package.json +26 -23
  93. package/dist/animation/Animation2DStateMachineVisualRuntime.d.ts +0 -27
  94. package/dist/animation/Particle2DDescriptorAdapter.d.ts +0 -5
  95. package/dist/animation3d/Animation3DResource.d.ts +0 -28
  96. package/dist/animation3d/hya/HyaAnimation3DStateMachineRuntime.d.ts +0 -65
  97. package/dist/animation3d/hya/index.d.ts +0 -4
  98. package/dist/animation3d/runtime/integration/Animation3DStateMachineMixerAdapter.d.ts +0 -81
  99. package/dist/animation3d/runtime/integration/Animation3DStateMachineMixerIntegration.d.ts +0 -39
  100. package/dist/animation3d/runtime/integration/index.d.ts +0 -2
  101. package/dist/animation3d/runtime/mixer/Action.d.ts +0 -150
  102. package/dist/animation3d/runtime/mixer/Animation3DMixerRuntimeStore.d.ts +0 -6
  103. package/dist/animation3d/runtime/mixer/Mixer.d.ts +0 -59
  104. package/dist/animation3d/runtime/mixer/PoseBuffer.d.ts +0 -1
  105. package/dist/animation3d/runtime/mixer/TrackSampler.d.ts +0 -24
  106. package/dist/animation3d/runtime/mixer/index.d.ts +0 -4
  107. package/dist/animation3d/runtime/state-machine/Animation3DBlendTreeWeights.d.ts +0 -1
  108. package/dist/animation3d/runtime/state-machine/Animation3DStateMachineCompiler.d.ts +0 -1
  109. package/dist/animation3d/runtime/state-machine/Animation3DStateMachineController.d.ts +0 -1
  110. package/dist/animation3d/runtime/state-machine/Animation3DStateMachineMixerPort.d.ts +0 -1
  111. package/dist/animation3d/runtime/state-machine/index.d.ts +0 -6
  112. package/dist/benchmark.d.ts +0 -30
  113. package/dist/chunks/2d-ui-animation-2d.generated-D4aHzFU2.js +0 -4
  114. package/dist/chunks/Animation2DStateMachine-9IonguNa.js +0 -3245
  115. package/dist/gltf/GltfAccessorReader.d.ts +0 -7
  116. package/dist/gltf/GltfDracoDecoder.d.ts +0 -4
  117. package/dist/gltf/GltfLoaderErrors.d.ts +0 -4
  118. package/dist/gltf/GltfMaterialDescriptor.d.ts +0 -23
  119. package/dist/gltf/GltfMaterialLoader.d.ts +0 -6
  120. package/dist/gltf-worker-runtime.d.ts +0 -7
  121. package/dist/plugins/pluginUtils.d.ts +0 -20
  122. package/dist/plugins.d.ts +0 -6
  123. package/dist/shaders/generated/2d-ui-artifact.generated.d.ts +0 -658
  124. package/dist/spine/Spine2DGpuRenderer.d.ts +0 -65
  125. package/dist/spine/Spine2DRuntime.d.ts +0 -103
  126. package/dist/spine/SpineAnimationBoneTimelines.d.ts +0 -8
  127. package/dist/spine/SpineFloatBuilder.d.ts +0 -15
  128. package/dist/spine/SpinePathConstraintSolver.d.ts +0 -32
  129. package/dist/spine/SpineSkeletonRuntime.d.ts +0 -185
  130. package/dist/spine/SpineSlotAnimation.d.ts +0 -17
  131. package/dist/spine/SpineTimelineRuntime.d.ts +0 -25
  132. package/dist/spine/SpineVertexBuilder.d.ts +0 -61
  133. package/dist/tilemap/Tilemap2DRenderer.d.ts +0 -24
  134. package/dist/utils/arrayAccess.d.ts +0 -4
  135. package/dist/utils/camera2d.d.ts +0 -12
  136. package/src/animation/Animation2DComponent.ts +0 -135
  137. package/src/animation/Animation2DExtensionRegistry.ts +0 -52
  138. package/src/animation/Animation2DRenderSystem.ts +0 -1026
  139. package/src/animation/Animation2DRuntime.ts +0 -1326
  140. package/src/animation/Animation2DStateMachine.ts +0 -39
  141. package/src/animation/Animation2DStateMachineComponent.ts +0 -228
  142. package/src/animation/Animation2DStateMachineRuntime.ts +0 -141
  143. package/src/animation/Animation2DStateMachineSystem.ts +0 -60
  144. package/src/animation/Animation2DStateMachineVisualRuntime.ts +0 -282
  145. package/src/animation/Animation2DSystem.ts +0 -72
  146. package/src/animation/AnimationAssetLoader.ts +0 -84
  147. package/src/animation/AnimationAudioClip.ts +0 -140
  148. package/src/animation/AnimationPathTessellator.ts +0 -691
  149. package/src/animation/AnimationTextRasterizer.ts +0 -340
  150. package/src/animation/AnimationVisual2D.ts +0 -153
  151. package/src/animation/HyaAnimation2DClipAdapter.ts +0 -845
  152. package/src/animation/Particle2DDescriptorAdapter.ts +0 -35
  153. package/src/animation/runtime/mixer/Action.ts +0 -876
  154. package/src/animation/runtime/mixer/Mixer.ts +0 -505
  155. package/src/animation/runtime/mixer/PoseBuffer.ts +0 -105
  156. package/src/animation/runtime/mixer/Sampler.ts +0 -252
  157. package/src/animation/runtime/mixer/Types.ts +0 -138
  158. package/src/animation/runtime/mixer/index.ts +0 -31
  159. package/src/animation-state-machine/AnimationStateMachine.ts +0 -146
  160. package/src/animation-state-machine/AnimationStateMachineChannels.ts +0 -116
  161. package/src/animation-state-machine/runtime/Animation2DStateMachineMixerAdapter.ts +0 -197
  162. package/src/animation-state-machine/runtime/AnimationStateMachineBlendTreeWeights.ts +0 -503
  163. package/src/animation-state-machine/runtime/AnimationStateMachineCompiler.ts +0 -763
  164. package/src/animation-state-machine/runtime/AnimationStateMachineController.ts +0 -987
  165. package/src/animation-state-machine/runtime/AnimationStateMachineMixerPort.ts +0 -54
  166. package/src/animation-state-machine/runtime/index.ts +0 -47
  167. package/src/animation.ts +0 -33
  168. package/src/animation3d/Animation3DAction.ts +0 -73
  169. package/src/animation3d/Animation3DBinding.ts +0 -116
  170. package/src/animation3d/Animation3DClip.ts +0 -22
  171. package/src/animation3d/Animation3DError.ts +0 -34
  172. package/src/animation3d/Animation3DMixer.ts +0 -82
  173. package/src/animation3d/Animation3DPose.ts +0 -100
  174. package/src/animation3d/Animation3DPoseBuffer.ts +0 -85
  175. package/src/animation3d/Animation3DResource.ts +0 -49
  176. package/src/animation3d/Animation3DStateMachine.ts +0 -126
  177. package/src/animation3d/Animation3DStateMachineRuntime.ts +0 -191
  178. package/src/animation3d/Animation3DTrack.ts +0 -29
  179. package/src/animation3d/hya/HyaAnimation3DRuntime.ts +0 -756
  180. package/src/animation3d/hya/HyaAnimation3DStateMachineRuntime.ts +0 -618
  181. package/src/animation3d/hya/HyaAnimation3DTypes.ts +0 -168
  182. package/src/animation3d/hya/index.ts +0 -10
  183. package/src/animation3d/index.ts +0 -76
  184. package/src/animation3d/runtime/integration/Animation3DStateMachineMixerAdapter.ts +0 -325
  185. package/src/animation3d/runtime/integration/Animation3DStateMachineMixerIntegration.ts +0 -158
  186. package/src/animation3d/runtime/integration/index.ts +0 -9
  187. package/src/animation3d/runtime/mixer/Action.ts +0 -833
  188. package/src/animation3d/runtime/mixer/Animation3DMixerRuntimeStore.ts +0 -26
  189. package/src/animation3d/runtime/mixer/Mixer.ts +0 -562
  190. package/src/animation3d/runtime/mixer/PoseBuffer.ts +0 -1
  191. package/src/animation3d/runtime/mixer/TrackSampler.ts +0 -399
  192. package/src/animation3d/runtime/mixer/index.ts +0 -8
  193. package/src/animation3d/runtime/state-machine/Animation3DBlendTreeWeights.ts +0 -4
  194. package/src/animation3d/runtime/state-machine/Animation3DStateMachineCompiler.ts +0 -1
  195. package/src/animation3d/runtime/state-machine/Animation3DStateMachineController.ts +0 -1
  196. package/src/animation3d/runtime/state-machine/Animation3DStateMachineMixerPort.ts +0 -1
  197. package/src/animation3d/runtime/state-machine/index.ts +0 -45
  198. package/src/animation3d.ts +0 -5
  199. package/src/benchmark.ts +0 -168
  200. package/src/canvas-text/CanvasText2DRenderSystem.ts +0 -292
  201. package/src/canvas-text/CanvasTextComponent.ts +0 -47
  202. package/src/canvas-text.ts +0 -4
  203. package/src/experimental-gltf-worker.ts +0 -18
  204. package/src/experimental-spine-worker.ts +0 -9
  205. package/src/gltf/GltfAccessorReader.ts +0 -271
  206. package/src/gltf/GltfAnimation3DAdapter.ts +0 -680
  207. package/src/gltf/GltfAnimationRuntime.ts +0 -392
  208. package/src/gltf/GltfAssetWorkerClient.ts +0 -136
  209. package/src/gltf/GltfCompatibilityReport.ts +0 -214
  210. package/src/gltf/GltfConservativeBounds.ts +0 -219
  211. package/src/gltf/GltfDracoDecoder.ts +0 -251
  212. package/src/gltf/GltfExtensionAdapter.ts +0 -340
  213. package/src/gltf/GltfLoaderContract.ts +0 -333
  214. package/src/gltf/GltfLoaderErrors.ts +0 -59
  215. package/src/gltf/GltfMaterialDescriptor.ts +0 -134
  216. package/src/gltf/GltfMaterialEncoder.ts +0 -173
  217. package/src/gltf/GltfMaterialLoader.ts +0 -293
  218. package/src/gltf/GltfModelComponent.ts +0 -115
  219. package/src/gltf/GltfModelSystem.ts +0 -208
  220. package/src/gltf/GltfPlugin.ts +0 -84
  221. package/src/gltf/GltfSchema.ts +0 -229
  222. package/src/gltf/GltfUvSemanticPlanner.ts +0 -166
  223. package/src/gltf/gltfLoader.ts +0 -910
  224. package/src/gltf-animation3d.ts +0 -10
  225. package/src/gltf-worker-runtime.ts +0 -10
  226. package/src/gltf.ts +0 -56
  227. package/src/grid/Grid2DComponent.ts +0 -69
  228. package/src/grid.ts +0 -2
  229. package/src/hya-state-machine.ts +0 -19
  230. package/src/index.ts +0 -2
  231. package/src/plugins/pluginUtils.ts +0 -50
  232. package/src/plugins.ts +0 -6
  233. package/src/shaders/generated/2d-ui-animation-2d.generated.wgsl +0 -242
  234. package/src/shaders/generated/2d-ui-artifact.generated.ts +0 -867
  235. package/src/shaders/generated/2d-ui-canvas-text-2d.generated.wgsl +0 -38
  236. package/src/shaders/generated/2d-ui-spine2d.generated.wgsl +0 -41
  237. package/src/shaders/generated/2d-ui-tilemap2d.generated.wgsl +0 -36
  238. package/src/spine/Spine2DComponent.ts +0 -168
  239. package/src/spine/Spine2DGpuRenderer.ts +0 -449
  240. package/src/spine/Spine2DRenderSystem.ts +0 -199
  241. package/src/spine/Spine2DRuntime.ts +0 -1529
  242. package/src/spine/SpineAnimationBoneTimelines.ts +0 -30
  243. package/src/spine/SpineAssetParser.ts +0 -20
  244. package/src/spine/SpineAssetWorkerClient.ts +0 -112
  245. package/src/spine/SpineAssetWorkerContract.ts +0 -4
  246. package/src/spine/SpineAtlasParser.ts +0 -127
  247. package/src/spine/SpineFloatBuilder.ts +0 -66
  248. package/src/spine/SpinePathConstraintSolver.ts +0 -582
  249. package/src/spine/SpinePlugin.ts +0 -76
  250. package/src/spine/SpineSkeletonRuntime.ts +0 -521
  251. package/src/spine/SpineSlotAnimation.ts +0 -195
  252. package/src/spine/SpineTimelineRuntime.ts +0 -453
  253. package/src/spine/SpineVertexBuilder.ts +0 -686
  254. package/src/spine.ts +0 -7
  255. package/src/tilemap/Tilemap2DComponent.ts +0 -232
  256. package/src/tilemap/Tilemap2DRenderSystem.ts +0 -58
  257. package/src/tilemap/Tilemap2DRenderer.ts +0 -289
  258. package/src/tilemap/TilemapPlugin.ts +0 -75
  259. package/src/tilemap.ts +0 -6
  260. package/src/tween/Tween2DComponent.ts +0 -83
  261. package/src/tween/Tween2DSystem.ts +0 -78
  262. package/src/tween.ts +0 -4
  263. package/src/types/earcut.d.ts +0 -7
  264. package/src/types/wgsl.d.ts +0 -4
  265. package/src/utils/RenderSystem2DBase.ts +0 -164
  266. package/src/utils/arrayAccess.ts +0 -17
  267. package/src/utils/camera2d.ts +0 -68
  268. package/src/utils/render2dGpu.ts +0 -132
  269. package/test/fixtures/gltf/animation-characterization.gltf +0 -344
@@ -1,59 +0,0 @@
1
- import { EngineError, EngineErrorCode } from '@haiyue/engine';
2
- import { ErrorDomain, ErrorRecovery } from '@haiyue/engine/core';
3
- import { createAbortError } from '@haiyue/engine/experimental/async';
4
-
5
- export function throwIfGltfLoadAborted(signal: AbortSignal | undefined): void {
6
- if (!signal?.aborted) return;
7
- throw createAbortError('glTF load aborted.', signal.reason);
8
- }
9
-
10
- export function attachGltfSource(error: unknown, src: string): Error {
11
- if (error instanceof Error && error.name === 'AbortError') return error;
12
- if (error instanceof EngineError) {
13
- return new EngineError(error.code, error.message, {
14
- domain: error.domain,
15
- recoverable: error.recoverable,
16
- recovery: error.recovery,
17
- context: { url: src, resourceType: 'model/gltf', ...error.context },
18
- ...(error.path === undefined ? {} : { path: error.path }),
19
- ...(error.hint === undefined ? {} : { hint: error.hint }),
20
- ...(error.docsPath === undefined ? {} : { docsPath: error.docsPath }),
21
- cause: error,
22
- });
23
- }
24
- return gltfDataError(error instanceof Error ? error.message : String(error), { url: src }, undefined, error);
25
- }
26
-
27
- export function gltfDataError(
28
- message: string,
29
- context: Record<string, unknown> = {},
30
- path?: string,
31
- cause?: unknown,
32
- ): EngineError {
33
- const accessor = /[Aa]ccessor\s+(\d+)/.exec(message)?.[1];
34
- const bufferView = /bufferView\s+(\d+)/i.exec(message)?.[1];
35
- const buffer = /buffer\s+(\d+)/i.exec(message)?.[1];
36
- const failedLoad = /^Failed to load/.test(message);
37
- const resolvedPath = path
38
- ?? (accessor === undefined ? undefined : `gltf.accessors[${accessor}]`)
39
- ?? (bufferView === undefined ? undefined : `gltf.bufferViews[${bufferView}]`)
40
- ?? (buffer === undefined ? undefined : `gltf.buffers[${buffer}]`)
41
- ?? 'gltf';
42
- return new EngineError(
43
- failedLoad ? EngineErrorCode.AssetLoadFailed : EngineErrorCode.AssetInvalidData,
44
- message,
45
- {
46
- domain: ErrorDomain.Component,
47
- recovery: failedLoad ? ErrorRecovery.Retry : ErrorRecovery.ReleaseResource,
48
- context: {
49
- resourceType: 'model/gltf',
50
- ...context,
51
- ...(accessor === undefined ? {} : { accessor: Number(accessor) }),
52
- ...(bufferView === undefined ? {} : { bufferView: Number(bufferView) }),
53
- ...(buffer === undefined ? {} : { buffer: Number(buffer) }),
54
- },
55
- path: resolvedPath,
56
- cause,
57
- },
58
- );
59
- }
@@ -1,134 +0,0 @@
1
- import { ColorSRGB } from '@haiyue/engine';
2
- import { type MaterialDescriptor, type MaterialTextureSource, type PbrMaterialState, type PbrTextureMappingOptions, type PbrTextureMappings, type PbrTextureSamplers, type PbrTextureSlot } from '@haiyue/engine/material';
3
- import type { GltfAsset, GltfMaterial, GltfPrimitive, GltfTextureInfo } from './GltfSchema';
4
- import {
5
- collectGltfMaterialExtensionPatches,
6
- type GltfExtensionAdapter,
7
- type GltfMaterialTextureBinding,
8
- } from './GltfExtensionAdapter';
9
-
10
- export interface ResolvedGltfMaterialTexture {
11
- readonly source: MaterialTextureSource;
12
- readonly mapping: PbrTextureMappingOptions;
13
- readonly sampler: GPUSamplerDescriptor | null;
14
- }
15
-
16
- export interface GltfMaterialDescriptorInput {
17
- readonly gltf: GltfAsset;
18
- readonly material: GltfMaterial | null;
19
- readonly primitive: GltfPrimitive;
20
- readonly materialPath: string;
21
- readonly defaultBaseColor?: readonly [number, number, number, number];
22
- readonly adapters: readonly GltfExtensionAdapter[];
23
- readonly resolveTexture: (binding: GltfMaterialTextureBinding) => ResolvedGltfMaterialTexture;
24
- }
25
-
26
- const textureStateKeys: Readonly<Record<PbrTextureSlot, keyof PbrMaterialState>> = Object.freeze({
27
- baseColor: 'baseColorTexture',
28
- metallicRoughness: 'metallicRoughnessTexture',
29
- normal: 'normalTexture',
30
- occlusion: 'occlusionTexture',
31
- emissive: 'emissiveTexture',
32
- clearcoat: 'clearcoatTexture',
33
- clearcoatRoughness: 'clearcoatRoughnessTexture',
34
- clearcoatNormal: 'clearcoatNormalTexture',
35
- specular: 'specularTexture',
36
- specularColor: 'specularColorTexture',
37
- sheenColor: 'sheenColorTexture',
38
- sheenRoughness: 'sheenRoughnessTexture',
39
- transmission: 'transmissionTexture',
40
- thickness: 'thicknessTexture',
41
- });
42
-
43
- /** Compiles glTF core material data and extension patches into one engine descriptor. */
44
- export function createGltfMaterialDescriptor(
45
- input: GltfMaterialDescriptorInput,
46
- ): Extract<MaterialDescriptor, { shadingModel: 'pbr-metallic-roughness' }> {
47
- const { material } = input;
48
- const pbr = material?.pbrMetallicRoughness;
49
- const state: PbrMaterialState = {
50
- baseColor: pbr?.baseColorFactor
51
- ? linearBaseColorFactorToSrgb(pbr.baseColorFactor)
52
- : input.defaultBaseColor ?? [1, 1, 1, 1],
53
- metallic: pbr?.metallicFactor ?? 1,
54
- roughness: pbr?.roughnessFactor ?? 1,
55
- normalScale: material?.normalTexture?.scale ?? 1,
56
- occlusionStrength: material?.occlusionTexture?.strength ?? 1,
57
- emissiveFactor: material?.emissiveFactor ?? [0, 0, 0],
58
- alphaMode: material?.alphaMode === 'BLEND' ? 'blend' : material?.alphaMode === 'MASK' ? 'mask' : 'opaque',
59
- alphaCutoff: material?.alphaCutoff ?? 0.5,
60
- doubleSided: material?.doubleSided ?? false,
61
- };
62
- const patches = collectGltfMaterialExtensionPatches(
63
- input.gltf,
64
- material,
65
- input.primitive,
66
- input.materialPath,
67
- input.adapters,
68
- );
69
- const textureMappings: Partial<Record<PbrTextureSlot, PbrTextureMappingOptions>> = {};
70
- const samplers: Partial<Record<PbrTextureSlot, GPUSamplerDescriptor | null>> = {};
71
- for (const patch of patches) {
72
- Object.assign(state, patch.state);
73
- }
74
- for (const binding of collectGltfMaterialTextureBindings(
75
- input.gltf,
76
- material,
77
- input.primitive,
78
- input.materialPath,
79
- input.adapters,
80
- )) {
81
- const texture = input.resolveTexture(binding);
82
- state[textureStateKeys[binding.slot]] = texture.source as never;
83
- textureMappings[binding.slot] = texture.mapping;
84
- samplers[binding.slot] = texture.sampler;
85
- }
86
- if (Object.keys(textureMappings).length > 0) state.textureMappings = textureMappings as PbrTextureMappings;
87
- if (Object.keys(samplers).length > 0) state.samplers = samplers as PbrTextureSamplers;
88
- return Object.freeze({
89
- shadingModel: 'pbr-metallic-roughness',
90
- state: Object.freeze(state),
91
- });
92
- }
93
-
94
- /** Shared semantic source for preload, UV planning, and descriptor compilation. */
95
- export function collectGltfMaterialTextureBindings(
96
- gltf: GltfAsset,
97
- material: GltfMaterial | null,
98
- primitive: GltfPrimitive,
99
- materialPath: string,
100
- adapters: readonly GltfExtensionAdapter[],
101
- ): readonly GltfMaterialTextureBinding[] {
102
- if (!material) return Object.freeze([]);
103
- const pbr = material.pbrMetallicRoughness;
104
- const bindings: GltfMaterialTextureBinding[] = [];
105
- addTexture(bindings, 'baseColor', pbr?.baseColorTexture, `${materialPath}.pbrMetallicRoughness.baseColorTexture`);
106
- addTexture(bindings, 'metallicRoughness', pbr?.metallicRoughnessTexture, `${materialPath}.pbrMetallicRoughness.metallicRoughnessTexture`);
107
- addTexture(bindings, 'normal', material.normalTexture, `${materialPath}.normalTexture`);
108
- addTexture(bindings, 'occlusion', material.occlusionTexture, `${materialPath}.occlusionTexture`);
109
- addTexture(bindings, 'emissive', material.emissiveTexture, `${materialPath}.emissiveTexture`);
110
- for (const patch of collectGltfMaterialExtensionPatches(gltf, material, primitive, materialPath, adapters)) {
111
- bindings.push(...patch.textures ?? []);
112
- }
113
- return Object.freeze(bindings);
114
- }
115
-
116
- function addTexture(
117
- bindings: GltfMaterialTextureBinding[],
118
- slot: PbrTextureSlot,
119
- textureInfo: GltfTextureInfo | undefined,
120
- path: string,
121
- ): void {
122
- if (textureInfo) bindings.push(Object.freeze({ slot, textureInfo, path }));
123
- }
124
-
125
- function linearBaseColorFactorToSrgb(
126
- value: readonly [number, number, number, number],
127
- ): [number, number, number, number] {
128
- return [
129
- ColorSRGB.linearToSRGB(value[0]),
130
- ColorSRGB.linearToSRGB(value[1]),
131
- ColorSRGB.linearToSRGB(value[2]),
132
- value[3],
133
- ];
134
- }
@@ -1,173 +0,0 @@
1
- import type { MaterialTextureSource, PbrMaterial, PbrTextureSlot } from '@haiyue/engine/material';
2
- import type { GltfMaterial, GltfTextureInfo, GltfTextureTransform } from './GltfSchema';
3
-
4
- export interface EncodeGltfPbrMaterialOptions {
5
- readonly name?: string;
6
- /**
7
- * Resolves an engine texture source to the texture index already allocated
8
- * by the surrounding glTF/GLB exporter.
9
- */
10
- readonly resolveTextureIndex: (slot: PbrTextureSlot, source: MaterialTextureSource) => number;
11
- }
12
-
13
- export interface EncodedGltfPbrMaterial {
14
- readonly material: GltfMaterial;
15
- readonly extensionsUsed: readonly string[];
16
- }
17
-
18
- /**
19
- * Encodes the standard glTF material portion without taking ownership of image,
20
- * sampler, or buffer allocation. Scene exporters can share this codec instead
21
- * of duplicating KHR material semantics.
22
- */
23
- export function encodeGltfPbrMaterial(
24
- material: PbrMaterial,
25
- options: EncodeGltfPbrMaterialOptions,
26
- ): EncodedGltfPbrMaterial {
27
- const extensionsUsed = new Set<string>();
28
- const texture = (slot: PbrTextureSlot, source: MaterialTextureSource): GltfTextureInfo | undefined => {
29
- if (!source) return undefined;
30
- const index = options.resolveTextureIndex(slot, source);
31
- if (!Number.isSafeInteger(index) || index < 0) {
32
- throw new RangeError(`glTF texture index for PBR slot "${slot}" must be a non-negative safe integer.`);
33
- }
34
- return encodeTextureInfo(material, slot, index, extensionsUsed);
35
- };
36
-
37
- const baseColor = new Float32Array(4);
38
- material.baseColor.writeLinear(baseColor);
39
- const baseColorTexture = texture('baseColor', material.baseColorTexture);
40
- const metallicRoughnessTexture = texture('metallicRoughness', material.metallicRoughnessTexture);
41
- const normalTexture = texture('normal', material.normalTexture);
42
- const occlusionTexture = texture('occlusion', material.occlusionTexture);
43
- const emissiveTexture = texture('emissive', material.emissiveTexture);
44
- const clearcoatTexture = texture('clearcoat', material.clearcoatTexture);
45
- const clearcoatRoughnessTexture = texture('clearcoatRoughness', material.clearcoatRoughnessTexture);
46
- const clearcoatNormalTexture = texture('clearcoatNormal', material.clearcoatNormalTexture);
47
- const specularTexture = texture('specular', material.specularTexture);
48
- const specularColorTexture = texture('specularColor', material.specularColorTexture);
49
- const sheenColorTexture = texture('sheenColor', material.sheenColorTexture);
50
- const sheenRoughnessTexture = texture('sheenRoughness', material.sheenRoughnessTexture);
51
- const transmissionTexture = texture('transmission', material.transmissionTexture);
52
- const thicknessTexture = texture('thickness', material.thicknessTexture);
53
-
54
- const extensions: NonNullable<GltfMaterial['extensions']> = {};
55
- if (
56
- material.clearcoatFactor !== 0
57
- || material.clearcoatRoughnessFactor !== 0
58
- || clearcoatTexture
59
- || clearcoatRoughnessTexture
60
- || clearcoatNormalTexture
61
- ) {
62
- extensions.KHR_materials_clearcoat = {
63
- clearcoatFactor: material.clearcoatFactor,
64
- ...(clearcoatTexture ? { clearcoatTexture } : {}),
65
- clearcoatRoughnessFactor: material.clearcoatRoughnessFactor,
66
- ...(clearcoatRoughnessTexture ? { clearcoatRoughnessTexture } : {}),
67
- ...(clearcoatNormalTexture ? {
68
- clearcoatNormalTexture: { ...clearcoatNormalTexture, scale: material.clearcoatNormalScale },
69
- } : {}),
70
- };
71
- extensionsUsed.add('KHR_materials_clearcoat');
72
- }
73
- if (material.ior !== 1.5) {
74
- extensions.KHR_materials_ior = { ior: material.ior };
75
- extensionsUsed.add('KHR_materials_ior');
76
- }
77
- if (
78
- material.specularFactor !== 1
79
- || material.specularColorFactor.some(channel => channel !== 1)
80
- || specularTexture
81
- || specularColorTexture
82
- ) {
83
- extensions.KHR_materials_specular = {
84
- specularFactor: material.specularFactor,
85
- ...(specularTexture ? { specularTexture } : {}),
86
- specularColorFactor: [...material.specularColorFactor],
87
- ...(specularColorTexture ? { specularColorTexture } : {}),
88
- };
89
- extensionsUsed.add('KHR_materials_specular');
90
- }
91
- if (
92
- material.sheenColorFactor.some(channel => channel !== 0)
93
- || material.sheenRoughnessFactor !== 0
94
- || sheenColorTexture
95
- || sheenRoughnessTexture
96
- ) {
97
- extensions.KHR_materials_sheen = {
98
- sheenColorFactor: [...material.sheenColorFactor],
99
- ...(sheenColorTexture ? { sheenColorTexture } : {}),
100
- sheenRoughnessFactor: material.sheenRoughnessFactor,
101
- ...(sheenRoughnessTexture ? { sheenRoughnessTexture } : {}),
102
- };
103
- extensionsUsed.add('KHR_materials_sheen');
104
- }
105
- if (material.transmissionFactor !== 0 || transmissionTexture) {
106
- extensions.KHR_materials_transmission = {
107
- transmissionFactor: material.transmissionFactor,
108
- ...(transmissionTexture ? { transmissionTexture } : {}),
109
- };
110
- extensionsUsed.add('KHR_materials_transmission');
111
- }
112
- if (
113
- material.thicknessFactor !== 0
114
- || thicknessTexture
115
- || material.attenuationDistance !== Infinity
116
- || material.attenuationColor.some(channel => channel !== 1)
117
- ) {
118
- extensions.KHR_materials_volume = {
119
- thicknessFactor: material.thicknessFactor,
120
- ...(thicknessTexture ? { thicknessTexture } : {}),
121
- ...(material.attenuationDistance === Infinity ? {} : { attenuationDistance: material.attenuationDistance }),
122
- attenuationColor: [...material.attenuationColor],
123
- };
124
- extensionsUsed.add('KHR_materials_volume');
125
- if (material.transmissionFactor === 0 && !transmissionTexture) {
126
- extensions.KHR_materials_transmission = { transmissionFactor: 0 };
127
- extensionsUsed.add('KHR_materials_transmission');
128
- }
129
- }
130
-
131
- const gltfMaterial: GltfMaterial = {
132
- ...(options.name ? { name: options.name } : {}),
133
- pbrMetallicRoughness: {
134
- baseColorFactor: [baseColor[0]!, baseColor[1]!, baseColor[2]!, baseColor[3]!],
135
- ...(baseColorTexture ? { baseColorTexture } : {}),
136
- ...(metallicRoughnessTexture ? { metallicRoughnessTexture } : {}),
137
- metallicFactor: material.metallic,
138
- roughnessFactor: material.roughness,
139
- },
140
- emissiveFactor: [...material.emissiveFactor],
141
- ...(emissiveTexture ? { emissiveTexture } : {}),
142
- ...(normalTexture ? { normalTexture: { ...normalTexture, scale: material.normalScale } } : {}),
143
- ...(occlusionTexture ? { occlusionTexture: { ...occlusionTexture, strength: material.occlusionStrength } } : {}),
144
- alphaMode: material.alphaMode === 'blend' ? 'BLEND' : material.alphaMode === 'mask' ? 'MASK' : 'OPAQUE',
145
- ...(material.alphaMode === 'mask' ? { alphaCutoff: material.alphaCutoff } : {}),
146
- doubleSided: material.doubleSided,
147
- ...(Object.keys(extensions).length > 0 ? { extensions } : {}),
148
- };
149
- return Object.freeze({
150
- material: gltfMaterial,
151
- extensionsUsed: Object.freeze([...extensionsUsed]),
152
- });
153
- }
154
-
155
- function encodeTextureInfo(
156
- material: PbrMaterial,
157
- slot: PbrTextureSlot,
158
- index: number,
159
- extensionsUsed: Set<string>,
160
- ): GltfTextureInfo {
161
- const mapping = material.getTextureMapping(slot);
162
- const transform: GltfTextureTransform = {};
163
- if (mapping.offset[0] !== 0 || mapping.offset[1] !== 0) transform.offset = [...mapping.offset];
164
- if (mapping.rotation !== 0) transform.rotation = mapping.rotation;
165
- if (mapping.scale[0] !== 1 || mapping.scale[1] !== 1) transform.scale = [...mapping.scale];
166
- const transformed = Object.keys(transform).length > 0;
167
- if (transformed) extensionsUsed.add('KHR_texture_transform');
168
- return {
169
- index,
170
- ...(mapping.texCoord !== 0 ? { texCoord: mapping.texCoord } : {}),
171
- ...(transformed ? { extensions: { KHR_texture_transform: transform } } : {}),
172
- };
173
- }
@@ -1,293 +0,0 @@
1
- import type { PbrMaterial } from '@haiyue/engine';
2
- import {
3
- createMaterialFromDescriptor,
4
- getPbrTextureFormat,
5
- type MaterialDescriptorVariant,
6
- type MaterialTextureSource,
7
- type PbrTextureMappingOptions,
8
- type PbrTextureSlot,
9
- } from '@haiyue/engine/material';
10
- import type { AssetHandle, CompressedTextureSourceDescriptor } from '@haiyue/engine/assets';
11
- import {
12
- collectGltfMaterialVariantReferences,
13
- } from './GltfExtensionAdapter';
14
- import {
15
- collectGltfMaterialTextureBindings,
16
- createGltfMaterialDescriptor,
17
- } from './GltfMaterialDescriptor';
18
- import { getGltfUvChannel, type GltfUvSemanticPlan } from './GltfUvSemanticPlanner';
19
- import { gltfDataError, throwIfGltfLoadAborted } from './GltfLoaderErrors';
20
- import type { GltfLoadContext, LoadGltfOptions } from './GltfLoaderContract';
21
- import type {
22
- GltfAsset,
23
- GltfImage,
24
- GltfMaterial,
25
- GltfPrimitive,
26
- GltfTextureInfo,
27
- } from './GltfSchema';
28
-
29
- export async function createGltfMaterial(gltf: GltfAsset, buffers: ArrayBuffer[], primitive: GltfPrimitive, options: LoadGltfOptions, context: GltfLoadContext, uvPlan: GltfUvSemanticPlan): Promise<PbrMaterial> {
30
- throwIfGltfLoadAborted(options.signal);
31
- const materialIndex = primitive.material;
32
- const gltfMaterial = materialIndex === undefined ? null : gltf.materials?.[materialIndex] ?? null;
33
- const createDescriptor = (material: GltfMaterial | null, materialPath: string) => createGltfMaterialDescriptor({
34
- gltf,
35
- material,
36
- primitive,
37
- materialPath,
38
- ...(options.baseColorFactor === undefined ? {} : { defaultBaseColor: options.baseColorFactor }),
39
- adapters: context.extensionAdapters,
40
- resolveTexture: binding => ({
41
- source: createTextureSource(gltf, buffers, binding.textureInfo.index, binding.slot, context),
42
- mapping: resolveGltfTextureMapping(binding.textureInfo, primitive, binding.path, uvPlan),
43
- sampler: createSamplerDescriptor(gltf, binding.textureInfo.index),
44
- }),
45
- });
46
- const descriptor = createDescriptor(
47
- gltfMaterial,
48
- materialIndex === undefined ? 'gltf.defaultMaterial' : `gltf.materials[${materialIndex}]`,
49
- );
50
- const variants: MaterialDescriptorVariant[] = collectGltfMaterialVariantReferences(
51
- gltf,
52
- primitive,
53
- context.extensionAdapters,
54
- ).map(variant => ({
55
- name: variant.name,
56
- state: createDescriptor(
57
- gltf.materials?.[variant.materialIndex] ?? null,
58
- `gltf.materials[${variant.materialIndex}]`,
59
- ).state,
60
- }));
61
- return createMaterialFromDescriptor({ ...descriptor, variants });
62
- }
63
-
64
- function resolveGltfTextureMapping(
65
- textureInfo: GltfTextureInfo,
66
- primitive: GltfPrimitive,
67
- path: string,
68
- uvPlan: GltfUvSemanticPlan,
69
- ): PbrTextureMappingOptions {
70
- const transform = textureInfo.extensions?.KHR_texture_transform;
71
- const textureCoord = transform?.texCoord ?? textureInfo.texCoord ?? 0;
72
- const texCoordPath = transform?.texCoord === undefined
73
- ? `${path}.texCoord`
74
- : `${path}.extensions.KHR_texture_transform.texCoord`;
75
- const semantic = `TEXCOORD_${textureCoord}`;
76
- if (primitive.attributes[semantic] === undefined) {
77
- throw gltfDataError(
78
- `Texture references ${semantic}, but the mesh primitive does not provide that attribute.`,
79
- { texCoord: textureCoord, semantic },
80
- texCoordPath,
81
- );
82
- }
83
- const channel = getGltfUvChannel(uvPlan, textureCoord);
84
- if (channel === null) {
85
- throw gltfDataError(
86
- `${semantic} was not assigned to a physical PBR UV channel.`,
87
- { texCoord: textureCoord, semantic, capacity: uvPlan.capacity },
88
- texCoordPath,
89
- );
90
- }
91
- return {
92
- texCoord: channel,
93
- offset: transform?.offset ?? [0, 0],
94
- rotation: transform?.rotation ?? 0,
95
- scale: transform?.scale ?? [1, 1],
96
- };
97
- }
98
-
99
- function createSamplerDescriptor(gltf: GltfAsset, textureIndex: number): GPUSamplerDescriptor | null {
100
- const texture = gltf.textures?.[textureIndex];
101
- const sampler = texture?.sampler === undefined ? null : gltf.samplers?.[texture.sampler] ?? null;
102
- return {
103
- addressModeU: mapWrapMode(sampler?.wrapS),
104
- addressModeV: mapWrapMode(sampler?.wrapT),
105
- magFilter: mapMagFilter(sampler?.magFilter),
106
- minFilter: mapMinFilter(sampler?.minFilter),
107
- mipmapFilter: mapMipmapFilter(sampler?.minFilter),
108
- };
109
- }
110
-
111
- function mapWrapMode(mode: number | undefined): GPUAddressMode {
112
- switch (mode) {
113
- case 33071: return 'clamp-to-edge';
114
- case 33648: return 'mirror-repeat';
115
- case 10497:
116
- case undefined:
117
- return 'repeat';
118
- default:
119
- return 'repeat';
120
- }
121
- }
122
-
123
- function mapMagFilter(filter: number | undefined): GPUFilterMode {
124
- return filter === 9728 ? 'nearest' : 'linear';
125
- }
126
-
127
- function mapMinFilter(filter: number | undefined): GPUFilterMode {
128
- switch (filter) {
129
- case 9728:
130
- case 9984:
131
- case 9986:
132
- return 'nearest';
133
- default:
134
- return 'linear';
135
- }
136
- }
137
-
138
- function mapMipmapFilter(filter: number | undefined): GPUMipmapFilterMode {
139
- switch (filter) {
140
- case 9984:
141
- case 9985:
142
- return 'nearest';
143
- case 9986:
144
- case 9987:
145
- return 'linear';
146
- default:
147
- return 'linear';
148
- }
149
- }
150
-
151
- interface GltfTextureReference {
152
- readonly source: string | CompressedTextureSourceDescriptor;
153
- readonly cacheKey: string;
154
- readonly requestKey: string;
155
- readonly format: 'rgba8unorm-srgb' | 'rgba8unorm';
156
- }
157
-
158
- export async function preloadGltfTextures(
159
- gltf: GltfAsset,
160
- buffers: ArrayBuffer[],
161
- options: LoadGltfOptions,
162
- context: GltfLoadContext,
163
- ): Promise<void> {
164
- const assetManager = options.assetManager;
165
- if (!assetManager) return;
166
- const requests = new Map<string, GltfTextureReference>();
167
- for (const mesh of gltf.meshes ?? []) {
168
- for (const primitive of mesh.primitives) {
169
- const materialIndexes = new Set<number>();
170
- if (primitive.material !== undefined) materialIndexes.add(primitive.material);
171
- for (const variant of collectGltfMaterialVariantReferences(gltf, primitive, context.extensionAdapters)) {
172
- materialIndexes.add(variant.materialIndex);
173
- }
174
- for (const materialIndex of materialIndexes) {
175
- const material = gltf.materials?.[materialIndex] ?? null;
176
- for (const binding of collectGltfMaterialTextureBindings(
177
- gltf,
178
- material,
179
- primitive,
180
- `gltf.materials[${materialIndex}]`,
181
- context.extensionAdapters,
182
- )) {
183
- const reference = resolveTextureReference(gltf, buffers, binding.textureInfo.index, binding.slot, context);
184
- if (reference) requests.set(reference.requestKey, reference);
185
- }
186
- }
187
- }
188
- }
189
- const results = await Promise.allSettled([...requests.values()].map(async reference => ({
190
- reference,
191
- handle: await assetManager.loadTexture(reference.source, {
192
- cacheKey: reference.cacheKey,
193
- format: reference.format,
194
- mipmaps: 'generate',
195
- ...(options.signal === undefined ? {} : { signal: options.signal }),
196
- }),
197
- })));
198
- const loaded: Array<{ reference: GltfTextureReference; handle: AssetHandle<GPUTexture> }> = [];
199
- let firstError: unknown = null;
200
- for (const result of results) {
201
- if (result.status === 'fulfilled') loaded.push(result.value);
202
- else if (firstError === null) firstError = result.reason;
203
- }
204
- if (firstError !== null) {
205
- for (const { handle } of loaded) handle.release();
206
- throw firstError;
207
- }
208
- for (const { reference, handle } of loaded) {
209
- context.preloadedTextures.set(reference.requestKey, handle.value);
210
- context.assetHandles.push(handle);
211
- }
212
- }
213
-
214
- function createTextureSource(
215
- gltf: GltfAsset,
216
- buffers: ArrayBuffer[],
217
- textureIndex: number,
218
- slot: PbrTextureSlot,
219
- context: GltfLoadContext,
220
- ): MaterialTextureSource {
221
- const reference = resolveTextureReference(gltf, buffers, textureIndex, slot, context);
222
- if (!reference) return null;
223
- return context.preloadedTextures.get(reference.requestKey) ?? reference.source;
224
- }
225
-
226
- function resolveTextureReference(
227
- gltf: GltfAsset,
228
- buffers: ArrayBuffer[],
229
- textureIndex: number,
230
- slot: PbrTextureSlot,
231
- context: GltfLoadContext,
232
- ): GltfTextureReference | null {
233
- const texture = gltf.textures?.[textureIndex];
234
- const basisuSource = texture?.extensions?.KHR_texture_basisu?.source;
235
- const imageIndex = basisuSource ?? texture?.source;
236
- if (imageIndex === undefined) return null;
237
- const image = gltf.images?.[imageIndex] ?? null;
238
- if (!image) return null;
239
- const compressed = basisuSource !== undefined || image.mimeType === 'image/ktx2';
240
- const src = createImageUrl(gltf, buffers, imageIndex, image, context);
241
- if (!src) return null;
242
- const source: string | CompressedTextureSourceDescriptor = compressed
243
- ? { kind: 'compressed-texture', type: 'texture/ktx2', src }
244
- : src;
245
- const cacheKey = createImageCacheKey(imageIndex, image, context);
246
- const format = getPbrTextureFormat(slot);
247
- return {
248
- source,
249
- cacheKey,
250
- requestKey: compressed ? `compressed:${cacheKey}` : `${format}:${cacheKey}`,
251
- format,
252
- };
253
- }
254
-
255
- function createImageCacheKey(imageIndex: number, image: GltfImage, context: GltfLoadContext): string {
256
- if (image.uri) {
257
- const url = image.uri.startsWith('data:') || image.uri.startsWith('blob:')
258
- ? image.uri
259
- : new URL(image.uri, context.baseUrl).href;
260
- return `url:${url}`;
261
- }
262
- return `gltf:${context.assetIdentity}:image:${imageIndex}`;
263
- }
264
-
265
- function createImageUrl(
266
- gltf: GltfAsset,
267
- buffers: ArrayBuffer[],
268
- imageIndex: number,
269
- image: GltfImage,
270
- context: GltfLoadContext,
271
- ): string | null {
272
- const cached = context.imageSources.get(imageIndex);
273
- if (typeof cached === 'string') return cached;
274
- if (image.uri) {
275
- const url = image.uri.startsWith('data:') || image.uri.startsWith('blob:')
276
- ? image.uri
277
- : new URL(image.uri, context.baseUrl).href;
278
- context.imageSources.set(imageIndex, url);
279
- return url;
280
- }
281
- if (image.bufferView === undefined) return null;
282
- const view = gltf.bufferViews?.[image.bufferView];
283
- if (!view) return null;
284
- const buffer = buffers[view.buffer];
285
- if (!buffer) throw gltfDataError(`Image bufferView references missing buffer ${view.buffer}.`);
286
- const bytes = new Uint8Array(buffer, view.byteOffset ?? 0, view.byteLength);
287
- const blob = new Blob([bytes.slice()], { type: image.mimeType || 'application/octet-stream' });
288
- const url = URL.createObjectURL(blob);
289
- if (!context.sharedImageSources) context.objectUrls.push(url);
290
- context.imageSources.set(imageIndex, url);
291
- return url;
292
- }
293
-