Changes
Co-authored-by: Reifonas <211114984+Reifonas@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,46 @@
|
|||||||
|
import * as THREE from 'three';
|
||||||
|
import { GLTFExporter } from 'three/examples/jsm/exporters/GLTFExporter.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Export the given root objects (already cloned or live in scene) as a single
|
||||||
|
* binary GLB, preserving each one's current world transform. Triggers a
|
||||||
|
* browser download.
|
||||||
|
*/
|
||||||
|
export async function exportObjectsAsGLB(
|
||||||
|
objects: THREE.Object3D[],
|
||||||
|
fileName: string
|
||||||
|
): Promise<void> {
|
||||||
|
if (objects.length === 0) return;
|
||||||
|
|
||||||
|
const scene = new THREE.Scene();
|
||||||
|
for (const src of objects) {
|
||||||
|
src.updateWorldMatrix(true, false);
|
||||||
|
const clone = src.clone(true);
|
||||||
|
// Bake world matrix into the clone so the export is position-correct
|
||||||
|
// regardless of parent chain.
|
||||||
|
clone.matrix.copy(src.matrixWorld);
|
||||||
|
clone.matrix.decompose(clone.position, clone.quaternion, clone.scale);
|
||||||
|
clone.matrixAutoUpdate = true;
|
||||||
|
scene.add(clone);
|
||||||
|
}
|
||||||
|
|
||||||
|
const exporter = new GLTFExporter();
|
||||||
|
const glb = await new Promise<ArrayBuffer>((resolve, reject) => {
|
||||||
|
exporter.parse(
|
||||||
|
scene,
|
||||||
|
(res) => resolve(res as ArrayBuffer),
|
||||||
|
(err) => reject(err),
|
||||||
|
{ binary: true }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const blob = new Blob([glb], { type: 'model/gltf-binary' });
|
||||||
|
const url = URL.createObjectURL(blob);
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.href = url;
|
||||||
|
a.download = fileName.endsWith('.glb') ? fileName : `${fileName}.glb`;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
setTimeout(() => URL.revokeObjectURL(url), 2000);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user