Skip to content

Instantly share code, notes, and snippets.

@andrewmunro
Created August 4, 2022 09:06
Show Gist options
  • Save andrewmunro/8955526d109dd1b8562cbf220ee4f8a5 to your computer and use it in GitHub Desktop.
Save andrewmunro/8955526d109dd1b8562cbf220ee4f8a5 to your computer and use it in GitHub Desktop.
Merge threejs GLTF/GLB geometries
import { BufferGeometryUtils } from 'three/examples/jsm/utils/BufferGeometryUtils';
import { GLTFExporter } from 'three/examples/jsm/exporters/GLTFExporter';
import { BufferGeometry, getMesh, LoadGLTF, Material, Mesh, MeshBasicMaterial } from '@milk-ecs/three';
import { Blob, FileReader } from 'vblob';
import { writeFileSync } from 'fs';
// Some hacks to get GLTFExporter working in nodejs
global.window = global;
global.Blob = Blob;
global.FileReader = FileReader;
global.document = {
createElement: nodeName => {
if (nodeName !== 'canvas') throw new Error(`Cannot create node ${nodeName}`);
}
};
const run = async () => {
const forest = await LoadGLTF('assets/golf/maps/forest.glb');
const materials = new Map<string, Material>();
const mats: Material[] = [];
const geometries: BufferGeometry[] = [];
forest.scene.updateMatrixWorld(true);
forest.scene.traverse(m => {
if (m instanceof Mesh) {
// Dedupe materials
if (!materials.has(m.material.name)) {
materials.set(m.material.name, m.material);
}
mats.push(materials.get(m.material.name) as Material);
// Bake position into geometry
// We need to clone it so children don't get matrixWorld applied multiple times.
const geom = m.geometry.clone() as BufferGeometry;
geom.applyMatrix4(m.matrixWorld);
geometries.push(geom);
}
});
let geometry = BufferGeometryUtils.mergeBufferGeometries(geometries, true);
geometry = BufferGeometryUtils.mergeVertices(geometry);
const mesh = new Mesh(geometry, mats);
const exporter = new GLTFExporter();
const options = {
trs: false,
onlyVisible: false,
truncateDrawRange: false,
binary: true,
maxTextureSize: 4096
};
exporter.parse(
mesh,
data => {
console.log(data);
writeFileSync('test.glb', Buffer.from(data as ArrayBuffer));
},
options
);
};
run();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment