11
votes

I am trying to use Three.js to render a cube with 6 different images on the faces.

The constructor of THREE.CubeGeometry looks like this:

THREE.CubeGeometry = function ( width, height, depth, segmentsWidth, segmentsHeight, segmentsDepth, materials, sides )

I can see from the code that "materials" is expected to be either a material, or an array of 6 different materials, but the materials passed in here never seem to be used when rendering.

Instead, the single material given to the Mesh constructor is used for all 6 faces.

var face_materials = ... <load 6 textures here>...
var cube_g = new THREE.CubeGeometry(400,400,400,1,1,1, face_materials); // <= ignored?
var cube = new THREE.Mesh(cube_g, some_material); // <= this is used instead

Even if I pass null or undefined as the "some_material", it seems to override the face_materials and render nothing.

Is there a way to make this work using CubeGeometry? Or do I have to create the 6 faces separately and add them to the scene?

3

3 Answers

18
votes

You need to use THREE.MeshFaceMaterial for the mesh. Here's example code:

var materials = [];
for (var i=0; i<6; i++) {
  var img = new Image();
  img.src = i + '.png';
  var tex = new THREE.Texture(img);
  img.tex = tex;
  img.onload = function() {
    this.tex.needsUpdate = true;
  };
  var mat = new THREE.MeshBasicMaterial({color: 0xffffff, map: tex});
  materials.push(mat);
}
var cubeGeo = new THREE.CubeGeometry(400,400,400,1,1,1, materials);
var cube = new THREE.Mesh(cubeGeo, new THREE.MeshFaceMaterial());
3
votes

For an example of using multiple materials in a cube, for a recent version of three.js version 56 (March 2013), check out the source code of the example at http://stemkoski.github.com/Three.js/Textures.html -- the biggest recent change is that THREE.MeshFaceMaterial needs to be passed an array of materials to be used in the CubeGeometry.

0
votes

MeshFaceMaterial is now deprecated so instead of using that you should pass in an array of MeshBasicMaterials.

However...if like me you only want to render a different color on each face anyways, then there is another way, described in WestLangley's answer here. The basic idea is that you set the color in the geometry object's faces, rather than as an array of materials.

var geo = new THREE.BoxGeometry( 5, 2, 5 );

var mat = new THREE.MeshBasicMaterial( { color:0xff0ff0, vertexColors: THREE.FaceColors } );

var mesh = new THREE.Mesh( geo, mat );

mesh.geometry.faces[ 5 ].color.setHex( 0x00ffff ); 

This is a really efficient way of doing things.