/******************************************************* stacks and queues *******************************************************/ #include "qrt.h" #include "pattern.h" /* #define STACKDEBUG 1 */ char *malloc(); /********************************************************** Calls the pre-computing routine for each object in the object tree. The pre-computing routines figure out some sub-expressions that don't change with different calls to the intersection routines. **********************************************************/ Do_Precomp(node) OBJ_PTR node; { # ifdef STACKDEBUG printf("DOPRECOMP: type = %d\n", node->type); # endif (*(ObjData[node->type].PreComp))(node); /* precompute */ if (node->child != NULL) { /* node has children ? */ # ifdef ROBUST if (node->type != BBOX) Error(INTERNAL_ERROR,802); # endif Do_Precomp(node->child); } if (node->nextobj != NULL) { Do_Precomp(node->nextobj); } } /********************************************************** Assigns bounding box values for entire object tree. This must be called once before any ray-tracing is done. **********************************************************/ Make_Bbox(node) OBJ_PTR node; { OBJ_PTR tnode; VECTOR v1,v2; # ifdef STACKDEBUG printf("MAKEBBOX\n"); # endif if (node->child!=NULL) { /* node has children ? */ # ifdef ROBUST if (node->type!=BBOX) Error(INTERNAL_ERROR,801); # endif Make_Bbox(node->child); } if (node->nextobj!=NULL) { /* node has siblings ? */ Make_Bbox(node->nextobj); } if (node->type==BBOX) { tnode=node->child; node->lower.x=node->lower.y=node->lower.z= 3e30; node->upper.x=node->upper.y=node->upper.z= -3e30; while (tnode!=NULL) { (*(ObjData[tnode->type].FindBbox))(&v1,&v2,tnode); node->lower.x=MIN(node->lower.x,v1.x); node->lower.y=MIN(node->lower.y,v1.y); node->lower.z=MIN(node->lower.z,v1.z); node->upper.x=MAX(node->upper.x,v2.x); node->upper.y=MAX(node->upper.y,v2.y); node->upper.z=MAX(node->upper.z,v2.z); # ifdef STACKDEBUG printf("MAKEBBOX: v1 x,y,z = %f %f %f\n", node->lower.x,node->lower.y,node->lower.z); printf(" v2 x,y,z = %f %f %f\n", node->upper.x,node->upper.y,node->upper.z); # endif tnode=tnode->nextobj; } } } /********************************************************** Returns pointer to pattern structure given name, or null if not found. **********************************************************/ PATTERN_PTR find_pat(name) char *name; { PATTERN_PTR pat; pat=THEWORLD.patlist; while (pat!=NULL) { if (strcmp(name,pat->name)==0) return(pat); pat=pat->sibling; } return(NULL); } /********************************************************** Allocates a new pattern structure and returns a pointer to it. **********************************************************/ PATTERN_PTR new_pat() { PATTERN_PTR pat; if ((pat=(PATTERN_PTR)malloc(sizeof(PATTERN)))==NULL) Error(MALLOC_FAILURE,802); pat->name = NULL; pat->child = pat->sibling = pat->link = NULL; return(pat); } /********************************************************** Allocates a new object structure, stuffs most of its information fields, and returns a pointer to it. **********************************************************/ OBJ_PTR new_obj(type,loc,v1,v2,v3,cinfo,pattern,remove,name, upper, lower, cterm, xmult, ymult) VECT_PTR loc, v1, v2, v3, upper, lower; CINFO_PTR cinfo; PATTERN_PTR pattern, remove; float cterm, xmult, ymult; char *name; { OBJ_PTR obj; if ((obj=(OBJ_PTR)malloc(sizeof(OBJ_STRUCT)))==NULL) Error(MALLOC_FAILURE,803); obj->type=type; /* copy info */ VectEQ(&(obj->loc),loc); VectEQ(&(obj->vect1),v1); VectEQ(&(obj->vect2),v2); VectEQ(&(obj->vect3),v3); VectEQ(&(obj->lower),lower); VectEQ(&(obj->upper),upper); obj->cterm = cterm; obj->xmult = xmult; obj->ymult = ymult; obj->name = name; copy_colorinfo(&(obj->cinfo),cinfo); /* colorinfo */ obj->nextobj = obj->child = NULL; /* no relatives */ obj->pattern = pattern; obj->remove = remove; return(obj); } /********************************************************** Generates an empty line **********************************************************/ OBJ_PTR new_line() { CINFO cinfo; VECTOR loc,v1,v2,v3, upper, lower; OBJ_PTR line; VectEqZero(&loc); VectEqZero(&v1); VectEqZero(&v2); VectEqZero(&v3); VectEqZero(&upper); VectEqZero(&lower); line=new_obj(LINE,&loc,&v1,&v2,&v3,&cinfo,NULL,NULL,NULL, &upper,&lower,(float)0.0,(float)0.0,(float)0.0); line->flag = FALSE; return(line); } /********************************************************** Adds a lamp to the world **********************************************************/ add_lamp(object) /* add a lamp to the world */ OBJ_PTR object; { object->nextobj=THEWORLD.lamps; THEWORLD.lamps=object; } /********************************************************** Debugging routine to print object structure MAY BE WRONG BY NOW **********************************************************/ #ifdef STACKDEBUG print_obj(obj) /* display object */ OBJ_PTR obj; { printf("OBJECT : type: "); switch (obj->type) { case LINE: printf("LINE\n"); break; case SPHERE: printf("SPHERE\n"); break; case PARALLELOGRAM: printf("PARALLELOGRAM\n"); break; case TRIANGLE: printf("TRIANGLE\n"); break; case LAMP: printf("LAMP\n"); break; case OBSERVER: printf("OBSERVER\n"); break; case GROUND: printf("GROUND\n"); break; case SKY: printf("SKY\n"); break; case BBOX: printf("BBOX\n"); break; case RING: printf("RING\n"); break; case QUADRATIC: printf("QUADRATIC\n"); break; default: printf("Unknown!\n"); break; } printf(" loc : %f, %f, %f\n", (obj->loc.x), (obj->loc.y), (obj->loc.z)); printf(" vect1 : %f, %f, %f\n", (obj->vect1.x), (obj->vect1.y), (obj->vect1.z)); printf(" vect2 : %f, %f, %f\n", (obj->vect2.x), (obj->vect2.y), (obj->vect2.z)); printf(" vect3 : %f, %f, %f\n", (obj->vect3.x), (obj->vect3.y), (obj->vect3.z)); } #endif /********************************************************** Prints some interesting statistics **********************************************************/ World_Stats() { printf("World Statistics:\n"); printf(" Objects: %4d\n",THEWORLD.objcount); printf(" Lamps: %4d\n",THEWORLD.lampcount); printf(" Intersect tests : %-8ld\n", THEWORLD.intersect_tests); printf(" Total Intersections : %-8ld\n",(THEWORLD.ray_intersects+ THEWORLD.bbox_intersects)); printf(" Object intersections : %-8ld\n", THEWORLD.ray_intersects); printf(" Bbox intersections : %-8ld\n", THEWORLD.bbox_intersects); printf(" Rays traced : %-8ld\n",(THEWORLD.primary_traced+ THEWORLD.to_lamp+ THEWORLD.refl_trans)); printf(" Primary : %-8ld\n", THEWORLD.primary_traced); printf(" To lamps : %-8ld\n", THEWORLD.to_lamp); printf(" Refl. or Trans. : %-8ld\n", THEWORLD.refl_trans); printf(" Pattern match checks : %-8ld\n", THEWORLD.pattern_matches); printf("\n Data sent to: %s\n\n",THEWORLD.outfile); } /********************************************************** Open file, and send image size **********************************************************/ Open_File() { if ((THEWORLD.filept=fopen(THEWORLD.outfile,"w"))==NULL) Error(FILE_ERROR,804); fputc((unsigned char)(XSIZE & 0xff),THEWORLD.filept); fputc((unsigned char)(XSIZE >> 8), THEWORLD.filept); fputc((unsigned char)(YSIZE & 0xff),THEWORLD.filept); fputc((unsigned char)(YSIZE >> 8), THEWORLD.filept); } /********************************************************** Close file **********************************************************/ Close_File() { if (fclose(THEWORLD.filept)) Error(FILE_ERROR,805); }