EJW EJW - 28 days ago 33
Javascript Question

Threejs textureLoader - scaling and mapping to mesh

I have a cube that I'm trying to map an image onto. I'm loading the image with a loading Manager. I'm wondering why the material.map is returning as undefined, also wondering if maybe I have a scaling issue. The original image is 512x512. The boxes are 20x20x20.

I left out all the code about camera, renderer, etc., but I attempted to include it all in the code snippet/interactive part below.

var loadingManager = new THREE.LoadingManager();

loadingManager.onProgress = function (item, loaded, total) {

//Loading percentage
console.log(loaded / total * 100 + '%');

}

//Signify loading done
loadingManager.onLoad = function () {

//Start the animation when the models are done loading
animate();
}

function init() {

//create a loader
var loader2 = new THREE.TextureLoader(loadingManager);

//load the texture, and when it's done, push it into a material
loader2.load("../img/leo.jpg", function (texture) {

//do I need to do this?
texture.wrapS = texture.wrapT = THREE.RepeatWrapping
texture.repeat.set(boxSize, boxSize)

//why is this texture not coming through?
console.log(texture)

//does not work:
material1 = new THREE.MeshBasicMaterial({
map: texture,
side: THREE.DoubleSide
});


})

var geo = new THREE.BoxGeometry(30, 30, 30)
var mat = new THREE.MeshBasicMaterial({
color: 0xb7b7b7
})
mesh = new THREE.Mesh(geo, material1)
scene.add(mesh)

}

// This works, so I know the image path is correct
var img = document.createElement('img');
img.src = '../img/leo.jpg';
document.getElementById('container').appendChild(img);


The value of texture from the console log is this:
enter image description here

enter image description here

Answer

The error is related to the fact that you are associating the material outside the callback of the load function of your loader, you have to do that inside the callback.

From the documentation for TextureLoader:

  • onLoad - Will be called when load completes.

You have to do as follow:

loader2.load("../img/leo.jpg", function(texture) {
      texture.wrapS = texture.wrapT = THREE.RepeatWrapping
      texture.repeat.set( boxSize,boxSize )
      //why is this texture 1 not coming through?
      console.log(texture)

      //neither of these work:
      var geo = new THREE.BoxGeometry(30,30,30);
      material1 = new THREE.MeshBasicMaterial({ map: texture,side: THREE.DoubleSide });

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

        // animation loop
       function animate() {

         requestAnimationFrame( animate );

         render();

        // update stats
        stats.update();
      }

      ...
});

To make this more readable and avoid a callback nightmare do something like this:

function myInit(texture) {
  ...
}

loader2.load("../img/leo.jpg", myInit);
Comments