Tutorial #12: Advanced Camera Functions
In the last several tutorials we’ve dealt with how cameras move and how the user can interact with them and control them in different ways. To finish off the chain of camera tutorials we’ll examine several functions (common to both types of camera’s) that allow you to control how much the camera can see. Like real cameras, the cameras in C3DL cannot see everything around them. They are both limited by a field of view. In addition, FreeCamera and OrbitCamera can choose to not see things that are very far away (why waste time drawing something that is so small you can barely see it), or very very close (because that might block your view and prevent you from seeing anything else). The distance at which near objects stop being drawn is known as the near clipping plane, while the distance at which far objects stop being drawn is called the far clipping plane. These three factors (field of view, near clipping plane, far clipping plane) are combined to determine what actually gets displayed to the user. An object must be inside the field of view, beyond the near clipping plane and closer than the far clipping plane in order to be seen. Anything outside of this will still be tracked by the program, but will not be drawn. For traditional photography, this would be outside the frame. The object is still there, you just can’t see it (or maybe can only see part of it).
These can be controlled with the functions setFieldOfView, setNearClippingPlane and setFarClippingPlane. The current values can also be queried using getFieldOfView, getNearClippingPlane and getFarClippingPlane.
The following code uses these functions to allow the user to control these settings in a scene. It requires the same duck model and texture we’ve been using in previous tutorials.
The HTML document
<html>
<head>
<title>Canvas3D tutorial #12: Advanced Camera Functions</title>
<script type="application/javascript" src="../canvas3dapi/c3dapi.js" ></script>
<script type="application/javascript" src="tutorial12.js"></script>
</head>
<body>
<!-- Add a canvas element to the page. It is scripted by using its id -->
<canvas id="tutorial" style="border: 2px solid blue" width="500" height="500"></canvas>
</body>
</html>
The JavaScript Code
You can press the arrow keys to move the camera around in the same was as tutorial 11. Instead of rotation, this tutorial includes controls for the clipping planes and field of view. The w and s keys move the far clipping plane (farther away and closer respectively), changing how far you can see ducks in the distance. The q and a buttons move the near clipping plane (farther away and closer respectively), changing how close you can see ducks in the foreground. the e key will expand the vertical field of view, and d will contract it. If you expand the field of view you are displaying more of the scene in the same size canvas, so things will be squished towards the middle of the canvas. If you reduce the field of view, you are displaying less of the scene in the same canvas, so objects in the middle will get stretched, while objects around the top and bottom may be moved off the canvas entirely.
// Tutorial 12
c3dl.addMainCallBack(canvasMain, "tutorial");
c3dl.addModel("duck.dae");
var lastKey = -1;
function down(event)
{
var cam = scn.getCamera();
var vel = [0,0,0];
if(event.keyCode != lastKey) {
lastKey = event.keyCode;
var mov = [0,0,0];
vel = cam.getLinearVel();
switch(event.keyCode) {//determine the key pressed
case 37://left arrow
mov = c3dl.multiplyVector(cam.getLeft(),1,mov);
break;
case 39://right arrow
mov = c3dl.multiplyVector(cam.getLeft(),-1,mov);
break;
case 40://down arrow
mov = c3dl.multiplyVector(cam.getDir(),-1,mov); //move the camera 'back' (towards the user)
break;
case 38://up arrow
mov = c3dl.multiplyVector(cam.getDir(),1,mov);//move the camera 'forward' (into the scene)
break;
}
cam.setLinearVel([vel[0]+mov[0],vel[1]+mov[1],vel[2]+mov[2]]);
}
}
function up(event)
{
var cam = scn.getCamera();
var vel;
lastKey = -1;
var pos = cam.getPosition();
vel = cam.getLinearVel();
switch(event.keyCode) {//determine the key released, if it is one of the linear velocity keys, set linear velocity to 0
case 37://left arrow
case 39://right arrow
cam.setLinearVel([0,vel[1],vel[2]]);
break;
case 40://down arrow
case 38://up arrow
cam.setLinearVel([vel[0],vel[1],0]);
break;
case 87://w key - move far clipping plane away
cam.setFarClippingPlane(cam.getFarClippingPlane() + 1000);
break;
case 83://s key - move far clipping plane closer
cam.setFarClippingPlane(cam.getFarClippingPlane() - 1000);
break;
case 81://q key - move near clipping plane farther away
cam.setNearClippingPlane(cam.getNearClippingPlane() + 1000);
break;
case 65://a key - move near clipping plane closer
cam.setNearClippingPlane(cam.getNearClippingPlane() - 1000);
break;
case 69://e key - increase field of view
cam.setFieldOfView(cam.getFieldOfView() + 5);
break;
case 68://d key - decrease field of view
cam.setFieldOfView(cam.getFieldOfView() - 5);
break;
}
}
function canvasMain(canvasName){
scn = new c3dl.Scene();
scn.setCanvasTag(canvasName);
renderer = new c3dl.WebGL();
renderer.createRenderer(this);
scn.setRenderer(renderer);
scn.init(canvasName);
if(renderer.isReady() )
{
var things = [];
for(var i = 0; i < 70; i++) {
things[i] = new c3dl.Collada();
things[i].init("duck.dae");
things[i].setTexture("duck.png");
things[i].setPosition([0,0,200-(1000*i)]);
scn.addObjectToScene(things[i]);
}
var cam = new c3dl.FreeCamera();
cam.setPosition([0,400,100]);
cam.setLookAtPoint([0,400,-100]);
scn.setCamera(cam);
scn.setKeyboardCallback(up,down);
scn.startScene();
}
}
These generally aren’t changed while a scene is running; you set them once at the beginning and leave them that way, otherwise you risk confusing the user. I thought it might be useful to take a look at them, so you can see what they do and learn how to change them if you need to. If you don’t want to change them, they start with a reasonable default.
