home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Encyclopedia of Graphics File Formats Companion
/
GFF_CD.ISO
/
formats
/
uray
/
code
/
support.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-06-20
|
11KB
|
369 lines
/************************************************************************
* *
* Copyright (c) 1988, David B. Wecker *
* All Rights Reserved *
* *
* This file is part of DBW_uRAY *
* *
* DBW_uRAY is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY. No author or distributor accepts *
* responsibility to anyone for the consequences of using it or for *
* whether it serves any particular purpose or works at all, unless *
* he says so in writing. Refer to the DBW_uRAY General Public *
* License for full details. *
* *
* Everyone is granted permission to copy, modify and redistribute *
* DBW_uRAY, but only under the conditions described in the *
* DBW_uRAY General Public License. A copy of this license is *
* supposed to have been given to you along with DBW_uRAY so you *
* can know your rights and responsibilities. It should be in a file *
* named LICENSE. Among other things, the copyright notice and this *
* notice must be preserved on all copies. *
************************************************************************
* *
* Authors: *
* DBW - David B. Wecker *
* *
* Versions: *
* V1.0 881023 DBW - First released version *
* V1.1 881110 DBW - Fixed scan coherence code *
* V1.2 881125 DBW - Removed ALL scan coherence code (useless) *
* added "fat" extent boxes *
* V1.3 881203 DBW - Fixed single precision TOLerances *
* *
************************************************************************/
#include "uray.h"
/************************************************************************/
/********************* support (misc) routines **************************/
/************************************************************************/
/* leave the program. if msg is not NULL then an error occurred */
/* also, return any used resources at this point */
void leave(msg,arg1,arg2)
char *msg,*arg1,*arg2;
{
/* are we writing a .tmp file */
if (bpp && fp) fclose(fp);
/* are we writing a .ilbm file (go back and put in the colortable) */
if (fp2) {
fseek(fp2,(long)pos2,0); wfil(fp2,4,&lsize);
lsize -= BODYsize;
lsize += FORMsize;
fseek(fp2,(long)pos1,0); wfil(fp2,4,&lsize);
fseek(fp2,(long)pos3,0);
fwrite(colors,1,48,fp2);
fclose(fp2);
}
/* is there an error message */
if (msg) {
fprintf(stderr,"\nURAY: ");
fprintf(stderr,msg,arg1,arg2);
fprintf(stderr,"\n");
exit(-2);
}
exit(1);
}
/* do a malloc and make sure that we got the memory */
char *my_malloc(size)
{
char *result,*malloc();
if (!(result = malloc(size))) leave("Can't malloc memory");
return result;
}
/* do a calloc and make sure that we got the memory */
char *my_calloc(size,num)
{
char *result,*calloc();
if (!(result = calloc(size,num))) leave("Can't calloc memory");
return result;
}
/* allocate and initialize a node (for input routine) */
NODE *doalloc(typ) {
NODE *nod;
EXTENT *newe;
/* get memory for the new object */
switch (typ) {
case TYP_E: nod = (NODE *)my_malloc(sizeof(EXTENT)); break;
case TYP_S: nod = (NODE *)my_malloc(sizeof(SPHERE)); break;
case TYP_T: nod = (NODE *)my_malloc(sizeof(TRIANGLE)); break;
case TYP_Q: nod = (NODE *)my_malloc(sizeof(QUAD)); break;
case TYP_R: nod = (NODE *)my_malloc(sizeof(RING)); break;
case TYP_L: nod = (NODE *)my_malloc(sizeof(LIGHT)); break;
}
if (typ == TYP_L) return;
nod->next = NULL;
nod->typ = typ;
/* if this is an extent, just return it */
if (typ == TYP_E) {
extcnt++;
return nod;
}
/* else get memory for an extent around the object (and count the obj) */
newe = (EXTENT *)doalloc(TYP_E);
newe->child = nod;
objcnt++;
/* and link it in to the extent tree */
newe->next = nodes;
nodes = (NODE *)newe;
/* return the object to the user */
return nod;
}
/* add a light to the list of lights (for fast lookup) */
void addlight(nod)
NODE *nod;
{
LIGHT *l;
if (nod->att->kl == 0.0) return;
l = (LIGHT *)doalloc(TYP_L);
l->next = lights;
l->child = nod;
lights = l;
}
/* debug routine (see DEBUG_dumpnodes in uray.h) for dumping nodes */
void dumpnodes(n,lev)
NODE *n;
{
int i;
EXTENT *e;
/* do each node at this level */
while (n) {
/* space over the current level amount */
for (i=0; i<lev; i++) printf(".");
/* print out type of node */
printf(" %c",TYPstr[n->typ]);
/* if an extent, then go down recursively */
if (n->typ == TYP_E) {
e = (EXTENT *)n;
if (e->child->typ != TYP_E) printf("%c",TYPstr[e->child->typ]);
else printf(" ");
/* print extent range */
printf(" [%7.4f,%7.4f] [%7.4f,%7.4f] [%7.4f,%7.4f]\n",
e->min[0],e->max[0],e->min[1],e->max[1],
e->min[2],e->max[2]);
/* do recursion */
if (e->child->typ == TYP_E) dumpnodes(e->child,lev+1);
}
/* get next node at this level */
n = n->next;
}
}
/* make vector into unit vector */
void vunit(A,B)
VEC A,B;
{
register FLTDBL tmp;
tmp = 1.0 / vnorm(A);
vscale(tmp, A, B);
}
/* find the normal to a sphere */
void spherenormal(intersect,s,normal)
VEC intersect,normal;
SPHERE *s;
{
VEC v1;
/* get the direction from the center */
vcomb(-1.0, intersect, s->cen, v1);
/* then normalize */
vunit(v1,normal);
}
/* find the normal to a plane */
void planenormal(s,normal)
QUAD *s;
VEC normal;
{
VEC v1;
/* first do vector cross product */
vcross(s->v1,s->v2,v1);
/* then normalize */
vunit(v1,normal);
}
/* read the input .dat file */
void readinput()
{
int i,j;
FLTDBL val;
int tmp1,tmp2;
/* get the input file open */
printf("Creating objects\n");
sprintf(str,"%s.dat",basnam);
fp = fopen(str,"r");
if (!fp) leave("Bad input file");
/* read each line of the file */
while (fgets(str,80,fp)) {
/* every legal (~comment) line must start with a string and a num */
if (sscanf(str,SCAN1,cmd,&val) != 2) continue;
/* read in the global parameters */
if (!strcmp(cmd,"DEPTH")) depth = (int)val;
else if (!strcmp(cmd,"ROWS")) rows = (short)val;
else if (!strcmp(cmd,"START")) startrow = (short)val;
else if (!strcmp(cmd,"END")) endrow = (short)val;
else if (!strcmp(cmd,"COLS")) cols = (short)val;
else if (!strcmp(cmd,"BPP")) bpp = (short)val;
else if (!strcmp(cmd,"AOV")) aov = (int)val;
else if (!strcmp(cmd,"ASPECT")) aspect = val;
else if (!strcmp(cmd,"NEAR"))
sscanf(str,SCAN2,cmd,&NEAR[0],&NEAR[1],&NEAR[2]);
else if (!strcmp(cmd,"FAR"))
sscanf(str,SCAN2,cmd,&FAR[0],&FAR[1],&FAR[2]);
else if (!strcmp(cmd,"GROUND"))
sscanf(str,SCAN2,cmd,&GROUND[0],&GROUND[1],&GROUND[2]);
else if (!strcmp(cmd,"BASE")) base = val;
/* read in attributes */
else if (!strcmp(cmd,"ATTRIBUTES")) {
natts = (int)val;
atts = (ATT *)my_calloc(sizeof(ATT),natts);
/* read in each attribute line */
for (i=0; i<natts; i++) {
fgets(str,80,fp);
if (sscanf(str,SCAN3,
&atts[i].color[0],&atts[i].color[1],&atts[i].color[2],
&atts[i].kd,&atts[i].ks,&atts[i].kt,&atts[i].ir,
&atts[i].kl,&atts[i].dist,&atts[i].kf,
&tmp1,&tmp2,
&atts[i].p1[0],&atts[i].p1[1],&atts[i].p1[2],
&atts[i].p2[0],&atts[i].p2[1],&atts[i].p2[2])
< 12
) leave("Bad attribute");
atts[i].wave = (short)tmp1;
atts[i].tex = (short)tmp2;
}
}
/* read in waves */
else if (!strcmp(cmd,"WAVES")) {
nwaves = (int)val;
waves = (WAVE *)my_calloc(sizeof(WAVE),nwaves);
/* read in each wave line */
for (i=0; i<nwaves; i++) {
fgets(str,80,fp);
if (sscanf(str,SCAN4,
&waves[i].cen[0],&waves[i].cen[1],&waves[i].cen[2],
&waves[i].amp,&waves[i].phase,&waves[i].length,
&waves[i].damp)
< 7) leave("Bad wave");
}
}
/* read in an object - SPHERE */
else if (!strcmp(cmd,"SPHERE")) {
sph = (SPHERE *)doalloc(TYP_S);
sscanf(str,SCAN5,cmd,&j,
&sph->cen[0],&sph->cen[1],&sph->cen[2],
&sph->rad);
sph->rad *= sph->rad;
sph->att = &atts[j];
if (sph->rad < TOL) sph->rad = TOL;
addlight(sph);
}
/* read in an object - QUAD */
else if (!strcmp(cmd,"QUAD")) {
qua = (QUAD *)doalloc(TYP_Q);
sscanf(str,SCAN6,cmd,&j,
&qua->p0[0],&qua->p0[1],&qua->p0[2],
&qua->v1[0],&qua->v1[1],&qua->v1[2],
&qua->v2[0],&qua->v2[1],&qua->v2[2]);
qua->att = &atts[j];
addlight(qua);
}
/* read in an object - TRIANGLE */
else if (!strcmp(cmd,"TRIANGLE")) {
tri = (TRIANGLE *)doalloc(TYP_T);
sscanf(str,SCAN6,cmd,&j,
&tri->p0[0],&tri->p0[1],&tri->p0[2],
&tri->v1[0],&tri->v1[1],&tri->v1[2],
&tri->v2[0],&tri->v2[1],&tri->v2[2]);
tri->att = &atts[j];
addlight(tri);
}
/* read in an object - RING */
else if (!strcmp(cmd,"RING")) {
rin = (RING *)doalloc(TYP_R);
sscanf(str,SCAN7,cmd,&j,
&rin->p0[0],&rin->p0[1],&rin->p0[2],
&rin->v1[0],&rin->v1[1],&rin->v1[2],
&rin->v2[0],&rin->v2[1],&rin->v2[2],
&rin->rad1,&rin->rad2);
rin->rad1 *= rin->rad1;
rin->rad2 *= rin->rad2;
rin->att = &atts[j];
vunit(rin->v1,rin->v1);
vunit(rin->v2,rin->v2);
addlight(rin);
}
}
/* fix up global parameters */
if (endrow > rows) endrow = rows;
if (startrow >= endrow) startrow = endrow - 1;
if (startrow < 0) startrow = 0;
cols &= 0xFFF8;
/* print out what we read in (sanity check) */
printf("\n");
printf(" Input file name: %14s\n",basnam);
printf(" Maximum recursion depth: %6d\n",depth);
printf(" Dimensions: %6d rows (%d,%d) %d columns\n",
rows,startrow,endrow,cols);
printf(" Bits/Pixel: %6d\n",bpp);
printf(" Angle of view: %6d degrees\n",aov);
printf(" Aspect ratio: %6.3f\n",(double)aspect);
printf(" Number of attributes: %6d\n",natts);
printf(" Number of waves: %6d\n",nwaves);
printf("\n");
/* terminate the input file */
fclose(fp);
fp = NULL;
}