Introduction
The 3D gamelib component is for displaying wirefrae 3D objects. It
doesn't do a hidden surface removal, but it does Z-buffering when
displaying. The world coordinates use a right-hand coordinate system
for objects, with the XY plane being the base plane and Z indicating
height. The camera coordinate system is also a right-hand coordinate
system, using the X axis as left/right, the Y axis as front/back and Z
as up/down.
Starting with version 0.3, there are two cameras available. The "old"
camera, capable of moving in X, Y and Z, always turning in the XY
plane and the "new" (or 3D) camera, having 6 degrees of freedom.
All game objects seem are defined as volumes, using the DEFVOLUME
macro.
DEFVOLUME takes three required parameters, one optional parameter and
a list of extra slots to define.
(DEFVOLUME class name vertex count (surface ...)
[visible surfaces] [extra slot]...)
The surface spec is as follows:
(type vertex 1 vertex 2 vertex 3 ...)
Vertex specs should be in clock-wise order around a normal seen from
outside the volume. Declaring the surfaces is, ideally, done from low
to high, though surfaces that will never be seen can be placed last
and stopped from ever displaying by using the "visible surfaces"
limiter.
The extra slots are user-defined slots for the shape class (ammunition
count or what-have-you).
Base and transform designators
Starting from version 0.3, there is a "fully 3D" camera available,
necessitating some new concepts and accessors (hopefully seamlessly
integrated into the whole). The most developer-visible of these are
"base designators" and "transform designators".
A "base designator" is either 3-element vector, array or list.
A "transform designator" is a 3-element sequence of "base
designators", specifying the (world coordinate) vectors from the
camera origo to [ 1, 0, 0 ], [ 0, 1, 0 ] and [ 0, 0, 1 ].
What will be shown and how?
All game objects that will be displayed should be added to the
*ALL-SHAPES* list. All game objects that have independent
movement should be added to the *MOVING-OBJECTS* list.
In DRAW-ALL-SHAPES, all objects are sorted in falling average
y-coordinate in camera space (effectively, that is depth). This
ensures that as we traverse the list, we can stop trying to display
items once we hit a negative y-average.
After that, the DRAW-SHAPE gf is called. For most shapes, this will
cause an update of the shape's cam-vertexes and then a list of all the
sides to be displayed (the lowest of the shape's to-show limit or all
defined sides) is generated, culled by a visibility test and sorted
by y-average. After that, DRAW-SHAPE is called for each flat surface
of the shape.
When applied to a flat, DRAW-SHAPE starts by checking if all vertexes
of the flat are visible. If all vertexes are visible, we convert each
vertex to an XY coordinate in screen-space. If not, we find a vertex
that is visible, then traverse the flat vertex by vertex, inserting
extra vertexes on the screen-edge where necessary and culling vertexes
outside the display, then return a list of XY coordinates for each
vertex-to-display. After all that, we call XLIB:DRAW-LINES twice on
the resulting coordinates, once filling the outline with white, the
second just generating the black outline.
Spheres is handled slightly differently. Looking at the sphere code, I
am suddenly not entirely sure that we are doing it correctly.
Exported symbols
- *camera*
- Global variable that contains the "player camera".
- *display*
- Global variable that contains the X display.
- *font-preference*
- List of fonts, in falling preference order. Only consulted on
initial connection and window creation.
- *grid-separation*
- Separation, in world-space units, for a "grid on the floor".
- *score-table*
- Tabulation of scores to object type. Used by score-from-object.
- +screen-side+
- Constant for the height and width of the X pixmap that all
3d-rendering is made on. Also guides the size of the X window it will
be displayed in.
- 3d-camera
- (3d-camera x y z &optional
transform)
Return a newly constructed 3d-camera object, at position [ X, Y, Z ].
If an optional transform designator is passed it, the camera will
use this as its transform, otherwise it will use a unit transform.
- box
- Shape class. 8 corners, 6 sides.
- camera
- Class.
- camera-to-screen
- (camera-to-screen coord cam &optional
clip)
Convert from coord (in camera-space) to screen coordinates,
return these as a list (X Y). If clip is non-nil and the
coordinates are outside the screen, return NIL.
- collide-p
- (collide-p object-1 object-2)
Generic function, determine if two objects are touching.
The default methods check for camera colliding with anything and
anything colliding with anything. The camera-collision is effectively
"is the camera inside a bounding box, infinitely high, of the second
object's footprint". The generic collision compares the bounding boxes
of the footprints and returns T if there is an overlap.
- collide-action
- (collide-action object-1 object-2)
Generic function, determine what happens when two objects collide. The
default method prints some diagnosting on *STANDARD-OUTPUT*.
- coord
- class
- defvolume
- (defvolume name vertexes sides
&optional show-limit &rest
extra-slots)
Helper macro. Define a shape-class. See defining volumes
- draw-all-shapes
- (draw-all-shapes)
Draw all shapes in *ALL-SHAPES*.
- draw-grid
- (draw-grid camera)
Draw a grid with lines parallel to the X and Y world axis.
- draw-shape
- (draw-shape shape)
Generic function.
- flat
- Shape class, superclass for all flat surfaces.
- full-move
- (full-move camera displacement)
Displace the camera by displacement, a 3D coordinate (using the
camera's position as origo, expressed in the camera coordinate
system). The displacement will be transformed into world coordinates
before being applied.
- get-centre
- (get-centre shape &optional
camera-p)
Get the geometric centre of a shape. If camera-p is non-nil,
return results in camera-space coordinates, otherwise return
coordinates in world-space.
- move
- (move object &optional distance)
Generic function. Move an object.
- octaeder
- Shape class
- score-from-object
- (score-from-object object)
Helper function, checks *score-table* for an entry for the class of
object and returns that (or 0).
- shape
- Shape super-class.
- tetraeder
- Shape class
- tetragon
- Shape class (flat)
- triangle
- Shape class (flat)
- turn
- (turn object angle &optional angle)
Generic function. Turn object through angle. If the
object is "the standard camera" it will be turned around the Z axis. A
3D camera will default to turn around teh Z axis unless otherwise
specified. Axes are designated by the :x :y or :z keywords. The angle
is specified in radians.
- volume
- Shape class, superclass for all volumes.
- world-to-camera
- (world-to-camera world-coord camera
&optional result)
Compute camera-sapce coordinates for a given coordinate and return
that. If result is provided, also side-effect-update this and
return that object as the result (lessens object-creation slightly).
- world-to-screen
- (world-to-screen world-coord camera
&optional clip)
Converts a world coordinate to a screen XY. Clips in te same manner as camera-to-screen.