Fix editor regressions and add Blender scene and animated material import

This commit is contained in:
emil28092005
2026-09-12 00:53:20 +03:00
parent 1a0bf725fa
commit 6f497d1977
34 changed files with 1241 additions and 213 deletions
+36 -1
View File
@@ -39,7 +39,7 @@ export function findNode(p: any, id: string) {
}
/** A generated triangle, optionally skinned and animated; no game assets. */
export function triangleGlb(animated = false): Buffer {
export function triangleGlb(animated = false, configure?: (document: any, add: (data: Float32Array | Uint16Array, type: string, count: number, bounds?: Record<string, any>) => number) => void): Buffer {
const chunks: Buffer[] = [];
const views: any[] = [];
const accessors: any[] = [];
@@ -115,6 +115,7 @@ export function triangleGlb(animated = false): Buffer {
},
];
}
configure?.(document, add);
Object.assign(document, {
buffers: [{ byteLength: length }],
bufferViews: views,
@@ -153,3 +154,37 @@ export const triangleAsset = (animated = false) => ({
uri:
"data:model/gltf-binary;base64," + triangleGlb(animated).toString("base64"),
});
/** Material, camera, light and morph animation in one real glTF clip. */
export function sceneAnimationGlb() {
return triangleGlb(false, (doc, add) => {
doc.materials = [{ name: 'AnimatedPBR', pbrMetallicRoughness: { baseColorFactor: [1, 0, 0, 1], metallicFactor: .1, roughnessFactor: .2 } }];
doc.meshes[0].primitives[0].material = 0;
doc.meshes[0].primitives[0].targets = [{ POSITION: add(new Float32Array([0,0,0, 0,0,0, 0,1,0]), 'VEC3', 3) }];
doc.meshes[0].weights = [0];
doc.cameras = [{ name: 'ImportedCamera', type: 'perspective', perspective: { yfov: .7, znear: .1 } }];
doc.nodes.push({ name: 'ImportedCamera', camera: 0, translation: [0, 0, 5] }, { name: 'ImportedLight', extensions: { KHR_lights_punctual: { light: 0 } } });
doc.scenes[0].nodes.push(1, 2);
doc.cameras.push({ name: 'Ortho', type: 'orthographic', orthographic: { xmag: 2, ymag: 1, znear: .1, zfar: 100 } });
doc.nodes.push({ name: 'Ortho', camera: 1 });doc.scenes[0].nodes.push(3);
doc.extensions = { KHR_lights_punctual: { lights: [{ name: 'ImportedLight', type: 'point', intensity: 10 }] } };
doc.extensionsUsed = ['KHR_lights_punctual', 'KHR_animation_pointer'];
const input = add(new Float32Array([0, 1]), 'SCALAR', 2, { min: [0], max: [1] });
const animation: any = { name: 'Scene', channels: [], samplers: [] };
for (const [pointer, type, values] of [
['/materials/0/pbrMetallicRoughness/baseColorFactor', 'VEC4', [1,0,0,1, 0,0,1,.5]],
['/materials/0/pbrMetallicRoughness/metallicFactor', 'SCALAR', [.1,.9]],
['/materials/0/pbrMetallicRoughness/roughnessFactor', 'SCALAR', [.2,.8]],
['/cameras/0/perspective/yfov', 'SCALAR', [.7,1.1]],
['/cameras/1/orthographic/xmag', 'SCALAR', [2,4]],
['/cameras/1/orthographic/ymag', 'SCALAR', [1,3]],
['/extensions/KHR_lights_punctual/lights/0/intensity', 'SCALAR', [10,20]],
] as const) {
animation.channels.push({ sampler: animation.samplers.length, target: { path: 'pointer', extensions: { KHR_animation_pointer: { pointer } } } });
animation.samplers.push({ input, output: add(new Float32Array(values), type, 2), interpolation: 'LINEAR' });
}
animation.channels.push({ sampler: animation.samplers.length, target: { node: 0, path: 'weights' } });
animation.samplers.push({ input, output: add(new Float32Array([0,1]), 'SCALAR', 2), interpolation: 'LINEAR' });
doc.animations = [animation];
});
}