jump to navigation

Building a Generic WebGL Camera Library May 10, 2011

Posted by Andor Saga in Open Source, webgl, C3DL, XB PointStream, point cloud.
2 comments

One problem with XB PointStream is the lack of a camera system. This exists because the WebGL library was built primarily for parsing and rendering point clouds files.

We’ve left it up to users to ‘create’ their own cameras by calling our low-level matrix transformations functions. However, as more projects begin to use the library (WebGL PhotoSynth Viewer, 3DTubeMe, 3DStream) it’s becoming apparent some form of easy-to-use camera for XB PointStream is necessary.

I began tackling this issue on my spare time since it bothered me so much. First, I investigated which types of cameras are supported by Arius3D‘s 3DImageSuiteViewer. They have three which are fairly well known: Orbit, Free and ArcBall. I started by implementing something simple, an orbit camera I already developed for C3DL. Orbit cameras are fairly simple, but harder to explain, so just play with the working demo:

When I started developing this, my plan was to strip out C3DL-specific code and get it working with XB PointStream. After a bit of tinkering, I realized the fixes I would be making should be fed back upstream to C3DL. Taking this one step further, any WebGL library should be able to make use of this code. So I closured the entire camera.

Here’s how you can use it:

// Create an orbit camera halfway between the closest and farthest point about 
// the default orbit point [0,0,0].
var cam = new OrbitCam({closest:0, farthest:100, distance: 50});

// override the values.
cam.setFarthestDistance(80);
cam.setClosestDistance(10);
cam.setDistance(10);

// go back as far as possible (uses 80)
cam.goFarther(100);

// figure out how much the cursor moved...
var deltaX = ....
var deltaY = ....

// Yaw about global Y.
cam.yaw(deltaX);

// Pitch about orbit point.
cam.pitch(deltaY);

// matrix magic!
pointStream.multMatrix(M4x4.makeLookAt(cam.position, cam.direction, cam.up));
pointStream.translate(-cam.position);

// done!
pointStream.render(pointCloud);

Okay, the demonstration isn’t all that impressive. What is really impressive is the encapsulated and sharable code. Any WebGL developer can take this and instantly have a working camera. The code takes care of making sure the camera doesn’t zoom out too far and always has the correct orientation. Neat eh? Once I (hopefully) finish the other main cameras (ArcBall and Free), I’ll place them on a github repository for other WebGL developers.