home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
gondwana.ecr.mu.oz.au/pub/
/
Graphics.tar
/
Graphics
/
VOGLE.ZIP
/
SRC
/
CURVES.C
< prev
next >
Wrap
C/C++ Source or Header
|
2000-02-11
|
5KB
|
277 lines
#include "vogle.h"
static int nsegs = 15; /* number of segs in a curve */
static int make_prec_called = 0; /* has precision matrix been made ?*/
static Matrix basismatrix;
static Matrix e; /* The curve precision matrix */
void drcurve();
/*
* curvebasis
*
* sets the basis type of curves.
*
*/
void
curvebasis(basis)
Matrix basis;
{
copymatrix(basismatrix, basis);
}
/*
* make_prec
*
* Make the precision matrix for a single curve
*/
static void
make_prec()
{
float n2, n3;
/*
* Set up the difference matrix.
*/
identmatrix(e);
n2 = (float)(nsegs * nsegs);
n3 = (float)(nsegs * n2);
e[0][0] = e[2][2] = e[3][3] = 0.0;
e[1][0] = 1.0 / n3;
e[1][1] = 1.0 / n2;
e[2][0] = e[3][0] = 6.0 / n3;
e[2][1] = 2.0 / n2;
e[1][2] = 1.0 / (float)nsegs;
e[0][3] = 1.0;
make_prec_called = 1;
}
/*
* curveprecision
*
* sets the number of line segments that make up a curve segment.
*
*/
void
curveprecision(nsegments)
int nsegments;
{
if (nsegments > 0)
nsegs = nsegments;
else
verror("curveprecision: number of segments <= 0");
make_prec();
}
/*
* rcurve
*
* draws a rational curve
*
*/
void
rcurve(geom)
Matrix geom;
{
Matrix d, tmp;
float *m, xlast, ylast, zlast;
Token *tok;
int i;
if (!vdevice.initialised)
verror("rcurve: vogle not initialised");
if (!make_prec_called)
make_prec();
mult4x4(d, basismatrix, geom);
/*
* Find the last point on the curve....
*/
xlast = d[0][0] + d[1][0] + d[2][0] + d[3][0];
ylast = d[0][1] + d[1][1] + d[2][1] + d[3][1];
zlast = d[0][2] + d[1][2] + d[2][2] + d[3][2];
/*
* Mult. by the precision matrix....
*/
mult4x4(tmp, e, d);
if (vdevice.inobject) {
tok = newtokens(21);
tok[0].i = RCURVE;
(++tok)->i = nsegs;
(++tok)->f = xlast;
(++tok)->f = ylast;
(++tok)->f = zlast;
m = (float *)tmp;
for (i = 0; i < 16; i++)
(++tok)->f = *m++;
return;
}
/*
* Multiply by the current transformation matrix.
*/
mult4x4(d, tmp, vdevice.transmat->m);
/*
* Draw the curve.....
*/
drcurve(nsegs, d);
/*
* Set the current world position to the last point (This
* is the untransformed one)
*/
vdevice.cpW[V_X] = xlast;
vdevice.cpW[V_Y] = ylast;
vdevice.cpW[V_Z] = zlast;
}
/*
* curve
*
* draws a curve
*
*/
void
curve(geom)
float geom[4][3];
{
Matrix tmp;
int i, j;
if (!vdevice.initialised)
verror("curve: vogle not initialised");
/*
* Fill in the w column for rcurve
*/
for (i = 0; i < 4; i++) {
tmp[i][3] = 1.0;
for (j = 0; j < 3; j++)
tmp[i][j] = geom[i][j];
}
rcurve(tmp);
}
/*
* drcurve
*
* Iterate a forward difference matrix to draw a curve.
* Also bypasses the normal multiplication by the current
* transformation matrix (ie. goes straight to clip).
*/
void
drcurve(n, r)
int n;
Matrix r;
{
int it, vx, vy, sync;
if ((sync = vdevice.sync)) /* We'll sync at the end */
vdevice.sync = 0;
vdevice.cpVvalid = 0; /* we start loop with a "move" */
if (vdevice.clipoff) {
vdevice.cpVx = WtoVx(r[0]);
vdevice.cpVy = WtoVy(r[0]);
}
for (it = 0; it < n; it++) {
vdevice.cpWtrans[V_X] = r[0][V_X];
vdevice.cpWtrans[V_Y] = r[0][V_Y];
vdevice.cpWtrans[V_Z] = r[0][V_Z];
vdevice.cpWtrans[V_W] = r[0][V_W];
/* These loops now unwound ....
* for (i = 0; i < 4; i++)
* for (j = 0; j < 3; j++)
* r[j][i] += r[j+1][i];
*/
r[0][0] += r[1][0];
r[1][0] += r[2][0];
r[2][0] += r[3][0];
r[0][1] += r[1][1];
r[1][1] += r[2][1];
r[2][1] += r[3][1];
r[0][2] += r[1][2];
r[1][2] += r[2][2];
r[2][2] += r[3][2];
r[0][3] += r[1][3];
r[1][3] += r[2][3];
r[2][3] += r[3][3];
if (vdevice.clipoff) {
vx = WtoVx(r[0]); /* just draw it */
vy = WtoVy(r[0]);
(*vdevice.dev.Vdraw)(vx, vy);
vdevice.cpVx = vx;
vdevice.cpVy = vy;
vdevice.cpVvalid = 0;
} else {
if (vdevice.cpVvalid)
quickclip(vdevice.cpWtrans, r[0]);
else
clip(vdevice.cpWtrans, r[0]);
}
}
vdevice.cpWtrans[V_X] = r[0][V_X];
vdevice.cpWtrans[V_Y] = r[0][V_Y];
vdevice.cpWtrans[V_Z] = r[0][V_Z];
vdevice.cpWtrans[V_W] = r[0][V_W];
/*
* must set current world position here - clip or quickclip will have
* set valid to the approriate value.
*/
if (sync) {
vdevice.sync = 1;
(*vdevice.dev.Vsync)();
}
}
/*
* curven
*
* draws a series of curve segments.
*
*/
void
curven(n, geom)
float geom[][3];
int n;
{
int i;
if (!vdevice.initialised)
verror("curven: vogle not initialised");
if (n < 4)
verror("curven: not enough points in geometry matrix");
for (i = 0; i <= n - 4; i++)
curve(&geom[i][0]);
}