Gltf.scene.traverse get TypeError: Cannot read property 'traverse' of undefined

I got a Cannot read property 'traverse' of undefined error when I try use Object3D.add in loader.

line61 TypeError: Cannot read property ‘traverse’ of undefined
at Object3D.traverse (three.js:8733)
at Object3D.traverse (three.js:8733)
at Object3D.traverse (three.js:8733)
at Object3D.traverse (three.js:8733)
at Object3D.traverse (three.js:8733)
at Scene.traverse (three.js:8733)
at 3d:53
at GLTFLoader.js:77
at GLTFLoader.js:235
at GLTFLoader.js:1726

            gltf.scene.traverse( function ( child ) {
                if ( child.isMesh ) {
                   ///////////////////this line caused error////////////////////////
                    newScene.add(child);
                   ///////////////////////////////////////////////////////////////////////////
                }
		    } );

did anyone have same issue?

2CylinderEngine.glb (1.8 MB)

code:

<!DOCTYPE html>
<html lang="en">
	<head>
		<title>three.js webgl - glTF loader</title>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
	</head>

	<body>
    <script type="text/javascript"  src="{{asset('/assets/threejs/three.js')}}"> </script>
    <script type="text/javascript"  src="{{asset('/assets/threejs/controls/OrbitControls.js')}}"></script>
    <script type="text/javascript"  src="{{asset('/assets/threejs/loaders/GLTFLoader.js')}}"></script>
    <script>

        var container,  controls;
        var camera, scene, renderer, light;

        init();
        animate();

        function init() {

            container = document.createElement( 'div' );
            document.body.appendChild( container );

            camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.001, 20000 );
            camera.position.set( - 1.8, 0.9, 2000 );

            controls = new THREE.OrbitControls( camera );
            controls.target.set( 0, - 0.2, - 0.2 );
            controls.update();

            scene = new THREE.Scene();

            light = new THREE.HemisphereLight( 0xbbbbff, 0x444422 );
            light.position.set( 0, 1, 0 );
            scene.add( light );

            
            renderer = new THREE.WebGLRenderer( { antialias: true } );
            renderer.setPixelRatio( window.devicePixelRatio );
            renderer.setSize( window.innerWidth, window.innerHeight );
            renderer.gammaOutput = true;
            container.appendChild( renderer.domElement );


            var loader = new THREE.GLTFLoader().setPath( '/assets/gltf/' );
            loader.load( '2CylinderEngine.glb', function ( gltf ) {

                var newScene = new THREE.Object3D();
                gltf.scene.traverse( function ( child ) {
                    if ( child.isMesh ) {
                       ///////////////////this line caused error////////////////////////
                        newScene.add(child);
                       ///////////////////////////////////////////////////////////////////////////
                    }
			    } );

                scene.add(newScene);
            }, undefined, function ( e ) {
                console.error( e );
            } );

        }

        //

        function animate() {

            requestAnimationFrame( animate );
            renderer.render( scene, camera );

        }

    </script>
	</body>
</html>

Why not just scene.add( gltf.scene )? The code looks OK but a live demo may help debug.

I try to load glb model and render it mesh by mesh during first rendering.

So I try to use the following code:

gltf.scene.traverse( function ( child ) {
if ( child.isMesh ) {
scene.add(child);
renderer.render( scene, camera );
}
} );

I had figure out why it have error.

maybe because of Adds object as child of this object. An arbitrary number of objects may be added. Any current parent on an object passed in here will be removed, since an object can have at most one parent.

I think the problem is that you’re trying to traverse a tree of objects, while at the same time modifying that tree of objects. Typically there is no need to add a model to the scene one mesh at a time like this – their original hierarchy may be important. If you need to do that, you could mark some of them .visible = false and gradually make them visible. Alternatively, traverse over them first to get an array of meshes, then (after that is done) add everything in the array to the scene.

5 Likes

nice idea! thanks @donmccurdy

1 Like

@donmccurdy @mahaidong

Hi friends,

I am having trouble to make group in gltf elements and i need to drag and drop 3d element.

i have use following code

three.js webgl - draggable cubes
	<style>
		body {
			font-family: Monospace;
			background-color: #f0f0f0;
			margin: 0px;
			overflow: hidden;
		}
	</style>
</head>
<body>

	<script src="three.js"></script>

	<script src="DragControls.js"></script>
	<script src="TrackballControls.js"></script>
	<script src="GLTFLoader.js"></script>
	<script src="stats.min.js"></script>

	<script>

		var stats;
		var camera, controls, scene, renderer;

		var objects = [];

		init();
		animate();

		function init() {

			camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 10 );
			camera.position.z = 2;

			controls = new THREE.TrackballControls( camera );
			controls.rotateSpeed = 1.0;
			controls.zoomSpeed = 1.2;
			controls.panSpeed = 0.8;
			controls.noZoom = false;
			controls.noPan = false;
			controls.staticMoving = true;
			controls.dynamicDampingFactor = 0.3;

			scene = new THREE.Scene();
			scene.background = new THREE.Color( 0xf0f0f0 );

			//

			var ambientLight = new THREE.AmbientLight( 0xcccccc, 0.4 );
			scene.add( ambientLight );

			var pointLight = new THREE.PointLight( 0xffffff, 0.8 );
			camera.add( pointLight );
			scene.add( camera );

			var loader = new THREE.GLTFLoader();
			loader.load( 'W3030/W3030.gltf', ( gltf ) => {
				this.scene.add( gltf.scene );
			  gltf.scene.scale.set(1, 1, 1);
				// gltf.scene.position.set(400,400,400)
				gltf.scene.traverse( function( object ) {
					if ( object.isMesh ) objects.push( object );
					if ( object.isMesh ) objects.castShadow = true;
				} );

			});

			renderer = new THREE.WebGLRenderer( { antialias: true } );
			renderer.setPixelRatio( window.devicePixelRatio );
			renderer.setSize( window.innerWidth, window.innerHeight );
			document.body.appendChild( renderer.domElement );

			var dragControls = new THREE.DragControls( objects, camera, renderer.domElement );
			dragControls.addEventListener( 'dragstart', function ( event ) { controls.enabled = false; } );
			dragControls.addEventListener( 'dragend', function ( event ) { controls.enabled = true; } );


			stats = new Stats();
			document.body.appendChild( stats.dom );

			//

			window.addEventListener( 'resize', onWindowResize, false );

		}

		function onWindowResize() {

			camera.aspect = window.innerWidth / window.innerHeight;
			camera.updateProjectionMatrix();

			renderer.setSize( window.innerWidth, window.innerHeight );

		}

		//

		function animate() {

			requestAnimationFrame( animate );

			render();
			stats.update();

		}

		function render() {

			controls.update();
			renderer.render( scene, camera );

		}

	</script>

</body>
kindly help me

i am also have same issue. cna you help me?

bro can you help me i am also getting this error

this.models[this.active_index].mesh.position.setFromMatrixPosition( _matrix );
_G.MYTHREE.scene.add( this.models[this.active_index].mesh ); <-- CRASHES

Adapted from https://github.com/mrdoob/three.js/blob/25d16a2c3c54befcb3916dbe756e051984c532a8/examples/webxr_ar_hittest.html

Been stuck with this error for a cool 6hrs now : ( Tried damn near everything but every time I add a gltf to scene it throws the error. I tested the exact same code but with collada(dae) animated models and all works fine. Any idea where it’s all going wrong? Thanks.

Could you start a new thread with enough information to reproduce this? The error alone just means something is null or undefined.