home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
gondwana.ecr.mu.oz.au/pub/
/
Graphics.tar
/
Graphics
/
atomart.tar.gz
/
atomart.tar
/
main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-06-22
|
7KB
|
338 lines
#include <stdio.h>
#include <math.h>
#include <sys/types.h>
#ifdef MSC
#include <fcntl.h>
#include <string.h>
#define rindex strrchr
#else
#ifdef SYSV
#include <fcntl.h>
#else
#include <sys/file.h>
#endif
#endif
#include "atomart.h"
#include "macro.h"
#include "gram.h"
#include "random.h"
extern char *rindex();
extern hlist *trace();
extern void shade();
extern time_t time();
FILE *logfile = stdout;
int linecount; /* line counter for parser */
object *oblist; /* object list */
light *lights; /* lights list */
attr astack[20], *astackp; /* attribute stack */
char *title; /* title of picture */
short raynumber = 1; /* index number of ray */
int raysperpix = 1; /* number of rays per pixel */
int maxhitlevel = 6; /* max number of rays traced in reflection */
long filetype = PIX_RLE; /* output file format */
object *treeinit();
static object *objlist; /* list used to reset raynumber field */
/*
* ambient colour and background pixel stuff
*/
colour ambient;
colour backcol = { 0.0, 0.0, 0.0 };
/*
* pointer to the free list for hit structures
*/
hlist *fhlist;
/*
* details for the primary rays
*/
vector org;
vector up = { 0.0, 1.0, 0.0 };
float focallength = -1.0;
matrix trans = {
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0
};
/*
* random number pointers
*/
float *randp = randtable,
*erandp = &randtable[sizeof(randtable) / sizeof(float)];
/*
* x, y offsets, scale, and sampleing
*/
static int xoff, yoff;
static float xscale, yscale;
static int ysperpix, xsperpix;
/*
* main driver
*/
main(ac, av)
int ac;
char *av[];
{
int y, x, chatty, indx;
char *p, name[BUFSIZ], buf[BUFSIZ];
FILE *f;
image *im;
object *o, *polyobjs, *sphereobjs, *nxtobj, *lastobjs;
unsigned short xsize, ysize;
unsigned char *red, *green, *blue, *alpha;
if (ac < 4)
fatal("atomart: usage atomart [-v] fname xsize ysize\n");
if (strcmp(av[1], "-v") == 0) {
indx = 2;
chatty = TRUE;
if (ac != 5)
fatal("atomart: usage atomart [-v] fname xsize ysize\n");
} else {
chatty = FALSE;
indx = 1;
}
mident4(astack[0].m);
astack[0].scales.x = astack[0].scales.y = astack[0].scales.z = 1.0;
astack[0].maxscale = 1.0;
astack[0].s.txtlist = (tlist *)NULL;
astackp = astack;
linecount = 1;
strcpy(name, av[indx]);
if ((p = rindex(name, '.')) == (char *)NULL)
fatal("atomart: input file should end with \".scn\".\n");
strcpy(p, ".log");
if ((logfile = fopen(name, "w")) == NULL) {
sprintf(buf, "atomart: unable to open %s for writing.\n", name);
fatal(buf);
}
#ifdef MSC
if ((f = freopen(av[indx], "rt", stdin)) == NULL) {
#else
if ((f = freopen(av[indx], "r", stdin)) == NULL) {
#endif
sprintf(buf, "atomart: unable to open file %s.\n", av[1]);
fatal(buf);
}
yyparse(); /* read in model and set oblist */
polyobjs = (object *)NULL;
sphereobjs = (object *)NULL;
for (o = oblist; o != (object *)NULL; o = nxtobj) {
nxtobj = o->nxt;
if (o->type == POLYGON) {
o->nxt = polyobjs;
polyobjs = o;
} else {
o->nxt = sphereobjs;
sphereobjs = o;
}
}
objlist = sphereobjs;
oblist = treeinit(sphereobjs);
oblist->nxt = polyobjs;
strcpy(rindex(name, '.'), PIX_SUFFIX);
xsize = (unsigned short)atoi(av[indx + 1]);
ysize = (unsigned short)atoi(av[indx + 2]);
trans[0][0] *= xsize / (double)ysize;
if ((im = openimage(name, "w")) == (image *)NULL) {
sprintf(buf, "atomart: unable to open %s for writing\n", name);
fatal(buf);
}
imagetype(im) = filetype;
imagewidth(im) = xsize;
imageheight(im) = ysize;
imagedepth(im) = 24;
imagedate(im) = time((time_t *)NULL);
imagebackgnd(im).r = backcol.r * 255.0;
imagebackgnd(im).g = backcol.g * 255.0;
imagebackgnd(im).b = backcol.b * 255.0;
if (title == (char *)NULL)
titlelength(im) = 0;
else {
titlelength(im) = strlen(title) + 1;
imagetitle(im) = title;
}
writeheader(im);
switch (raysperpix) {
case 1:
xsperpix = 1;
ysperpix = 1;
break;
case 2:
xsperpix = 2;
ysperpix = 1;
break;
case 4:
xsperpix = 2;
ysperpix = 2;
break;
case 8:
xsperpix = 4;
ysperpix = 2;
break;
case 16:
xsperpix = 4;
ysperpix = 4;
break;
case 32:
xsperpix = 8;
ysperpix = 4;
break;
default:
fatal("atomart: bad number of rays per pixel - must be power of two\n");
}
xoff = xsize / 2;
yoff = ysize / 2;
if (xsize > ysize)
xscale = yscale = ysize / 2;
else
xscale = yscale = xsize / 2;
red = (unsigned char *)smalloc(xsize);
green = (unsigned char *)smalloc(xsize);
blue = (unsigned char *)smalloc(xsize);
alpha = (unsigned char *)smalloc(xsize);
if (chatty)
for (y = ysize - 1; y >= 0; y--) {
for (x = 0; x != xsize; x++) {
printf("\r((%03d), (%03d))", x, y);
dotrace(x, y, &red[x], &green[x], &blue[x], &alpha[x]);
}
if (alphachannel(im))
writergbaline(im, red, green, blue, alpha);
else
writergbline(im, red, green, blue);
}
else
for (y = ysize - 1; y >= 0; y--) {
for (x = 0; x != xsize; x++)
dotrace(x, y, &red[x], &green[x], &blue[x], &alpha[x]);
if (alphachannel(im))
writergbaline(im, red, green, blue, alpha);
else
writergbline(im, red, green, blue);
}
closeimage(im);
exit(0);
}
/*
* dotrace
*
* traces the neccessary number of rays and calculates r, g, b, and
* alpha info
*/
dotrace(x, y, r, g, b, a)
int x, y;
char *r, *g, *b, *a;
{
int i, j;
float red, green, blue, alpha;
float k1, k2;
hlist *hit, *p, *lp, *end;
pixel pix;
ray ir;
object *o;
red = green = blue = alpha = 0.0;
for (i = 0; i != xsperpix; i++)
for (j = 0; j != ysperpix; j++) {
if (raysperpix != 1) {
k1 = ((x - xoff) + (i + randnum()) / xsperpix) / xscale;
k2 = ((y - yoff) + (j + randnum()) / ysperpix) / yscale;
} else {
k1 = (x - xoff) / xscale;
k2 = (y - yoff) / yscale;
}
ir.org.x = k1;
ir.org.y = k2;
ir.org.z = 0;
ir.dir.x = k1;
ir.dir.y = k2;
ir.dir.z = focallength;
if (raynumber < 0) {
for (o = objlist; o != (object *)NULL; o = o->nxt)
o->raynumber = 0;
raynumber = 1;
}
ir.raynumber = raynumber++;
normalise(ir.dir);
if ((hit = trace(&ir, oblist)) != (hlist *)NULL) {
shade(&pix, &ir, hit, 0);
red += pix.r;
green += pix.g;
blue += pix.b;
alpha++;
release(hit);
} else {
red += backcol.r;
green += backcol.g;
blue += backcol.b;
}
}
if (alpha != 0.0) {
*r = (red / raysperpix) * 255.0 + randnum();
*g = (green / raysperpix) * 255.0 + randnum();
*b = (blue / raysperpix) * 255.0 + randnum();
*a = alpha * 255.0 / raysperpix;
} else {
*r = (red / raysperpix) * 255.0;
*g = (green / raysperpix) * 255.0;
*b = (blue / raysperpix) * 255.0;
*a = 0;
}
}