home *** CD-ROM | disk | FTP | other *** search
- /* 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();
- }
-