@certe/atmos-assets 0.1.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 (44) hide show
  1. package/LICENCE +674 -0
  2. package/README.md +122 -0
  3. package/dist/gltf-animation.d.ts +11 -0
  4. package/dist/gltf-animation.d.ts.map +1 -0
  5. package/dist/gltf-animation.js +50 -0
  6. package/dist/gltf-animation.js.map +1 -0
  7. package/dist/gltf-material.d.ts +9 -0
  8. package/dist/gltf-material.d.ts.map +1 -0
  9. package/dist/gltf-material.js +49 -0
  10. package/dist/gltf-material.js.map +1 -0
  11. package/dist/gltf-mesh.d.ts +14 -0
  12. package/dist/gltf-mesh.d.ts.map +1 -0
  13. package/dist/gltf-mesh.js +189 -0
  14. package/dist/gltf-mesh.js.map +1 -0
  15. package/dist/gltf-parser.d.ts +123 -0
  16. package/dist/gltf-parser.d.ts.map +1 -0
  17. package/dist/gltf-parser.js +155 -0
  18. package/dist/gltf-parser.js.map +1 -0
  19. package/dist/gltf-scene.d.ts +11 -0
  20. package/dist/gltf-scene.d.ts.map +1 -0
  21. package/dist/gltf-scene.js +171 -0
  22. package/dist/gltf-scene.js.map +1 -0
  23. package/dist/gltf-skin.d.ts +12 -0
  24. package/dist/gltf-skin.d.ts.map +1 -0
  25. package/dist/gltf-skin.js +108 -0
  26. package/dist/gltf-skin.js.map +1 -0
  27. package/dist/gltf-texture.d.ts +15 -0
  28. package/dist/gltf-texture.d.ts.map +1 -0
  29. package/dist/gltf-texture.js +59 -0
  30. package/dist/gltf-texture.js.map +1 -0
  31. package/dist/index.d.ts +9 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +6 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/model-instantiate.d.ts +22 -0
  36. package/dist/model-instantiate.d.ts.map +1 -0
  37. package/dist/model-instantiate.js +203 -0
  38. package/dist/model-instantiate.js.map +1 -0
  39. package/dist/types.d.ts +87 -0
  40. package/dist/types.d.ts.map +1 -0
  41. package/dist/types.js +2 -0
  42. package/dist/types.js.map +1 -0
  43. package/package.json +30 -0
  44. package/src/index.ts +17 -0
package/README.md ADDED
@@ -0,0 +1,122 @@
1
+ # 📦 @certe/atmos-assets
2
+
3
+ glTF 2.0 / GLB asset pipeline for the Atmos Engine. Parses binary glTF into a CPU-only `ModelAsset`, then instantiates it as a live `GameObject` hierarchy with GPU resources — meshes, materials, textures, skeletal skins, and animation clips.
4
+
5
+ ---
6
+
7
+ ## 🔑 Two-Stage Pipeline
8
+
9
+ ```
10
+ ArrayBuffer → parseGltfModel() → ModelAsset (CPU-only)
11
+
12
+ instantiateModel() → GameObject (GPU-ready)
13
+ ```
14
+
15
+ **Stage 1** is thread-safe (no GPU access). **Stage 2** uploads to the GPU and creates engine components.
16
+
17
+ ---
18
+
19
+ ## 🚀 Quick Start
20
+
21
+ ```ts
22
+ import { parseGltfModel, instantiateModel } from '@certe/atmos-assets';
23
+
24
+ // Load a .glb file
25
+ const buffer = await fetch('/models/character.glb').then(r => r.arrayBuffer());
26
+
27
+ // Parse (CPU-only, no GPU needed)
28
+ const asset = parseGltfModel(buffer, 'Character');
29
+
30
+ // Instantiate into the scene
31
+ const root = await instantiateModel(asset, { renderSystem });
32
+ scene.add(root);
33
+ ```
34
+
35
+ For skinned meshes, `instantiateModel` automatically creates `SkinnedMeshRenderer` and `AnimationMixer` components, and auto-plays the first animation clip.
36
+
37
+ ---
38
+
39
+ ## 📖 API Overview
40
+
41
+ ### Core Functions
42
+
43
+ | Function | Description |
44
+ |---|---|
45
+ | `parseGltfModel(buffer, name?)` | Parse GLB → `ModelAsset` |
46
+ | `instantiateModel(asset, options)` | Create GameObject tree with GPU resources |
47
+
48
+ ### ModelAsset Contents
49
+
50
+ | Field | Description |
51
+ |---|---|
52
+ | `meshes: ModelMesh[]` | Geometry data (32B standard or 52B skinned stride) |
53
+ | `materials: ModelMaterial[]` | PBR params + texture indices |
54
+ | `textures: ModelTexture[]` | CPU-side image bytes |
55
+ | `rootNodes: ModelNode[]` | Scene hierarchy with TRS |
56
+ | `skins: ModelSkin[]` | Joint hierarchies + inverse bind matrices |
57
+ | `animations: ModelAnimation[]` | Keyframe tracks per joint |
58
+
59
+ ### Skinned Mesh Support
60
+
61
+ When a mesh has `JOINTS_0` and `WEIGHTS_0` attributes:
62
+
63
+ - Vertices are interleaved into a **52-byte format**: position(3) + normal(3) + uv(2) + joints(u8×4) + weights(f32×4)
64
+ - `ModelMesh.skinned = true` and `skinIndex` links to the skin data
65
+ - `instantiateModel()` creates a `SkinnedMeshRenderer` with a bone buffer, and an `AnimationMixer` pre-loaded with all clips
66
+
67
+ ### Low-Level Parser API
68
+
69
+ For advanced use cases:
70
+
71
+ ```ts
72
+ import { parseGlb, readAccessor, readBufferView } from '@certe/atmos-assets';
73
+
74
+ const doc = parseGlb(buffer); // { json, buffers }
75
+ const positions = readAccessor(doc, 0); // Float32Array
76
+ const imageBytes = readBufferView(doc, 2); // Uint8Array
77
+ ```
78
+
79
+ | Function | Description |
80
+ |---|---|
81
+ | `parseGlb(buffer)` | Parse GLB container |
82
+ | `parseGltfJson(json, buffers?)` | Wrap standalone .gltf |
83
+ | `readAccessor(doc, index)` | Read typed array from accessor |
84
+ | `readBufferView(doc, index)` | Read raw bytes from buffer view |
85
+ | `extractSkins(doc)` | Extract skin data (joints, IBM, rest pose) |
86
+ | `extractAnimations(doc)` | Extract animation clips |
87
+
88
+ ---
89
+
90
+ ## 🧠 Design Notes
91
+
92
+ - **Custom parser** (~350 lines) — no external glTF dependencies
93
+ - Interleaves vertex attributes into engine-native stride formats
94
+ - Supports indexed meshes with both `Uint16Array` and `Uint32Array` indices
95
+ - PBR metallic-roughness workflow with embedded texture extraction
96
+ - Node hierarchy preserved with TRS decomposition
97
+
98
+ ---
99
+
100
+ ## 📁 Structure
101
+
102
+ ```
103
+ packages/assets/src/
104
+ index.ts # Public API
105
+ types.ts # ModelAsset, ModelMesh, ModelSkin, etc.
106
+ gltf-parser.ts # GLB/glTF binary parser
107
+ gltf-mesh.ts # Mesh extraction + vertex interleaving
108
+ gltf-material.ts # Material extraction
109
+ gltf-scene.ts # Scene graph assembly
110
+ gltf-skin.ts # Skin extraction (joints, IBM, rest pose)
111
+ gltf-animation.ts # Animation channel extraction
112
+ model-instantiate.ts # GPU instantiation + component creation
113
+ ```
114
+
115
+ ---
116
+
117
+ ## 🔗 Dependencies
118
+
119
+ - `@certe/atmos-core` — GameObject, Component, Transform
120
+ - `@certe/atmos-math` — Vec3, Mat4, Quat
121
+ - `@certe/atmos-renderer` — Mesh, Material, MeshRenderer, SkinnedMeshRenderer, textures
122
+ - `@certe/atmos-animation` — Skeleton, AnimationClip, AnimationMixer
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Extract animation data from a glTF document.
3
+ * Reads animation channels and samplers into ModelAnimation format.
4
+ */
5
+ import type { GltfDocument } from './gltf-parser.js';
6
+ import type { ModelAnimation } from './types.js';
7
+ /**
8
+ * Extract all animations from the glTF document.
9
+ */
10
+ export declare function extractAnimations(doc: GltfDocument): ModelAnimation[];
11
+ //# sourceMappingURL=gltf-animation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gltf-animation.d.ts","sourceRoot":"","sources":["../src/gltf-animation.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD,OAAO,KAAK,EAAE,cAAc,EAAuB,MAAM,YAAY,CAAC;AAEtE;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,YAAY,GAAG,cAAc,EAAE,CAgDrE"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Extract animation data from a glTF document.
3
+ * Reads animation channels and samplers into ModelAnimation format.
4
+ */
5
+ import { readAccessor } from './gltf-parser.js';
6
+ /**
7
+ * Extract all animations from the glTF document.
8
+ */
9
+ export function extractAnimations(doc) {
10
+ const gltfAnimations = doc.json.animations ?? [];
11
+ const animations = [];
12
+ for (let i = 0; i < gltfAnimations.length; i++) {
13
+ const anim = gltfAnimations[i];
14
+ const tracks = [];
15
+ for (const channel of anim.channels) {
16
+ if (channel.target.node === undefined)
17
+ continue;
18
+ const path = channel.target.path;
19
+ if (path !== 'translation' && path !== 'rotation' && path !== 'scale')
20
+ continue;
21
+ const sampler = anim.samplers[channel.sampler];
22
+ if (!sampler)
23
+ continue;
24
+ const timesRaw = readAccessor(doc, sampler.input);
25
+ const valuesRaw = readAccessor(doc, sampler.output);
26
+ const times = timesRaw instanceof Float32Array
27
+ ? timesRaw
28
+ : new Float32Array(timesRaw);
29
+ const values = valuesRaw instanceof Float32Array
30
+ ? valuesRaw
31
+ : new Float32Array(valuesRaw);
32
+ const interpolation = sampler.interpolation === 'STEP' ? 'STEP' : 'LINEAR';
33
+ tracks.push({
34
+ targetNode: channel.target.node,
35
+ path,
36
+ interpolation,
37
+ times,
38
+ values,
39
+ });
40
+ }
41
+ if (tracks.length > 0) {
42
+ animations.push({
43
+ name: anim.name ?? `animation_${i}`,
44
+ tracks,
45
+ });
46
+ }
47
+ }
48
+ return animations;
49
+ }
50
+ //# sourceMappingURL=gltf-animation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gltf-animation.js","sourceRoot":"","sources":["../src/gltf-animation.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGhD;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAiB;IACjD,MAAM,cAAc,GAAG,GAAG,CAAC,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC;IACjD,MAAM,UAAU,GAAqB,EAAE,CAAC;IAExC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/C,MAAM,IAAI,GAAG,cAAc,CAAC,CAAC,CAAE,CAAC;QAChC,MAAM,MAAM,GAA0B,EAAE,CAAC;QAEzC,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACpC,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS;gBAAE,SAAS;YAEhD,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC;YACjC,IAAI,IAAI,KAAK,aAAa,IAAI,IAAI,KAAK,UAAU,IAAI,IAAI,KAAK,OAAO;gBAAE,SAAS;YAEhF,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAC/C,IAAI,CAAC,OAAO;gBAAE,SAAS;YAEvB,MAAM,QAAQ,GAAG,YAAY,CAAC,GAAG,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;YAClD,MAAM,SAAS,GAAG,YAAY,CAAC,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;YAEpD,MAAM,KAAK,GAAG,QAAQ,YAAY,YAAY;gBAC5C,CAAC,CAAC,QAAQ;gBACV,CAAC,CAAC,IAAI,YAAY,CAAC,QAAQ,CAAC,CAAC;YAE/B,MAAM,MAAM,GAAG,SAAS,YAAY,YAAY;gBAC9C,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,IAAI,YAAY,CAAC,SAAS,CAAC,CAAC;YAEhC,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,KAAK,MAAM,CAAC,CAAC,CAAC,MAAe,CAAC,CAAC,CAAC,QAAiB,CAAC;YAE7F,MAAM,CAAC,IAAI,CAAC;gBACV,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI;gBAC/B,IAAI;gBACJ,aAAa;gBACb,KAAK;gBACL,MAAM;aACP,CAAC,CAAC;QACL,CAAC;QAED,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtB,UAAU,CAAC,IAAI,CAAC;gBACd,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,aAAa,CAAC,EAAE;gBACnC,MAAM;aACP,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Extract materials from a glTF document.
3
+ * Maps PBR metallic-roughness to engine MaterialParams.
4
+ */
5
+ import type { GltfDocument } from './gltf-parser.js';
6
+ import type { ModelMaterial } from './types.js';
7
+ /** Extract all materials from the document. */
8
+ export declare function extractMaterials(doc: GltfDocument): ModelMaterial[];
9
+ //# sourceMappingURL=gltf-material.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gltf-material.d.ts","sourceRoot":"","sources":["../src/gltf-material.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,+CAA+C;AAC/C,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,YAAY,GAAG,aAAa,EAAE,CA8CnE"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Extract materials from a glTF document.
3
+ * Maps PBR metallic-roughness to engine MaterialParams.
4
+ */
5
+ /** Extract all materials from the document. */
6
+ export function extractMaterials(doc) {
7
+ const gltfMaterials = doc.json.materials ?? [];
8
+ if (gltfMaterials.length === 0) {
9
+ // Default material when none defined
10
+ return [{
11
+ name: 'default',
12
+ params: { albedo: [1, 1, 1, 1], metallic: 0, roughness: 0.5 },
13
+ albedoTextureIndex: null,
14
+ }];
15
+ }
16
+ return gltfMaterials.map((gltfMat, i) => {
17
+ const pbr = gltfMat.pbrMetallicRoughness;
18
+ const baseColor = pbr?.baseColorFactor ?? [1, 1, 1, 1];
19
+ // Resolve texture: glTF material → texture → image source index
20
+ let albedoTextureIndex = null;
21
+ const texInfo = pbr?.baseColorTexture;
22
+ if (texInfo !== undefined) {
23
+ const gltfTex = doc.json.textures?.[texInfo.index];
24
+ if (gltfTex?.source !== undefined) {
25
+ albedoTextureIndex = gltfTex.source;
26
+ }
27
+ }
28
+ // glTF alphaMode: "MASK" uses alphaCutoff (default 0.5 per spec)
29
+ const alphaCutoff = gltfMat.alphaMode === 'MASK'
30
+ ? (gltfMat.alphaCutoff ?? 0.5)
31
+ : 0;
32
+ return {
33
+ name: gltfMat.name ?? `material_${i}`,
34
+ params: {
35
+ albedo: [
36
+ baseColor[0] ?? 1,
37
+ baseColor[1] ?? 1,
38
+ baseColor[2] ?? 1,
39
+ baseColor[3] ?? 1,
40
+ ],
41
+ metallic: pbr?.metallicFactor ?? 0,
42
+ roughness: pbr?.roughnessFactor ?? 0.5,
43
+ alphaCutoff,
44
+ },
45
+ albedoTextureIndex,
46
+ };
47
+ });
48
+ }
49
+ //# sourceMappingURL=gltf-material.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gltf-material.js","sourceRoot":"","sources":["../src/gltf-material.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,+CAA+C;AAC/C,MAAM,UAAU,gBAAgB,CAAC,GAAiB;IAChD,MAAM,aAAa,GAAG,GAAG,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC;IAC/C,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,qCAAqC;QACrC,OAAO,CAAC;gBACN,IAAI,EAAE,SAAS;gBACf,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE;gBAC7D,kBAAkB,EAAE,IAAI;aACzB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,aAAa,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE;QACtC,MAAM,GAAG,GAAG,OAAO,CAAC,oBAAoB,CAAC;QACzC,MAAM,SAAS,GAAG,GAAG,EAAE,eAAe,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAEvD,gEAAgE;QAChE,IAAI,kBAAkB,GAAkB,IAAI,CAAC;QAC7C,MAAM,OAAO,GAAG,GAAG,EAAE,gBAAgB,CAAC;QACtC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YACnD,IAAI,OAAO,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;gBAClC,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC;YACtC,CAAC;QACH,CAAC;QAED,iEAAiE;QACjE,MAAM,WAAW,GAAG,OAAO,CAAC,SAAS,KAAK,MAAM;YAC9C,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,IAAI,GAAG,CAAC;YAC9B,CAAC,CAAC,CAAC,CAAC;QAEN,OAAO;YACL,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,YAAY,CAAC,EAAE;YACrC,MAAM,EAAE;gBACN,MAAM,EAAE;oBACN,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;oBACjB,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;oBACjB,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;oBACjB,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;iBACkB;gBACrC,QAAQ,EAAE,GAAG,EAAE,cAAc,IAAI,CAAC;gBAClC,SAAS,EAAE,GAAG,EAAE,eAAe,IAAI,GAAG;gBACtC,WAAW;aACZ;YACD,kBAAkB;SACnB,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Extract meshes from a glTF document.
3
+ * Interleaves vertex data into the engine's format:
4
+ * Static: position(3) + normal(3) + uv(2) = 8 floats = 32 bytes
5
+ * Skinned: position(3) + normal(3) + uv(2) + joints_u8x4(1) + weights(4) = 13 floats = 52 bytes
6
+ */
7
+ import type { GltfDocument } from './gltf-parser.js';
8
+ import type { ModelMesh } from './types.js';
9
+ /**
10
+ * Extract all meshes from the document.
11
+ * Each glTF mesh may have multiple primitives; we flatten them into separate ModelMeshes.
12
+ */
13
+ export declare function extractMeshes(doc: GltfDocument): ModelMesh[];
14
+ //# sourceMappingURL=gltf-mesh.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gltf-mesh.d.ts","sourceRoot":"","sources":["../src/gltf-mesh.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAiB,MAAM,kBAAkB,CAAC;AAEpE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,YAAY,GAAG,SAAS,EAAE,CAe5D"}
@@ -0,0 +1,189 @@
1
+ /**
2
+ * Extract meshes from a glTF document.
3
+ * Interleaves vertex data into the engine's format:
4
+ * Static: position(3) + normal(3) + uv(2) = 8 floats = 32 bytes
5
+ * Skinned: position(3) + normal(3) + uv(2) + joints_u8x4(1) + weights(4) = 13 floats = 52 bytes
6
+ */
7
+ import { VERTEX_STRIDE_FLOATS, SKINNED_VERTEX_STRIDE_FLOATS } from '@certe/atmos-renderer';
8
+ import { computeBoundingSphere } from '@certe/atmos-renderer';
9
+ import { readAccessor } from './gltf-parser.js';
10
+ /**
11
+ * Extract all meshes from the document.
12
+ * Each glTF mesh may have multiple primitives; we flatten them into separate ModelMeshes.
13
+ */
14
+ export function extractMeshes(doc) {
15
+ const meshes = [];
16
+ const gltfMeshes = doc.json.meshes ?? [];
17
+ for (let mi = 0; mi < gltfMeshes.length; mi++) {
18
+ const gltfMesh = gltfMeshes[mi];
19
+ for (let pi = 0; pi < gltfMesh.primitives.length; pi++) {
20
+ const prim = gltfMesh.primitives[pi];
21
+ const name = gltfMesh.primitives.length === 1
22
+ ? (gltfMesh.name ?? `mesh_${mi}`)
23
+ : `${gltfMesh.name ?? `mesh_${mi}`}_prim${pi}`;
24
+ meshes.push(extractPrimitive(doc, prim, name));
25
+ }
26
+ }
27
+ return meshes;
28
+ }
29
+ function extractPrimitive(doc, prim, name) {
30
+ // Read position (required)
31
+ const posAccessor = prim.attributes['POSITION'];
32
+ if (posAccessor === undefined)
33
+ throw new Error(`Mesh "${name}" missing POSITION attribute`);
34
+ const positions = readAccessor(doc, posAccessor);
35
+ const vertexCount = positions.length / 3;
36
+ // Read normals (optional – generate flat normals if missing)
37
+ let normals;
38
+ const normalAccessor = prim.attributes['NORMAL'];
39
+ if (normalAccessor !== undefined) {
40
+ normals = readAccessor(doc, normalAccessor);
41
+ }
42
+ else {
43
+ normals = generateFlatNormals(positions, vertexCount);
44
+ }
45
+ // Read UVs (optional – zero if missing)
46
+ let uvs;
47
+ const uvAccessor = prim.attributes['TEXCOORD_0'];
48
+ if (uvAccessor !== undefined) {
49
+ uvs = readAccessor(doc, uvAccessor);
50
+ }
51
+ else {
52
+ uvs = new Float32Array(vertexCount * 2);
53
+ }
54
+ // Detect skinning attributes
55
+ const jointsAccessor = prim.attributes['JOINTS_0'];
56
+ const weightsAccessor = prim.attributes['WEIGHTS_0'];
57
+ const skinned = jointsAccessor !== undefined && weightsAccessor !== undefined;
58
+ let vertices;
59
+ let stride;
60
+ if (skinned) {
61
+ stride = SKINNED_VERTEX_STRIDE_FLOATS; // 13
62
+ vertices = interleaveSkinnedVertices(doc, positions, normals, uvs, vertexCount, jointsAccessor, weightsAccessor);
63
+ }
64
+ else {
65
+ stride = VERTEX_STRIDE_FLOATS; // 8
66
+ vertices = new Float32Array(vertexCount * stride);
67
+ for (let i = 0; i < vertexCount; i++) {
68
+ const vo = i * stride;
69
+ const p = i * 3;
70
+ const u = i * 2;
71
+ vertices[vo] = positions[p];
72
+ vertices[vo + 1] = positions[p + 1];
73
+ vertices[vo + 2] = positions[p + 2];
74
+ vertices[vo + 3] = normals[p];
75
+ vertices[vo + 4] = normals[p + 1];
76
+ vertices[vo + 5] = normals[p + 2];
77
+ vertices[vo + 6] = uvs[u];
78
+ vertices[vo + 7] = uvs[u + 1];
79
+ }
80
+ }
81
+ // Read indices
82
+ let indices;
83
+ if (prim.indices !== undefined) {
84
+ const raw = readAccessor(doc, prim.indices);
85
+ if (raw instanceof Uint32Array) {
86
+ indices = raw;
87
+ }
88
+ else if (raw instanceof Uint16Array) {
89
+ indices = raw;
90
+ }
91
+ else {
92
+ indices = new Uint16Array(raw.length);
93
+ for (let i = 0; i < raw.length; i++)
94
+ indices[i] = raw[i];
95
+ }
96
+ if (indices instanceof Uint16Array && vertexCount > 65535) {
97
+ const u32 = new Uint32Array(indices.length);
98
+ for (let i = 0; i < indices.length; i++)
99
+ u32[i] = indices[i];
100
+ indices = u32;
101
+ }
102
+ }
103
+ else {
104
+ indices = vertexCount > 65535
105
+ ? new Uint32Array(vertexCount)
106
+ : new Uint16Array(vertexCount);
107
+ for (let i = 0; i < vertexCount; i++)
108
+ indices[i] = i;
109
+ }
110
+ const bounds = computeBoundingSphere(vertices, stride);
111
+ return {
112
+ name,
113
+ geometry: { vertices, indices, bounds },
114
+ materialIndex: prim.material ?? 0,
115
+ skinned,
116
+ };
117
+ }
118
+ /**
119
+ * Interleave skinned vertex data into 56-byte format.
120
+ * Layout: pos(3f) + normal(3f) + uv(2f) + joints_u16x4(2f) + weights(4f)
121
+ */
122
+ function interleaveSkinnedVertices(doc, positions, normals, uvs, vertexCount, jointsAccessorIdx, weightsAccessorIdx) {
123
+ const stride = SKINNED_VERTEX_STRIDE_FLOATS; // 14
124
+ const jointsRaw = readAccessor(doc, jointsAccessorIdx);
125
+ const weightsRaw = readAccessor(doc, weightsAccessorIdx);
126
+ const vertices = new Float32Array(vertexCount * stride);
127
+ // Uint16 view overlaid on same buffer for packing joint indices
128
+ const verticesU16 = new Uint16Array(vertices.buffer);
129
+ for (let i = 0; i < vertexCount; i++) {
130
+ const vo = i * stride;
131
+ const p = i * 3;
132
+ const u = i * 2;
133
+ const j = i * 4;
134
+ // Position
135
+ vertices[vo] = positions[p];
136
+ vertices[vo + 1] = positions[p + 1];
137
+ vertices[vo + 2] = positions[p + 2];
138
+ // Normal
139
+ vertices[vo + 3] = normals[p];
140
+ vertices[vo + 4] = normals[p + 1];
141
+ vertices[vo + 5] = normals[p + 2];
142
+ // UV
143
+ vertices[vo + 6] = uvs[u];
144
+ vertices[vo + 7] = uvs[u + 1];
145
+ // Joint indices: 4 × u16 at byte offset 32 (= float offset 8 × 4 bytes)
146
+ const u16Offset = (vo * 4 + 32) / 2; // byte offset → u16 index
147
+ verticesU16[u16Offset] = jointsRaw[j] & 0xFFFF;
148
+ verticesU16[u16Offset + 1] = jointsRaw[j + 1] & 0xFFFF;
149
+ verticesU16[u16Offset + 2] = jointsRaw[j + 2] & 0xFFFF;
150
+ verticesU16[u16Offset + 3] = jointsRaw[j + 3] & 0xFFFF;
151
+ // Weights: 4 × f32 at float offset 10 (byte offset 40)
152
+ vertices[vo + 10] = weightsRaw[j];
153
+ vertices[vo + 11] = weightsRaw[j + 1];
154
+ vertices[vo + 12] = weightsRaw[j + 2];
155
+ vertices[vo + 13] = weightsRaw[j + 3];
156
+ }
157
+ return vertices;
158
+ }
159
+ /** Generate flat normals from triangle positions. */
160
+ function generateFlatNormals(positions, vertexCount) {
161
+ const normals = new Float32Array(vertexCount * 3);
162
+ const triCount = Math.floor(vertexCount / 3);
163
+ for (let t = 0; t < triCount; t++) {
164
+ const i0 = t * 9;
165
+ const ax = positions[i0 + 3] - positions[i0];
166
+ const ay = positions[i0 + 4] - positions[i0 + 1];
167
+ const az = positions[i0 + 5] - positions[i0 + 2];
168
+ const bx = positions[i0 + 6] - positions[i0];
169
+ const by = positions[i0 + 7] - positions[i0 + 1];
170
+ const bz = positions[i0 + 8] - positions[i0 + 2];
171
+ let nx = ay * bz - az * by;
172
+ let ny = az * bx - ax * bz;
173
+ let nz = ax * by - ay * bx;
174
+ const len = Math.sqrt(nx * nx + ny * ny + nz * nz);
175
+ if (len > 0) {
176
+ nx /= len;
177
+ ny /= len;
178
+ nz /= len;
179
+ }
180
+ const n0 = t * 9;
181
+ for (let v = 0; v < 3; v++) {
182
+ normals[n0 + v * 3] = nx;
183
+ normals[n0 + v * 3 + 1] = ny;
184
+ normals[n0 + v * 3 + 2] = nz;
185
+ }
186
+ }
187
+ return normals;
188
+ }
189
+ //# sourceMappingURL=gltf-mesh.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gltf-mesh.js","sourceRoot":"","sources":["../src/gltf-mesh.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Minimal glTF 2.0 / GLB parser.
3
+ * Handles the binary container format and accessor/bufferView resolution.
4
+ * No external dependencies.
5
+ */
6
+ export interface GltfAccessor {
7
+ bufferView?: number;
8
+ byteOffset?: number;
9
+ componentType: number;
10
+ normalized?: boolean;
11
+ count: number;
12
+ type: string;
13
+ min?: number[];
14
+ max?: number[];
15
+ }
16
+ export interface GltfBufferView {
17
+ buffer: number;
18
+ byteOffset?: number;
19
+ byteLength: number;
20
+ byteStride?: number;
21
+ }
22
+ export interface GltfBuffer {
23
+ byteLength: number;
24
+ uri?: string;
25
+ }
26
+ export interface GltfImage {
27
+ bufferView?: number;
28
+ mimeType?: string;
29
+ uri?: string;
30
+ }
31
+ export interface GltfTexture {
32
+ source?: number;
33
+ }
34
+ export interface GltfMaterialPbr {
35
+ baseColorFactor?: number[];
36
+ baseColorTexture?: {
37
+ index: number;
38
+ };
39
+ metallicFactor?: number;
40
+ roughnessFactor?: number;
41
+ }
42
+ export interface GltfMaterial {
43
+ name?: string;
44
+ pbrMetallicRoughness?: GltfMaterialPbr;
45
+ alphaMode?: string;
46
+ alphaCutoff?: number;
47
+ }
48
+ export interface GltfPrimitive {
49
+ attributes: Record<string, number>;
50
+ indices?: number;
51
+ material?: number;
52
+ }
53
+ export interface GltfMesh {
54
+ name?: string;
55
+ primitives: GltfPrimitive[];
56
+ }
57
+ export interface GltfNode {
58
+ name?: string;
59
+ mesh?: number;
60
+ skin?: number;
61
+ children?: number[];
62
+ translation?: number[];
63
+ rotation?: number[];
64
+ scale?: number[];
65
+ matrix?: number[];
66
+ }
67
+ export interface GltfSkin {
68
+ name?: string;
69
+ inverseBindMatrices?: number;
70
+ skeleton?: number;
71
+ joints: number[];
72
+ }
73
+ export interface GltfAnimationSampler {
74
+ input: number;
75
+ output: number;
76
+ interpolation?: string;
77
+ }
78
+ export interface GltfAnimationChannel {
79
+ sampler: number;
80
+ target: {
81
+ node?: number;
82
+ path: string;
83
+ };
84
+ }
85
+ export interface GltfAnimation {
86
+ name?: string;
87
+ channels: GltfAnimationChannel[];
88
+ samplers: GltfAnimationSampler[];
89
+ }
90
+ export interface GltfScene {
91
+ nodes?: number[];
92
+ }
93
+ export interface GltfJson {
94
+ asset: {
95
+ version: string;
96
+ };
97
+ accessors?: GltfAccessor[];
98
+ bufferViews?: GltfBufferView[];
99
+ buffers?: GltfBuffer[];
100
+ images?: GltfImage[];
101
+ textures?: GltfTexture[];
102
+ materials?: GltfMaterial[];
103
+ meshes?: GltfMesh[];
104
+ nodes?: GltfNode[];
105
+ scenes?: GltfScene[];
106
+ scene?: number;
107
+ skins?: GltfSkin[];
108
+ animations?: GltfAnimation[];
109
+ }
110
+ /** Parsed glTF document with resolved binary buffers. */
111
+ export interface GltfDocument {
112
+ json: GltfJson;
113
+ buffers: ArrayBuffer[];
114
+ }
115
+ /** Parse a GLB binary container into JSON + binary buffer(s). */
116
+ export declare function parseGlb(data: ArrayBuffer): GltfDocument;
117
+ /** Parse a standalone .gltf JSON file with external buffer(s). */
118
+ export declare function parseGltfJson(json: GltfJson, buffers?: ArrayBuffer[]): GltfDocument;
119
+ /** Read a typed array from an accessor. */
120
+ export declare function readAccessor(doc: GltfDocument, accessorIndex: number): Float32Array | Uint16Array | Uint32Array | Int16Array | Uint8Array | Int8Array;
121
+ /** Read raw bytes from a bufferView (for embedded images). */
122
+ export declare function readBufferView(doc: GltfDocument, bufferViewIndex: number): Uint8Array;
123
+ //# sourceMappingURL=gltf-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gltf-parser.d.ts","sourceRoot":"","sources":["../src/gltf-parser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,MAAM,WAAW,YAAY;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,SAAS;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,gBAAgB,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACrC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oBAAoB,CAAC,EAAE,eAAe,CAAC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,aAAa,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACzC;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,oBAAoB,EAAE,CAAC;IACjC,QAAQ,EAAE,oBAAoB,EAAE,CAAC;CAClC;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3B,SAAS,CAAC,EAAE,YAAY,EAAE,CAAC;IAC3B,WAAW,CAAC,EAAE,cAAc,EAAE,CAAC;IAC/B,OAAO,CAAC,EAAE,UAAU,EAAE,CAAC;IACvB,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC;IACrB,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;IACzB,SAAS,CAAC,EAAE,YAAY,EAAE,CAAC;IAC3B,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC;IACpB,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;IACnB,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;IACnB,UAAU,CAAC,EAAE,aAAa,EAAE,CAAC;CAC9B;AAED,yDAAyD;AACzD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB;AAqCD,iEAAiE;AACjE,wBAAgB,QAAQ,CAAC,IAAI,EAAE,WAAW,GAAG,YAAY,CA4BxD;AAED,kEAAkE;AAClE,wBAAgB,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,WAAW,EAAE,GAAG,YAAY,CAEnF;AAqBD,2CAA2C;AAC3C,wBAAgB,YAAY,CAAC,GAAG,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,GAAG,YAAY,GAAG,WAAW,GAAG,WAAW,GAAG,UAAU,GAAG,UAAU,GAAG,SAAS,CAgErJ;AAED,8DAA8D;AAC9D,wBAAgB,cAAc,CAAC,GAAG,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,GAAG,UAAU,CAQrF"}