Importing 3D models from Blender

Hello everyone!
I’ve started using three.js yesterday.
I’m following some tutorials I found online, but I encountered some problems when I tried to import a file I made in Blender.

Basically most of the tutorials require you to import a json file. Blender doesn’t export in this format. All the tutorials require you to install an addon in Blender, found on GitHub that allows exporting in this format. The problem is that this addon doesn’t exists anymore, and for this reason I got stuck.
I tried to import an obj model, but all I get is the model imported in wireframe. Every time I try to assign a texture or a diffuse color it’s either rendered in wireframe or not rendered at all.

Do you know a tutorial that explains how to import obj’s properly or alternatively how to convert blend, alembic or obj files into json?

Second question regards the textures.
If I export a model {in obj or json} does it retain the UV mapping? I managed to import an OBJ model but all I can see is the wireframe version. Even if I try to assign just a color the model remains in wireframe.

I tried to search everywhere but haven’t found anything on the subject.
I managed to create primitives etc, but not properly import objects or multiple objects and scenes.

Thank you VERY MUCH for your help!
I’m so excited to learn how to use three.js properly!

Please read: https://threejs.org/docs/index.html#manual/en/introduction/Loading-3D-models

Many tutorials refer to the obsolete JSON Blender exporter which is not maintained anymore. It was removed from the project several releases ago. The recommended 3D format is glTF. Please also avoid the usage of OBJ since glTF is the far better option.

And yes, when you export a model to glTF, texture coordinates will be respected.

Hello Mugen87!

Thank you!
I managed to import a 3D model I did in Blender in glTF.

The problem I’m experiencing now is related to the textures. Basically the texture is rotated somehow.

What I did was creating a material THREE.MeshPhongMaterial() and specify map and normalMap.
They actually appear on my model, but it’s like the map was rotated 90’ on one of it’s axes.

The model was UV unwrapped. I tried in Blender to rotate the map on the model and it seems it’s actually rotated 90’ on one of it’s axes.

Do you know if this is a common problem?
Also do you know how to sort it out in case (for example rotating somehow the projection).

Can you please try to set flipY to false on your both textures? Check out the Textures section of GLTFLoaders doc page to understand why this is necessary.

1 Like

I sorted out inverting the actual jpg map :joy:

Now I am proceeding and I have the problems that the model doesn’t project shadows on other objects.
I am using a point light… I tried to activate project shadows, etc. but nothing. For some reason shadows don’t appear.

I also activated the shadows on the models {cast and receive shadows set on true}.

I’m about to watch a tutorial (https://www.youtube.com/watch?v=vB5lSSJRJR0) I hope it will help!

I’ll take a look at the flipY option for my next works. I’m enjoying three.js a lot and I’d like to start developing properly with it!

Thank you so much for your help

There can be many reasons for this. Do you mind sharing your code that shows your lighting and shadow setup?

Sure!
This is the code…

<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<title>THREE.JS MODELS</title>
	<meta name="description" content="Three.Js">
	
	<link rel="stylesheet" href="style.css">
	
	<script src="js/three.js"></script>
	<script src="js/OrbitControls.js"></script>
	<script src="js/GLTFLoader.js"></script>
	
</head>

<body>

	<canvas id="myCanvas"></canvas>

	<script>

		//CREATION OF THE RENDERER
		var renderer = new THREE.WebGLRenderer({canvas: document.getElementById('myCanvas'), antialias: true});
		renderer.setClearColor(0x808080);
		renderer.setPixelRatio(window.devicePixelRatio);
		renderer.setSize(window.innerWidth, window.innerHeight);


		//CREATION OF THE CAMERA
		var camera = new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 0.1, 3000);
		camera.position.set(0, 0, 20);


		var controls = new THREE.OrbitControls( camera );
		//controls.update() must be called after any manual changes to the camera's transform
		controls.update();


		//CREATION OF THE SCENE
		var scene =  new THREE.Scene();


		//ADDING LIGHTS TO THE SCENE
		//Ambient Light
		var light1 = new THREE.AmbientLight(0xFFFFFF, 0.5);
		scene.add(light1);


		//PointLight
		var posizioneLuce = [10, 10, 10];
		
		var light2 = new THREE.PointLight(0xFFFFFF, 0.5, 600);
		light2.castShadow = true;			
		light2.position.set (posizioneLuce[0], posizioneLuce[1], posizioneLuce[2]);
		scene.add(light2);

		light2.shadow.mapSize.width = 512;
		light2.shadow.mapSize.height = 512;
		light2.shadow.camera.near = 0.5;
		light2.shadow.camera.far = 500;
		
		//For the sake of ■■■■ this is just a visualiser
		vedilo = new THREE.SphereBufferGeometry(1, 32, 32);
		var vediMat = new THREE.MeshBasicMaterial({
			color: 0x000000,
			//AGGIUNGERE IL MODO WIREFRAME
		});
		var visto = new THREE.Mesh(vedilo, vediMat);
		visto.position.set (posizioneLuce[0], posizioneLuce[1], posizioneLuce[2]);
		scene.add(visto);


		//CREATION OF MATERIAL
		//Shoe material
		var material = new THREE.MeshPhongMaterial({
			map: new THREE.TextureLoader().load('textures/diffuse.jpg'),
			normalMap: new THREE.TextureLoader().load('textures/normals.jpg'),
		});

		//Floor material
		var material1 = new THREE.MeshLambertMaterial({
		color: 0xAFEEEE,
		side: THREE.DoubleSide
		});


		//OBJECTS
		//Load the shoe model
		var loader = new THREE.GLTFLoader();
		loader.load('models/meshia.glb', handle_load);

		var mesh;

		function handle_load(gltf){
			mesh = gltf.scene.children[0];
			mesh.material = material;
			mesh.material.shading = THREE.SmoothShading;
			//mesh.castShadow = true;
			//mesh.receiveShadow = false;
			scene.add(mesh);
		}

		//Creation of the circular floor
		circle = new THREE.CircleBufferGeometry(10, 50);
		var cerchio = new THREE.Mesh(circle, material1);
		cerchio.rotation.x = -1.5708;
		cerchio.position.y = -2;
		//cerchio.castShadow = false;
		//cerchio.receiveShadow = true;
		scene.add(cerchio);


		//EVERY FRAME UPDATE
		render();

		var delta = 0;
		var prevTime = Date.now();

		function render(){
			delta += 0.1;
			if(mesh){
				mesh.rotation.y += 0.001;
			}

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


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

		function onWindowResize(){
			camera.aspect = window.innerWidth / window.innerHeight;
			camera.updateProjectionMatrix();
			renderer.setSize( window.innerWidth, window.innerHeight );
		}
	</script>
	
</body>

Updated fiddle (with parts of your code): https://jsfiddle.net/k20yjax3/1/

You missed to enabled shadow maps like so:

renderer.shadowMap.enabled = true;
1 Like

Oh Thank you!

I’m really new to this so I’m expecting plenty of similar mistakes in the future from myself.

:slight_smile:

I have had this issue a few times when importing OBJ models, for me this usually lies with the normals or double faces. In Blender go to Edit Mode -> Mesh -> Normals -> Recalculate Outside and/or Edit Mode -> Mesh -> Clean Up -> Remove Doubles. It can also be a problem with the .mtl file - sometimes it’s worth deleting it before exporting again. Hope this helps!

Hello!
Thank you very much for this.
It actually helps a lot.

I don’t know why Blender exported the file in that way. I checked the normals and all of them point outside.

For now, as I am just testing, I simply inverted the map using Photoshop, but for the future I’ll have to learn ho to do it via code as it may be quicker and less “distructive” for the map itself.