home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
gondwana.ecr.mu.oz.au/pub/
/
Graphics.tar
/
Graphics
/
atomart.tar.gz
/
atomart.tar
/
poly.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-06-23
|
5KB
|
278 lines
#include <math.h>
#include <stdio.h>
#include "atomart.h"
#include "macro.h"
#include "gram.h"
extern attr *astackp;
extern hlist *fhlist;
extern matrix trans;
/*
* polygoni
*
* returns the intersection point between the ray r and the polygon
* in o.
*/
hlist *
polygoni(r, o)
ray *r;
object *o;
{
register float t;
register polygon *poly;
register edge *e;
hlist *hp;
vector v;
poly = o->u.ply;
hp = (hlist *)NULL;
t = dprod(poly->n, r->dir);
if (t == 0.0)
return((hlist *)NULL);
t = -(dprod(poly->n, r->org) + poly->cnst) / t;
if (t < TOLERANCE)
return((hlist *)NULL);
v.x = r->org.x + t * r->dir.x;
v.y = r->org.y + t * r->dir.y;
v.z = r->org.z + t * r->dir.z;
for (e = poly->edges; e != (edge *)NULL; e = e->nxt)
if ((dprod(e->n, v) + e->cnst) > 0.0)
break;
if (e == (edge *)NULL) {
fetch(hp);
hp->t = t;
hp->obj = o;
hp->nxt = (hlist *)NULL;
}
return(hp);
}
/*
* polygonn
*
* returns the normal to a polygon with index number indx
*/
void
polygonn(n, l, o)
vector *n, *l;
object *o;
{
*n = o->u.ply->n;
}
/*
* getaxis
*
* get the major axis of v.
*/
int
getaxis(v)
vector v;
{
int axis;
if (fabs(v.x) > fabs(v.y))
if (fabs(v.x) > fabs(v.z))
axis = XAXIS;
else
axis = ZAXIS;
else
if (fabs(v.y) > fabs(v.z))
axis = YAXIS;
else
axis = ZAXIS;
return(axis);
}
/*
* polygonc
*
* returns the colour of polygon o at point l
*/
void
polygonc(o, txt, l, n, pcol, type)
object *o;
texture *txt;
vector *l, *n;
pixel *pcol;
int type;
{
int indx, w, h;
vector loc, tmp;
float xlensq, ylensq, zlensq;
totexture(txt, loc, *l);
xlensq = (loc.x - txt->vref1.x) * (loc.x - txt->vref1.x);
ylensq = (loc.y - txt->vref1.y) * (loc.y - txt->vref1.y);
zlensq = (loc.z - txt->vref1.z) * (loc.z - txt->vref1.z);
switch (txt->axis) {
case XAXIS:
w = sqrt((double)(zlensq + xlensq)) * txt->scalew;
h = sqrt((double)(ylensq + xlensq)) * txt->scaleh;
break;
case YAXIS:
w = sqrt((double)(xlensq + ylensq)) * txt->scalew;
h = sqrt((double)(zlensq + ylensq)) * txt->scaleh;
break;
case ZAXIS:
w = sqrt((double)(xlensq + zlensq)) * txt->scalew;
h = sqrt((double)(ylensq + zlensq)) * txt->scaleh;
break;
default:
fatal("atomart: bad axis in polyc.\n");
}
indx = (w % txt->pixw + (h % txt->pixh) * txt->pixw) * 3;
pcol->r = (unsigned char)txt->map[indx] / 255.0;
pcol->g = (unsigned char)txt->map[indx + 1] / 255.0;
pcol->b = (unsigned char)txt->map[indx + 2] / 255.0;
}
/*
* polygoninit
*
* initialise the function pointers and fields for a polygon
*/
object *
polygoninit(d)
details *d;
{
object *o;
polygon *poly;
int i, count;
matrix m;
tlist *tl;
vector v, v1, v2, ovt[MAXVERTS], vt[MAXVERTS];
float maxx, maxy, maxz, minx, miny, minz;
float xlensq, ylensq, zlensq;
edge *e;
details *ld;
o = (object *)smalloc(sizeof(object));
o->type = POLYGON;
o->normal = polygonn;
o->intersects = polygoni;
setattributes(o);
mmult4(m, trans, astackp->m);
poly = o->u.ply = (polygon *)smalloc(sizeof(polygon));
count = 0;
while (d != (details *)NULL) {
switch (d->type) {
case VERTEX:
/* transform vertex into ray space */
ovt[count] = d->u.v;
d->u.v.x -= m[3][0];
d->u.v.y -= m[3][1];
d->u.v.z -= m[3][2];
v3x3tmult(vt[count], d->u.v, m);
vt[count].x /= astackp->scales.x;
vt[count].y /= astackp->scales.y;
vt[count].z /= astackp->scales.z;
count++;
break;
default:
warning("atomart: illegal field in polygon ignored.\n");
}
ld = d;
d = d->nxt;
free(ld);
}
vsub(v1, vt[0], vt[1]);
vsub(v2, vt[0], vt[count - 1]);
xprod(poly->n, v1, v2);
normalise(poly->n);
poly->cnst = -dprod(poly->n, vt[0]);
poly->edges = (edge *)NULL;
for (i = 0; i != count; i++) {
e = (edge *)smalloc(sizeof(edge));
v.x = vt[(i + 1) % count].x - vt[i].x;
v.y = vt[(i + 1) % count].y - vt[i].y;
v.z = vt[(i + 1) % count].z - vt[i].z;
xprod(e->n, v, poly->n);
normalise(e->n);
e->cnst = -dprod(e->n, vt[i]);
e->nxt = poly->edges;
poly->edges = e;
}
minx = maxx = ovt[0].x;
miny = maxy = ovt[0].y;
minz = maxz = ovt[0].z;
for (i = 1; i != count; i++) {
minmax(minx, maxx, ovt[i].x);
minmax(miny, maxy, ovt[i].y);
minmax(minz, maxz, ovt[i].z);
}
for (tl = o->s.txtlist; tl != (tlist *)NULL; tl = tl->nxt) {
if (tl->txtcol == (void (*)())NULL) {
tl->txtcol = polygonc;
/*
* find major axis of polygon normal
*/
vsub(v1, ovt[0], ovt[1]);
vsub(v2, ovt[0], ovt[count - 1]);
xprod(v, v1, v2);
tl->txt.axis = getaxis(v);
tl->txt.vref1 = ovt[count - 1];
/*
* adjust scale so relative to 0 to 1
*/
xlensq = (minx - maxx) * (minx - maxx);
ylensq = (miny - maxy) * (miny - maxy);
zlensq = (minz - maxz) * (minz - maxz);
switch (tl->txt.axis) {
case XAXIS:
tl->txt.scalew /= sqrt((double)(zlensq + xlensq));
tl->txt.scaleh /= sqrt((double)(ylensq + xlensq));
break;
case YAXIS:
tl->txt.scalew /= sqrt((double)(xlensq + ylensq));
tl->txt.scaleh /= sqrt((double)(zlensq + ylensq));
break;
case ZAXIS:
tl->txt.scalew /= sqrt((double)(xlensq + zlensq));
tl->txt.scaleh /= sqrt((double)(ylensq + zlensq));
break;
default:
fatal("atomart: bad axis in polygoninit.\n");
}
}
}
return(o);
}