Blender object with multiple (two) materials exported as gltf generates "children[i] is undefined" error when traversing scene

I have a model/object for camping trailer badge I’m exporting via gltf from Blender. The object has two PBR materials. When I try to traverse the scene(which is necessary to later apply a baked texture map), I get the error “Uncaught (in promise) TypeError: children[i] is undefined”. If I remove the two PBR materials in Blender before exporting, everything works fine. Why is this the case?

import * as THREE from "three"
import {GLTFLoader} from "three/examples/jsm/loaders/GLTFLoader.js"
import {RGBELoader} from "three/examples/jsm/loaders/RGBELoader.js"
import {OrbitControls} from "three/examples/jsm/controls/OrbitControls.js"

(async () => {
    const gScene = new THREE.Scene()
    const canvas = document.querySelector("#c")
    const gCamera = new THREE.PerspectiveCamera(50, canvas.clientWidth/canvas.clientHeight, 0.1, 1000)
    const gltfLoader = new GLTFLoader()
    const gRenderer = new THREE.WebGLRenderer({canvas})
    gRenderer.setPixelRatio( window.devicePixelRatio );
    gRenderer.setSize( window.innerWidth, window.innerHeight );
    gRenderer.toneMapping = THREE.ACESFilmicToneMapping;
    gRenderer.toneMappingExposure = 1;
    gRenderer.outputEncoding = THREE.sRGBEncoding;

    gCamera.position.x = .3
    gCamera.position.z = .3
    const controls = new OrbitControls(gCamera, canvas)
    controls.target.set(0,0,0)
    controls.update()
    const pmremGenerator = new THREE.PMREMGenerator( gRenderer );
    pmremGenerator.compileEquirectangularShader();
    const rgbeLoader = new RGBELoader()

    rgbeLoader
    .setDataType(THREE.UnsignedByteType)
    .load("./cubemap.hdr",
    (tex)=> {
        const envMap = pmremGenerator.fromEquirectangular(tex).texture
        gScene.background = envMap
        gScene.environment = envMap
    } )

    gltfLoader.load('./scene.glb', (glb) => {    
            glb.scene.traverse((child) => {      
                    gScene.add(child)
            })

    })

    window.addEventListener('resize', onWindowResize)
    function onWindowResize(){
        gCamera.aspect = window.innerWidth / window.innerHeight
        gCamera.updateProjectionMatrix()
        gRenderer.setSize(window.innerWidth, window.innerHeight)
    }

    function render(){
        gRenderer.render(gScene,gCamera)
        requestAnimationFrame(render)
    }
    requestAnimationFrame(render)

})()

scene.glb: scene.glb - Google Drive
cubemap.hdr: cubemap.hdr - Google Drive
CaravelBadge.blend: CaravelBadge.blend - Google Drive

the GLTF provided is broken.
It work after a clean export from the blender file

After the model is loaded, this is the code I’m using to dodge THREE.group (multi-material generate group) and target only mesh to avoid some traverse undefined errors.

//traverse to find any mesh
gltf.scene.traverse( function ( child ) {
	if (child.isMesh) {
	//some mesh operation here....
	}
});

//since we use group, we need whole GLTF scene instead of individual children
scene.add(gltf.scene);

working file: scene.glb (413.3 KB)

2 Likes

Thanks a bunch for the help, it solved my problem! It seems like adding the whole scene with scene.add(gltf.scene) instead of doing gScene.add(child) for each individual child did the trick . It seems weird that the latter approach doesn’t work, even if I check if(child.isMesh) beforehand.