0
votes

Okay, hello. I'm just getting into threejs. I am currently developing a kind of block game (compare Minecraft).

I decided not to base the whole program on objects, but on planes. (per PlaneGeometry class)

Since I've almost finished writing my renderer, I want to use different blocks with different textures - like in minecraft - because so far the texture is the same for each block.

How can I use different THREE.Mesh textures with one Geometry object?

Is that even possible - and does anyone have any idea how I can do that?

I have published parts of my code below:

/* geometry.js */

let size = 100;
let matrix = new THREE.Matrix4();

for (let z = 0; z < world.size.depth; z++) {
  for (let x = 0; x < world.size.width; x++) {
    for (let y = 0; y < world.size.height; y++) {
      matrix.makeTranslation(
        x * size - (world.size.width / 2) * size,
        y * size,
        z * size - (world.size.depth / 2) * size
      );
      // generate 6 PlaneGeometry's (6 cube sides)
      // and merge visible ones to the geometry
      geometry.merge(PlaneGeometry_N_0to5, matrix);
    }
  }
}
geometry = new THREE.BufferGeometry().fromGeometry(geometry);

/* texture.js */

// make this stuff for multiple textures (different $path$) for sure
let loader = new THREE.TextureLoader();
let texture = loader.load("$path$"); // path of texture
texture.magFilter = THREE.NearestFilter;
texture.minFilter = THREE.LinearMipMapLinearFilter;

let mesh = new THREE.Mesh(
  geometry,
  new THREE.MeshLambertMaterial({
    map: texture,
    vertexColors: THREE.VertexColors,
    side: THREE.DoubleSide
  })
);
scene.add(mesh)
2

2 Answers

0
votes

I'm not sure I understand your question correctly but a geometry object has no dependency to a material. So you can reuse a single geometry for different meshes and apply different materials to it. Each material can of course refer to different textures. Simple code example:

const loader = new THREE.TextureLoader();
const texture1 = loader.load( 'path/to/texture1.jpg' );
const texture2 = loader.load( 'path/to/texture2.jpg' );

const material1 = new THREE.MeshLambertMaterial( { map: texture1 } );
const material2 = new THREE.MeshLambertMaterial( { map: texture2 } );

const mesh1 = new THREE.Mesh( geometry, material1 );
const mesh2 = new THREE.Mesh( geometry, material2 );

BTW: It also makes sense to reuse material objects. So it's not necessary to create a material for each mesh.

three.js R106

0
votes

you can apply several textures to the same geometry, just create one blank texture and stack each existing texture as a horizontal slice on that blank texture. then, remap the uvs for each part of the geometry. for instance: if you want a cube to have 5 sides with one texture and 1 side with another texture, just create a blank texture with two stripes: the bottom stripe, will be mapped to uv: (0,0)-(0.5, 1) and the upper stripe: (0.5,0)-(1,1) then, in your cube geometry, you can map the 5 sides with uvs from (0,0) to (0.5,1) and the 6th side will fetch the texture from the upper strip, mapping its uvs from (0.5, 0) to (1,1) :-)