10
votes

geometry.faces accessible only for new THREE.BoxGeometry. Then I try to use THREE.BoxBufferGeometry I can't change color for faces.

Not working:

  var geometry = new THREE.BoxBufferGeometry( 100, 100, 100 );
  for ( var i = 0; i < geometry.faces.length; i ++ ) {
    geometry.faces[ i ].color.setHex( Math.random() * 0xffffff );
  }

Working:

  var geometry = new THREE.BoxGeometry( 100, 100, 100 );
  for ( var i = 0; i < geometry.faces.length; i ++ ) {
    geometry.faces[ i ].color.setHex( Math.random() * 0xffffff );
  }
2
THREE.BoxBufferGeometry() doesn't have faces property, but this is an indexed geometry.prisoner849
Yes, for TubeBufferGeometry I see geometry: normals, binormals, tangents, parameters, attributes.. but I don't understand how to access plane color.Gabriel
you can start from this pointprisoner849

2 Answers

36
votes

BufferGeometries in three.js are fundamentally different from the regular Geometries. They are not oriented towards ease of manipulation but rather towards how meshes need to be delivered to the WebGL API.

That being said, there is no explicit notion of "faces" for BufferGeometries, they are implicit. A BufferGeometry consists of a number of attributes (for background see here), one of them is the position-attribute.

In a regular BufferGeometry (as opposed to "indexed"), the faces are stored as sequences of three vertices within that attribute (something like [x1, y1, z1, x2, y2, z2, x3, ...], so for the first face position[0] is the x-component of the first vertex and position[8] is the z-component of the third vertex). All other attributes use a similar indexing-scheme. If you define an attribute color for the geometry, you can control the face-colors by writing the same color-value at the positions of all three face-vertices (so in this example a color-attribute with [r, g, b, r, g, b, r, g, b, ...] would assign the same rgb-value to the three vertices of the first triangle).

Indexed geometries are different: Instead of repeating the vertices for all triangles, every vertex is stored only once. An additional attribute index is used to connect the vertices into triangles. So an index-attribute might look like this: [0, 1, 2, 0, 2, 3, ...] which reads as "construct first triangle from vertices at positions 0, 1 and 2" and so on.

As this is a very efficient way of storing geometries, this technique is used with most (maybe even all) of the builtin geometries in three.js.

With indexed geometries it is not possible to have colors per face-vertex because the vertex must have the same color everywhere it is used. You can however use bufferGeometry.toNonIndexed() to convert an indexed geometry into a regular one.

3
votes

All necesarry here https://threejs.org/docs/index.html#api/en/core/BufferGeometry

See examples: Mesh with non-indexed faces, Mesh with indexed faces...

and i think that little example be more useful:

const geometry = new THREE.BoxBufferGeometry( 100, 100, 100 );
const colorsAttr = geometry.attributes.position.clone();
// Faces will be colored by vertex colors
geometry.setAttribute('color', colorsAttr);
const material = new THREE.MeshBasicMaterial({
    vertexColors: THREE.VertexColors
});
const cube = new THREE.Mesh( geometry, material );