home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
GEMini Atari
/
GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso
/
zip
/
graphics
/
utility
/
raymovi2.lzh
/
RAYMOVI2
/
MAIN.C
(
.txt
)
< prev
next >
Wrap
C/C++ Source or Header
|
1988-12-21
|
12KB
|
447 lines
/* main.c
*
*****************************************************************
* *
* basic ray tracing: *
* spheres and a floor (reflection, refraction and diffuse) *
* programmer: friedrich knauss *
* 7-4-86 to 7-21-86 *
* ported to st: allen king 5/87, added: *
* limited color *
* low rez display first *
* .25 to 16 rays per pixel *
* object definitions in file *
* multiple-frame movies *
* bouncing and gravity *
* *
*****************************************************************/
#include <stdio.h>
#include <math.h>
#include <osbind.h>
#include <gemdefs.h>
#include "rtd.h"
#define dprintf if (debug) printf
/* these definitions describe a window in the x-y plane
that the whole thing is viewd through. */
int XMIN, YMIN, XMAX, YMAX;
float xmin, ymax; /* floating pt versions */
wOnewSize(x,y, w,h)
int x,y, w,h;
{ XMIN = x; YMIN = y;
XMAX = x+w+2; YMAX = y+h+2;
}
/* Nomenclature notes:
* 1. <a>P<b> stands for "the number of <a>'s PER <b>
* 2. r stands for rays
* 3. p stands for pixels
* 4. s stands for either side of the screen
* 5. the suffix "Max" denotes the max number compiled into the program
*
* Note: these are linear (not area) conversions. A value of 2 rPp (rays PER
* pixel) is applied in both x and y directions to get an area (and more
* true to life) conversion of 4 (square) rays through each (square) pixel.
*/
float rPp; /* rays PER pixel (on a (linear) side)*/
# define rPpMax 4
/* maximum rays PER pixel (ditto) */
int pPs; /* pixels PER side (of screen) */
int rPs; /* rays PER side (of screen) */
int rPsMax; /* Max rays PER side (of screen) */
#define INC 1
#define INCY (1.25/rPpMax)
#define INCX (1.0/rPpMax)
int colorInd; /* color index (1->b/w, 2->2tones, 3->3tones)*/
#define colors(r,g,b) 1000*(2*(r)+1)/16, 1000*(2*(g)+1)/16, 1000*(2*(b)+1)/16,
int oldClut[16][3], trClut[][3] =
{
#include "colors.h"
0};
struct
{ int (*pal)[][3];
int Navg;
} cConfig[] = {{trClut, 16}, {trClut+16, 32}, {trClut+32, 43}};
FILE *fp, *fopen();
char getline();
char outname[6] = "pearl";
int wHandle;
int pxy_array[4];
#define Nball 15
struct ball bl[Nball];
int level,
nob;
struct vector vp;
float gravity = 0.0, attraction = 0.0;
int step, Step = 1000, bounce = 1;;
int fr=0, frames=1;
int debug =0;
struct sphere ls;
main ()
{ static float xco,
yco, yup;
struct ray rr;
int h, i, j, k;
int c, cr, cg, cb;
int x0, y0, x1, y1, dx, dy, dmax, xMax, yMax;
double red, green, blue; /* was int */
long ctr, BavgN;
float tmp;
char str[200], *buf;
int Navg, *avg, *Bavg;
rPp = 1.0;/* defaults: */
colorInd = 1;
/* graf_mouse(M_OFF, 0L);/**/
printf("\033E");
do
{ printf(" RAYMOVI.PRG\n\n");
printf("Enter scene descriptor\nfilename: ");
if (getline(str, sizeof(str)) == '\003')
exit(0);
printf("\nreading file %s\n", str);
} while(scene_inz(str) == 0);
printf("\033E");
wHandle = w_open(0, "raymovi", 0); /* open window (typeless, menueless) */
w_lClut(cConfig[colorInd-1].pal, oldClut);
v_hide_c(wHandle);
xmin = XMIN; ymax = YMAX;
dx = XMAX-XMIN;
dy = YMAX-YMIN;
if (rPp > 1.0001)
{ BavgN = (long)dx * dy * colorInd;
Bavg = Malloc(BavgN * sizeof(int));
if (Bavg == 0)
{ long l1;
printf("limited to 1 ray/pixel due to insufficient RAM\n");
if (rPp > 1.0)
rPp = 1.0;
for (l1=0; l1<200000; l1++);
}
for (tmp = 1.0; rPp >= 1.0001; tmp *= 2.0, rPp /= 2.0);
}
else
for (tmp = 1.0; rPp < .5001; tmp /= 2.0, rPp *= 2.0);
rPp = tmp;
dmax = (dx>dy)? dx: dy;
for (i=dmax-1, pPs=1; i>0 ; i>>=1, pPs<<=1);
for (i=rPp*pPs-0.5, rPs=1; i>0 ; i>>=1, rPs<<=1);
rPsMax = rPpMax * pPs;
xMax = ((long)rPsMax*dx)/pPs; yMax = ((long)rPsMax*dy)/pPs;
for (; fr<=frames; fr++)
{ int len, len1, p34, x, y, Elen, Ey;
redraw:
if (Bavg) for (avg = Bavg, ctr=0; ctr<BavgN; ctr++)
*avg++ = 0;
Navg = cConfig[colorInd-1].Navg;
ctr = 0;
for (len = rPsMax; len>= rPsMax/rPs; len /=2)
{ p34 = 3;
if (len>=rPpMax)
{ len1 = len/rPpMax - 1;
Elen = 0;
}else
{ len1 = 0;
Elen = rPpMax -1;
Navg *= 4;
}
for (y=0; y<yMax; y += len)
{ p34 = (p34 | 1) ^ 2;
if (Elen)
Ey = (((y + len)&Elen) == 0);
y0 = y/rPpMax;
y1 = y0 + YMIN;
pxy_array[1] = y1;
pxy_array[3] = y1 + len1;
yco = ymax - INCY*y;
for (x=0; x<xMax; x += len)
{ if ((p34 ^=1) == 0 && ctr !=0)
continue;
ctr++;
x0 = x/rPpMax;
x1 = x0 + XMIN;
pxy_array[0] = x1;
pxy_array[2] = x1 + len1;
xco = xmin + INCX*x;
/* define the ray through a pixel; find out value for that pixel */
mv (xco, yco, 0.0, &(rr.org));
sv (&(rr.dir), &(rr.org), &vp);
shade (&rr, &red, &green, &blue); /* find out color */
cb = blue;
cr = red;
cg = green;
if (Bavg) /* compute sum for all rays */
{ register int *array;
array = Bavg + ((long)y0*dx+x0+1)*colorInd;
switch(colorInd)
{ case 3:
cg = *--array += cg;
case 2:
cr = *--array += cr;
case 1:
cb = *--array += cb;
} }
if (Elen==0 || Ey && ((x+len)&Elen) == 0 )
{ switch(colorInd)
{ case 1: /* white (and black): */
c = (cb/Navg + 1) & 0xf; /* white */
break;
case 2: /* white and red: */
if (2*cr < 3*cb)
c = cb/Navg+1 & 7; /* white */
else c = (cr/Navg & 7) + 8; /* red */
break;
case 3: /* white, red, blue: */
if (4*cr > 3*(cg+cb))
{ c = cr/Navg % 6; /* red */
if (c) c += 5; /* red */
else c = 1;
}
else if (4*cb > 3*(cr+cg))
{ c = cb/Navg % 6; /* blue */
if (c) c += 10; /* red */
else c = 1;
}
else c = (cg/Navg+1) % 6; /* white */
break;
}
dprintf("%d,%d,%d -> %d\n", cr, cg, cb, c);
vsf_color(wHandle, c); /*draw colored box*/
v_bar(wHandle, pxy_array);
}
if ((ctr&15)== 0 && kbd() == -1)
goto redraw;
}
sprintf(str, "%s%03d: RAYMOVI.PRG rpp=%05.3f",
outname, fr, (float)ctr/((long)dx*dy));
di_header(1, str);
} }
sprintf(str, "%s%03d.pi1", outname, fr);
f_write(str, colorInd-1);
movie(&bl, nob, step, Step, gravity, bounce, attraction);
write_ckpt("checkpt");
}
exit:
w_lClut(oldClut, (long)0);
w_close();
}
kbd()
{ char key, fname[20];
int found_first = 0, fr1, rval=0;
if (Cconis() == 0)
return(0);
key = Cconin();
while (1)
{ sprintf(fname, "%s%03d.pi1", outname, fr);
switch(key)
{ case ('?'): case ('\0'): /* help */
printf("\033E\n\n RayMovi\n\
\nw - write \"%s\" from screen,\
\nr - read \"%s\" to screen,\
\np - play movie \"%sXXX.pi1\
\ne - exit\n\n", fname, fname, outname);
key = Cconin();
printf("\033E");
rval = -1;
break;
case ('D'):
debug = 1-debug;
return (rval);
case ('w'):
f_write(fname, colorInd-1);
return (rval);
case ('r'): case ('p'):
fr1 = 1;
while (key == 'p' || key == 'r')
{ sprintf(fname,"%s%03d.pi1", outname, fr1++);
if (f_read(fname, (long)0) <0)
{ if (found_first)
{ fr1 = 1;
found_first = 0;
} }
else
found_first = 1;
if (Cconis() != 0 || key == 'r' && found_first)
key = Cconin();
}
rval = -1;
break;
case ('e'): case('\003'):
w_lClut(oldClut, (long)0);
w_close();
exit(0);
default:
return(rval);
} } }
scene_inz(inz_file)
char *inz_file;
{ int h, i, j, k; char str[200], *buf;
if ((fp=fopen(inz_file, "r"))==0)
{ printf("can't open file '%s'\n", inz_file);
return(0);
}
j=0, h=0;
while (1)
{ int linenum;
buf = str;
for (k=0; (i = getc(fp)) != '\n' && i != EOF && ++k<sizeof(str)-1;)
*buf++ = i;
*buf = '\0';
linenum++;
printf("%d: %s\n", linenum, str);
buf = str;
if (i == EOF)
break;
switch (buf[0])
{ case ('p'): /* physical ball properties */
if (j >= Nball)
panic("**** ERROR: too many balls (%d >= %d)", j,Nball);
if (7 !=sscanf(buf+1," %f,%f,%f,%f,%f,%f,%f", &bl[j].s.cent.x,
&bl[j].v.x, &bl[j].s.cent.y, &bl[j].v.y,&bl[j].s.cent.z,
&bl[j].v.z, &bl[j].s.rad)) goto errors;
j++;
break;
case ('o'): /* optical ball properties */
if (h >= Nball)
panic("**** ERROR: Too many balls (%d >= %d)", h,Nball);
if(8 !=sscanf(buf+1," %f,%f,%f,%f,%f,%f,%f,%f", &bl[h].ior,
&bl[h].rfr, &bl[h].rfl, &bl[h].dif, &bl[h].amb,
&bl[h].red, &bl[h].green, &bl[h].blue)) goto errors;
bl[h].ior *= bl[h].ior;
h++;
break;
case ('v'): /* define viewpoint */
if (3 != sscanf(buf+1, " %f,%f,%f", &vp.x, &vp.y, &vp.z))
goto errors;
break;
case ('l'): /* define light source (rad = how fuzzy shadows are) */
if (4 != sscanf(buf+1, " %f,%f,%f,%f", &ls.cent.x, &ls.cent.y,
&ls.cent.z, &ls.rad)) goto errors;
break;
case ('r'): /* define number of rays per pixel and color scheme */
if (2 != sscanf(buf+1, " %f, %d", &rPp, &colorInd))
goto errors;
colorInd = colorInd<1? 1: colorInd>=3? 3: colorInd;
rPp = sqrt(rPp>16.0? 16.0: rPp);
break;
case ('g'): /* gravity, etc */
if (3 != sscanf(buf+1, " %f, %f, %d", &gravity, &attraction,
&bounce)) goto errors;
gravity /= Step * 10;
break;
case ('f'): /* define the filename */
while(*(++buf) == ' '); /* skip leading spaces */
for (i=0; i<5 && *buf!=','; i++)
outname[i] = *buf++;
outname[i] = 0;
if (2 != sscanf(buf+1, "%d,%d", &fr, &frames))
goto errors;
break;
case ('\t'): /* comment */
case (' '):
case ('\0'):
break;
default:
errors:
printf("**** ERROR in line %d:\n%s\n", linenum, buf);
} }
fclose(fp);
if (h != j)
panic("Number of 'o' lines (%ld) mismatches\n number of 'p' lines (%ld)\n",
(long)h, (long)j);
nob = j;
return(1);
}
write_ckpt(name)
char *name;
{ int i;
if ((fp = fopen(name, "w")) != 0)
{
fprintf(fp, "f %s, %d, %d\n", outname, fr+1, frames);
for (i=0; i<nob; i++)
{ fprintf(fp, "p %f,%f,%f,%f,%f,%f,%f\n", bl[i].s.cent.x,
bl[i].v.x, bl[i].s.cent.y, bl[i].v.y, bl[i].s.cent.z,
bl[i].v.z, bl[i].s.rad);
fprintf(fp, "o %f,%f,%f,%f,%f,%f, %f,%f,%f\n\n",sqrt(bl[i].ior),
bl[i].rfr, bl[i].rfl, bl[i].dif, bl[i].amb,
bl[i].red, bl[i].green,bl[i].blue);
}
fprintf(fp, "v %f,%f,%f\n", vp.x, vp.y,vp.z);
fprintf(fp, "l %f,%f,%f,%f\n",
ls.cent.x, ls.cent.y, ls.cent.z, ls.rad);
fprintf(fp, "r %f, %d\n", rPp*rPp, colorInd);
fprintf(fp, "g %f, %f, %d\n", gravity*Step* 10, attraction, bounce);
fclose(fp);
} }
char getline(str, sizeofstr)
char *str;
int sizeofstr;
{ char *buf, c;
int k, i;
buf = str;
for (k = sizeofstr; k > 0;)
{ c = i = Cconin();
if (c == '\n' || c == '\r' || c == ' ')
return (c);
else if (c == '\003' || c == '\214') /* ^c or Undo */
return ('\003');
else if (c == '\b')
{ if (k < sizeofstr)
{ *--buf = 0;
k++;
}else
printf(" ");
}
else
{ *buf++ = c;
*buf = '\0';
k--;
} } }
panic(s,l1,l2)
char *s;
long l1,l2;
{ printf("\n");
printf(s,l1,l2);
printf("\npress any key to continue");
Cconin();
if (wHandle)
{ w_lClut(oldClut, (long)0);
w_close();
}
exit(1);
atoi();
}