Merging a Group of Meshes into a Single Mesh

Hello! I am trying to merge a Group ( THREE.Group<THREE.Object3DEventMap> ) into a single Mesh, so that i can manage it in an easier way.
I came upon this post, and tried to adapt the last answer, but didn’t succeed, due to being a beginner at ThreeJS, and it being slightly different to what I was looking for.

function groupToMesh ( group ) {

    if ( ! group.isGroup ) return;

    let geoms = [];
    let meshes = [];
    group.children.forEach( e => {
        if ( e.geometry.attributes.uv1 ) { delete e.geometry.attributes.uv1; }
        e.isMesh && meshes.push( e ) && ( geoms.push( ( e.geometry.index ) ? e.geometry.toNonIndexed() : e.geometry.clone() ) ) 
    } );
    geoms.forEach( ( g, i ) => g.applyMatrix4( meshes[i].matrixWorld ) );
    console.log(geoms);
    let gg = BufferGeometryUtils.mergeGeometries( geoms );
    gg.applyMatrix4( group.matrix.clone().invert() );
    gg.userData.materials = meshes.map( m => m.material );
    return new THREE.Mesh( gg , gg.userData.materials );

}

This is my function, but when i try to add the mesh to my scene, it does not show up, as if there was literally nothing there.
Can someone help me please?

Are your meshes in an initial group?

And are all of your meshes the first children in hierarchical depth? The above only iterates through the children of the initial group so if any meshes are nested deeper in hierarchy eg in another group they will be omitted it looks like, you may be better off adapting this to use traverse

2 Likes

Yes! All the meshes are in a Group ( THREE.Group<THREE.Object3DEventMap> ).
It’s this:


As you can see, all the meshes are in the children element

1 Like

Have you tried testing with just one instance of a new MeshStandardMaterial? You may need to setup geometry groups to use multiple materials, however this will still result in one draw call per material afaia, you’ll simply just have one mesh definition for all parts (which is what it seems you’re looking for)

Have you also tried camera.lookAt(mesh.position) (or use orbit controls to look around) once this function is finished just to check the mesh hasn’t ended up behind camera or something after the matrix transformations?

Hey, I just tried and, although it the mesh finally shows, I think there is some kind of problem with the material (in the image left is done with the previus function, while right is correct)


So, is it just impossible to have the same result with only one instance of material? Or is there some function/class or library I just don’t know?

You have 2 options in this case, you can use BufferGeometry.groups whereby you would track and specify each geometry’s attributes.position.count additively along with a material index of the mesh where materials are stored in a relative array (baring in mind that one draw call will be used for every group)

Otherwise you could use a third party program such as blender to create a new uv set where all meshes uv’s are laid out and bake all of your individual meshes textures to one larger uv map and apply that texture to one material which can be applied to all parts (setting the new uv map to active and deleting each individual uv map per part)

2 Likes

Thank you, I will try the first option, since I need this to work for every mesh (group) the user inputs

This may be a bit too simplistic, but can’t you just add the meshes together, using the “add” command. I use that method to create a single mesh from a collection of standard cube and triangle meshes.