THREE.FBXLoader: Won't load 2 models

I am learning to bring in models. Since the Blender plugin has been deprecated, I figured I would learn to use the FBX format instead.

However, I output a box.fbx. Then I output a sphere.fbx. Only one will load at a time. If I comment out the box, the sphere loads. Otherwise, even if the sphere is not commented out, the box will load.

I’m sure it is something I’ve done wrong but at least I’m trying! Could it be that I’m using Fenix to test? Would that matter at all? Here is the code:

three.js webgl - FBX loader
	<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
	<style>
		body {
			font-family: Monospace;
			background-color: #000;
			color: #fff;
			margin: 0px;
			overflow: hidden;
		}
		#info {
			color: #fff;
			position: absolute;
			top: 10px;
			width: 100%;
			text-align: center;
			z-index: 100;
			display:block;
		}
		#info a {
			color: #046;
			font-weight: bold;
		}
	</style>
</head>

<body>
	<div id="info">
		<a href="http://threejs.org/" target="_blank" rel="noopener">three.js</a> - FBXLoader<br>
		Character and animation from <a href="https://www.mixamo.com/" target="_blank" rel="noopener">Mixamo</a>
	</div>

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

	<script src="./index_files/inflate.min.js.download"></script>
	<script src="./index_files/FBXLoader.js.download"></script>

	<script src="./index_files/OrbitControls.js.download"></script>

	<script src="./index_files/Detector.js.download"></script>
	<script src="./index_files/stats.min.js.download"></script>

	<script>

		if ( ! Detector.webgl ) Detector.addGetWebGLMessage();

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

		var clock = new THREE.Clock();

		var mixers = [];

		init();
		animate();

		function init() {

			renderer = new THREE.WebGLRenderer( { antialias: true } );
			renderer.setPixelRatio( window.devicePixelRatio );
			renderer.setSize( window.innerWidth, window.innerHeight );
			renderer.shadowMap.enabled = true;


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

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

			camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
			camera.position.set( 100, 200, 300 );

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

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


			light = new THREE.HemisphereLight( 0xffffff, 0x444444 );
			light.position.set( 0, 200, 0 );
			scene.add( light );

			light = new THREE.DirectionalLight( 0xffffff );
			light.position.set( 0, 200, 100 );
			light.castShadow = true;
			light.shadow.camera.top = 180;
			light.shadow.camera.bottom = -100;
			light.shadow.camera.left = -120;
			light.shadow.camera.right = 120;
			scene.add( light );

			// scene.add( new THREE.CameraHelper( light.shadow.camera ) );

			// ground


			var burners = new THREE.FBXLoader();
			burners.load( '/fbx/box.fbx', function ( object ) {
				object.traverse( function ( child ) {
					if( child.material ) {
						child.material = new THREE.MeshBasicMaterial ( {
							color: 0x151515,
							wireframe: true

						} );
					}
				} )
				object.position.set( 0, 0, 0);
				scene.add ( object );
			} );

			// model
			var range = new THREE.FBXLoader();
			range.load( '/fbx/sphere.fbx', function ( object2 ) {
				object2.traverse( function ( child2 ) {
					if( child2.material ) {
						child2.material = new THREE.MeshBasicMaterial ( {
							color: 0xffffff,
							wireframe: true,
						} );
					}
				} )
				object2.position.set( 0, 0, 0);
				scene.add ( object2 );
			} );

			//burners

container.appendChild( renderer.domElement );


			// stats
			stats = new Stats();
			container.appendChild( stats.dom );

		}

		function onWindowResize() {

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

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

		}

		//

		function animate() {

			requestAnimationFrame( animate );

			if ( mixers.length > 0 ) {

				for ( var i = 0; i < mixers.length; i ++ ) {

					mixers[ i ].update( clock.getDelta() );

				}

			}

			renderer.render( scene, camera );

			stats.update();

		}

	</script><div><canvas width="1920" height="898" style="width: 1920px; height: 898px;"></canvas><div style="position: fixed; top: 0px; left: 0px; cursor: pointer; opacity: 0.9; z-index: 10000;"><canvas width="80" height="48" style="width: 80px; height: 48px; display: block;"></canvas><canvas width="80" height="48" style="width: 80px; height: 48px; display: none;"></canvas><canvas width="80" height="48" style="width: 80px; height: 48px; display: none;"></canvas></div></div><div><canvas width="928" height="898" style="width: 928px; height: 898px;"></canvas><div style="position: fixed; top: 0px; left: 0px; cursor: pointer; opacity: 0.9; z-index: 10000;"><canvas width="80" height="48" style="width: 80px; height: 48px; display: block;"></canvas><canvas width="80" height="48" style="width: 80px; height: 48px; display: none;"></canvas><canvas width="80" height="48" style="width: 80px; height: 48px; display: none;"></canvas></div></div>

This should already be fixed in the latest dev version of FBXLoader. See the respective PR:

1 Like

Hi, so what do I need to do then? What do I need to download?

Try it with this version of FBXLoader. It’s the latest dev version.

https://raw.githubusercontent.com/mrdoob/three.js/dev/examples/js/loaders/FBXLoader.js

OK thanks!

So either it is not fixed or something is wrong with my code. Nothing changed for me.

Looking at your code, I’ve noticed that you create an instance of FBXLoader for each model. Try to create a single loader and reuse it for all requests instead. The pattern looks like this:

var loader = new THREE.FBXLoader();

loader.load( '/fbx/box.fbx', function ( object ) {
    //...
} );

loader.load( '/fbx/sphere.fbx', function ( object2 ) {
    //...
} );

Besides, try to position your models not at the same place. Otherwise they might cover each other.

It still doesn’t work

three.js webgl - FBX loader
	<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
	<style>
		body {
			font-family: Monospace;
			background-color: #000;
			color: #fff;
			margin: 0px;
			overflow: hidden;
		}
		#info {
			color: #fff;
			position: absolute;
			top: 10px;
			width: 100%;
			text-align: center;
			z-index: 100;
			display:block;
		}
		#info a {
			color: #046;
			font-weight: bold;
		}
	</style>
</head>

<body>
	<div id="info">
		<a href="http://threejs.org/" target="_blank" rel="noopener">three.js</a> - FBXLoader<br>
		Character and animation from <a href="https://www.mixamo.com/" target="_blank" rel="noopener">Mixamo</a>
	</div>

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

	<script src="./index_files/inflate.min.js.download"></script>
	<script src="./index_files/FBXLoader.js.download"></script>

	<script src="./index_files/OrbitControls.js.download"></script>

	<script src="./index_files/Detector.js.download"></script>
	<script src="./index_files/stats.min.js.download"></script>

	<script>

		if ( ! Detector.webgl ) Detector.addGetWebGLMessage();

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

		var clock = new THREE.Clock();

		var mixers = [];

		init();
		animate();

		function init() {

			renderer = new THREE.WebGLRenderer( { antialias: true } );
			renderer.setPixelRatio( window.devicePixelRatio );
			renderer.setSize( window.innerWidth, window.innerHeight );
			renderer.shadowMap.enabled = true;


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

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

			camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
			camera.position.set( 100, 200, 300 );

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

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


			light = new THREE.HemisphereLight( 0xffffff, 0x444444 );
			light.position.set( 0, 200, 0 );
			scene.add( light );

			light = new THREE.DirectionalLight( 0xffffff );
			light.position.set( 0, 200, 100 );
			light.castShadow = true;
			light.shadow.camera.top = 180;
			light.shadow.camera.bottom = -100;
			light.shadow.camera.left = -120;
			light.shadow.camera.right = 120;
			scene.add( light );

			scene.add( new THREE.CameraHelper( light.shadow.camera ) );

			// ground


			var loader = new THREE.FBXLoader();
			loader.load( '/fbx/box.fbx', function ( object ) {
				object.traverse( function ( child ) {
					if( child.material ) {
						child.material = new THREE.MeshBasicMaterial ( {
							color: 0x151515,
							wireframe: true

						} );
					}
				} )
				object.position.set( 0, 0, 0);
				scene.add ( object );
			} );

//burners

			loader.load( '/fbx/sphere.fbx', function ( object2 ) {
				object2.traverse( function ( child2 ) {
					if( child2.material ) {
						child2.material = new THREE.MeshBasicMaterial ( {
							color: 0x151515,
							wireframe: true

						} );
					}
				} )
				object.position.set( 0, 0, 20);
				scene.add ( object2 );
			} );


container.appendChild( renderer.domElement );


			// stats
			stats = new Stats();
			container.appendChild( stats.dom );

		}

		function onWindowResize() {

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

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

		}

		//

		function animate() {

			requestAnimationFrame( animate );

			if ( mixers.length > 0 ) {

				for ( var i = 0; i < mixers.length; i ++ ) {

					mixers[ i ].update( clock.getDelta() );

				}

			}

			renderer.render( scene, camera );

			stats.update();

		}

	</script><div><canvas width="1920" height="898" style="width: 1920px; height: 898px;"></canvas><div style="position: fixed; top: 0px; left: 0px; cursor: pointer; opacity: 0.9; z-index: 10000;"><canvas width="80" height="48" style="width: 80px; height: 48px; display: block;"></canvas><canvas width="80" height="48" style="width: 80px; height: 48px; display: none;"></canvas><canvas width="80" height="48" style="width: 80px; height: 48px; display: none;"></canvas></div></div><div><canvas width="928" height="898" style="width: 928px; height: 898px;"></canvas><div style="position: fixed; top: 0px; left: 0px; cursor: pointer; opacity: 0.9; z-index: 10000;"><canvas width="80" height="48" style="width: 80px; height: 48px; display: block;"></canvas><canvas width="80" height="48" style="width: 80px; height: 48px; display: none;"></canvas><canvas width="80" height="48" style="width: 80px; height: 48px; display: none;"></canvas></div></div>

Can you please share box.fbx and sphere.fbx in this thread?

yes!

I have revised the code a little bit. I have exported 2 different versions of the box and sphere fbx. What I find really interesting is that when both code is active, it takes whatever object had been exported the latest first, which I find weird that it would search the file for a timestamp and use that as a guide on which should take precedent (which it shouldn’t do at all really)

box.fbx (10.9 KB)

sphere.fbx (26.0 KB)

three.js webgl - FBX loader
	<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
	<style>
		body {
			font-family: Monospace;
			background-color: #000;
			color: #fff;
			margin: 0px;
			overflow: hidden;
		}
		#info {
			color: #fff;
			position: absolute;
			top: 10px;
			width: 100%;
			text-align: center;
			z-index: 100;
			display:block;
		}
		#info a {
			color: #046;
			font-weight: bold;
		}
	</style>
</head>

<body>
	<div id="info">
		<a href="http://threejs.org/" target="_blank" rel="noopener">three.js</a> - FBXLoader<br>
		Character and animation from <a href="https://www.mixamo.com/" target="_blank" rel="noopener">Mixamo</a>
	</div>

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

	<script src="./index_files/inflate.min.js.download"></script>
	<script src="./index_files/FBXLoader.js.download"></script>

	<script src="./index_files/OrbitControls.js.download"></script>

	<script src="./index_files/Detector.js.download"></script>
	<script src="./index_files/stats.min.js.download"></script>

	<script>

		if ( ! Detector.webgl ) Detector.addGetWebGLMessage();

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

		var clock = new THREE.Clock();

		var mixers = [];

		init();
		animate();

		function init() {

			renderer = new THREE.WebGLRenderer( { antialias: true } );
			renderer.setPixelRatio( window.devicePixelRatio );
			renderer.setSize( window.innerWidth, window.innerHeight );
			renderer.shadowMap.enabled = true;


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

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

			camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
			camera.position.set( 100, 200, 300 );

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

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


			light = new THREE.HemisphereLight( 0xffffff, 0x444444 );
			light.position.set( 0, 200, 0 );
			scene.add( light );

			light = new THREE.DirectionalLight( 0xffffff );
			light.position.set( 0, 200, 100 );
			light.castShadow = true;
			light.shadow.camera.top = 180;
			light.shadow.camera.bottom = -100;
			light.shadow.camera.left = -120;
			light.shadow.camera.right = 120;
			scene.add( light );

			scene.add( new THREE.CameraHelper( light.shadow.camera ) );

			// ground


			var loader = new THREE.FBXLoader();
			loader.load( '/fbx/box2.fbx', function ( object ) {
				object.traverse( function ( child ) {
					if( child.material ) {
						child.material = new THREE.MeshBasicMaterial ( {
							color: 0x151515,
							wireframe: true

						} );
					}
				} )
				object.position.set( 0, 0, 0);
				scene.add ( object );
			} );

//burners

			loader.load( '/fbx/sphere2.fbx', function ( object2 ) {
				object2.traverse( function ( child2 ) {
					if( child2.material ) {
						child2.material = new THREE.MeshBasicMaterial ( {
							color: 0x151515,
							wireframe: true

						} );
					}
				} )
				object2.position.set( 100, 0, 0);
				scene.add ( object2 );
			} );


container.appendChild( renderer.domElement );


			// stats
			stats = new Stats();
			container.appendChild( stats.dom );

		}

		function onWindowResize() {

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

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

		}

		//

		function animate() {

			requestAnimationFrame( animate );

			if ( mixers.length > 0 ) {

				for ( var i = 0; i < mixers.length; i ++ ) {

					mixers[ i ].update( clock.getDelta() );

				}

			}

			renderer.render( scene, camera );

			stats.update();

		}

	</script><div><canvas width="1920" height="898" style="width: 1920px; height: 898px;"></canvas><div style="position: fixed; top: 0px; left: 0px; cursor: pointer; opacity: 0.9; z-index: 10000;"><canvas width="80" height="48" style="width: 80px; height: 48px; display: block;"></canvas><canvas width="80" height="48" style="width: 80px; height: 48px; display: none;"></canvas><canvas width="80" height="48" style="width: 80px; height: 48px; display: none;"></canvas></div></div><div><canvas width="928" height="898" style="width: 928px; height: 898px;"></canvas><div style="position: fixed; top: 0px; left: 0px; cursor: pointer; opacity: 0.9; z-index: 10000;"><canvas width="80" height="48" style="width: 80px; height: 48px; display: block;"></canvas><canvas width="80" height="48" style="width: 80px; height: 48px; display: none;"></canvas><canvas width="80" height="48" style="width: 80px; height: 48px; display: none;"></canvas></div></div>

box2.fbx (10.8 KB)
sphere2.fbx (24.6 KB)

I don’t know why but your sphere has a scaling of (100,100,100). If I set the default values for scaling, both meshes show up nicely.

https://jsfiddle.net/f2Lommf5/12181/

Since these weird scale values are set in the FBX, there might be a problem in your export workflow. The following screenshot shows the scaling parsed from the FBX file:

image

1 Like

hmmm…how are you able to see the information you are parsing in that screenshot? That would be helpful in my diagnosing things :slight_smile:

I’m using the debugger of Chrome Developer Tools:

1 Like

Set a breakpoint at that specific line?

Yes. In this way you can inspect the current data of modelNode.

Thanks so much for answering my dumb questions. So this is what I get though.

image

“modelNode is not defined”

Can you please share the FBX in this thread?

It loads fine. I just probably don’t know what I’m doing when setting a breakpoint.

Edit: I also solved the size issue. All models are loading as expected.
Edit 2: For visibility, when exporting out of Blender, one must select the “FBX All” under scaling.

1 Like