Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

two meshes, same texture, different offset?

Using three.js, I'm working on a web page to display a flip cube (a.k.a. magic cube; see e.g. the video on this page).

Flip cube

On a flip cube, there are typically images that are spread out across multiple pieces of the cube. For example, the boat image shown above is spread across the faces of four cubelets. In three.js terms, there are multiple meshes that need to use the same image for their material texture, but each at a different offset.

As far as I understand it, in three.js, offset is a property of a texture, not of a material or a mesh. Therefore, it would appear that you cannot have a single texture that is used at a different offset in two different places.

So does that mean that in order to have different parts of the boat image shown on four different faces, I have to create four separate textures, meaning that we load the boat image into memory four times? I'm hoping that's not the case.

Here's a relevant piece of the code:

  // create an array with the textures
  var textureArray = [];
  var texNames = ['boat', 'camels', 'elephants', 'hippo',
    'natpark', 'ostrich', 'coatofarms-w', 'kenyamap-w', 'nairobi-w'];
  texNames.map(function(texName) {
    textureArray.push(THREE.ImageUtils.loadTexture(
      'images/256/' + texName + '.jpg' ));
  });

    // Create a material for each texture.
  for (var x=0; x <= 1; x++) {
    for (var y=0; y <= 1; y++) {
      for (var z=0; z <= 1; z++) {
        var materialArray = [];
        textureArray.map(function(tex) {
          // Learned: cannot set this offset for one material,
          // without it affecting all materials that use this texture.
          tex.offset.x = x * 0.2;
          tex.offset.y = y * 0.2;

          materialArray.push(new THREE.MeshBasicMaterial( { map: tex }));
        });
        var cubeMaterial = new THREE.MeshFaceMaterial(materialArray.slice(0, 6));
        var cube = new THREE.Mesh( cubeGeom, cubeMaterial );
        cube.position.set(x * 50 - 25, y * 50 - 25, z * 50 - 25);
        scene.add(cube);
      }
    }
  }

If you look at it on http://www.huttar.net/lars-kathy/tmp/flipcube.html, you'll see that all the texture images are displayed offset by the same amount on each cubelet face, even though they are set to different offsets on different cubelets. This seems to confirm that you can't have different uses of the same texture with different offsets.

How can I get different meshes to use the same texture at different offsets, so I don't have to load the same image multiple times into multiple textures?

like image 895
LarsH Avatar asked Nov 02 '22 20:11

LarsH


1 Answers

What you say is true. Instead of adjusting the texture offsets, adjust the face vertex UVs of the geometry.

EDIT: There is another solution more in line with what you want to do. You can clone a texture like so:

var tex = new THREE.Texture.clone();

Cloning a texture will result in the loaded image being reused, and the new texture can have it's own offsets. Do not try to clone the texture until the image loads, however.

With this alternate approach, you do not have to adjust UVs, and you do not have to load an image more than once.

three.js r.58

like image 133
WestLangley Avatar answered Nov 20 '22 15:11

WestLangley