rankind rankind - 1 month ago 21
Javascript Question

Three JS Level Horizon Camera

I've dug around everywhere looking for a solution to this. It seems that on OrbitControls and TrackballControlls the camera wont stay horizontal! As you move around with TrackballControlls the scene starts to roll. OrbitControlls dragging from left to right only rolls the scene. I'd like to be able to use the TrackballControls but keep the camera level with the horizon when moving around the center of the scene. Is this possible?

My code:

// SETUP GLOBAL VARIABLES

var camera, controls, scene, renderer;
// PLANET PHYSICAL LOCATIONS
var sun, mercPL, venPL, earthPL, marsPL, jupPL, satPL, urPL, nepPL;
// TIME, AND SCALARS
var now, scalar, planetScalar;

init();
animate();

function init() {

scene = new THREE.Scene();

renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );

var container = document.getElementById( 'container' );
container.appendChild( renderer.domElement );

camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 100000 );
camera.position.z = 200;

controls = new THREE.OrbitControls( camera, renderer.domElement );
//controls.addEventListener( 'change', render ); // add this only if there is no animation loop (requestAnimationFrame)
controls.enableDamping = true;
controls.dampingFactor = 0.8;
controls.enableZoom = true;




// ADD THE SUN PHYSICAL LOCATION
var geometry = new THREE.SphereGeometry(5, 30, 30, 0, Math.PI * 2, 0, Math.PI * 2);
var material = new THREE.MeshBasicMaterial({color: "Yellow"});
sun = new THREE.Mesh(geometry, material);
scene.add(sun);

var segmentCount = 32,
radius = 80,
geometry = new THREE.Geometry(),
material = new THREE.LineBasicMaterial({ color: 0xFFFFFF });

for (var i = 0; i <= segmentCount; i++) {
var theta = (i / segmentCount) * Math.PI * 2;
geometry.vertices.push(
new THREE.Vector3(
Math.cos(theta) * radius,
Math.sin(theta) * radius,
0));
}
scene.add(new THREE.Line(geometry, material));

var segmentCount2 = 32,
radius2 = 120,
geometry2 = new THREE.Geometry(),
material2 = new THREE.LineBasicMaterial({ color: 0xFFFFFF });

for (var i = 0; i <= segmentCount2; i++) {
var theta = (i / segmentCount2) * Math.PI * 2;
geometry2.vertices.push(
new THREE.Vector3(
Math.cos(theta) * radius2,
Math.sin(theta) * radius2,
0));
}

scene.add(new THREE.Line(geometry2, material2));

//

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

render();



}

function onWindowResize() {

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

}


function animate() {

requestAnimationFrame( animate );
controls.update();

render(); // MUST BE HERE FOR ANIMATION

}


function render() {

renderer.render( scene, camera );
}


Thanks!

Answer

Perhaps this can help you ( all the options are commented in the orbit library)

Level Horizon:

controls.minPolarAngle = Math.PI / 2;
controls.maxPolarAngle = Math.PI / 2;

Focus of Orbit:

controls.target = (cube.position);

Result: (Note: My mouse controls are inverted (Orbit Right / Pan Left) )

Three.js Lock Orbit Controls

Edit: After reviewing your comments code, I think this is what you want:

Three.js Orbit Controls pt 2.

The gist is that :

a) you need to provide the camera with an up vector:

camera.up.set( 0, 0, 1 );

And

b) Target the sun with the camera:

camera.lookAt(sun.position);

You can still play with the damping, and lock the angles ( there are also vertical constraints if you need them) and speed up down the yaw, but I hope this gets you closer.