How to assign cloned material to cloned mesh

Hi guys :slight_smile:

So I’m struggling a little with cloning meshes and materials…
I’m currently loading a GLTF model into the scene. I then want to clone the root mesh and material several times so I have copies of the original model but each a different colour (so presumably I need to also clone the material each time and assign a new colour to each material?).

Currently, I load the model. This gives me 2 meshes. I then have a function which iterates X amount of times, each time creating a clone of mesh[0] and a clone of mesh[1]. I position the clone using mesh[0] and make colour changes to the cloned material on mesh[1].
The cloning is working as expected - I have X amount of models rendered correctly where they should be. However, they are all still sharing their original material. I can see that the new cloned materials exist with their new respective colours, but I don’t know how to assign the new cloned materials to their new clone parents?
Any help would be much appreciated :slight_smile:

Thanks!
Olly

Basically it will be something like
clonedMesh.material = myNewMaterial;
You don’t need to clone materials separately, mesh cloning is enough. But you need to create a new material and then assign it to the desired mesh (meshes).
If you are able to share a repro in PG it would be easier to answer.

1 Like

Thanks @labris
So I have to create a new material each time, I cannot clone the first material and change a single attribute?
I have tried clonedMesh.material = clonedMaterial which semi works (it does create the new material, but it is not assigning the new material to the cloned mesh).
The original model has a root mesh for positions and transforms etc and a second mesh for materials etc.
mesh[0].material is null. The material is coming from mesh[1]. How does Babylon know the two meshes are associated with each other? When I make a clone of mesh[0], the clone seems to still be reading the material from mesh[1], regardless of what I set the material attribute to be on the cloned mesh.
Worth noting that when the model is loaded, it is an ‘abstractMesh’ object. Mesh[0] and mesh[1] are under the ‘meshes’ key of this object. Perhaps it is necessary to create a copy of the entire ‘abstractMesh’ object instead?
I’m using React with the react-babylonjs library, so I could create a PG, but it wouldn’t necessarily reflect what’s actually happening :confused:
Maybe I can set up a codesandbox with all dependancies etc if we can’t figure it out without.

When you clone a mesh, the same material is assigned to the cloned mesh. You can clone the material and assign it to the cloned mesh and you will be able to change some properties that won’t affect the original material:

Here you are: the example with GLTF Boombox - https://playground.babylonjs.com/#NETYHK#3

Thank for your help guys :slight_smile:
So it seems that’s exactly what I’m doing. My code reads…

const newPlayer = player.clone(`playerClone ${i}`);
  const newPlayerMaterial = playerMaterial.clone(`newPlayerMat ${i}`);
  newPlayerMaterial.albedoColor = new Color3.FromHexString('#EAFB00');
  newPlayer.material = newPlayerMaterial;

  newPlayer.position = getPosition({
    of: OBJECT_POSITION_ENUM.PLAYER,
    playerData: teamPlayer,
  });

The new meshes are being correctly positioned. The new material is being correctly assigned to the material attribute of the the cloned mesh, but the colour of the mesh clones is not changing. They are still all using the original albedo colour.

Here is a screen shot of the inspector…

The newPlayerMat materials are the new cloned materials. However all cloned meshes are still using the oppositionFuzball_textre material.

@labris @Evgeni_Popov
Perhaps also worth mentioning is that if I find the cloned mesh under ‘nodes’ in the inspector, under the general tab I can see that the active material is still the ‘oppositionFuzball_textre’ from the original model (pre cloning). Here I can set the active material to be one of the new cloned materials which is exactly what I want to accomplish. But how do I do this in code?!

Do you have any messages in the console?

It should work :slight_smile:
The reasons why it doesn’t work may be different but often it happens just because some variable is undefined when it is needed. Actually you may try to find (with the help of Chrome debugger tool) what is happening when you are trying to apply your newPlayerMaterial to the NewPlayer.

2 Likes

It looks like the mesh with the material is the grandchild of the one that was cloned so maybe something like below would work?

newPlayer.getChildren()[0].getChildren()[0].material = newPlayerMaterial;
3 Likes

That’s exactly right @Blake , thank you :slight_smile:
I understand better what’s happening now. Excellent :+1:

2 Likes