Reputation: 6136
What I am trying to achieve is to have two control modes, a free "flying" one, and an object-centered one (trackball) and with a button press seamlessly switch between them.
I initially tried with TrackBallControls and FlyControls. The problem with those two, is that TrackballControls is based on Euler angles, while FlyControls is based on Quartenions. I tried converting the camera.rotation vector to a quaternion by doing,
quaternion.setFromEuler( target ); //where target, a Vector3 that contains degrees
And setting the position manually (since they use the same position object), and while it seemed to be working, rotating the camera a bit - and switching controls, started yielding horribly wrong results. Also, grabbing Euler angles from the quaternion (setEulerFromQuaternion) resulted in wrong data.
So, while I was able to switch between them, I was never able to sync their rotation coordinates, so "on switch" while the camera position is correct the rotation is wrong.
PS. I had some results with the FirstPersonControls (euler angles as well) but the screen lat,long method it is using is very error prone and fails completely when there is Z axis rotation.
Upvotes: 7
Views: 5411
Reputation: 11
Making a new camera is the easiest way to unbind all the keyboard/mouse events that were setup with the previous controls. If you don't do this you'll have orbitcontrols events fire with fly mode on.
Upvotes: 1
Reputation: 19592
What about something like this?
function onClick() {
var prevCamera = camera;
camera = new THREE.PerspectiveCamera(...);
camera.position.copy( prevCamera.position );
camera.rotation.copy( prevCamera.rotation );
var MODE = { TRACKBALL: 0, FLY: 1 };
switch( mode ) {
case MODE.FLY:
controls = new THREE.TrackballControls( camera );
mode = MODE.TRACKBALL;
break;
case MODE.TRACKBALL:
controls = new THREE.FlyControls( camera );
mode = MODE.FLY;
break;
}
}
Upvotes: 14