# Importing GLB file - every material is single mesh

**URL:** <https://discourse.threejs.org/t/importing-glb-file-every-material-is-single-mesh/16227>\
**Category:** Questions\
**Tags:** gltf-loader\
**Created:** [June 14, 2020, 8:19pm UTC](https://discourse.threejs.org/t/importing-glb-file-every-material-is-single-mesh/16227 "2020-06-14T20:19:26Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![mirko.simanic](https://avatars.discourse-cdn.com/v4/letter/m/919ad9/32.png) [@mirko.simanic](https://discourse.threejs.org/u/mirko.simanic)\
**Post date:** [June 14, 2020, 8:19pm UTC](https://discourse.threejs.org/t/importing-glb-file-every-material-is-single-mesh/16227/1 "2020-06-14T20:19:26Z")

</div>

Hello,

I am trying to import GLB file into a scene (using THREE.GLTFLoader) and the issue I am facing with is the following:  
The GLB file itself has a object with 4 different materials, and during the export I am getting 4 different meshes out of it. This makes things difficult because I want to have everything as a single mesh.

on the picture you may see the structure of GLB file in Blender.

 ![materials](https://canada1.discourse-cdn.com/flex035/uploads/threejs/original/2X/e/e83d38bed8ba6f26e5640c6e98a8c58b819836b3.png)

---

<div class="post-metadata">

**Author:** ![donmccurdy](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/donmccurdy/32/33209_2.png) [@donmccurdy](https://discourse.threejs.org/u/donmccurdy)\
**Post date:** [June 14, 2020, 10:38pm UTC](https://discourse.threejs.org/t/importing-glb-file-every-material-is-single-mesh/16227/2 "2020-06-14T22:38:25Z")

</div>

GLTFLoader does not create multi-material meshes. In the screenshot above it will create four meshes as children of a single parent [Group](https://threejs.org/docs/#api/en/objects/Group). You’ll need to either work with that Group instead, or merge them after loading using [BufferGeometryUtils](https://threejs.org/docs/#examples/en/utils/BufferGeometryUtils.mergeBufferGeometries).

---

<div class="post-metadata">

**Author:** ![mirko.simanic](https://avatars.discourse-cdn.com/v4/letter/m/919ad9/32.png) [@mirko.simanic](https://discourse.threejs.org/u/mirko.simanic)\
**Post date:** [June 19, 2020, 9:34am UTC](https://discourse.threejs.org/t/importing-glb-file-every-material-is-single-mesh/16227/3 "2020-06-19T09:34:53Z")

</div>

Thanks for your answer. I was able to merge all those different meshes into one with the following function:

```
function createMesh(insertedMeshes) {

var materials = [],
geometries = [],
mergedGeometry = new THREE.BufferGeometry(),
meshMaterial,
mergedMesh;

insertedMeshes.forEach(function(mesh, index) {
  mesh.updateMatrix();
  geometries.push(mesh.geometry);
  meshMaterial = new THREE.MeshStandardMaterial(mesh.material);
  materials.push(meshMaterial);
});

mergedGeometry = THREE.BufferGeometryUtils.mergeBufferGeometries(geometries, true);
mergedGeometry.groupsNeedUpdate = true;

mergedMesh = new THREE.Mesh(mergedGeometry, materials);

return mergedMesh;

```

}

I hope it will help somebody.

Mirko

---

<div class="post-metadata">

**Author:** ![abhishek461993](https://avatars.discourse-cdn.com/v4/letter/a/bbce88/32.png) [@abhishek461993](https://discourse.threejs.org/u/abhishek461993)\
**Post date:** [September 24, 2021, 10:20am UTC](https://discourse.threejs.org/t/importing-glb-file-every-material-is-single-mesh/16227/4 "2021-09-24T10:20:28Z")

</div>

Hi @donmccurdy … Is it ok group multiple meshes to a group to reduce the draw calls?

---

<div class="post-metadata">

**Author:** ![donmccurdy](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/donmccurdy/32/33209_2.png) [@donmccurdy](https://discourse.threejs.org/u/donmccurdy)\
**Post date:** [September 24, 2021, 7:01pm UTC](https://discourse.threejs.org/t/importing-glb-file-every-material-is-single-mesh/16227/5 "2021-09-24T19:01:48Z")

</div>

If you mean putting multiple THREE.Mesh instances as children of a shared THREE.Group, then there’s nothing wrong with that but it will not reduce draw calls. One Mesh/Material pair is one draw call. InstancedMesh will help if you’re drawing many of the same Mesh/Material pair.

---

<div class="post-metadata">

**Author:** ![chaitanya360](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/chaitanya360/32/41651_2.png) [@chaitanya360](https://discourse.threejs.org/u/chaitanya360)\
**Post date:** [June 6, 2024, 9:18am UTC](https://discourse.threejs.org/t/importing-glb-file-every-material-is-single-mesh/16227/6 "2024-06-06T09:18:54Z")

</div>

as you said in case of multimaterial it creates new group and adds meshes formed by separating materials to it.  
i need to identify this group later. is there any way to identify this ? or could you provide the part of code in the gltf loader where this process is done so that i can add one property in the userData for that group.

---

<div class="post-metadata">

**Author:** ![donmccurdy](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/donmccurdy/32/33209_2.png) [@donmccurdy](https://discourse.threejs.org/u/donmccurdy)\
**Post date:** [June 6, 2024, 10:18pm UTC](https://discourse.threejs.org/t/importing-glb-file-every-material-is-single-mesh/16227/7 "2024-06-06T22:18:23Z")

</div>

The relevant code is here:

> <https://github.com/mrdoob/three.js/blob/7a62164566e030611c0e4c92e9747bc005cdab26/examples/jsm/loaders/GLTFLoader.js#L3870-L3882>

I believe you can assume that if you see several THREE.Mesh instances as direct children of a THREE.Group in the output of GLTFLoader, they were originally a multi-primitive mesh. There is no precise match to the concept of “multi-material mesh” in glTF.

---

<div class="post-metadata">

**Author:** ![chaitanya360](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/chaitanya360/32/41651_2.png) [@chaitanya360](https://discourse.threejs.org/u/chaitanya360)\
**Post date:** [June 7, 2024, 6:50am UTC](https://discourse.threejs.org/t/importing-glb-file-every-material-is-single-mesh/16227/8 "2024-06-07T06:50:44Z")

</div>

Thanks for the answer, by checking the response of the GLTF loader, I could find nodes and meshes in parser.json.  
Using this I identified nodes with multiple primitives, names of these nodes matches with the names of groups in the scene whose children are separated by materials.

here’s the code snippet

```javascript
const loader = new GLTFLoader();

      // Load the GLB scene
      loader.load(
        url,
        (gltf: any) => {
         
          const scene = gltf.scene;
          processJson(gltf.parser.json);
          processScene(scene);
        },
        (xhr: ProgressEvent<EventTarget>) => {
          console.log((xhr.loaded / xhr.total) * 100);
        },
        (error) => {
         console.log(error);
        }
      );
    })

```

```javascript

processJson(json: any) {
    const { meshes, nodes } = json;

    // identify groups with multi mat separated children
    if (meshes) {
      for (const node of nodes){
        const {mesh: meshIndex, name} = node;
        const mesh = meshes[meshIndex];
        let primitivesWithMatCount = 0;
        const { primitives } = mesh;

        for (const primitive of primitives) {
          if ("material" in primitive) {
            primitivesWithMatCount++;
          }
        }

        if (primitivesWithMatCount > 1) {
          combinedMeshesParentNames.push(name);
        }
      }
    }
  }

```

combine meshes into one

```javascript

    const areChildrenSeparatedByMat= (child: any) => {
      if (!child.isGroup) return false;

      const { name } = child;

      return combinedMeshesParentNames.includes(name);
    };

   const combineMeshes = (meshes: any[]) => {
      var materials = [],
        geometries = [],
        mergedGeometry: any = new THREE.BufferGeometry(),
        meshMaterial,
        mergedMesh;

      for (const mesh of meshes) {
        mesh.updateMatrix();
        geometries.push(mesh.geometry);
        meshMaterial = new THREE.MeshStandardMaterial(mesh.material as any);
        materials.push(meshMaterial);
      }

      mergedGeometry = mergeBufferGeometries(geometries, true);
      mergedGeometry.groupsNeedUpdate = true;

      mergedMesh = new THREE.Mesh(mergedGeometry, materials);

      return mergedMesh;
    };

    const combineChildren = (group: THREE.Group) => {
      const children = group.children;
      const mergedMesh = combineMeshes(children);
      mergedMesh.name = group.name;
      mergedMesh.userData = group.userData;
      if (group.parent) {
        group.parent.add(mergedMesh);
        group.parent.remove(group);
      } else {
        // todo : need to handle this
      }
    };

 

```

```javascript
  processScene(scene: THREE.Scene) =>{

      if (combinedMeshesParentNames.length == 0) return  
   
     scene.traverse((child: any) => {
    

        if (areChildrenSeparatedByMat(child)) {
          combineChildren(child);
        }
   

      });
   }

```

can help someone struggling with the same problem
