Adding multiple materials(layers) to a loaded object

Hi again.

At the moment I’m trying to add multiple materials/material-layers to an object.
The following link pretty much shows what I’m aiming for:

https://stackoverflow.com/questions/49702885/is-there-a-built-in-way-to-layer-textures-within-the-standard-pbr-shader/49708915#49708915

or in this fiddle:

http://jsfiddle.net/o6atcaeg/

Unlike in this example I’m trying to to add materials to an object I loaded with the gltf-loader.
(so there is no group like in “BoxBufferGeometry”)
So I was wondering if it’s possible to create an own group for my loaded object? Or is there a better way to add multiple materials to an object?

In my case -> I have a shiny object (base layer) which I want to have a rough-looking sticker for example. (second layer)

Thanks in advance!

Well, the same pattern (meaning geometry.addGroup( 0, Infinity, n );) should work with any kind of geometry.

Oh really? I thought BoxBufferGeometry was an exception. Well thanks, I’ll give it a try!

Okay, now I had the problem which gave me the impression that BoxBufferGeometry was an exception.

If I try the code -> myObject.addGroup(0, Infinity, 0);
I get this error -> myObject.addGroup is not a function.

To put it more into context:

let loader = new THREE.GLTFLoader();

            loader.load('myObjects/myObject.glb', function (gltf) {

                myObject = gltf.scene;

                myObject.addGroup(0, Infinity, 0);

                myObject.addGroup(0, Infinity, 1);

                let myMaterials = [material1, material2];

                myNewObject = new THREE.Mesh(myObject, materials);

                scene.add(myNewObject);

But the code stops working because of the error mentioned above.

myObject.traverse(function (child) {

                    if (child.isMesh) {

                        child.material = myNewMaterial;

               }

Even though the last code doesnt make much sense (assigning to myNewMaterial) I just wanted to show that myObject ist actually a mesh/geometry. (Because of “if(child.isMesh)”)

Is there a step I am missing? Or do I get something wrong?

1 Like

addGroup() is a method of BufferGeometry, not Object3D, Group or Mesh.

https://threejs.org/docs/index.html#api/en/core/BufferGeometry.addGroup

Okay, thats what I kind of though. (thanks for the correction tho)

But what I actually wanted to know:
Is there a way to do something similar to my imported object?
Because I want a similar result for my object (like in the links I shared)

Because I want my object to have something like a group so I can add multiple materials/layers like in the examples.

You can try to traverse through gltf.scene and use addGroup() for all geometries you encounter in the hierarchy.

But I thought “addGroup” was only for BufferGeometry and not my imported myObject. (I only have one Object in my whole scene)

I think I’m misunderstanding something important here.
Am I able to add myObject to BufferGeometry?

            loader.load('myObjects/myObject.glb', function (gltf) {

                myObject = gltf.scene;

                myObject.addGroup(0, Infinity, 0);

                myObject.addGroup(0, Infinity, 1);

                let myMaterials = [material1, material2];

                myNewObject = new THREE.Mesh(myObject, materials);

                scene.add(myNewObject);

As U mentioned → there is no “addGroup”-method for my object “myObject” since it’s no BufferGeometry.
But which step would you recommend if I want to give my object “myObject” multiple materials?

Now how should I be able to use addGroup() if I’m using an imported object ( and not a BufferGeometry)

Do I have to save/put “myObject” into another mesh or group?

Sorry but I’m still having trouble understanding your advice. :frowning:

Your imported object still consists of instances of BufferGeometry. You can log them like so:

gltf.scene.traverse( function( object ) {

    if ( object.geometry ) console.log( object.geometry );

} ):

You can use addGroup() on these instances.

okay, thanks. I’ll have a look!

My log looks like the following: ( There are like 20 of these B’s)

B {uuid: “9DA7E11F-CAB7-4B78-900D-338F64952845”, name: “”, type: “BufferGeometry”, index: M, attributes: {…}, …}

Am I still able to use these instances even though the “name” is empty? Am I still able to address them?

Or should I name them as I export the object ?

Empty names are not important for this issue.

Okay, thats good to know!
So these B’s are my BufferGeometry-Instances. Do I still need to parse them to get their information?
Because my code obviously doesn’t know what B is.

Okay, I think I got what I wanted.

let loader = new THREE.GLTFLoader();

            loader.load('myObjects/myObject.glb', function (gltf) {

                myObject = gltf.scene;

                let materials = [material1, material2];
          
                myObject.traverse(function (child) {

                    if (child.isMesh && child.geometry) {

                        let geometry = child.geometry;

                        geometry.clearGroups();

                        geometry.addGroup(0, Infinity, 0);

                        geometry.addGroup(0, Infinity, 1);

                        child.material = materials;

                    }

                })

                scene.add(myObject);

            });

        });

    }

I hope there are no major mistakes in this one. But thanks for leading me there!

1 Like

Hi to all, the problem is that with this method after it is impossible to export the object with GLTFExporter