4

Suppose someone selects a .zip file (<input type="file">) with the following content:

3d-model.zip
    |- 3d-model.obj
    |- 3d-model.mtl
    |- texture1.jpg
    |- texture2.jpg

Here are some methods I tried

✔️ means that it worked

✖️ means that it didn't work


✔️ #1 Mesh-only

const objBlob = await createBlob(zipfiles['3d-model.obj'])
const objUrl = URL.createObjectURL(objBlob)
const objLoader = new THREE.OBJLoader()
objLoader.load(objUrl, obj => {

    // mesh is displayed correctly
    scence.add(obj)

    const gltfExporter = new GLTFExporter()
    // parsing works fine
    gltfExporter.parse(obj, result => {
        const output = JSON.stringify(result, null, 2)
        const blob = new Blob([output], { type: 'text/plain' }, `3d-model.gltf`)
    })

})

✔️ #2 Mesh with simple material

# 3d-model.mtl file

newmtl material1
Kd 0 1 0

newmtl material2
Kd 1 0 0

const objBlob = await createBlob(zipfiles['3d-model.obj'])
const objUrl = URL.createObjectURL(objBlob)

const mtlBlob = await createBlob(zipfiles['3d-model.mtl'])
const mtlUrl = URL.createObjectURL(mtlBlob)

const mtlLoaer = new THREE.MTLLoader()
mtlLoader.load(mtlUrl, mtl => {
    const objLoader = new THREE.OBJLoader()
    objLoader.setMaterials(mtl)
    objLoader.load(objUrl, obj => {

        // mesh is displayed correctly
        scence.add(obj)

        // parsing works fine
        const gltfExporter = new GLTFExporter()
        gltfExporter.parse(obj, result => {
            const output = JSON.stringify(result, null, 2)
            const blob = new Blob([output], { type: 'text/plain' }, `3d-model.gltf`)
        })

    })
})

✖️ #3 Mesh + material with texture maps

# 3d-model.mtl file

newmtl material1
map_Kd texture1.jpg

newmtl material2
map_Kd texture2.jpg

const objBlob = await createBlob(zipfiles['3d-model.obj'])
const objUrl = URL.createObjectURL(objBlob)

const mtlBlob = await createBlob(zipfiles['3d-model.mtl'])
const mtlUrl = URL.createObjectURL(mtlBlob)

const mtlLoaer = new THREE.MTLLoader()
mtlLoader.load(mtlUrl, mtl => {
    const objLoader = new THREE.OBJLoader()
    objLoader.setMaterials(mtl)
    objLoader.load(objUrl, obj => {

        // error while adding mesh (see screenshot below)
        scence.add(obj)

        // parsing throws error (see screenshot below)
        const gltfExporter = new GLTFExporter()
        gltfExporter.parse(obj, result => {
            const output = JSON.stringify(result, null, 2)
            const blob = new Blob([output], { type: 'text/plain' }, `3d-model.gltf`)
        })

    })
})

I get some errors, which makes total sense (because those textures do not exist at this location)

Error while adding mesh to the scene error while adding mesh to the scene

Error while parsing to GLTF error while parsing to gltf https://github.com/mrdoob/three.js/blob/398c4f39ebdb8b23eefd4a7a5ec49ec0c96c7462/examples/jsm/exporters/GLTFExporter.js#L778


✖️ #4 So, I tried the following

# 3d-model.mtl file

newmtl material1
map_Kd texture1.jpg

newmtl material2
map_Kd texture2.jpg

const objBlob = await createBlob(zipfiles['3d-model.obj'])
const objUrl = URL.createObjectURL(objBlob)

const texture1Blob = await createBlob(zipfiles['texture1.jpg'])
const texture1Url = URL.createObjectURL(texture1Blob)
const texture2Blob = await createBlob(zipfiles['texture2.jpg'])
const texture2Url = URL.createObjectURL(texture2Blob)

const mtlFileContent = `
newmtl material1
map_Kd ${texture1Url}

newmtl material2
map_Kd ${texture2Url}
`
const mtlBlob = new Blob([mtlFileContent])
const mtlUrl = URL.createObjectURL(mtlBlob)

const mtlLoaer = new THREE.MTLLoader()
mtlLoader.load(mtlUrl, mtl => {
    const objLoader = new THREE.OBJLoader()
    objLoader.setMaterials(mtl)
    objLoader.load(objUrl, obj => {

        // adding the object to the scence works fine (with materials and textures)
        scence.add(obj)

        // but parsing throws error (see screenshot below)
        const gltfExporter = new GLTFExporter()
        gltfExporter.parse(obj, result => {
            const output = JSON.stringify(result, null, 2)
            const blob = new Blob([output], { type: 'text/plain' }, `3d-model.gltf`)
        })
    })
})

With this method, the object is added to the Three.js scene with materials and textures. Awesome! But the GLTFExporter still isn't happy:

Error while parsing to GLTF error while parsing to gltf https://github.com/mrdoob/three.js/blob/398c4f39ebdb8b23eefd4a7a5ec49ec0c96c7462/examples/jsm/exporters/GLTFExporter.js#L778

It seems like the GLTFExporter cant fetch blob URLs?!


Do I need to rewrite the GLTFExporter to support "blob URLs" or is there another way to load the textures from a zip file?

gman
  • 100,619
  • 31
  • 269
  • 393
Florian Ludewig
  • 4,338
  • 11
  • 71
  • 137

0 Answers0