I have two files: "model.gltf" and "texture.jpeg". I want to apply texture file to model and render it using three.js but after 3 days of continuous research and hundreds of attempts, I just can't get it to work properly. My method that sets the current object in the scene:
/**
* SET method: Sets object in the scene (deleting previous one)
*
* @author Anton Pernisch <anton@pernisch.dev>
* @param {string} modelPath - Path to object in glTF format
* @param {string} texturePath - Path to texture
* @returns {boolean}
*
* @todo Texture
*/
SET_Object: function(modelPath, texturePath) {
// Clear out the scene
for (var i = this.prodconf3_scene.children.length - 1; i >= 0; i--) {
obj = this.prodconf3_scene.children[i];
this.prodconf3_scene.remove(obj);
}
const modelLoader = new THREE.GLTFLoader();
modelLoader.load(modelPath, (gltf) => {
// HERE? apply texture from texturePath to this gltf
this.prodconf3_obj = gltf.scene;
this.prodconf3_scene.add(this.prodconf3_obj);
});
return true;
}
This code imports glTF just fine, it's just black. Eventually, I was able to apply .jpeg texture to this model, but only sort of. This is the best result I could get: here
And that was by this method:
/**
* SET method: Sets current object to scene (deleting previous one)
*
* @author Anton Pernisch <anton@pernisch.dev>
* @param {string} modelPath - Path to object in glTF format
* @param {string} texturePath - Path to texture
* @returns {boolean}
*
* @todo Texture
*/
SET_Object: function(modelPath, texturePath) {
// Clear out the scene
for (var i = this.prodconf3_scene.children.length - 1; i >=0 ; i--) {
obj = this.prodconf3_scene.children[i];
this.prodconf3_scene.remove(obj);
}
const modelLoader = new THREE.GLTFLoader();
const textureLoader = new THREE.TextureLoader();
modelLoader.load(modelPath, (gltf) => {
var model = gltf.scene;
model.traverse((o) => {
if (o.isMesh) {
o.material = new THREE.MeshBasicMaterial({map: textureLoader.load(texturePath)});
}
});
this.prodconf3_obj = model;
this.prodconf3_scene.add(this.prodconf3_obj);
});
return true;
}
I have also tried creating texture by TextureLoader load method and then meshing it together with gltf.scene
from modelLoader.load
function. That didn't work at all, I was getting
Uncaught TypeError: Cannot read property 'center' of undefined
error (I'm not sure about using gltf.scene
as the first argument in THREE.Mesh()
tho).
So, my question is, what is the proper and updated approach to properly apply the texture to glTF in three.js?
This looks fine to me, but I wonder if we're supposed to pass a reference to an already loaded texture.
Object3D#Traverse
isn't asynchronous, so we'll have to update the material synchronously.
SET_Object: async function(modelPath, texturePath) {
// Clear out the scene
for (let i = this.prodconf3_scene.children.length - 1; i >= 0; i--) {
obj = this.prodconf3_scene.children[i];
this.prodconf3_scene.remove(obj);
}
const modelLoader = new THREE.GLTFLoader();
const textureLoader = new THREE.TextureLoader();
// Load texture
const texture = await textureLoader.loadAsync(texturePath);
texture.flipY = false;
// Load model
const { scene: model } = await modelLoader.loadAsync(modelPath);
// Update model
model.traverse((o) => {
if (o.isMesh) {
o.material.map = texture;
o.material.needsUpdate = true;
}
});
this.prodconf3_obj = model;
this.prodconf3_scene.add(this.prodconf3_obj);
return this.prodconf3_obj;
}