The Networker The Networker - 6 months ago 24
Javascript Question

How to update colors after vertex colors are changed?

I copy and paste the whole(short) html file here to illustrate the problem. Basically, I create a simple triangle geometry as a global variable. When you click the "Red" button, function red() is called to render the triangle as red. The problem is that clicking "Green" does not render it as green if the triangle has already been rendered as red.

<html>
<body>
<div id="container"></div>
<button onclick="red()">Red</button>
<button onclick="green()">Green</button>

<script src="http://threejs.org/build/three.js"></script>
<script>
//Boilerplate stuff
var w=300;
var h=300;
var renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(w, h);
document.getElementById('container').appendChild( renderer.domElement );

var scene = new THREE.Scene();
var light = new THREE.DirectionalLight(0xffffff);
light.position.z = 10;
scene.add(light);

var camera = new THREE.PerspectiveCamera( 20, w / h, 1, 1000 );
camera.position.z = 10;

var materials = [new THREE.MeshPhongMaterial( { color: 0xffffff, shading: THREE.FlatShading, vertexColors: THREE.VertexColors, shininess: 0 } )];

//Make a geometry
var shape = new THREE.Shape();
shape.moveTo( 0,0 );
shape.lineTo( 0, 1 );
shape.lineTo( 1, 0);
var geometry = new THREE.ShapeGeometry([shape]);
var obj = THREE.SceneUtils.createMultiMaterialObject(geometry, materials);
scene.add(obj);

//
function red()
{
change_color(new THREE.Color(0xff0000));
renderer.render(scene, camera);
}
//
function green()
{
change_color(new THREE.Color(0x00ff00));
renderer.render(scene, camera);
}
//
function change_color(color)
{
geometry.colorsNeedUpdate = true;
for(var i=0;i<geometry.faces.length;i++)
{
if(geometry.faces[i].vertexColors[0]==undefined)
{
geometry.faces[i].vertexColors[0]=color;
}
else
{
geometry.faces[i].vertexColors[0].copy(color);
}

if(geometry.faces[i].vertexColors[1]==undefined)
{
geometry.faces[i].vertexColors[1]=color ;
}
else
{
geometry.faces[i].vertexColors[1].copy(color);
}

if(geometry.faces[i].vertexColors[2]==undefined)
{
geometry.faces[i].vertexColors[2]=color;
}
else
{
geometry.faces[i].vertexColors[2].copy(color);
}
}
}

</script>

</body>
</html>

Answer

You are changing vertex colors after the first render of a mesh.

Currently, you can't use the following pattern in three.js once the object has been rendered at least once.

geometry.faces[ i ].vertexColors[ 0 ] = color; // assigning a Color object

You have to use this pattern instead:

geometry.faces[ i ].vertexColors[ 0 ].copy( color ); // or use set()

You must also set the needsUpdate flag when the vertex colors are changed.

geometry.colorsNeedUpdate = true;

Consequently, in your program, you need to add vertex colors to your geometry when you create it. Then just change the color values.

three.js r.77