Changing material of single mesh in model

1. A concise explanation of the problem you're experiencing.
I have a glTF model made up of several meshes and I would like to set the emissiveFactor on a single mesh. However this mesh shares a material with other meshes. I would like to make a copy of this material or assign a temporary material to the mesh to "highlight" it. Is there a way to do this?

2. A minimal code example. If you've found a bug, this helps us reproduce and repair it.

var mat = primitive.getMaterial(primitive.getMesh(node.mesh).materials[0].name);
mat.setValue("emissiveFactor", new Cesium.Cartesian3(1, 0, 0));

Here the problem is that the material is shared across multiple meshes so changing the emissive factor affects all of them instead of just the mesh I want. How can I properly duplicate the material?

3. Context. Why do you need to do this? We might know a better way to accomplish your goal.

I want to color a single node/mesh so that each portion of the model doesn't have to be a separate glTF

4. The Cesium version you're using, your operating system and browser.

So after doing some research and testing yesterday I also noticed that something like this does not behave as I expected.
primitive.getMesh(node.mesh).materials[0] = primitive.getMesh(node.mesh).materials[1];

Given a mesh with two materials, I would expect the mesh to be colored with the same material in slot 1. But the mesh is still colored with two different materials. I understand MeshMaterial is probably just the interface for setting values on the actual material, but how can I actually get this latest example to work for instance? If this can get answered I think I can solve my original problem.

Good to see you back around here Richard!

I’m assuming you’ve already considered this, but is duplicated the material ahead of time an option? Or is the goal to do this interactively to essentially highlight nodes of the model on mouse over? I know 3D Tiles you do this (which uses glTF as a payload), although I think this is accomplished with the batch table and the shader.

Is the application you’re working on public? I’d be curious to see how it’s all coming together!

Hey Omar,

Good to hear from you as well too! I guess I was getting too good with Cesium hence I was not around lately haha. Duplicating the material ahead of time is ok. In fact I tried this by making a deep copy of the ModelMaterial I wanted to alter and then assigning the altered ModelMaterial to the mesh like so:

primitive.getMesh(node.mesh).materials[0] = myNewMaterial;

I essentially followed the same code as here and made sure my new material was added to the model’s runtime structures for storing the material.

https://github.com/AnalyticalGraphicsInc/cesium/blob/1.59/Source/Scene/Model.js#L2013-L2041

Can you point me to info on the batch table? I will try to share an example on glitch soon, unfortunately we cannot share the models still but you can at least see how I am trying to make things work. -Cheers

Ok I finally found a solution to this. The answer is to affect the desired node commands for a given primitive, for example:

primitive._nodeCommands[i].command._uniformMap.u_emissiveFactor = function(){return new Cesium.Cartesian3(1,0,0);};

1 Like