How to color a model?

Hello,

Is it possible to highlight/color an individual model a specific color? For example, if I have two entities with the same model uri side by side, I would like to make one blue and the other red. Is this possible? If so, can someone provide a simple example?

I saw another similar post in a search but it wasn't clear if this was currently possible or if it was a future feature.

Thank you!

Yes, it is possible. For example, you would do something like this but set “diffuse”, not “specular:”

https://github.com/AnalyticalGraphicsInc/cesium/blob/master/Specs/Scene/ModelSpec.js#L386

Also see issue #2387, which should be fixed in the next few releases.

Patrick

Thanks Patrick. My models are currently created using the Entity API. How can I get the model/material object you referenced from the entity object?

There is no public means to access either the mesh or the material from an entities ModelGraphics object. You’ll need to use the basic Model object when loading your model if you want to have low-level access to it.

http://cesiumjs.org/Cesium/Build/Documentation/Model.html?classFilter=model

Mike, you are mistaken. I put a gist together to show how to do this: https://gist.github.com/mramato/2b6becee077c664bf25d You can just copy and paste the code into Sandcastle. Here are the relevant bits and explanations.

The below function will retrieve the given Model primitive for any valid entity instance. Since the Entity API does not have any support for node/mesh/material manipulation you can safely change the values under the hood without the Entity API interfering.

function getModelForEntity(entity) {

var primitives = viewer.scene.primitives;

for (var i = 0; i < primitives.length; i++) {

var primitive = primitives.get(i);

if (primitive instanceof Cesium.Model && primitive.id === entity) {

return primitive;

}

}

};

We can use this function to look up the primitive and color it. In my example, I used a primitive that has a material named ‘Red’ (the fact that the name is a color is coincidental)

var model = getModelForEntity(entity);

if (model) {

var material = model.getMaterial(‘Red’);

material.setValue(‘diffuse’, Cesium.Cartesian4.fromColor(Cesium.Color.fromRandom()));

}

When this code runs, the box model changes to the new random color.

I also through in a simple mouse-over example to show how that would work. You don’t actually need the Entity in this case, but it’s available to you if you want to color based on other entity information. The one caveat to this approach is that if you change models on the fly, you have to re-apply the color yourself, Cesium or the Entity API won’t track any of the changes you make automatically. If an Entity always has the same model though, you’re golden.

Eventually we’ll expose this all via Entity API and CZML, but for now this approach should work well, you just need to know the name of the model material you want to color.

Let me know if you’re still having problems.

Thanks,

Matt

I’ve had to use this approach to get down to the primitive and manipulate the model. Changing the color was a surprisingly common request.

Matthew and rest of team, thank you! I was able to play around with your gist and sandcastle and figured out how to manipulate my project to use it. Thanks so much.

One thing I noticed that may be helpful for others, is that the primitive doesn't seem to be immediately available after creating the entity with viewer.entities.add(). So in the following code, "model" would be undefined.

var entity = viewer.entities.add(...);
var model = getModelForEntity(entity);

Hi Matthew,

thank you for providing this working example. I am facing a slightly different issue (I guess, I have mentioned in a different thread as well). I am trying to a highlight a textured gltf model with a different color or a transparency. Would it be possible to do that using a similar approach? For example, in your code, if we replace

uri : ‘…/…/…/Specs/Data/Models/Box/CesiumBoxTest.gltf’,

with

uri : ‘…/…/…/Specs/Data/Models/Box-Textured/CesiumTexturedBoxTest.gltf’,

can we ‘mouse-over highlight’ such textured model using a different color or transparency in the same way as being done in your code.

As I understand, the model material’s diffuse property is cartesian colors in your example, which can be replaced by another cartesian color for highlighting. However, in case of diffuse property as texture (in case of textured gltf model), we are struggling to replace with another color to produce highlighting effect. We are not able to replace texture with a color property.

Any help would be appreciated.

Best regards,

Kanishk

I’m by no means an expert in this area, but you definitely need to set the value of a texture material with another texture. So for example, if you have a solid blue texture, it’s trivial to modify the code I posted to turn the model blue on mouseover and then set back the original texture when finished.

If you want to have the highlight color be translucent and simply tint the underlying texture, I believe that’s more involved and not something we currently support with the public API (though I could be wrong). I could imagine you could set up your model in such a way to make it possible. We plan on having support for this use case as part of the building effort we have been actively working on.

Hi Matthew - thank you for your response. It works now! Attached is the screenshot:

Hi,Kanishk。 I try changed gltf texture with specified color。 like Color.RED.
but it not work. It shows not my specified color . it looks like links below:

http://xiangce.baidu.com/picture/album/list/13542bc473ba5217e20545c55b2d45034f6f3a74

it used like surface texture.
Is my code is there a problem?
thanks for your help.
code below

Hi,

it is not possible to replace the texture with cartesian color value (as you have defined here in your code)

material.setValue(‘diffuse’, Cesium.Cartesian4.fromColor(Cesium.Color.GREEN))

You can only replace the value of a texture material with another texture. You can create a texture with a solid color and use that texture value in material.setValue(). For example, if the name of your highlighting texture is newTexture, use

material.setValue(‘diffuse’,newTexture)

Hi ,Kanishk
Thank you for your reply.
you mean I can use newTexture with defined color?
I'm very sorry, I'm still does not create newTexture.
The following code does not work:

ModelMaterials are different and seperate from Materials.

http://cesiumjs.org/Cesium/Build/Documentation/ModelMaterial.html?classFilter=material ModelMaterials are used by models. Materials are used by entities ( http://cesiumjs.org/Cesium/Build/Documentation/Material.html?classFilter=material ).

Hi,Kanishk and Denver.
thank for your help. it works now.

Hi All,

I have asked this question in other threads, hopefully this is the right thread to post it in.

Anyway, I’m attempting to replicate an effect (colour change on mouse hover) for glTF files and by using the “EntityModelColor.js”.

At first glance it seems to work but I have come across the situation where an object(s) stays selected (as depicted in the image below) even after the mouse cursor position is away from it, which is not desirable. Might you know what this is caused by?

Below is the section of the code used for the selection which is a slightly modified version the original “EntityModelColor.js”.

    //Change color on mouse over.  This relies on the fact that given a primitive,

//you can retrieve an associted en

 var lastColor;

var lastPick;

var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);

handler.setInputAction(function(movement) {

        var primitive;

     var pickedObject = viewer.scene.pick(movement.endPosition);

        if (pickedObject) {

                primitive = pickedObject.primitive;

                if (pickedObject !== lastPick && primitive instanceof Cesium.Model) {

                            //We don't use the entity here, but if you need to color based on

                          //some entity property, you can get to that data it here.

                          var entity = [primitive.id](http://primitive.id/);

                            var material = primitive.getMaterial('Material_0');

                        //var material = primitive.getMaterial('Red'); - original line

                     lastColor = material.getValue('diffuse').clone();

                          //material.setValue('diffuse', Cesium.Cartesian4.fromColor(Cesium.Color.BLUE));

                    material.setValue('diffuse', Cesium.Cartesian4.fromColor(Cesium.Color.YELLOW));

                    lastPick = pickedObject;

                   }

          } else if (lastPick) {

             primitive = lastPick.primitive;

            var material = primitive.getMaterial('Material_0');

                //var material = primitive.getMaterial('Red'); - original line

             material.setValue('diffuse', lastColor);

                   lastPick = undefined;

      }

  }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

``

Regards

Kabiro