Sandy 1.2 is still in beta state, and even if quite stable, it is still missing some features. Among the things that have changed in Sandy 1.2 versus Sandy 1.1 (the latest stable version) is the Camera3D class.
The camera is an important part of your Sandy world, because it represents the viewer. Without it, you wouldn't see your carefully crafted 3D objects. It is essential to know that the camera is part of the world, not some ghostly gadget peeking into the world from outer space.
Although the camera itself is not visible, it has a position in world coordinates, and it can be moved around and rotated in all imaginable ways. It is the eye of the visitor to your world–a kind of agent or avatar. Whatever the camera sees is drawn by the rendering engine to the screen.
If you have used the Sandy 1.1 version of the camera, you'll noteice that it has changed a bit in Sandy 1.2. The Sandy 1.2 camera no longer has the notion of a focal or nodal length but instead uses an angle-of-view and a view volume.
In Sandy 1.1 you would create a new camera, and add it to the world like this.
// Create a ClipScreen on which to render the world. var screen: ClipScreen = new ClipScreen( this.createEmptyMovieClip( 'screen', 1 ), 200, 200 ); // Set the camera's focal length and specify the screen from preceding step. var camera:Camera3D = new Camera3D( 700, screen ); // Add the camera to the world. world.addCamera( camera );
So we passed a focal distance and the projection screen to the Camera3D constructor in Sandy 1.1.
In Sandy 1.1, we could change the focal distance at runtime–with Camera3D.setFocal()–to alter the field of view of the camera. A lower value represented a wide-angle lens and a higher value a telephoto lens. setFocal() is no longer supported in Sandy 1.2.
The new camera in Sandy 1.2 has the notion of a field-of-view (FOV) or angle-of-view, which determines what can potentially be seen by the camera. Together with the aspect ratio of the projection screen, it defines the view volume for the camera.
Borrowed from Wikipedia. “A camera's angle of view can be measured horizontally, vertically, or diagonally.”
The new camera is created and added to the world like this, using default values:
var camera:Camera3D = new Camera3D( 300, 200 ); camera.setPosition(0,0,-200); world.setCamera( camera );
The values passed to the Camera3D constructor in Sandy 1.2 have changed from 1.1–they are now the width and height of the viewport or projection screen.
Furthermore, note that the World3D.addCamera() method in Sandy 1.1 has changed to World3D.setCamera() to reflect the fact that Sandy 1.2 allows only one camera per world.
The default value for the view angle is 45 degrees, but can be changed at run time using the setPerspectiveProjection() method.
To effectively change the perspective and other properties of the camera, we should know a few things about the viewing volume, and how it works in Sandy.
The viewing volume is defined by four planes, building a pyramid with its top at the camera position. All visible objects are within this volume. To further limit the viewing volume, most 3D systems introduce a near plane and a far plane, both perpendicular to the viewing direction. This defines a cut pyramid or “frustum”, called the “view frustum”. To save computational power, objects outside this volume are not computed or rendered.
When we create the Sandy camera, the frustum planes are calculated from the default view angle of 45 degrees, the aspect ratio, and the position of the near and far planes. The aspect ratio is the quotient viewport width/height. The near and far planes are set at a distance of 50 and 3000 respectively.
If we want to change the camera properties, we call its setPerspectiveProjection() method.
// Assuming camera is a Camera3D instance: camera.setPerspectiveProjection(fovY:Number, aspectRatio:Number, zNear:Number, zFar:Number):Void
The arguments are the angle of view (fovY), the aspectRatio, the distance zNear to the near plane, and the distance zFar to the far plane.
Here is an example that changes the positions of the frustum near and far planes, in effect changing the depth of the view volume along the line of sight.
camera.setPerspectiveProjection( null, null, zNear, zFar );
Here zNear and zFar has been given values in an event handler. The null values for view angle and aspect ratio leaves them undefined, and set to the default values.
When we dig in a bit, it's amazing how little we see of our world and how far fetching [far-fetched? far-reaching?] conclusions we draw ;) First of all, we can skip at least half the world, as we cannot see anything behind the camera. In fact, as we have seen, any object or part of object we can see must be within the view frustum.
But of course, it doesn't end there. An object or parts of it can be hidden behind other objects, and objects that we do see will have surfaces that are hidden. Some surfaces are on the back side of an object, some are on the inside. Objects, surfaces, and faces we don't see should not be rendered.
For a real camera in the real world, this is not any problem. What is registered on the film is light reflected from surfaces that the camera can really see.
For our digital counterfeit, it is not as simple. No rays of light are stopped from reaching the film, so everything has to be calculated. Optimizations are essential, and the frustum is one of the tools.
You can read more about Angle of View at Wikipedia or frustum culling at flipcode or at Lighthouse3D.
Here are some tips on working with the fov, and near and far planes: