Peter Wang Peter Wang - 12 days ago 5
Javascript Question

Changing Sphere Colors independently three.js

In my scene I have 7 spheres in a flower petal formation (6 on the perimeter and 1 in the center). I want to change the colors of each of these spheres randomly. Here is the code I used to try to do this:

function changeSphereColors() {
var hex, color, len = spheres.length;
var change = function(i) {
var hex = "#000000".replace(/0/g,function(){return (~~(Math.random()*16)).toString(16);});
color = new THREE.Color(hex);
spheres[i].material.color = color;

}
for (var i=0; i<len; i++) {
change(i);
}
}
var render = function() {
requestAnimationFrame(render);
rotateSpheres();
var num = Math.random();
if (num<0.1) {
changeSphereColors();
}
renderer.render(scene, camera);
}
render();


spheres
is an array of length 7 that has each sphere in it. Since I loop through each sphere and assign a random hex color to each one, there should be 7 spheres of all different colors, but instead, all the spheres are the same color.

I looked at the output to see if each color was different and that the loop was going as expected, and everything seemed to be working fine. There was a different hex color generated on each iteration of the loop, and it was assigning the hex color to each sphere.

Why are all the spheres the same color?

Answer

It is likely because they are sharing the same material. Create a separate material for each.

Here's an example I created with 3 spheres. Two share the same material, one doesn't. If I set the colour of one of the spheres with the shared material the other changes too:

var geometry = new THREE.SphereGeometry(3, 50, 50, 0, Math.PI * 2, 0, Math.PI * 2);

var material1 = new THREE.MeshBasicMaterial();
var material2 = new THREE.MeshBasicMaterial();

var sphere = [new THREE.Mesh(geometry, material1), new THREE.Mesh(geometry, material1), new THREE.Mesh(geometry, material2)];

scene.add(sphere[0]);
scene.add(sphere[1]);
scene.add(sphere[2]);    

var hex = "0x" + "000000".replace(/0/g,function(){return (~~(Math.random()*16)).toString(16);});        
sphere[0].material.color.setHex(hex);

hex = "0x" + "000000".replace(/0/g,function(){return (~~(Math.random()*16)).toString(16);});        
sphere[2].material.color.setHex(hex);

// sphere[0] & sphere[1] now share the same colour, even though I didn't set for sphere[1]. 
// Sphere[2] colour is unique.

http://jsfiddle.net/ebnfsa5h/3/