Hi there,
I’m trying to create a tool where users can upload their obj file, an mtl file and the necessary jpeg for textures (required by the mtl file). The loadmodel function is triggered by a multiple file input button in the html.
Since I can’t use the options mtlloader.setpath or mtlloader.setbaseurl to give it the directory where the textures would be because i want the users to load their own obj mtl and textures is there a way to adapt the mtlLoader (or use another solution)?
it’s returning error when i try to upload an obj with its mtl and jpg textures:
Uncaught TypeError: Failed to execute ‘createObjectURL’ on 'url: No function was found that matched the signature provided.
at eval (mainmodules.js:391)
at LoadingManager.resolveURL (three.module.js:36377)
at ImageLoader.load (three.module.js:37089)
at TextureLoader.load (three.module.js:37236)
at MTLLoader.MaterialCreator.loadTexture (MTLLoader.js:528)
at setMapForType (MTLLoader.js:331)
at MTLLoader.MaterialCreator.createMaterial_ (MTLLoader.js:380)
at MTLLoader.MaterialCreator.create (MTLLoader.js:293)
at MTLLoader.MaterialCreator.preload (MTLLoader.js:261)
at eval (mainmodules.js:422)
not sure if the problem is the assets take time to load and are not available yet when the rest of the can run? isnt createobjecturl instantaneous istead of reasAsDataUrl?
any help would be great Thanks!
function loadModel(e){
var mesh = undefined;
const files = document.getElementById("uploadedModel").files;
var extension = undefined;
var gltf = undefined;
var obj = undefined;
var mtl = undefined;
var formatAndTextureFiles = {};
for(const file of files) {
extension = file.name.split('.')[1];
console.log("checking extension " + file.name );
if (extension === "gltf"){
gltf = file.name;
var gltfUrl = file.name;
formatAndTextureFiles[file.name] = file;
}else if (extension === "obj"){
obj = file.name;
var objUrl = file.name;
formatAndTextureFiles[file.name] = file;
}else if (extension === "mtl"){
mtl = file.name;
var mtlUrl = file.name;
formatAndTextureFiles[file.name] = file;
}else if (extension === "jpg" || extension === "jpeg" || extension === "png" || extension === "bmp" ){
formatAndTextureFiles[file.name] = file;
}
}
var manager = new THREE.LoadingManager();
var objectURLs = [];
manager.setURLModifier( ( url ) => {
url = URL.createObjectURL( formatAndTextureFiles[url]);
objectURLs.push( url );
return url;
} );
if (gltf !== undefined){
console.log("there is a gltf");
var gltfLoader = new GLTFLoader(manager);
gltfLoader.load( gltf, (model) => {
mesh = model.scene.children[0];
mesh.traverse(function(o) {
if (o.isMesh) {
o.castShadow = true;
//o.receiveShadow = true;
}
});
scene.add(mesh);
console.log("gltf loaded");
console.log(mesh);
});
//objectURLs.forEach( ( url ) => URL.revokeObjectURL( url ) );
}else if (obj !== undefined && mtl !== undefined){
console.log("there is a obj and mtl");
var mtlLoader = new MTLLoader(manager);
var objLoader = new OBJLoader(manager);
mtlLoader.load( mtl, function (materials) {
materials.preload();
objLoader.setMaterials(materials);
objLoader.load( obj, (model) => {
mesh = model;
scene.add(mesh);
console.log("obj with mtl loaded");
console.log(mesh);
});
});
//objectURLs.forEach( ( url ) => URL.revokeObjectURL( url ) );
}
else if (obj !== undefined && mtl === undefined){
console.log("there is just an obj");
var objLoader = new OBJLoader(manager);
objLoader.load( obj, (model) => {
mesh = model;
scene.add(mesh);
console.log("obj loaded");
console.log(mesh);
});
}
}
if i choose to go with overriding textureloader how can i doo it for the mtlloader?
i imagine something like this:
let texture = new THREE.Texture(
url //URL = a base 64 JPEG string in this case
);