I am having some trouble getting the texture from a user uploaded file and applying it to an object being loaded using the OBJLoader. The user is able to upload the OBJ, MTL and JPG using html elements which are then used to load the model into the scene:
var newModel = document.getElementById('NewModel').files[0];
var OBJFile = URL.createObjectURL( newModel );
var newMat = document.getElementById('NewMaterial').files[0];
var MTLFile = URL.createObjectURL( newMat );
var newTex = document.getElementById('NewTexture').files[0];
var JPGFile = URL.createObjectURL( newTex );
var objLoader = new THREE.OBJLoader();
var mtlLoader = new THREE.MTLLoader();
if(typeof document.getElementById('NewModel').files[0] !== 'undefined')
{
if(typeof document.getElementById('NewTexture').files[0] !== 'undefined')
{
mtlLoader.setResourcePath(JPGFile);
mtlLoader.load(MTLFile, function (materials) {
materials.preload();
objLoader.setMaterials(materials)
objLoader.load(OBJFile, function (object) {
var texture = new THREE.TextureLoader().load(JPGFile);
object.traverse(function (child) {
if (child instanceof THREE.Mesh) {
child.material.map = texture;
}
});
scene.add(object);
});
});
}
}
The model loads fine (with textures) when using local files and the same code - I think the problem may be something to do with the path defined in the .mtl file but I can’t find a way of changing this on the fly. Any help with this would be greatly appreciated. Thanks!
Looking at some console.log outputs I can see that the error is coming from the mtlloader adding the name of the texture file, found at the end of the material file, onto the resource URL. As the URL is from an upload and not in the file structure, the loader is unable to find the file.
GET blob:http://127.0.0.1:3000/0e70edd7-4a6f-4e39-ac88-88d0294afffcDonut.png net::ERR_FILE_NOT_FOUND
So in this example the image is at http://127.0.0.1:3000/0e70edd7-4a6f-4e39-ac88-88d0294afffc but it is trying to find it with ‘Donut.png’ on the end of the path.
I can’t find where this is being appended and therefore can’t solve this issue. I assume it is in the material loader. Does anyone have any idea how to solve this?
I tried using the MTLLoader.setResourcePath in the snippet above, maybe I am not using it correctly? I don’t have any experience with the LoadingManager, I gave it a go and it appears that it is loading the texture (as it appears in the model hierarchy when it is logged) but is not mapping it to the model… Any ideas? Thanks again and sorry for not understanding!
function loadNewModel() {
var newModel = document.getElementById('NewModel').files[0];
var OBJFile = URL.createObjectURL( newModel );
var newMat = document.getElementById('NewMaterial').files[0];
var MTLFile = URL.createObjectURL( newMat );
var newTex = document.getElementById('NewTexture').files[0];
var JPGFile = URL.createObjectURL( newTex );
var manager = new THREE.LoadingManager();
manager.setURLModifier (function ( url ) {
url = JPGFile;
return url;
});
var objLoader = new THREE.OBJLoader();
var mtlLoader = new THREE.MTLLoader(manager);
var texLoader = new THREE.TextureLoader();
if(typeof document.getElementById('NewModel').files[0] !== 'undefined')
{
if(typeof document.getElementById('NewTexture').files[0] !== 'undefined')
{
//mtlLoader.setResourcePath(JPGFile);
mtlLoader.load(MTLFile, function (materials) {
materials.preload();
objLoader.setMaterials(materials)
objLoader.load(OBJFile, function (object) {
var texture = texLoader.load(JPGFile);
object.traverse(function (child) {
if (child instanceof THREE.Mesh) {
child.material.map = texture;
}
});
scene.add(object);
Raycasts.push(object);
});
});
}
}
}
The resource path would need to be a folder, and the filename in the MTL file gets appended onto that. With setURLModifier you can do arbitrary changes to the URL or replace it entirely. But your snippets above look OK otherwise, so I’m not sure what’s going on… would you be able to share a running demo?
I thought that might be the case, would that mean that when the user uploads the file it is stored into a directory before being loaded?
It’s available here, if you click the icon on the top left it’s in the orange model section of the GUI. If you’re looking at the source code the function starts at line 552!