lib3d, version 2.0
SLJ 4/99
--
The idea of the 3d graphics library is to provide some fast routines, for
doing things like rotations and drawing polygons.
Version 2.0 of the library contains a number of significant changes and
enhancements, in large part to support obj3d, the 3d object library.
Changes include:
o New memory map, in particular reorganized zero page.
o Rotation accumulation routines now take a _pointer_
to the matrix to be accumulated (formerly used zp matrix)
o ROTPROJ multiplies by both orientation and viewpoint
matrix before projecting; also stores rotated z-coords
in PLISTZLO/HI (useful for depth-sorting objects)
o New routines PLOT and DRAWLINE let you, well, plot points
and draw lines.
o Multicolor! There is now both a hires and a multicolor
version of the library. The line/plot/polyfill routines
all plot in multicolor, and ROTPROJ corrects for the
screen aspect ratio.
o VERSION routine lets you determine which library is in use
Although most people will probably use lib3d via obj3d, it is an
exceptionally good idea for obj3d users to read through this document.
--
As to the library, it consists of five routine groups: routines to calculate
rotation matrices, a routine to rotate centers (16-bit signed coordinates),
a routine to rotate objects (restricted signed 8-bit coords, but fast)
and project them, a polygon rendering routine, and point/line drawing
routines.
Although the routines are based on the polygonamy routines and ideas
all routines were derived and written from scratch. They are not the
fastest possible routines, but I believe they the fastest routines for
their size and flexibility.
The library is designed to work with any VIC bank -- there is always
enough room for a bitmap, and usually enough room for eight sprite
definitions.
--
There are ten routines:
CALCMAT - Calculate a rotation matrix
ACCROTX - Add a rotation to rotation matrix
ACCROTY
ACCROTZ
GLOBROT - 16-bit rotation (of centers)
ROTPROJ - Rotate and project objects
POLYFILL - Draw a filled polygon
PLOT - Plot a single point
DRAWLINE - Draw a line
VERSION - Returns library version
You must set some stuff up for them, and they in turn will clobber some other
stuff for you. A small jump table into the routines is at $8800.
Memory map
----------
Zero page:
$41-$49 MATRIX Orientation (local rotation) matrix
$4A-$52 VIEWMAT Viewpoint matrix
$53 XOFFSET Location of origin on screen (e.g. 160,100)
$54 YOFFSET
$55-$72 Intermediate variables. These locations are regularly hosed
by the routines. Feel free to use them, but keep in mind that
you will lose them!
$60-$67 X1,Y1,X2,Y2
Coordinates for PLOT and DRAWLINE routines.
$8B-$8F PLISTZLO, PLISTZHI
Before projecting, ROTPROJ stores the z-coordinate of each
point into these lists. The obj3d library uses these to
depth-arrange compound objects, for example.
$A3-$AE C0XLO, C0XHI, C0YLO, ...
Pointers to rotated object centers, i.e. where the objects are
relative to you. Centers are 16-bit signed (2's complement).
$AF-$B0 ROTMATH
Pointer to the multiplication table at $C200-$C3FF.
$B1-$B9 Rotation matrix.
$B1-$B8 MULTLO1, MULTLO2, MULTHI1, MULTHI2
Pointers to math tables at $C400-$C9FF
MULTLO1 -> $C500
MULTLO2 -> $C400
MULTHI1 -> $C800
MULTHI2 -> $C700
(Only the high bytes of the pointers are actually relevant).
$B9 BITMAP
High byte of bitmap base address.
$BB-$BC FILLPAT
Pointer to fill pattern (eight bytes, 8x8 character)
$BD-$C0 PLISTXLO, PLISTXHI
$C1-$C4 PLISTYLO, PLISTYHI
Pointers to rotated object points, e.g. used by polygon renderer.
Numbers are 16-bit 2's complement.
Library:
$0200-$027F Point queue.
$8400-$9FFF Routines, tables, etc.
$8800 Jump table into routines
Tables:
$5E00-$5FFF ROTMATH, pointed to by $AF-$B0
$C000-$C2FF MULTLO, pointed to by $F7-$F8 and $F9-$FA
$C300-$C5FF MULTHI, pointed to by $FB-$FC and $FD-$FE
$C600-$C6FF CDEL, table of f(x)=x*cos(delta)
$C700-$C7FF CDELREM remainder
$C800-$C8FF SDEL x*sin(delta)
$C900-$C9FF SDELREM
$CA00-$CAFF PROJTAB, projection table, f(x)=d/x, integer part
$CB00-$CBFF PROJREM, projection table, 256*remainder
$CC00-$CCFF LOG, logarithm table
$CD00-$CDFF EXP, exponential table
$CE00-$CEFF NEGEXP, exponential table
$CF00-$CFFF TRIG, table of 32*sin(2*pi*x/128) -- 160 bytes.
The tables from $C600-$CFFF are fixed and must not be moved. The
tables ROTMATH, MULTLO, and MULTHI on the other hand are only
accessed indirectly, and thus may be relocated. Thus there is
room for a color map and eight sprite definitions in any VIC bank
except bank 2, where lib3d is located (only enough room for a
bitmap there).
Library Routines
----------------
$8800 CALCMAT Calculate a rotation matrix
Stuff to set up: Nothing.
On entry: .X .Y .A = theta_x theta_y theta_z
On exit: Rotation matrix is contained in
Cycle count: 390 cycles, worst case.
$8803 ACCROTX This will "accumulate" a rotation matrix by one rotation
around the x-axis by the angle delta=2*pi/128. Because
this is such a small angle the fractional parts must also
be stored. These routines are necessary to do independent
3d rotations (i.e. rotate around local axis).
On entry: carry clear/set to indicate positive/negative rotations.
.AY = address of matrix+remainder to be accumulated
On exit: Accumulated matrix!
Cycle count: Somewhere around 150, I think.
$8806 ACCROTY Similar around y-axis
$8809 ACCROTZ Similar around z-axis
$880C GLOBROT Perform a global rotation of 16-bit signed coordinates
(Rotate centers)
Stuff to set up:
MULTLO1 MULTLO2 MULTHI1 MULTHI2 = $B1-$B8
C0XLO, C0XHI, C0YLO, C0YHI, C0ZLO, C0ZHI = $63-$6E
Pointers to points to be rotated. Note also that $63-$6E
has a habit of getting hosed by the other routines.
CXLO, CXHI, CYLO, CYHI, CZLO, CZHI = $A3-$AE
Pointers to where rotated points will be stored.
On entry: .Y = number of points to rotate (0..Y-1).
On exit: Rotated points are stored in CXLO CXHI etc.
$880F ROTPROJ Rotate and project object points (vertices). Points must
be in range -96..95. Upon rotation, they are added to
the object center, projected, and stored in the point
list.
Points are first rotated by the orientation matrix at $41,
then by the viewpoint matrix at $4A, then added to the
object center. The z-coordinates are stored in PLISTZLO/HI,
and the points are then projected, with the results stored
in PLISTXLO/HI and PLISTYLO/HI.
The _length_ of a vertex vector (sqrt(x^2 + y^2 + z^2)) must
be less than 95.
Stuff to set up:
Orientatin and viewpoint matrix = $41-$52
ROTMATH = $B0
P0X P0Y P0Z = $69-$6E
Pointers to points to be rotated. As with GLOBROT, these pointers
will get clobbered by other routines. Points are 8-bit signed
numbers in range -96..95.
PLISTXLO PLISTXHI ... = $BD-$C4, PLISTZLO = $8B-$8E
Where to store the rotated+projected points.
CXLO CXHI ... = $A3-$AE
List of object centers. Center will be added to rotated point
before projection.
XOFFSET, YOFFSET = $53, $54
Location of origin on the screen. Added to projected points
before storing in PLIST. 160,100 gives center of screen.
On entry: .X = Object center index (center is at CXLO,X CXHI,X etc.).
.Y = Number of points to rotate (0..Y-1).
On exit: Rotated, projected points in PLIST.
$8812 POLYFILL Draw pattern-filled polygon into bitmap.
Stuff to set up:
MULTLO1, MULTLO2, MULTHI1, MULTHI2 = $B1-$B8
BITMAP = $B9
FILLPAT = $BB-$BC
PLISTXLO, PLISTXHI, PLISTYLO, PLISTYHI = $BD-$C4
Point queue = $0200. Entries are _indices_ into the PLISTs,
must be ordered _counter clockwise_, and must _close_ on
itself (example: 4 1 2 4).
On entry: .X = Number of points in point queue (LDX #3 in above example)
On exit: Gorgeous looking polygon in bitmap at BITMAP.
$8815 PLOT Plot a point to the bitmap
To set up:
BITMAP = $B9
X1,Y1 = $60,$62 = (signed) 16-bit coordinates.
FILLPAT = $BB-$BC -- point is ANDED with fill pattern
before plotting.
On exit: Plotted point!
$8818 DRAWLINE Draw a line between two points.
Note that this is not the fastest routine around; it was
designed more for compactness than efficiency (but is still
reasonably fast!).
To set up:
BITMAP = $B9
X1,Y1,X2,Y2 = $60,$62,$64,$66 = (signed) 16-bit coordinates.
FILLPAT = $BB-$BC -- point is ANDED with fill pattern
before plotting.
On exit: line drawn from X1,Y1 to X2,Y2. Note that off-screen coordinates
are allowed.
**NOTE** In both PLOT and DRAWLINE, the coordinates are *16-bits* -- make
sure the high bytes are set correctly!
$881B VERSION Returns version number of library
On entry:
On exit: version number returned in .A
High bit set -> multicolor, so currently VERSION will either
return $02 or $82.