@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,203 @@
|
|
|
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 { createMesh, createMaterial, createTextureFromRGBA, decodeImageToRGBA, MeshRenderer, SkinnedMeshRenderer, SKINNED_VERTEX_STRIDE_FLOATS, } from '@certe/atmos-renderer';
|
|
8
|
+
import { AnimationMixer, AnimationHandler, createSkeleton, createAnimationClip, } from '@certe/atmos-animation';
|
|
9
|
+
/**
|
|
10
|
+
* Create a GameObject tree from a ModelAsset.
|
|
11
|
+
* Decodes and uploads textures, creates GPU meshes and materials.
|
|
12
|
+
* Automatically sets up SkinnedMeshRenderer + AnimationMixer for skinned models.
|
|
13
|
+
* Returns the root GameObject (caller adds to scene).
|
|
14
|
+
*/
|
|
15
|
+
export async function instantiateModel(asset, options) {
|
|
16
|
+
const { device } = options.renderSystem;
|
|
17
|
+
// 1. Decode and upload textures
|
|
18
|
+
const gpuTextures = await uploadTextures(asset, device);
|
|
19
|
+
// 2. Create materials (with texture references)
|
|
20
|
+
const materials = asset.materials.map(mat => {
|
|
21
|
+
const albedoTex = mat.albedoTextureIndex !== null
|
|
22
|
+
? gpuTextures[mat.albedoTextureIndex] ?? undefined
|
|
23
|
+
: undefined;
|
|
24
|
+
return createMaterial({
|
|
25
|
+
...mat.params,
|
|
26
|
+
albedoTexture: albedoTex,
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
// 3. Create GPU meshes + material index lookup
|
|
30
|
+
const meshes = [];
|
|
31
|
+
const meshMatIndices = [];
|
|
32
|
+
for (const m of asset.meshes) {
|
|
33
|
+
const stride = m.skinned ? SKINNED_VERTEX_STRIDE_FLOATS : 8;
|
|
34
|
+
const gpuMesh = createMesh(device, m.geometry.vertices, m.geometry.indices, stride);
|
|
35
|
+
gpuMesh.bounds = m.geometry.bounds;
|
|
36
|
+
meshes.push(gpuMesh);
|
|
37
|
+
meshMatIndices.push(m.materialIndex);
|
|
38
|
+
}
|
|
39
|
+
// 4. Build GameObject tree from nodes
|
|
40
|
+
const ctx = {
|
|
41
|
+
meshes, materials, meshMatIndices,
|
|
42
|
+
renderSystem: options.renderSystem,
|
|
43
|
+
asset,
|
|
44
|
+
};
|
|
45
|
+
if (asset.rootNodes.length === 1) {
|
|
46
|
+
const root = buildNode(asset.rootNodes[0], ctx);
|
|
47
|
+
setupSkinning(root, asset, ctx);
|
|
48
|
+
return root;
|
|
49
|
+
}
|
|
50
|
+
// Multiple root nodes → wrap in a parent
|
|
51
|
+
const root = new GameObject(asset.name);
|
|
52
|
+
for (const node of asset.rootNodes) {
|
|
53
|
+
const child = buildNode(node, ctx);
|
|
54
|
+
child.setParent(root);
|
|
55
|
+
}
|
|
56
|
+
setupSkinning(root, asset, ctx);
|
|
57
|
+
return root;
|
|
58
|
+
}
|
|
59
|
+
async function uploadTextures(asset, device) {
|
|
60
|
+
const results = [];
|
|
61
|
+
for (const tex of asset.textures) {
|
|
62
|
+
const blob = new Blob([tex.data], { type: tex.mimeType });
|
|
63
|
+
const decoded = await decodeImageToRGBA(blob);
|
|
64
|
+
results.push(createTextureFromRGBA(device, decoded.data, decoded.width, decoded.height));
|
|
65
|
+
}
|
|
66
|
+
return results;
|
|
67
|
+
}
|
|
68
|
+
function buildNode(node, ctx) {
|
|
69
|
+
const go = new GameObject(node.name);
|
|
70
|
+
// Apply TRS
|
|
71
|
+
const t = go.transform;
|
|
72
|
+
t.setPosition(node.position[0], node.position[1], node.position[2]);
|
|
73
|
+
t.setRotation(node.rotation[0], node.rotation[1], node.rotation[2], node.rotation[3]);
|
|
74
|
+
t.setScale(node.scale[0], node.scale[1], node.scale[2]);
|
|
75
|
+
// Attach meshes
|
|
76
|
+
if (node.meshIndices.length === 1) {
|
|
77
|
+
attachMesh(go, node.meshIndices[0], node, ctx);
|
|
78
|
+
}
|
|
79
|
+
else if (node.meshIndices.length > 1) {
|
|
80
|
+
for (const mi of node.meshIndices) {
|
|
81
|
+
const child = new GameObject(`${node.name}_mesh${mi}`);
|
|
82
|
+
child.setParent(go);
|
|
83
|
+
attachMesh(child, mi, node, ctx);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// Recurse children
|
|
87
|
+
for (const childNode of node.children) {
|
|
88
|
+
const childGo = buildNode(childNode, ctx);
|
|
89
|
+
childGo.setParent(go);
|
|
90
|
+
}
|
|
91
|
+
return go;
|
|
92
|
+
}
|
|
93
|
+
function attachMesh(go, mi, node, ctx) {
|
|
94
|
+
const mesh = ctx.meshes[mi];
|
|
95
|
+
if (!mesh)
|
|
96
|
+
return;
|
|
97
|
+
const modelMesh = ctx.asset.meshes[mi];
|
|
98
|
+
const matIdx = ctx.meshMatIndices[mi] ?? 0;
|
|
99
|
+
const material = matIdx < ctx.materials.length ? ctx.materials[matIdx] : ctx.materials[0];
|
|
100
|
+
if (modelMesh?.skinned && node.skinIndex !== undefined && node.skinIndex < ctx.asset.skins.length) {
|
|
101
|
+
const skin = ctx.asset.skins[node.skinIndex];
|
|
102
|
+
const jointCount = skin.jointNodeIndices.length;
|
|
103
|
+
const smr = go.addComponent(SkinnedMeshRenderer);
|
|
104
|
+
smr.init(ctx.renderSystem, mesh, jointCount, material);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
const mr = go.addComponent(MeshRenderer);
|
|
108
|
+
mr.init(ctx.renderSystem, mesh, material);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* After the full node tree is built, set up AnimationMixer on nodes that have skins.
|
|
113
|
+
* This must be done after building the tree so we can resolve joint node references.
|
|
114
|
+
*/
|
|
115
|
+
function setupSkinning(root, asset, _ctx) {
|
|
116
|
+
if (asset.skins.length === 0)
|
|
117
|
+
return;
|
|
118
|
+
const allObjects = collectAllObjects(root);
|
|
119
|
+
for (const go of allObjects) {
|
|
120
|
+
const smr = go.getComponent(SkinnedMeshRenderer);
|
|
121
|
+
if (!smr)
|
|
122
|
+
continue;
|
|
123
|
+
const skinIndex = findSkinIndexForObject(go, asset);
|
|
124
|
+
if (skinIndex === undefined)
|
|
125
|
+
continue;
|
|
126
|
+
const skin = asset.skins[skinIndex];
|
|
127
|
+
if (!skin)
|
|
128
|
+
continue;
|
|
129
|
+
// Create skeleton using pre-computed parent indices and names
|
|
130
|
+
const joints = skin.jointParents.map((parentIdx, i) => ({
|
|
131
|
+
name: skin.jointNames[i] ?? `joint_${i}`,
|
|
132
|
+
parentIndex: parentIdx,
|
|
133
|
+
}));
|
|
134
|
+
const skeleton = createSkeleton(joints, skin.inverseBindMatrices, skin.restT, skin.restR, skin.restS);
|
|
135
|
+
const mixer = go.addComponent(AnimationMixer);
|
|
136
|
+
mixer.skeleton = skeleton;
|
|
137
|
+
// Convert model animations to clips (remap node indices → joint indices)
|
|
138
|
+
const nodeToJoint = new Map();
|
|
139
|
+
for (let ji = 0; ji < skin.jointNodeIndices.length; ji++) {
|
|
140
|
+
nodeToJoint.set(skin.jointNodeIndices[ji], ji);
|
|
141
|
+
}
|
|
142
|
+
for (const anim of asset.animations) {
|
|
143
|
+
const tracks = [];
|
|
144
|
+
for (const track of anim.tracks) {
|
|
145
|
+
const jointIndex = nodeToJoint.get(track.targetNode);
|
|
146
|
+
if (jointIndex === undefined)
|
|
147
|
+
continue;
|
|
148
|
+
tracks.push({
|
|
149
|
+
jointIndex,
|
|
150
|
+
channel: track.path,
|
|
151
|
+
interpolation: track.interpolation,
|
|
152
|
+
times: track.times,
|
|
153
|
+
values: track.values,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
if (tracks.length > 0) {
|
|
157
|
+
const clip = createAnimationClip(anim.name, tracks);
|
|
158
|
+
mixer.addClip(clip);
|
|
159
|
+
if (!mixer.initialClip) {
|
|
160
|
+
mixer.initialClip = clip.name;
|
|
161
|
+
}
|
|
162
|
+
if (mixer.layers.length === 0) {
|
|
163
|
+
mixer.play(clip);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
// Add AnimationHandler on root to aggregate all child mixers
|
|
169
|
+
if (!root.getComponent(AnimationHandler)) {
|
|
170
|
+
const handler = root.addComponent(AnimationHandler);
|
|
171
|
+
// Pick first clip name found across all mixers
|
|
172
|
+
const allMixers = collectAllObjects(root)
|
|
173
|
+
.map(go => go.getComponent(AnimationMixer))
|
|
174
|
+
.filter((m) => m !== null);
|
|
175
|
+
for (const mixer of allMixers) {
|
|
176
|
+
if (mixer.initialClip) {
|
|
177
|
+
handler.initialClip = mixer.initialClip;
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
function collectAllObjects(root) {
|
|
184
|
+
const result = [root];
|
|
185
|
+
for (const child of root.children) {
|
|
186
|
+
result.push(...collectAllObjects(child));
|
|
187
|
+
}
|
|
188
|
+
return result;
|
|
189
|
+
}
|
|
190
|
+
function findSkinIndexForObject(go, asset) {
|
|
191
|
+
return findSkinInNodes(go.name, asset.rootNodes);
|
|
192
|
+
}
|
|
193
|
+
function findSkinInNodes(name, nodes) {
|
|
194
|
+
for (const node of nodes) {
|
|
195
|
+
if (node.name === name && node.skinIndex !== undefined)
|
|
196
|
+
return node.skinIndex;
|
|
197
|
+
const found = findSkinInNodes(name, node.children);
|
|
198
|
+
if (found !== undefined)
|
|
199
|
+
return found;
|
|
200
|
+
}
|
|
201
|
+
return undefined;
|
|
202
|
+
}
|
|
203
|
+
//# sourceMappingURL=model-instantiate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-instantiate.js","sourceRoot":"","sources":["../src/model-instantiate.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { GeometryData } from '@certe/atmos-renderer';
|
|
2
|
+
import type { MaterialParams } from '@certe/atmos-renderer';
|
|
3
|
+
/** A single mesh extracted from a model file. */
|
|
4
|
+
export interface ModelMesh {
|
|
5
|
+
name: string;
|
|
6
|
+
geometry: GeometryData;
|
|
7
|
+
materialIndex: number;
|
|
8
|
+
/** True if vertex data includes joint indices + weights (52B skinned format). */
|
|
9
|
+
skinned: boolean;
|
|
10
|
+
/** Index into ModelAsset.skins (only set if skinned). */
|
|
11
|
+
skinIndex?: number;
|
|
12
|
+
}
|
|
13
|
+
/** Raw texture data extracted from a model file (CPU-side, not yet uploaded). */
|
|
14
|
+
export interface ModelTexture {
|
|
15
|
+
name: string;
|
|
16
|
+
data: Uint8Array;
|
|
17
|
+
width: number;
|
|
18
|
+
height: number;
|
|
19
|
+
mimeType: string;
|
|
20
|
+
}
|
|
21
|
+
/** Material extracted from a model file. */
|
|
22
|
+
export interface ModelMaterial {
|
|
23
|
+
name: string;
|
|
24
|
+
params: MaterialParams;
|
|
25
|
+
albedoTextureIndex: number | null;
|
|
26
|
+
}
|
|
27
|
+
/** A node in the model's scene hierarchy. */
|
|
28
|
+
export interface ModelNode {
|
|
29
|
+
name: string;
|
|
30
|
+
meshIndices: number[];
|
|
31
|
+
position: [number, number, number];
|
|
32
|
+
rotation: [number, number, number, number];
|
|
33
|
+
scale: [number, number, number];
|
|
34
|
+
children: ModelNode[];
|
|
35
|
+
/** Index into ModelAsset.skins (set when the node references a glTF skin). */
|
|
36
|
+
skinIndex?: number;
|
|
37
|
+
}
|
|
38
|
+
/** Skin data extracted from a model file (joint hierarchy + inverse bind matrices). */
|
|
39
|
+
export interface ModelSkin {
|
|
40
|
+
name: string;
|
|
41
|
+
/** Indices into the node array, identifying which nodes are joints. */
|
|
42
|
+
jointNodeIndices: number[];
|
|
43
|
+
/** Flat Float32Array: jointCount * 16 floats (one mat4 per joint). */
|
|
44
|
+
inverseBindMatrices: Float32Array;
|
|
45
|
+
/** Parent joint index for each joint (-1 = root). Pre-computed from node hierarchy. */
|
|
46
|
+
jointParents: number[];
|
|
47
|
+
/** Node names for each joint, indexed same as jointNodeIndices. */
|
|
48
|
+
jointNames: string[];
|
|
49
|
+
/** Rest-pose local translations: jointCount * 3 floats. */
|
|
50
|
+
restT: Float32Array;
|
|
51
|
+
/** Rest-pose local rotations (quaternions): jointCount * 4 floats. */
|
|
52
|
+
restR: Float32Array;
|
|
53
|
+
/** Rest-pose local scales: jointCount * 3 floats. */
|
|
54
|
+
restS: Float32Array;
|
|
55
|
+
}
|
|
56
|
+
/** A single animation track targeting one node's T/R/S channel. */
|
|
57
|
+
export interface ModelAnimationTrack {
|
|
58
|
+
/** Index into the model's node array. */
|
|
59
|
+
targetNode: number;
|
|
60
|
+
/** Which channel: 'translation' | 'rotation' | 'scale' */
|
|
61
|
+
path: 'translation' | 'rotation' | 'scale';
|
|
62
|
+
/** Interpolation mode. */
|
|
63
|
+
interpolation: 'LINEAR' | 'STEP';
|
|
64
|
+
/** Keyframe timestamps (seconds). */
|
|
65
|
+
times: Float32Array;
|
|
66
|
+
/** Keyframe values (3 or 4 floats per keyframe). */
|
|
67
|
+
values: Float32Array;
|
|
68
|
+
}
|
|
69
|
+
/** A named animation extracted from a model file. */
|
|
70
|
+
export interface ModelAnimation {
|
|
71
|
+
name: string;
|
|
72
|
+
tracks: ModelAnimationTrack[];
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Format-agnostic, GPU-free model representation.
|
|
76
|
+
* Parse off the main thread, then instantiate on the GPU thread.
|
|
77
|
+
*/
|
|
78
|
+
export interface ModelAsset {
|
|
79
|
+
name: string;
|
|
80
|
+
meshes: ModelMesh[];
|
|
81
|
+
materials: ModelMaterial[];
|
|
82
|
+
textures: ModelTexture[];
|
|
83
|
+
rootNodes: ModelNode[];
|
|
84
|
+
skins: ModelSkin[];
|
|
85
|
+
animations: ModelAnimation[];
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,iDAAiD;AACjD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,YAAY,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,iFAAiF;IACjF,OAAO,EAAE,OAAO,CAAC;IACjB,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,iFAAiF;AACjF,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,4CAA4C;AAC5C,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,cAAc,CAAC;IACvB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED,6CAA6C;AAC7C,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3C,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,QAAQ,EAAE,SAAS,EAAE,CAAC;IACtB,8EAA8E;IAC9E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,uFAAuF;AACvF,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,sEAAsE;IACtE,mBAAmB,EAAE,YAAY,CAAC;IAClC,uFAAuF;IACvF,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,mEAAmE;IACnE,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,2DAA2D;IAC3D,KAAK,EAAE,YAAY,CAAC;IACpB,sEAAsE;IACtE,KAAK,EAAE,YAAY,CAAC;IACpB,qDAAqD;IACrD,KAAK,EAAE,YAAY,CAAC;CACrB;AAED,mEAAmE;AACnE,MAAM,WAAW,mBAAmB;IAClC,yCAAyC;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,IAAI,EAAE,aAAa,GAAG,UAAU,GAAG,OAAO,CAAC;IAC3C,0BAA0B;IAC1B,aAAa,EAAE,QAAQ,GAAG,MAAM,CAAC;IACjC,qCAAqC;IACrC,KAAK,EAAE,YAAY,CAAC;IACpB,oDAAoD;IACpD,MAAM,EAAE,YAAY,CAAC;CACtB;AAED,qDAAqD;AACrD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,mBAAmB,EAAE,CAAC;CAC/B;AAED;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,SAAS,EAAE,SAAS,EAAE,CAAC;IACvB,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,UAAU,EAAE,cAAc,EAAE,CAAC;CAC9B"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@certe/atmos-assets",
|
|
3
|
+
"description": "glTF 2.0 / GLB asset pipeline for the Atmos Engine",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/certesolutions-cyber/atmos.git",
|
|
8
|
+
"directory": "packages/assets"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/certesolutions-cyber/atmos",
|
|
11
|
+
"license": "GPL-3.0-or-later",
|
|
12
|
+
"keywords": ["gltf", "glb", "asset-pipeline", "game-engine", "3d-model", "atmos"],
|
|
13
|
+
"type": "module",
|
|
14
|
+
"main": "src/index.ts",
|
|
15
|
+
"types": "src/index.ts",
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"main": "dist/index.js",
|
|
18
|
+
"types": "dist/index.d.ts"
|
|
19
|
+
},
|
|
20
|
+
"files": ["dist", "!dist/__tests__", "package.json", "README.md", "LICENCE"],
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@certe/atmos-core": "^0.1.0",
|
|
23
|
+
"@certe/atmos-math": "^0.1.0",
|
|
24
|
+
"@certe/atmos-renderer": "^0.1.0",
|
|
25
|
+
"@certe/atmos-animation": "^0.1.0"
|
|
26
|
+
},
|
|
27
|
+
"scripts": {
|
|
28
|
+
"test": "vitest run"
|
|
29
|
+
}
|
|
30
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
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 {
|
|
5
|
+
ModelAsset,
|
|
6
|
+
ModelMesh,
|
|
7
|
+
ModelMaterial,
|
|
8
|
+
ModelTexture,
|
|
9
|
+
ModelNode,
|
|
10
|
+
ModelSkin,
|
|
11
|
+
ModelAnimation,
|
|
12
|
+
ModelAnimationTrack,
|
|
13
|
+
} from './types.js';
|
|
14
|
+
export { parseGlb, parseGltfJson, readAccessor, readBufferView } from './gltf-parser.js';
|
|
15
|
+
export type { GltfDocument, GltfJson } from './gltf-parser.js';
|
|
16
|
+
export { extractSkins } from './gltf-skin.js';
|
|
17
|
+
export { extractAnimations } from './gltf-animation.js';
|