@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
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal glTF 2.0 / GLB parser.
|
|
3
|
+
* Handles the binary container format and accessor/bufferView resolution.
|
|
4
|
+
* No external dependencies.
|
|
5
|
+
*/
|
|
6
|
+
/* ------------------------------------------------------------------ */
|
|
7
|
+
/* GLB magic / constants */
|
|
8
|
+
/* ------------------------------------------------------------------ */
|
|
9
|
+
const GLB_MAGIC = 0x46546C67; // 'glTF'
|
|
10
|
+
const GLB_CHUNK_JSON = 0x4E4F534A;
|
|
11
|
+
const GLB_CHUNK_BIN = 0x004E4942;
|
|
12
|
+
/* ------------------------------------------------------------------ */
|
|
13
|
+
/* Component type → TypedArray mapping */
|
|
14
|
+
/* ------------------------------------------------------------------ */
|
|
15
|
+
const COMPONENT_TYPES = {
|
|
16
|
+
5120: { BYTES: 1, Array: Int8Array },
|
|
17
|
+
5121: { BYTES: 1, Array: Uint8Array },
|
|
18
|
+
5122: { BYTES: 2, Array: Int16Array },
|
|
19
|
+
5123: { BYTES: 2, Array: Uint16Array },
|
|
20
|
+
5125: { BYTES: 4, Array: Uint32Array },
|
|
21
|
+
5126: { BYTES: 4, Array: Float32Array },
|
|
22
|
+
};
|
|
23
|
+
const TYPE_COUNTS = {
|
|
24
|
+
SCALAR: 1,
|
|
25
|
+
VEC2: 2,
|
|
26
|
+
VEC3: 3,
|
|
27
|
+
VEC4: 4,
|
|
28
|
+
MAT2: 4,
|
|
29
|
+
MAT3: 9,
|
|
30
|
+
MAT4: 16,
|
|
31
|
+
};
|
|
32
|
+
/* ------------------------------------------------------------------ */
|
|
33
|
+
/* Public API */
|
|
34
|
+
/* ------------------------------------------------------------------ */
|
|
35
|
+
/** Parse a GLB binary container into JSON + binary buffer(s). */
|
|
36
|
+
export function parseGlb(data) {
|
|
37
|
+
const view = new DataView(data);
|
|
38
|
+
const magic = view.getUint32(0, true);
|
|
39
|
+
if (magic !== GLB_MAGIC)
|
|
40
|
+
throw new Error('Not a valid GLB file');
|
|
41
|
+
const version = view.getUint32(4, true);
|
|
42
|
+
if (version !== 2)
|
|
43
|
+
throw new Error(`Unsupported glTF version: ${version}`);
|
|
44
|
+
let offset = 12; // skip header (magic + version + length)
|
|
45
|
+
let json = null;
|
|
46
|
+
const buffers = [];
|
|
47
|
+
while (offset < data.byteLength) {
|
|
48
|
+
const chunkLength = view.getUint32(offset, true);
|
|
49
|
+
const chunkType = view.getUint32(offset + 4, true);
|
|
50
|
+
const chunkData = data.slice(offset + 8, offset + 8 + chunkLength);
|
|
51
|
+
if (chunkType === GLB_CHUNK_JSON) {
|
|
52
|
+
const decoder = new TextDecoder();
|
|
53
|
+
json = JSON.parse(decoder.decode(chunkData));
|
|
54
|
+
}
|
|
55
|
+
else if (chunkType === GLB_CHUNK_BIN) {
|
|
56
|
+
buffers.push(chunkData);
|
|
57
|
+
}
|
|
58
|
+
offset += 8 + chunkLength;
|
|
59
|
+
}
|
|
60
|
+
if (!json)
|
|
61
|
+
throw new Error('GLB file missing JSON chunk');
|
|
62
|
+
return { json, buffers };
|
|
63
|
+
}
|
|
64
|
+
/** Parse a standalone .gltf JSON file with external buffer(s). */
|
|
65
|
+
export function parseGltfJson(json, buffers) {
|
|
66
|
+
return { json, buffers: buffers ?? [] };
|
|
67
|
+
}
|
|
68
|
+
/** DataView readers indexed by componentType. */
|
|
69
|
+
const DV_READ = {
|
|
70
|
+
5120: (dv, o) => dv.getInt8(o),
|
|
71
|
+
5121: (dv, o) => dv.getUint8(o),
|
|
72
|
+
5122: (dv, o) => dv.getInt16(o, true),
|
|
73
|
+
5123: (dv, o) => dv.getUint16(o, true),
|
|
74
|
+
5125: (dv, o) => dv.getUint32(o, true),
|
|
75
|
+
5126: (dv, o) => dv.getFloat32(o, true),
|
|
76
|
+
};
|
|
77
|
+
/** Normalization divisors for integer component types (signed / unsigned). */
|
|
78
|
+
const NORM_DIVISOR = {
|
|
79
|
+
5120: 127, // INT8 → [-1,1]
|
|
80
|
+
5121: 255, // UINT8 → [0,1]
|
|
81
|
+
5122: 32767, // INT16 → [-1,1]
|
|
82
|
+
5123: 65535, // UINT16 → [0,1]
|
|
83
|
+
5125: 4294967295, // UINT32
|
|
84
|
+
};
|
|
85
|
+
/** Read a typed array from an accessor. */
|
|
86
|
+
export function readAccessor(doc, accessorIndex) {
|
|
87
|
+
const accessor = doc.json.accessors?.[accessorIndex];
|
|
88
|
+
if (!accessor)
|
|
89
|
+
throw new Error(`Accessor ${accessorIndex} not found`);
|
|
90
|
+
const ct = COMPONENT_TYPES[accessor.componentType];
|
|
91
|
+
if (!ct)
|
|
92
|
+
throw new Error(`Unknown component type: ${accessor.componentType}`);
|
|
93
|
+
const typeCount = TYPE_COUNTS[accessor.type];
|
|
94
|
+
if (typeCount === undefined)
|
|
95
|
+
throw new Error(`Unknown accessor type: ${accessor.type}`);
|
|
96
|
+
const elementCount = accessor.count * typeCount;
|
|
97
|
+
const normalized = accessor.normalized === true;
|
|
98
|
+
if (accessor.bufferView === undefined) {
|
|
99
|
+
return normalized ? new Float32Array(elementCount) : new ct.Array(elementCount);
|
|
100
|
+
}
|
|
101
|
+
const bufferView = doc.json.bufferViews?.[accessor.bufferView];
|
|
102
|
+
if (!bufferView)
|
|
103
|
+
throw new Error(`BufferView ${accessor.bufferView} not found`);
|
|
104
|
+
const buffer = doc.buffers[bufferView.buffer];
|
|
105
|
+
if (!buffer)
|
|
106
|
+
throw new Error(`Buffer ${bufferView.buffer} not found`);
|
|
107
|
+
const byteOffset = (bufferView.byteOffset ?? 0) + (accessor.byteOffset ?? 0);
|
|
108
|
+
const elementBytes = ct.BYTES * typeCount;
|
|
109
|
+
const stride = bufferView.byteStride ?? elementBytes;
|
|
110
|
+
// Fast path: tightly packed floats, no normalization — direct view
|
|
111
|
+
if (!normalized && stride === elementBytes && accessor.componentType === 5126) {
|
|
112
|
+
return new Float32Array(buffer, byteOffset, elementCount);
|
|
113
|
+
}
|
|
114
|
+
// Fast path: tightly packed non-float, no normalization, aligned
|
|
115
|
+
if (!normalized && stride === elementBytes && byteOffset % ct.BYTES === 0) {
|
|
116
|
+
return new ct.Array(buffer, byteOffset, elementCount);
|
|
117
|
+
}
|
|
118
|
+
// General path: DataView handles any alignment and stride
|
|
119
|
+
const dv = new DataView(buffer);
|
|
120
|
+
const read = DV_READ[accessor.componentType];
|
|
121
|
+
if (!read)
|
|
122
|
+
throw new Error(`No reader for componentType ${accessor.componentType}`);
|
|
123
|
+
if (normalized) {
|
|
124
|
+
// Normalized integer → float output
|
|
125
|
+
const divisor = NORM_DIVISOR[accessor.componentType] ?? 1;
|
|
126
|
+
const result = new Float32Array(elementCount);
|
|
127
|
+
for (let i = 0; i < accessor.count; i++) {
|
|
128
|
+
const elemStart = byteOffset + i * stride;
|
|
129
|
+
for (let j = 0; j < typeCount; j++) {
|
|
130
|
+
result[i * typeCount + j] = read(dv, elemStart + j * ct.BYTES) / divisor;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return result;
|
|
134
|
+
}
|
|
135
|
+
// Non-normalized strided copy
|
|
136
|
+
const result = new ct.Array(elementCount);
|
|
137
|
+
for (let i = 0; i < accessor.count; i++) {
|
|
138
|
+
const elemStart = byteOffset + i * stride;
|
|
139
|
+
for (let j = 0; j < typeCount; j++) {
|
|
140
|
+
result[i * typeCount + j] = read(dv, elemStart + j * ct.BYTES);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return result;
|
|
144
|
+
}
|
|
145
|
+
/** Read raw bytes from a bufferView (for embedded images). */
|
|
146
|
+
export function readBufferView(doc, bufferViewIndex) {
|
|
147
|
+
const bv = doc.json.bufferViews?.[bufferViewIndex];
|
|
148
|
+
if (!bv)
|
|
149
|
+
throw new Error(`BufferView ${bufferViewIndex} not found`);
|
|
150
|
+
const buffer = doc.buffers[bv.buffer];
|
|
151
|
+
if (!buffer)
|
|
152
|
+
throw new Error(`Buffer ${bv.buffer} not found`);
|
|
153
|
+
return new Uint8Array(buffer, bv.byteOffset ?? 0, bv.byteLength);
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=gltf-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gltf-parser.js","sourceRoot":"","sources":["../src/gltf-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Assemble a complete ModelAsset from a glTF document.
|
|
3
|
+
* Orchestrates parser, mesh, material, texture, skin, and animation extraction.
|
|
4
|
+
*/
|
|
5
|
+
import type { ModelAsset } from './types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Parse a GLB buffer into a format-agnostic ModelAsset.
|
|
8
|
+
* This is CPU-only – no GPU access needed.
|
|
9
|
+
*/
|
|
10
|
+
export declare function parseGltfModel(data: ArrayBuffer, name?: string): ModelAsset;
|
|
11
|
+
//# sourceMappingURL=gltf-scene.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gltf-scene.d.ts","sourceRoot":"","sources":["../src/gltf-scene.ts"],"names":[],"mappings":"AAAA;;;GAGG;AASH,OAAO,KAAK,EAAE,UAAU,EAAa,MAAM,YAAY,CAAC;AAExD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,UAAU,CAG3E"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Assemble a complete ModelAsset from a glTF document.
|
|
3
|
+
* Orchestrates parser, mesh, material, texture, skin, and animation extraction.
|
|
4
|
+
*/
|
|
5
|
+
import { parseGlb } from './gltf-parser.js';
|
|
6
|
+
import { extractMeshes } from './gltf-mesh.js';
|
|
7
|
+
import { extractMaterials } from './gltf-material.js';
|
|
8
|
+
import { extractTextures } from './gltf-texture.js';
|
|
9
|
+
import { extractSkins } from './gltf-skin.js';
|
|
10
|
+
import { extractAnimations } from './gltf-animation.js';
|
|
11
|
+
/**
|
|
12
|
+
* Parse a GLB buffer into a format-agnostic ModelAsset.
|
|
13
|
+
* This is CPU-only – no GPU access needed.
|
|
14
|
+
*/
|
|
15
|
+
export function parseGltfModel(data, name) {
|
|
16
|
+
const doc = parseGlb(data);
|
|
17
|
+
return buildModelAsset(doc, name ?? 'model');
|
|
18
|
+
}
|
|
19
|
+
function buildModelAsset(doc, name) {
|
|
20
|
+
const meshes = extractMeshes(doc);
|
|
21
|
+
const materials = extractMaterials(doc);
|
|
22
|
+
const textures = extractTextures(doc);
|
|
23
|
+
const skins = extractSkins(doc);
|
|
24
|
+
const animations = extractAnimations(doc);
|
|
25
|
+
const rootNodes = buildNodeTree(doc);
|
|
26
|
+
// Propagate skin indices from nodes to meshes
|
|
27
|
+
propagateSkinIndices(doc, meshes, rootNodes);
|
|
28
|
+
return { name, meshes, materials, textures, rootNodes, skins, animations };
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Walk the node tree and propagate skin index from nodes to their meshes.
|
|
32
|
+
*/
|
|
33
|
+
function propagateSkinIndices(doc, meshes, _rootNodes) {
|
|
34
|
+
const gltfNodes = doc.json.nodes ?? [];
|
|
35
|
+
const meshIndexMap = buildMeshIndexMap(doc);
|
|
36
|
+
for (const node of gltfNodes) {
|
|
37
|
+
if (node.skin !== undefined && node.mesh !== undefined) {
|
|
38
|
+
const flatIndices = meshIndexMap.get(node.mesh) ?? [];
|
|
39
|
+
for (const mi of flatIndices) {
|
|
40
|
+
const mesh = meshes[mi];
|
|
41
|
+
if (mesh) {
|
|
42
|
+
mesh.skinIndex = node.skin;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function buildNodeTree(doc) {
|
|
49
|
+
const gltfNodes = doc.json.nodes ?? [];
|
|
50
|
+
const sceneIndex = doc.json.scene ?? 0;
|
|
51
|
+
const scene = doc.json.scenes?.[sceneIndex];
|
|
52
|
+
const rootIndices = scene?.nodes ?? [];
|
|
53
|
+
const meshIndexMap = buildMeshIndexMap(doc);
|
|
54
|
+
return rootIndices
|
|
55
|
+
.map(i => buildNode(gltfNodes, i, meshIndexMap))
|
|
56
|
+
.filter((n) => n !== null);
|
|
57
|
+
}
|
|
58
|
+
function buildNode(nodes, index, meshIndexMap) {
|
|
59
|
+
const node = nodes[index];
|
|
60
|
+
if (!node)
|
|
61
|
+
return null;
|
|
62
|
+
let position = [0, 0, 0];
|
|
63
|
+
let rotation = [0, 0, 0, 1];
|
|
64
|
+
let scale = [1, 1, 1];
|
|
65
|
+
if (node.matrix) {
|
|
66
|
+
const m = node.matrix;
|
|
67
|
+
position = [m[12] ?? 0, m[13] ?? 0, m[14] ?? 0];
|
|
68
|
+
scale = decomposeScale(m);
|
|
69
|
+
rotation = decomposeRotation(m, scale);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
if (node.translation) {
|
|
73
|
+
position = [
|
|
74
|
+
node.translation[0] ?? 0,
|
|
75
|
+
node.translation[1] ?? 0,
|
|
76
|
+
node.translation[2] ?? 0,
|
|
77
|
+
];
|
|
78
|
+
}
|
|
79
|
+
if (node.rotation) {
|
|
80
|
+
rotation = [
|
|
81
|
+
node.rotation[0] ?? 0,
|
|
82
|
+
node.rotation[1] ?? 0,
|
|
83
|
+
node.rotation[2] ?? 0,
|
|
84
|
+
node.rotation[3] ?? 1,
|
|
85
|
+
];
|
|
86
|
+
}
|
|
87
|
+
if (node.scale) {
|
|
88
|
+
scale = [
|
|
89
|
+
node.scale[0] ?? 1,
|
|
90
|
+
node.scale[1] ?? 1,
|
|
91
|
+
node.scale[2] ?? 1,
|
|
92
|
+
];
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const meshIndices = node.mesh !== undefined
|
|
96
|
+
? (meshIndexMap.get(node.mesh) ?? [])
|
|
97
|
+
: [];
|
|
98
|
+
const children = (node.children ?? [])
|
|
99
|
+
.map(ci => buildNode(nodes, ci, meshIndexMap))
|
|
100
|
+
.filter((n) => n !== null);
|
|
101
|
+
const result = {
|
|
102
|
+
name: node.name ?? `node_${index}`,
|
|
103
|
+
meshIndices,
|
|
104
|
+
position,
|
|
105
|
+
rotation,
|
|
106
|
+
scale,
|
|
107
|
+
children,
|
|
108
|
+
};
|
|
109
|
+
if (node.skin !== undefined) {
|
|
110
|
+
result.skinIndex = node.skin;
|
|
111
|
+
}
|
|
112
|
+
return result;
|
|
113
|
+
}
|
|
114
|
+
function buildMeshIndexMap(doc) {
|
|
115
|
+
const map = new Map();
|
|
116
|
+
const gltfMeshes = doc.json.meshes ?? [];
|
|
117
|
+
let flatIndex = 0;
|
|
118
|
+
for (let mi = 0; mi < gltfMeshes.length; mi++) {
|
|
119
|
+
const primCount = gltfMeshes[mi].primitives.length;
|
|
120
|
+
const indices = [];
|
|
121
|
+
for (let p = 0; p < primCount; p++) {
|
|
122
|
+
indices.push(flatIndex++);
|
|
123
|
+
}
|
|
124
|
+
map.set(mi, indices);
|
|
125
|
+
}
|
|
126
|
+
return map;
|
|
127
|
+
}
|
|
128
|
+
function decomposeScale(m) {
|
|
129
|
+
const sx = Math.sqrt((m[0] ?? 0) ** 2 + (m[1] ?? 0) ** 2 + (m[2] ?? 0) ** 2);
|
|
130
|
+
const sy = Math.sqrt((m[4] ?? 0) ** 2 + (m[5] ?? 0) ** 2 + (m[6] ?? 0) ** 2);
|
|
131
|
+
const sz = Math.sqrt((m[8] ?? 0) ** 2 + (m[9] ?? 0) ** 2 + (m[10] ?? 0) ** 2);
|
|
132
|
+
return [sx, sy, sz];
|
|
133
|
+
}
|
|
134
|
+
function decomposeRotation(m, s) {
|
|
135
|
+
const sx = s[0] || 1, sy = s[1] || 1, sz = s[2] || 1;
|
|
136
|
+
const r00 = (m[0] ?? 0) / sx, r01 = (m[4] ?? 0) / sy, r02 = (m[8] ?? 0) / sz;
|
|
137
|
+
const r10 = (m[1] ?? 0) / sx, r11 = (m[5] ?? 0) / sy, r12 = (m[9] ?? 0) / sz;
|
|
138
|
+
const r20 = (m[2] ?? 0) / sx, r21 = (m[6] ?? 0) / sy, r22 = (m[10] ?? 0) / sz;
|
|
139
|
+
const trace = r00 + r11 + r22;
|
|
140
|
+
let x, y, z, w;
|
|
141
|
+
if (trace > 0) {
|
|
142
|
+
const s2 = 0.5 / Math.sqrt(trace + 1);
|
|
143
|
+
w = 0.25 / s2;
|
|
144
|
+
x = (r21 - r12) * s2;
|
|
145
|
+
y = (r02 - r20) * s2;
|
|
146
|
+
z = (r10 - r01) * s2;
|
|
147
|
+
}
|
|
148
|
+
else if (r00 > r11 && r00 > r22) {
|
|
149
|
+
const s2 = 2 * Math.sqrt(1 + r00 - r11 - r22);
|
|
150
|
+
w = (r21 - r12) / s2;
|
|
151
|
+
x = 0.25 * s2;
|
|
152
|
+
y = (r01 + r10) / s2;
|
|
153
|
+
z = (r02 + r20) / s2;
|
|
154
|
+
}
|
|
155
|
+
else if (r11 > r22) {
|
|
156
|
+
const s2 = 2 * Math.sqrt(1 + r11 - r00 - r22);
|
|
157
|
+
w = (r02 - r20) / s2;
|
|
158
|
+
x = (r01 + r10) / s2;
|
|
159
|
+
y = 0.25 * s2;
|
|
160
|
+
z = (r12 + r21) / s2;
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
const s2 = 2 * Math.sqrt(1 + r22 - r00 - r11);
|
|
164
|
+
w = (r10 - r01) / s2;
|
|
165
|
+
x = (r02 + r20) / s2;
|
|
166
|
+
y = (r12 + r21) / s2;
|
|
167
|
+
z = 0.25 * s2;
|
|
168
|
+
}
|
|
169
|
+
return [x, y, z, w];
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=gltf-scene.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gltf-scene.js","sourceRoot":"","sources":["../src/gltf-scene.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract skin data from a glTF document.
|
|
3
|
+
* Reads inverse bind matrices, joint node indices, parent hierarchy, and names.
|
|
4
|
+
*/
|
|
5
|
+
import type { GltfDocument } from './gltf-parser.js';
|
|
6
|
+
import type { ModelSkin } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Extract all skins from the glTF document.
|
|
9
|
+
* Each skin maps joint nodes → inverse bind matrices + pre-computed parent chain.
|
|
10
|
+
*/
|
|
11
|
+
export declare function extractSkins(doc: GltfDocument): ModelSkin[];
|
|
12
|
+
//# sourceMappingURL=gltf-skin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gltf-skin.d.ts","sourceRoot":"","sources":["../src/gltf-skin.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAG5C;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,YAAY,GAAG,SAAS,EAAE,CAoG3D"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract skin data from a glTF document.
|
|
3
|
+
* Reads inverse bind matrices, joint node indices, parent hierarchy, and names.
|
|
4
|
+
*/
|
|
5
|
+
import { readAccessor } from './gltf-parser.js';
|
|
6
|
+
import { Mat4 } from '@certe/atmos-math';
|
|
7
|
+
/**
|
|
8
|
+
* Extract all skins from the glTF document.
|
|
9
|
+
* Each skin maps joint nodes → inverse bind matrices + pre-computed parent chain.
|
|
10
|
+
*/
|
|
11
|
+
export function extractSkins(doc) {
|
|
12
|
+
const gltfSkins = doc.json.skins ?? [];
|
|
13
|
+
const gltfNodes = doc.json.nodes ?? [];
|
|
14
|
+
const skins = [];
|
|
15
|
+
// Build a global nodeIndex → parentNodeIndex map from glTF children arrays
|
|
16
|
+
const nodeParentMap = new Map();
|
|
17
|
+
for (let ni = 0; ni < gltfNodes.length; ni++) {
|
|
18
|
+
for (const childIdx of gltfNodes[ni].children ?? []) {
|
|
19
|
+
nodeParentMap.set(childIdx, ni);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
for (let i = 0; i < gltfSkins.length; i++) {
|
|
23
|
+
const skin = gltfSkins[i];
|
|
24
|
+
const jointCount = skin.joints.length;
|
|
25
|
+
let inverseBindMatrices;
|
|
26
|
+
if (skin.inverseBindMatrices !== undefined) {
|
|
27
|
+
const raw = readAccessor(doc, skin.inverseBindMatrices);
|
|
28
|
+
if (raw instanceof Float32Array) {
|
|
29
|
+
inverseBindMatrices = raw;
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
inverseBindMatrices = new Float32Array(raw.length);
|
|
33
|
+
for (let j = 0; j < raw.length; j++) {
|
|
34
|
+
inverseBindMatrices[j] = raw[j];
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
inverseBindMatrices = new Float32Array(jointCount * 16);
|
|
40
|
+
const identity = Mat4.create();
|
|
41
|
+
Mat4.identity(identity);
|
|
42
|
+
for (let j = 0; j < jointCount; j++) {
|
|
43
|
+
inverseBindMatrices.set(identity, j * 16);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// Build a set for quick lookup: which glTF node indices are joints in this skin
|
|
47
|
+
const jointNodeSet = new Set(skin.joints);
|
|
48
|
+
// Compute parent joint index and rest-pose TRS for each joint
|
|
49
|
+
const jointParents = [];
|
|
50
|
+
const jointNames = [];
|
|
51
|
+
const restT = new Float32Array(jointCount * 3);
|
|
52
|
+
const restR = new Float32Array(jointCount * 4);
|
|
53
|
+
const restS = new Float32Array(jointCount * 3);
|
|
54
|
+
for (let ji = 0; ji < jointCount; ji++) {
|
|
55
|
+
const nodeIdx = skin.joints[ji];
|
|
56
|
+
const node = gltfNodes[nodeIdx];
|
|
57
|
+
jointNames.push(node?.name ?? `joint_${ji}`);
|
|
58
|
+
// Rest-pose TRS from node
|
|
59
|
+
if (node?.translation) {
|
|
60
|
+
restT[ji * 3] = node.translation[0] ?? 0;
|
|
61
|
+
restT[ji * 3 + 1] = node.translation[1] ?? 0;
|
|
62
|
+
restT[ji * 3 + 2] = node.translation[2] ?? 0;
|
|
63
|
+
}
|
|
64
|
+
if (node?.rotation) {
|
|
65
|
+
restR[ji * 4] = node.rotation[0] ?? 0;
|
|
66
|
+
restR[ji * 4 + 1] = node.rotation[1] ?? 0;
|
|
67
|
+
restR[ji * 4 + 2] = node.rotation[2] ?? 0;
|
|
68
|
+
restR[ji * 4 + 3] = node.rotation[3] ?? 1;
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
restR[ji * 4 + 3] = 1; // identity quaternion
|
|
72
|
+
}
|
|
73
|
+
if (node?.scale) {
|
|
74
|
+
restS[ji * 3] = node.scale[0] ?? 1;
|
|
75
|
+
restS[ji * 3 + 1] = node.scale[1] ?? 1;
|
|
76
|
+
restS[ji * 3 + 2] = node.scale[2] ?? 1;
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
restS[ji * 3] = 1;
|
|
80
|
+
restS[ji * 3 + 1] = 1;
|
|
81
|
+
restS[ji * 3 + 2] = 1;
|
|
82
|
+
}
|
|
83
|
+
// Walk up the node hierarchy to find the first ancestor that's also a joint
|
|
84
|
+
let current = nodeParentMap.get(nodeIdx);
|
|
85
|
+
let parentJointIdx = -1;
|
|
86
|
+
while (current !== undefined) {
|
|
87
|
+
if (jointNodeSet.has(current)) {
|
|
88
|
+
parentJointIdx = skin.joints.indexOf(current);
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
current = nodeParentMap.get(current);
|
|
92
|
+
}
|
|
93
|
+
jointParents.push(parentJointIdx);
|
|
94
|
+
}
|
|
95
|
+
skins.push({
|
|
96
|
+
name: skin.name ?? `skin_${i}`,
|
|
97
|
+
jointNodeIndices: [...skin.joints],
|
|
98
|
+
inverseBindMatrices,
|
|
99
|
+
jointParents,
|
|
100
|
+
jointNames,
|
|
101
|
+
restT,
|
|
102
|
+
restR,
|
|
103
|
+
restS,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
return skins;
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=gltf-skin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gltf-skin.js","sourceRoot":"","sources":["../src/gltf-skin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract embedded textures from a glTF document.
|
|
3
|
+
* Supports bufferView-embedded images and data URIs.
|
|
4
|
+
* Actual RGBA decoding happens at instantiation time (requires DOM).
|
|
5
|
+
*/
|
|
6
|
+
import type { GltfDocument } from './gltf-parser.js';
|
|
7
|
+
import type { ModelTexture } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Extract all images from the document as raw bytes.
|
|
10
|
+
* Returns one ModelTexture per glTF image.
|
|
11
|
+
* width/height are set to 0 here – they're resolved during GPU upload
|
|
12
|
+
* via decodeImageToRGBA().
|
|
13
|
+
*/
|
|
14
|
+
export declare function extractTextures(doc: GltfDocument): ModelTexture[];
|
|
15
|
+
//# sourceMappingURL=gltf-texture.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gltf-texture.d.ts","sourceRoot":"","sources":["../src/gltf-texture.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,YAAY,GAAG,YAAY,EAAE,CAkCjE"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract embedded textures from a glTF document.
|
|
3
|
+
* Supports bufferView-embedded images and data URIs.
|
|
4
|
+
* Actual RGBA decoding happens at instantiation time (requires DOM).
|
|
5
|
+
*/
|
|
6
|
+
import { readBufferView } from './gltf-parser.js';
|
|
7
|
+
/**
|
|
8
|
+
* Extract all images from the document as raw bytes.
|
|
9
|
+
* Returns one ModelTexture per glTF image.
|
|
10
|
+
* width/height are set to 0 here – they're resolved during GPU upload
|
|
11
|
+
* via decodeImageToRGBA().
|
|
12
|
+
*/
|
|
13
|
+
export function extractTextures(doc) {
|
|
14
|
+
const images = doc.json.images ?? [];
|
|
15
|
+
const textures = [];
|
|
16
|
+
for (let i = 0; i < images.length; i++) {
|
|
17
|
+
const img = images[i];
|
|
18
|
+
const mimeType = img.mimeType ?? 'image/png';
|
|
19
|
+
let data;
|
|
20
|
+
if (img.bufferView !== undefined) {
|
|
21
|
+
// Embedded in GLB binary chunk
|
|
22
|
+
data = readBufferView(doc, img.bufferView);
|
|
23
|
+
}
|
|
24
|
+
else if (img.uri) {
|
|
25
|
+
if (img.uri.startsWith('data:')) {
|
|
26
|
+
data = decodeDataUri(img.uri);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
// External URI – not supported in MVP, skip
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
textures.push({
|
|
37
|
+
name: `texture_${i}`,
|
|
38
|
+
data,
|
|
39
|
+
width: 0, // resolved at decode time
|
|
40
|
+
height: 0,
|
|
41
|
+
mimeType,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
return textures;
|
|
45
|
+
}
|
|
46
|
+
/** Decode a base64 data URI to raw bytes. */
|
|
47
|
+
function decodeDataUri(uri) {
|
|
48
|
+
const commaIndex = uri.indexOf(',');
|
|
49
|
+
if (commaIndex === -1)
|
|
50
|
+
throw new Error('Invalid data URI');
|
|
51
|
+
const base64 = uri.slice(commaIndex + 1);
|
|
52
|
+
const binary = atob(base64);
|
|
53
|
+
const bytes = new Uint8Array(binary.length);
|
|
54
|
+
for (let i = 0; i < binary.length; i++) {
|
|
55
|
+
bytes[i] = binary.charCodeAt(i);
|
|
56
|
+
}
|
|
57
|
+
return bytes;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=gltf-texture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gltf-texture.js","sourceRoot":"","sources":["../src/gltf-texture.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGlD;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,GAAiB;IAC/C,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC;IACrC,MAAM,QAAQ,GAAmB,EAAE,CAAC;IAEpC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAE,CAAC;QACvB,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,IAAI,WAAW,CAAC;QAE7C,IAAI,IAAgB,CAAC;QAErB,IAAI,GAAG,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YACjC,+BAA+B;YAC/B,IAAI,GAAG,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;QAC7C,CAAC;aAAM,IAAI,GAAG,CAAC,GAAG,EAAE,CAAC;YACnB,IAAI,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;gBAChC,IAAI,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAChC,CAAC;iBAAM,CAAC;gBACN,4CAA4C;gBAC5C,SAAS;YACX,CAAC;QACH,CAAC;aAAM,CAAC;YACN,SAAS;QACX,CAAC;QAED,QAAQ,CAAC,IAAI,CAAC;YACZ,IAAI,EAAE,WAAW,CAAC,EAAE;YACpB,IAAI;YACJ,KAAK,EAAE,CAAC,EAAG,0BAA0B;YACrC,MAAM,EAAE,CAAC;YACT,QAAQ;SACT,CAAC,CAAC;IACL,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,6CAA6C;AAC7C,SAAS,aAAa,CAAC,GAAW;IAChC,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACpC,IAAI,UAAU,KAAK,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;IAC3D,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5B,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { parseGltfModel } from './gltf-scene.js';
|
|
2
|
+
export { instantiateModel } from './model-instantiate.js';
|
|
3
|
+
export type { InstantiateOptions, InstantiateContext } from './model-instantiate.js';
|
|
4
|
+
export type { ModelAsset, ModelMesh, ModelMaterial, ModelTexture, ModelNode, ModelSkin, ModelAnimation, ModelAnimationTrack, } from './types.js';
|
|
5
|
+
export { parseGlb, parseGltfJson, readAccessor, readBufferView } from './gltf-parser.js';
|
|
6
|
+
export type { GltfDocument, GltfJson } from './gltf-parser.js';
|
|
7
|
+
export { extractSkins } from './gltf-skin.js';
|
|
8
|
+
export { extractAnimations } from './gltf-animation.js';
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,YAAY,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACrF,YAAY,EACV,UAAU,EACV,SAAS,EACT,aAAa,EACb,YAAY,EACZ,SAAS,EACT,SAAS,EACT,cAAc,EACd,mBAAmB,GACpB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACzF,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { parseGltfModel } from './gltf-scene.js';
|
|
2
|
+
export { instantiateModel } from './model-instantiate.js';
|
|
3
|
+
export { parseGlb, parseGltfJson, readAccessor, readBufferView } from './gltf-parser.js';
|
|
4
|
+
export { extractSkins } from './gltf-skin.js';
|
|
5
|
+
export { extractAnimations } from './gltf-animation.js';
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAY1D,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEzF,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Instantiate a ModelAsset into the engine's GameObject hierarchy.
|
|
3
|
+
* Uploads textures to the GPU and creates Meshes + Materials + MeshRenderers.
|
|
4
|
+
* Supports skeletal animation via SkinnedMeshRenderer + AnimationMixer.
|
|
5
|
+
*/
|
|
6
|
+
import { GameObject } from '@certe/atmos-core';
|
|
7
|
+
import type { MeshRendererContext, SkinnedRendererContext } from '@certe/atmos-renderer';
|
|
8
|
+
import type { ModelAsset } from './types.js';
|
|
9
|
+
/** Minimal interface so callers can pass a RenderSystem without importing it. */
|
|
10
|
+
export interface InstantiateContext extends MeshRendererContext, SkinnedRendererContext {
|
|
11
|
+
}
|
|
12
|
+
export interface InstantiateOptions {
|
|
13
|
+
renderSystem: InstantiateContext;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Create a GameObject tree from a ModelAsset.
|
|
17
|
+
* Decodes and uploads textures, creates GPU meshes and materials.
|
|
18
|
+
* Automatically sets up SkinnedMeshRenderer + AnimationMixer for skinned models.
|
|
19
|
+
* Returns the root GameObject (caller adds to scene).
|
|
20
|
+
*/
|
|
21
|
+
export declare function instantiateModel(asset: ModelAsset, options: InstantiateOptions): Promise<GameObject>;
|
|
22
|
+
//# sourceMappingURL=model-instantiate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-instantiate.d.ts","sourceRoot":"","sources":["../src/model-instantiate.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAU/C,OAAO,KAAK,EAAoC,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAQ3H,OAAO,KAAK,EAAE,UAAU,EAAa,MAAM,YAAY,CAAC;AAExD,iFAAiF;AACjF,MAAM,WAAW,kBAAmB,SAAQ,mBAAmB,EAAE,sBAAsB;CAAG;AAE1F,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,kBAAkB,CAAC;CAClC;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,UAAU,CAAC,CAiDrB"}
|