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?

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!

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

Hi
I tested this code
I have 2 material one is color and second is image png .
Second does not apear