3D Model Not Rotating around its center

camera-controls
orbit-controls

#1

Hi, I am rendering a 3D model using MTL/OBJ Loader. Model render correctly but when i am dragging mouse from left to right or visa versa, model is not rotating accordingly. It is basically flipping around y axis or x axis. As i have seen multiple examples related to MTL/OBJ loader where same is happening but in my case it is not. Please Help.

Video Url:

Also On loading, Model orientation is not correct. Please Find attached screenshots for current & expected orientation. One more thing can we make this orientation generic so that whatever model i render, its orientation remains same?

Default/Current Orientation:

Expected Orientation:

Code snippet is attached.

	// All of these variables will be needed later, just ignore them for now.
	var container;
	var camera, controls, scene, renderer;
	var lighting, ambient, directionalLight;
	var windowHalfX = window.innerWidth / 2;
	var windowHalfY = window.innerHeight / 2;
	var raycaster;
	var mouse;		
	var objects = [];
	var cnt = 0;
	
	init();
	animate();

	function init() {
		container = document.getElementById("container");
		
		//SCENE
		scene = new THREE.Scene();	
		
		//CAMERA
		camera = new THREE.PerspectiveCamera(65, window.innerWidth / window.innerHeight, .1, 5000);
		camera.position.x = -200;
		camera.position.y = -1000;
		camera.position.z = 1200;
		
		// Add the camera to the scene:
		scene.add(camera);
	
		//LIGHTING
		ambient = new THREE.AmbientLight(0x404040, 1.0);
		scene.add(ambient);
		
		directionalLight = new THREE.DirectionalLight( new THREE.Color('hsl(0, 0%, 75%)'), 1 );
		directionalLight.position.set( 0, 0, 1 );
		scene.add( directionalLight );

		//3D Object Loading
		var mtlLoader = new THREE.MTLLoader();
		mtlLoader.setBaseUrl('http://localhost:81/3dtest/assets/');
		mtlLoader.setPath('http://localhost:81/3dtest/assets/');
		mtlLoader.load('MSRDC_JUNE_16_P4PRO_ARIVALI_M2_simplified_3d_mesh.mtl', function (materials) {

			materials.preload();

			materials.materials.texture.map.magFilter = THREE.NearestFilter;
			materials.materials.texture.map.minFilter = THREE.LinearFilter;

			var objLoader = new THREE.OBJLoader();
			objLoader.setMaterials(materials);
			objLoader.setPath('http://localhost:81/3dtest/assets/');						
			objLoader.load('MSRDC_JUNE_16_P4PRO_ARIVALI_M2_simplified_3d_mesh.obj', function (object) {
					object.traverse( function ( child ) {
							if ( child instanceof THREE.Mesh ) {
								//The child is the bit needed for the raycaster.intersectObject() method
								objects.push( child );
							}
						});

						scene.add(object);
						console.log('Object::',object);
			});

		});		
		
		raycaster = new THREE.Raycaster();
		mouse = new THREE.Vector2();			
			
		//RENDERER
		renderer = new THREE.WebGLRenderer({ antialias: true });
		renderer.setPixelRatio(window.devicePixelRatio);
		renderer.setSize(window.innerWidth, window.innerHeight);
		renderer.setClearColor(new THREE.Color("hsl(0, 0%, 10%)"));

		container.appendChild(renderer.domElement);		
		
		//CONTROLS
		controls = new THREE.OrbitControls(camera, renderer.domElement);
		controls.enableDamping = true;
		controls.dampingFactor = 0.25;
		controls.enableZoom = true;


		//EVENTS
		window.addEventListener('resize', onWindowResize, false);
		document.addEventListener( 'dblclick', onDocumentMouseDown, false );

		
	}

	function onDocumentMouseDown( event ) 
	{
		console.log("Click.");
		cnt += 1;
		event.preventDefault();

		mouse.x = ( event.clientX / renderer.domElement.clientWidth ) * 2 - 1;
		mouse.y = - ( event.clientY / renderer.domElement.clientHeight ) * 2 + 1;

		raycaster.setFromCamera( mouse, camera );

		var intersects = raycaster.intersectObjects( objects );
			
		var current,selected;

		for(var i=0,l=intersects.length;i<l;i++) {

			current=intersects[i].point;
			if(selected instanceof THREE.Vector3){
			
				if(selected.distanceTo(camera.position)>current.distanceTo(camera.position)){
					selected=current;	
				}
			}else{
				selected=current;
			}
					
		}

		if(selected instanceof THREE.Vector3){
			makeTextSprite(cnt.toString(),selected);
		}
		
	}
	
	function toString(v) { return "[ " + v.x + ", " + v.y +", " + v.z + " ]"; }

	function makeTextSprite(annoid,pos)
	{										
		// Sprite			
		var numberTexture = new THREE.TextureLoader().load('location.png');			
		numberTexture.minFilter = THREE.LinearFilter;
		numberTexture.magFilter = THREE.LinearFilter;
		numberTexture.needsUpdate = true;
		
		var spriteMaterial = new THREE.SpriteMaterial({
			map: numberTexture,
			alphaTest: 0.5,
			transparent: true,
			depthTest: false,
			depthWrite: false
		});

		sprite = new THREE.Sprite(spriteMaterial);
		sprite.position.copy( pos );
		sprite.scale.x = sprite.scale.y = 32;

		scene.add(sprite);
	}
	
	function onWindowResize() {

        windowHalfX = window.innerWidth / 2;
        windowHalfY = window.innerHeight / 2;

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

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

    }

	function animate() 
	{

		requestAnimationFrame( animate );
		controls.update(); // required if controls.enableDamping = true, or if controls.autoRotate = true
		render();
	}

	function render() {
		// Set the camera to always point to the centre of our scene, i.e. at vector 0, 0, 0
		camera.lookAt( scene.position );
		renderer.render( scene, camera );
	}

Thanks in Advance.

Avinash


#2

Regarding rotation: OrbitControls rotates the camera, not the object. So, the behavior depends on the location of the camera.

Regarding the default orientation: Couldn’t you adjust that by changing the initial camera position?


#3

Hi Bill,

I am totally new to ThreeJS and i have just started learning it. So honestly say, I really don’t know how to use orbit controls to rotate the camera. I tried no. of angles and axis coordinates but couldn’t get success.If you have any example for reference then it would be a great help.Actually i am trying to create functionality like Sketchfab where any model you do load, it loads in same orientation and also if we rotate it then it rotate smoothly around its center.

Please Help.


#4

You can use this to set the control’s target to the center of the object.
You’ll have to call it inside the objLoader.load function, i.e. after the object has loaded.

var boundingBox = new THREE.Box3();

boundingBox.setFromObject( object );
var center = boundingBox.getCenter();

 // set camera to rotate around center of object
controls.target = center;


#5

Hi Looeee,

Thanks for your help. But the code is not working. My problem is still same. I wanted to rotate my model in a horizontal circular path so that it could rotate at 180 degree across X axis smoothly.


#6

Hi Avinash,
Are you trying to restrict the movement of the camera so that it stays on the same plane? If so, you might try something like this:

controls.minPolarAngle = controls.maxPolarAngle = 60*(Math.PI/180);

(You can change the angle from 60 to something else as needed.)

-Bill


#7

Hi Bill,

I tried yours as well but no gain. Do i need to put your logic with looeee’s logic or i need to use this where i am declaring orbit controls.

Please visit the below url for my expectation.

Actually i want my model to be rotate in any direction as it is happening in the example i have shared.

Thanks
Avinash


#8

It is not clear to me – what is the problem you are facing? I implemented your code locally and it basically works in the same way as the sketchfab embed. Could you please explain the problem in more detail?


#9

Hi Bill,

Please see the attached video Url for my problem. This video has voice as well. I have explained my problem in this video. I hope after seeing this you could actually understand my issue.

Current Code Snippet:

	var container;
	var camera, controls, scene, renderer;
	var lighting, ambient, directionalLight;
	var windowHalfX = window.innerWidth / 2;
	var windowHalfY = window.innerHeight / 2;
	var raycaster;
	var mouse;		
	var objects = [];		
	var curIntersect;
	
	init();
	animate();						

	function init() {
	
		container = document.getElementById("container");
		
		//SCENE
		scene = new THREE.Scene();	
		
		//CAMERA
		camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, .1, 7000);
		camera.position.x = -5;
		camera.position.y = -1500;
		camera.position.z = 100;
		
		// Add the camera to the scene:
		scene.add(camera);
	
		//LIGHTING
		ambient = new THREE.AmbientLight(0x404040, 1.0);
		scene.add(ambient);
		
		directionalLight = new THREE.DirectionalLight( new THREE.Color('hsl(0, 0%, 75%)'), 1 );
		directionalLight.position.set( 0, 0, 1 );
		scene.add( directionalLight );

        var onProgress = function (xhr) {
			if (xhr.lengthComputable) {
				$("#container").LoadingOverlay("show");
				var percentComplete = xhr.loaded / xhr.total * 100;
				console.log(Math.round(percentComplete, 2) + '% downloaded');
				if (Math.round(percentComplete, 2) == 100){
					console.log('Object Loaded');
					$("#container").LoadingOverlay("hide", true);						
				}
			}
		};

		var onError = function (xhr) { };			
		
		//3D Object Loading
		var mtlLoader = new THREE.MTLLoader();			
		mtlLoader.setPath('http://localhost:81/threed/assets/');
		mtlLoader.load('MSRDC_JUNE_16_P4PRO_ARIVALI_M2_simplified_3d_mesh.mtl', function (materials) {

			materials.preload();

			materials.materials.texture.map.magFilter = THREE.NearestFilter;
			materials.materials.texture.map.minFilter = THREE.LinearFilter;

			var objLoader = new THREE.OBJLoader();
			objLoader.setMaterials(materials);
			objLoader.setPath('http://localhost:81/threed/assets/');						
			objLoader.load('MSRDC_JUNE_16_P4PRO_ARIVALI_M2_simplified_3d_mesh.obj', function (object) {
				
				object.traverse( function ( child ) {
						if ( child instanceof THREE.Mesh ) {
							objects.push( child );
						}
					});

					scene.add(object);
					console.log('Object::',object);
			}, onProgress, onError);
		});		
		
		raycaster = new THREE.Raycaster();
		mouse = new THREE.Vector2();			
		
		//RENDERER
		renderer = new THREE.WebGLRenderer({ antialias: true });
		renderer.setPixelRatio(window.devicePixelRatio);
		renderer.setSize(window.innerWidth, window.innerHeight);
		renderer.setClearColor(new THREE.Color("hsl(0, 0%, 10%)"));

		container.appendChild(renderer.domElement);		
		
		//CONTROLS
		controls = new THREE.OrbitControls(camera, renderer.domElement);
		controls.enableDamping = true;
		controls.dampingFactor = 0.25;
		controls.enableZoom = true;

		//EVENTS
		window.addEventListener('resize', onWindowResize, false);			
	}
			
	function onWindowResize() {

        windowHalfX = window.innerWidth / 2;
        windowHalfY = window.innerHeight / 2;

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

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

	function animate() 
	{
		requestAnimationFrame( animate );
		controls.update();
		render();
	}

	function render() {
		// Set the camera to always point to the centre of our scene, i.e. at vector 0, 0, 0
		camera.lookAt( scene.position );
		renderer.render( scene, camera );
	}		

Thanks
Avinash


#10

Ok, I understand now! :slight_smile:

It looks like the model is not at the center (0,0,0). Maybe there is some offset built into the model?

Try adding an AxisHelper to see where the center is, and then reposition the object so it is sitting at the center point.

var axisHelper = new THREE.AxisHelper(100);
scene.add(axisHelper);

#11

How did you solve it?