Circular camera rotation around a central point in threejs

How to perform a circular rotation on a single axis in webGL

webGL, Javascript, threeJS

04/27/2012

For anyone who's good with math, I suppose this is a fairly easy one, but if you're not, rotating a camera in threeJS can be a bit tricky. I did a lot of asking around, and most of the answers I got involved using pre-built libraries such as the built in trackball controls, or the great drag-pan controls offered in the threejs boilerplate from learningthreejs.com. The problem with these is that they allow for rotation along all axis, which makes things weird if you've got something that's never supposed to go upside down, like say, a building, or a case in which you want to constrain how far around something you can rotate, or if you want to use the keyboard instead of the mouse for your controls, as I did.

So, for my scenario, I wanted to rotate around a bunch of buildings. I wanted the y position to stay fixed, but needed to manipulate the x and z position in a circular path, while maintaining a focus on the center of my scene. So I set my camera to its initial position:

camera.position.set(0,20,35); 

And set a variable for the speed at which I want the camera to rotate:

var rotSpeed = .02 

Obviously, for your scene, you will have to manipulate both of these values.

Then, with the help of the KeyboardState.js file available in the threeJS boilerplate, I set up my keyboard actions. Within the animate() function, which gets called consistently in my scene, I made a call to a checkRotation() function, which looks like this:


function checkRotation(){

  var x = camera.position.x,
    y = camera.position.y,
    z = camera.position.z;

  if (keyboard.pressed("left")){
    camera.position.x = x * Math.cos(rotSpeed) + z * Math.sin(rotSpeed);
    camera.position.z = z * Math.cos(rotSpeed) - x * Math.sin(rotSpeed);
  } else if (keyboard.pressed("right")){
    camera.position.x = x * Math.cos(rotSpeed) - z * Math.sin(rotSpeed);
    camera.position.z = z * Math.cos(rotSpeed) + x * Math.sin(rotSpeed);
  }

  camera.lookAt(scene.position);

}

So, basically ,this is just using the equation for circular movement to manipulate the x and z position values of my camera. If you push left, the camera moves counter-clockwise around the object. If you push right, the camera moves clockwise. Regardless of which key you hit, the camera shifts its focus toward the scene origin (0,0,0, in my case).

Now if I could only figure out camera zooming...