Change colors problem

Hi i’d like some help if i needed to use a function to change each object color on press of buton?

function multico() {
        scene.traverse( function( tested ) {
        for (let i=0; i<= tested.lengtht; i++){
            console.log('tested');
        };


so i got to use traverse to visit all geometry gltf
so i’m visibly wrong with tested.lenght its type is wrong
and after maybe some of you know to adress each ‘object.material’ to change it,
in the for loop?
like this that i got previously
object.material.color.set( Math.random() * 0xffffff );
but now into a ‘for’ in a ‘traverse’ , well its more harsh than expected. Cheers!

for (let i=0; i<= tested.lengtht; i++){
to
for (let i=0; i<= tested.length; i++){

function multico() 
scene.traverse(function(child){
if(child.isMesh && child.material.length==undefined){
child.material.color.set( Math.random() * 0xffffff );
}
});
2 Likes

that’s a very subtle correction, if i may say so. You might have wanted to point out the initially wrong spelling of “length”, which had a surplus “t” at its end. I myself had to look more than twice until I realized that … :face_with_monocle:

1 Like

that looks amazing, thanks for your 2 feedbacks.

ok i’m back i really’ve been searching on this, but why ’ child.material.color is undefined ’ when pressing my function

function multico(child) {
	//change of colors random
	scene.traverse( function(child) {
		if(child.isMesh){
		child.material.color.set( Math.random() * 0xffffff );
	}});
};

maybe the child is not a unique object everytime? It’s a medium-to-good level custom code. Thanks,

Maybe is array material not single

1 Like

thanks. Maybe, to create array , and use it to stock materials, i’m very new to this (see subject) medium-to-good problem here :nerd_face: !!

as per this topic

As per docs - you should not add / remove / modify any elements when using Object3D.traverse. If you need to do that - you can use children.forEach or save referenced to the elements you’d like to remove in an array outside of thetraverse callback.

that i read here Cannot read property 'traverse' of undefined when traverse object in scene and remove it - #2 by mjurczyk
i will try to build my fonction using ‘children.forEach’ but,
problem: where is this technique children.foreach, documented? :sunglasses:

maybe using ‘needsupdate’ see here GLB Replace mesh material on traverse with MeshPhysicalMaterial results in black

mesh.material.needsUpdate = true;

Here for example - it’s just a method of JavaScript arrays (acts pretty much the same as any for-loop, loops through the items in an array.)

1 Like

Veery very cool. Will study this, thanks

Hi! been really looking into it, so close now


function(){

var newMats = [];
//i add an array
scene.traverse(child => {
//i traverse
if ( child.isMesh ) {
if ( child.material )
//i found using 'push' to fill my array
newMats.push( { newMats: child.material.color, child : child} );	}});

//here i read my array is now full
newMats.forEach((element) => console.log(element));

for (var i = 0, n = newMats.length; i < n; i++){
newMats[i].object.color = material.color.set( Math.random() * 0xffffff );
}
};
	
//why my material is not defined ?

it’s mega tuned code yet simple

this looks very much the next step.

The .traverse thread you’ve linked does not really apply here, since you’re not modifying the order / count of children. Your entire function can be cleaned up and simplified to just:

const updateMaterialColors = () => {
  scene.traverse(child => {
    if (!child.isMesh || !child.material) {
      return;
    }

    child.material = child.material.clone();
    child.material.color = new THREE.Color(Math.random() * 0xffffff);
  });
};

updateMaterialColors();

No additional arrays or needUpdates necessary, just make sure this function is called after model is 100% loaded (keeping in mind that model loading is async.)

1 Like

My bad! i should have told they all share a one same material
maybe, that’s why i get 'child.material.color undefined ’ , idk?

soo :cowboy_hat_face: MANY THANKS to you @mjurczyk , i’m all so close.

maybe, to ‘live duplicate’ the materials or something?

In that case it means the material you’re trying to edit color of does not have a color (at least assuming you used the snippet above.)

Instead of color.set simply assign a new THREE.Color (edited the snippet above to include that.)

Yes i’ve use your snippet as is, thank you. It works as needed . Many thanks, it’s so satisfying, as you said Instead of color.set simply assign a new THREE.Color was the problem, and it did the trick. :+1: It’s a huge step