@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.
- package/LICENCE +674 -0
- package/README.md +122 -0
- package/dist/gltf-animation.d.ts +11 -0
- package/dist/gltf-animation.d.ts.map +1 -0
- package/dist/gltf-animation.js +50 -0
- package/dist/gltf-animation.js.map +1 -0
- package/dist/gltf-material.d.ts +9 -0
- package/dist/gltf-material.d.ts.map +1 -0
- package/dist/gltf-material.js +49 -0
- package/dist/gltf-material.js.map +1 -0
- package/dist/gltf-mesh.d.ts +14 -0
- package/dist/gltf-mesh.d.ts.map +1 -0
- package/dist/gltf-mesh.js +189 -0
- package/dist/gltf-mesh.js.map +1 -0
- package/dist/gltf-parser.d.ts +123 -0
- package/dist/gltf-parser.d.ts.map +1 -0
- package/dist/gltf-parser.js +155 -0
- package/dist/gltf-parser.js.map +1 -0
- package/dist/gltf-scene.d.ts +11 -0
- package/dist/gltf-scene.d.ts.map +1 -0
- package/dist/gltf-scene.js +171 -0
- package/dist/gltf-scene.js.map +1 -0
- package/dist/gltf-skin.d.ts +12 -0
- package/dist/gltf-skin.d.ts.map +1 -0
- package/dist/gltf-skin.js +108 -0
- package/dist/gltf-skin.js.map +1 -0
- package/dist/gltf-texture.d.ts +15 -0
- package/dist/gltf-texture.d.ts.map +1 -0
- package/dist/gltf-texture.js +59 -0
- package/dist/gltf-texture.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/model-instantiate.d.ts +22 -0
- package/dist/model-instantiate.d.ts.map +1 -0
- package/dist/model-instantiate.js +203 -0
- package/dist/model-instantiate.js.map +1 -0
- package/dist/types.d.ts +87 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +30 -0
- 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":"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"}
|