3

I'm still pretty new at Three.JS, I'm pretty happy where I have gotten so far, but just need some help.

I have an GLTF object loaded into the scene, I want to be able to load different textures onto the object on the website by the user selecting a style, (like a customization feature).

Below is my code, at the moment it outputs nothing and I get the following error:

In Chrome:

"TypeError: Cannot set property 'map' of undefined"

In Firefox:

"TypeError: model.material is undefined"

var textureLoader = new THREE.TextureLoader();
var texture = textureLoader.load('../gtf/green/green.png');
texture.flipY = false;

var loader = new THREE.GLTFLoader();
loader.load( '../gtf/Box.gltf', function ( gltf ) {
    model = gltf.scene;
    scene.add( model );
});

model.material.map = texture;

Any help would be greatly appreciated.

HugoTeixeira
  • 4,674
  • 3
  • 22
  • 32
TheGoldenD0nut
  • 123
  • 1
  • 13

2 Answers2

1

The function loader.load() runs asynchronously and you don't have the model variable immediately set after you call it. So the solution you are looking for is to move the model.material.map = texture; inside the callback function, like this:

loader.load( '../gtf/Box.gltf', function (gltf) {
    model = gltf.scene;
    texture.flipY = false; // for glTF models only
    model.material.map = texture; // <-- move here
    scene.add( model );
});

This will guarantee that you have a valid model object that you can use.

Don McCurdy
  • 10,975
  • 2
  • 37
  • 75
HugoTeixeira
  • 4,674
  • 3
  • 22
  • 32
  • Hey Hugo, Thanks for that. I got it working, and pretty happy with it. I've posted a new question, below is the link, if you have any insight to that problem, that would be amazing. https://stackoverflow.com/questions/52068620/create-an-array-of-meshes-from-object-three-js-and-gltf – TheGoldenD0nut Aug 29 '18 at 02:27
0

The problem that you are running into is that the scene that you have assigned as model contains a lot more information than just the mesh and material information. You will need to iterate over the scene object model in order to find the mesh, and then change the material accordingly. While the initial data format that you are using is different, the answers you are looking for can be found in a previous post here:

Change texture of loaded .obj in three.js at runtime

Edit:
@HugoTeixeira is right that assignment of the texture needs to be moved into the callback function of loader.load() (sorry, I totally overlooked this previously), but the actual assignment model.material.map = texture; isn't going to work. You will still need to iterate over the gltf.scene object as mentioned above in order to find the mesh that you want to assign the texture to.

jlcox5
  • 3
  • 2
  • Thanks @jlcox5, Seems to make sense, and just got it working. Would you know, if its possible to apply a texture to a certain part of the model? So the GLTF is from Blender, could I apply a texture to one side? Or should I be using an .obj and .MTL file and using an array of objects? – TheGoldenD0nut Aug 29 '18 at 01:30
  • Hey @TheGoldenD0nut, the [GLTF format](https://github.com/KhronosGroup/glTF/blob/master/README.md) specifies that you can have multiple meshes per file. You should be able to find the specific mesh you want to change with the iteration mentioned above, and assign new textures individually. That said, how your model is organized will depend on its construction in Blender, and the exporter you used when creating the GLTF file to begin with. It's easy to open the .gltf file and look for the "meshes" entry in the JSON blob to get an idea. Issues like this will be present for most formats. – jlcox5 Aug 29 '18 at 04:22