threedkit - a set of functions for 3D support.
The 3dkit consists mainly of the following triangle functions
Beware, these functions are not a direct part of the svgalib library. Instead
their source is part of svgalib and can be found in the threeDkit/
subdirectory of the original svgalib distribution. However, it is not
installed in the system by default, s.t. it is unclear where you can find it
if your svgalib was installed by some linux distribution.
In case of any such problem, simply get an svgalib distribution from the net.
You even don't need to install it. Just make
in the threeDkit/
subdirectory. As of this writing, svgalib-1.2.12.tar.gz
is the latest
version and can be retrieved by ftp from sunsite.unc.edu
which will most probably be mirrored by a site
close to you.
The functions are defined in the tri.o
their resp. sources) which you must link to your program.
This is main engine for 3D rendering.
- The function called from outside of 3dkit.c is TD_drawsolid.
This first calculates the rotation matrix from the camera rotation angles
(see below for more details). It then allocates memory for the temporary
array for holding temporary coords in subsequently called functions. It
also sorts the surfaces from furthest to closest; according to the
distance of the centre grid-point of each surface from the camera.
It also establishes whether ROTATE_OBJECT option is on and zero's the
camera position if so --- this is for displaying the object at the screen
centre like in a 3D CAD package, as apposed to virtual reality where the
object can be anywhere and the actual camera position can move.
In the case of ROTATE_OBJECT being on, although the camera position
is zero, some distance has to be placed between the camera and the object
(or else it would appear to be infinitely large on the screen). This is
done using the variable s_cam which is initialized to
distance which is set by the calling application. It then loops
through each surface (ordering them in the way they were just sorted ---
i.e. according to sortarray indexing) and calls one of five graphic
routines to write the 3D surface to the hardware.
- Assume that TD_drawsolid then calls TD_drawmesh. Here, each
surface grid point is first TD_translate'd into a 2D screen point
and stored in the temp array. There are obviously w(idth)*h(eight)
points in the grid.
Following, each line from the 2D temp array is drawn on the screen. To draw
the surface, the corner wishbone (two lines) from each grid square is
drawn while advancing across and the down. After completing the scan, the
furthest two edges of the surface must then be filled in, vis.:
_ _ _ _ _ _
| | | | | |
To understand the object rotation, a knowledge of matrix multiplication is
required. I once derived a camera rotation before I learned matrix
computation. It amounted to the same thing, but was unnecessarily
complicated to optimise.
- TD_translate called from TD_drawmesh (and others) converts
from the 3D grid point coordinate to the 2D screen coordinate using:
(a) the three camera position coordinates, (or the single camera
distance value, s_cam, if ROTATE_OBJECT is set), and
(b) the three camera rotation angles. However, the three camera
rotation angles have already been converted into a rotation matrix when
TD_calc_rotation_matrix was called by TD_draw_solid.
To convert from a 3D coordinate to a 2D screen coordinate, the camera
position (or more correctly, the position of the object from the camera)
must first be added to each of the 3D grid coordinates. If the user has
chosen to use 32 bit values for the discription of the surface, then these
must be right shifted to the same size as the 16 bit case.
x, y and z now hold the 3D position of the object
relative to the camera centre (or in these terms, the centre of the video
screen RIGHT ON the screen). The vector [x y
z] must now be multiplied by the rotation matrix. The xt
value must also have the camera distance, s_cam, added to it in
case the ROTATE_CAMERA is set (in which case x_cam,
y_cam and z_cam (the camera position) will be zero and
instead s_cam will have a value to provide the necessary
object-camera distance). A test is also made as to whether this value is
zero or negative. In the case, the point is too close to the camera, or
behind the camera, and must not be drawn.
After the multiplication, the resulting vector [xt yt
zt] has been rotated to be aligned with screen. The vector is
now adjusted for perspective by dividing the yt and zt
values (horizontal and vertical respectively) by the xt value (into
the screen). Division is done by muldiv64 because the intermediate
product is larger than 32 bits. xscale and yscale are
factors that scale the image to size. posx and posy is just
the centre of the screen, or more precisely:
The exact position of the pinhole camera viewing the object.
- TD_calc_rotation_matrix calculates the nine entries of the 3 by 3
matrix used in TD_translate. In order that only integer arithmetic
is performed, these values are stored and used as integers. Since this
matrix's entries are always between -1 and +1, they have to be integer
left shifted to give them accuracy. TD_MULCONSTANT scales them to
sufficient bits of accuracy before they are converted to integers.
This also means that results (of multiplications with them) have to be
scaled down by the same amount. This scaling is inherent in the final
multiplication and division (muldiv64) done in the
TD_translate function, so an extra division is not consumed.
The rotation matrix effectively rotates the vector by the Eulerian angles
alpha, beta and gamma. These angles represent
successive rotations about each of the 3D axes. You can test which angles
do what by looking at the calling application. Their precise definitions
are not all that important since you can get the keyboard to do the right
thing with a little trial and error.
Intrisics of drawing non-transparent surfaces...
to be continued ?!
This manual page was edited by Michael Weller
<email@example.com>. The demos, the initial documentation and
the whole threedkit stuff was done by Paul Sheer <firstname.lastname@example.org>.
P O BOX 890507
Donations (by check or postal order) will be appreciated and will encourage
further development of this software. However this is strictly on a voluntary
basis where this software falls under the GNU LIBRARY GENERAL PUBLIC