Path: utzoo!utgpu!cs.utexas.edu!usc!srhqla!avatar!kory From: kory@avatar.avatar.com (Kory Hamzeh) Newsgroups: alt.sources Subject: prt: a parallel raytracer. Part 3 of 3. Message-ID: <111@avatar.avatar.com> Date: 6 Dec 90 03:40:23 GMT Organization: Kory Hamzeh, Canoga Park, Ca, USA Lines: 916 Archive-name: prt/Part03 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'input.c' <<'END_OF_FILE' X X/* X * input.c - This files reads in and interperts the input file for rt. X * X * Copyright (C) 1990, Kory Hamzeh X */ X X#include X#include X#include X#include "rt.h" X#include "externs.h" X Xint Parse_from(), Parse_at(), Parse_up(), Parse_angle(), Parse_res(); Xint Parse_light(), Parse_bkgnd(), Parse_surface(), Parse_cone(); Xint Parse_sphere(), Parse_hallow_sphere(), Parse_poly(), Parse_ring(); Xint Parse_quadric(), Parse_instance(), Parse_end_instance(); Xint Parse_instanceof(); X Xchar *Get_token(), *strchr(); Xint iflag = 0; X X Xstruct parse_procs X{ X int (*parse) (); X char *token; X}; X X XFILE *in_fp; Xint line; Xchar line_buf[255], token[32], *info_ptr; Xchar *sp = "%lg %lg %lg %lg %lg %lg %lg %lg %lg %lg %lg %lg %lg %lg %lg %lg %lg %lg %lg"; X Xstruct parse_procs tokens[MAX_TOKENS] = X{ X {Parse_from, "from"}, X {Parse_at, "at"}, X {Parse_up, "up"}, X {Parse_angle, "angle"}, X {Parse_res, "resolution"}, X {Parse_light, "light"}, X {Parse_bkgnd, "background"}, X {Parse_surface, "surface"}, X {Parse_cone, "cone"}, X {Parse_sphere, "sphere"}, X {Parse_hallow_sphere, "hsphere"}, X {Parse_poly, "polygon"}, X {Parse_ring, "ring"}, X {Parse_quadric, "quadric"}, X {Parse_instance, "instance"}, X {Parse_end_instance, "end_instance"}, X {Parse_instanceof, "instance_of"} X}; X X/* X * Read_input_file() X * X * Read the input file given by the user. Interpert and build all of the X * required structures. X */ X XRead_input_file(filename) Xchar *filename; X{ X int i, rc; X char *p; X X if (filename) X { X if ((in_fp = fopen(input_file, "r")) == NULL) X { X fprintf(stderr, "%s: can't open input file '%s'\n", X my_name, input_file); X exit(1); X } X } X else X { X in_fp = stdin; X } X X line = 1; X X while (fgets(line_buf, sizeof(line_buf), in_fp)) X { X X if (verbose) X fprintf(stderr, "%s: parsing line %d\r", my_name, line); X X if (line_buf[0] == '#' || line_buf[0] == '\n') X { X ++line; X continue; X } X X if ((p = strchr(line_buf, '\n')) != NULL) X *p = 0; X X info_ptr = Get_token(line_buf, token); X X for (i = 0; i < MAX_TOKENS; i++) X { X if (!strcmp(tokens[i].token, token)) X break; X } X X X if (i == MAX_TOKENS) X { X fprintf(stderr, "%s: invalid token in line %d\n", my_name, X line); X } X else if ((*tokens[i].parse) () != 0) X { X Syntax_error(); X exit(1); X } X ++line; X } X X if (filename) X fclose(in_fp); X X} X X X/* X * Syntax_error() X * X * Pretty self explanatory. X */ X XSyntax_error() X{ X X fprintf(stderr, "%s: syntax error on line %d in input file\n", X my_name, line); X fclose(in_fp); X exit(1); X} X X X/* X * Get_token() X * X * Grab the token from the given line. Return a pointer to the next token in the X * line buffer. X */ X Xchar * XGet_token(ln, tk) Xchar *ln, *tk; X{ X char c; X X /* skip leading white spaces */ X X while (*ln && isspace(*ln)) X ++ln; X X do X { X c = *ln++; X if (c == ' ' || c == 0) X break; X X *tk++ = c; X } while (1); X X *tk = 0; X return (ln); X} X X/* X * Next_line() X * X * Read the next line from the input file and bump the line counter. Croak on X * EOF. X */ X XNext_line() X{ X ++line; X if (!fgets(line_buf, sizeof(line_buf), in_fp)) X { X fprintf(stderr, "%s: unexpected end-of-file\n", my_name); X exit(1); X } X} X X/* X * Bad_malloc() X * X * Malloc has failed. Print an error message on stderr and exit. X */ X XBad_malloc() X{ X X fprintf(stderr, "%s: malloc failed.\n", my_name); X exit(1); X} X X X/* X * Parse_from() X * X * Parse the from token. The format is: X * X * from x y z X * X */ X XParse_from() X{ X X if (sscanf(info_ptr, "%lg %lg %lg", &view.from.x, &view.from.y, X &view.from.z) != 3) X return (1); X else X return (0); X} X X/* X * Parse_at() X * X * Parse the at token. The format is: X * X * at x y z X * X */ X XParse_at() X{ X X if (sscanf(info_ptr, "%lg %lg %lg", &view.look_at.x, &view.look_at.y, X &view.look_at.z) != 3) X return (1); X else X return (0); X} X X X/* X * Parse_up() X * X * Parse the up token. The format is: X * X * up x y z X * X */ X XParse_up() X{ X X if (sscanf(info_ptr, "%lg %lg %lg", &view.up.x, &view.up.y, X &view.up.z) != 3) X return (1); X else X return (0); X} X X/* X * Parse_angle() X * X * Parse the angle token. The format is: X * X * angle fov X * X */ X XParse_angle() X{ X X if (sscanf(info_ptr, "%lg", &view.angle) != 1) X return (1); X else X return (0); X} X X X/* X * Parse_res() X * X * Parse the resolution token. The format is: X * X * resolution x_res y_res X * X */ X XParse_res() X{ X X if (sscanf(info_ptr, "%d %d", &view.x_res, &view.y_res) != 2) X return (1); X else X return (0); X} X X X X X/* X * Parse_light() X * X * Parse the positional light token. The format is: X * X * l x y z X * X */ X XParse_light() X{ X LIGHT *l; X X if (nlights == MAX_LIGHTS) X { X fprintf(stderr, "%s: too many light sources defined\n", my_name); X return (1); X } X X if ((l = (LIGHT *) calloc(1, sizeof(LIGHT))) == NULL) X Bad_malloc(); X X if (sscanf(info_ptr, "%lg %lg %lg", &l->pos.x, &l->pos.y, &l->pos.z) != 3) X return (1); X X lights[nlights++] = l; X return (0); X} X X X/* X * Parse_bkgnd() X * X * Parse the background token. The format is: X * X * b x y z c X * X */ X XParse_bkgnd() X{ X X if (sscanf(info_ptr, "%lg %lg %lg %c", &bkgnd.col.r, &bkgnd.col.g, X &bkgnd.col.b, &bkgnd.cue) != 4) X return (1); X X if (bkgnd.cue != 'n' && bkgnd.cue != 'x' && bkgnd.cue != 'y' && X bkgnd.cue != 'z') X return (1); X else X return (0); X} X X X/* X * Parse_surface() X * X * This one is a biggy. Parse the four million parameters will follow the X * surface info token. X */ X XParse_surface() X{ X SURFACE *s; X X if ((s = (SURFACE *) malloc(sizeof(SURFACE))) == NULL) X Bad_malloc(); X X if (sscanf(info_ptr, sp, X &s->c_reflect.r, &s->c_reflect.g, &s->c_reflect.b, &s->p_reflect, X &s->c_refract.r, &s->c_refract.g, &s->c_refract.b, &s->p_refract, X &s->c_ambient.r, &s->c_ambient.g, &s->c_ambient.b, X &s->c_diffuse.r, &s->c_diffuse.g, &s->c_diffuse.b, X &s->c_specular.r, &s->c_specular.g, &s->c_specular.b, X &s->spec_width, &s->i_refraction) != 19) X return (1); X X /* X * If we are in the middle of an instance, then jsut log it. X */ X X if (iflag) X Add_to_ilist(s, I_SURFACE, 0); X else X cur_surface = s; X return (0); X} X X X/* X * Parse_cone() X * X * Parse the cone primitive. X */ X XParse_cone() X{ X CONE *cd; X X if ((cd = (CONE *) malloc(sizeof(CONE))) == NULL) X Bad_malloc(); X X /* get the cone base info */ X Next_line(); X if (sscanf(line_buf, "%lg %lg %lg %lg", &cd->base.x, &cd->base.y, X &cd->base.z, &cd->base_radius) != 4) X return (1); X X /* and the apex stuff */ X Next_line(); X if (sscanf(line_buf, "%lg %lg %lg %lg", &cd->apex.x, &cd->apex.y, X &cd->apex.z, &cd->apex_radius) != 4) X return (1); X X if (iflag) X Add_to_ilist(cd, I_OBJECT, T_CONE); X else X Build_cone(cd); X return (0); X X} X X/* X * Parse_sphere() X * X * Parse the sphere primitive. X */ X XParse_sphere() X{ X SPHERE *s; X X if ((s = (SPHERE *) malloc(sizeof(SPHERE))) == NULL) X Bad_malloc(); X X if (sscanf(info_ptr, "%lg %lg %lg %lg", &s->center.x, &s->center.y, X &s->center.z, &s->radius) != 4) X return (1); X X X if (iflag) X Add_to_ilist(s, I_OBJECT, T_SPHERE); X else X Build_sphere(s); X return (0); X} X X/* X * Parse_hallow_sphere() X * X * Parse the hallow sphere primitive. The format is X * X * hsphere center.x center.y center.z radius tickness X */ X XParse_hallow_sphere() X{ X HSPHERE *s; X double thickness; X X if ((s = (HSPHERE *) malloc(sizeof(HSPHERE))) == NULL) X Bad_malloc(); X X if (sscanf(info_ptr, "%lg %lg %lg %lg %lg", &s->center.x, &s->center.y, X &s->center.z, &s->radius, &thickness) != 5) X return (1); X X s->i_radius = s->radius - thickness; X X if (iflag) X Add_to_ilist(s, I_OBJECT, T_HSPHERE); X else X Build_hsphere(s); X return (0); X} X X X/* X * Parse_poly() X * X * Parse the polygon verticies info. X */ X XParse_poly() X{ X int np, i; X POLYGON *p; X X /* get the number of points */ X if (sscanf(info_ptr, "%d", &np) != 1) X return (1); X X if ((p = (POLYGON *) malloc(sizeof(POLYGON) + (sizeof(VECTOR) * (np - 1)))) X == NULL) X Bad_malloc(); X X if (np < 3) X return (1); X X for (i = 0; i < np; i++) X { X Next_line(); X if (sscanf(line_buf, "%lg %lg %lg", &p->points[i].x, &p->points[i].y, X &p->points[i].z) != 3) X return (1); X } X X p->npoints = np; X X if (iflag) X Add_to_ilist(p, I_OBJECT, T_POLYGON); X else X Build_poly(p); X return (0); X} X X X X/* X * Parse_ring() X * X * Parse the ring primitive. The format is: X * X * ring center.x center.y center.z p1.x p1.y p1.z p2.x p2.y p2.z or ir X */ X XParse_ring() X{ X RING *r; X X if ((r = (RING *) malloc(sizeof(RING))) == NULL) X Bad_malloc(); X X if (sscanf(info_ptr, "%lg %lg %lg %lg %lg %lg %lg %lg %lg %lg %lg", X &r->center.x, &r->center.y, &r->center.z, X &r->point1.x, &r->point1.y, &r->point1.z, X &r->point2.x, &r->point2.y, &r->point2.z, X &r->o_radius, &r->i_radius) != 11) X return (1); X X if (iflag) X Add_to_ilist(r, I_OBJECT, T_RING); X else X Build_ring(r); X return (0); X} X X X/* X * Parse_quadric() X * X * Parse the quadric data type. The format is: X * X * quadric loc.x loc.y loc.z a b c d e f g h i j X */ X XParse_quadric() X{ X QUADRIC *q; X X /* X * Allocate a data structure. X */ X X if ((q = (QUADRIC *) malloc(sizeof(QUADRIC))) == NULL) X Bad_malloc(); X X /* X * Get the center of the quadratic. X */ X X if (sscanf(info_ptr, "%lg %lg %lg", &q->loc.x, &q->loc.y, &q->loc.z) != 3) X return (1); X X /* X * Get the min and max values. X */ X X Next_line(); X if (sscanf(line_buf, "%lg %lg %lg %lg %lg %lg", X &q->min.x, &q->min.y, &q->min.z, X &q->max.x, &q->max.y, &q->max.z) != 6) X return (1); X X /* X * Get the A, B, C, D, and E coefficients. X */ X X Next_line(); X if (sscanf(line_buf, "%lg %lg %lg %lg %lg", &q->a, &q->b, &q->c, &q->d, X &q->e) != 5) X return (1); X X /* X * Get the F, G, H, I, and J coefficients. X */ X X Next_line(); X if (sscanf(line_buf, "%lg %lg %lg %lg %lg", &q->f, &q->g, &q->h, &q->i, X &q->j) != 5) X return (1); X X if (iflag) X Add_to_ilist(q, I_OBJECT, T_QUADRIC); X else X Build_quadric(q); X return (0); X} X X X/* X * Parse_instance() X * X * Start a new instance definition here. X */ X XParse_instance() X{ X INSTANCE *i; X char name[128]; X X /* X * Instances can not be nested. X */ X X if (iflag) X { X fprintf(stderr, "%s: instance definitions can't be nested\n.", X my_name); X return (1); X } X X if (num_instance == MAX_INSTANCE) X { X fprintf(stderr, "%s: too many instances defined.\n"); X return (1); X } X X X /* X * Get the name for this instances. X */ X X Get_token(info_ptr, name); X if (strlen(name) < 1) X { X fprintf(stderr, "%s: missing or invalid instance label.\n", my_name); X return (1); X } X X if ((i = (INSTANCE *) malloc(sizeof(INSTANCE))) == NULL) X Bad_malloc(); X X if ((i->name = malloc(strlen(name))) == NULL) X Bad_malloc(); X X strcpy(i->name, name); X i->type = i->subtype = -1; X i->next = i->data = (void *) 0; X X instances[num_instance] = i; X iflag = 1; X return (0); X} X X/* X * Parse_end_instance() X * X * Clean up and save stuff. X */ X XParse_end_instance() X{ X X /* X * if we are not in an instance, itsa booboo. X */ X X if (!iflag) X { X fprintf(stderr, "%s: unexpected 'end_instance'.\n", my_name); X return (1); X } X X iflag = 0; X ++num_instance; X return (0); X} X X/* X * Parse_instanceof() X * X * Build the instance requested using the given offset. Format is X * X * instance_of fubar loc.x loc.y loc.z X */ X XParse_instanceof() X{ X INSTANCE *inst; X SPHERE *s; X HSPHERE *hs; X POLYGON *p, *p1; X CONE *c; X RING *r; X QUADRIC *q; X VECTOR off; X char name[32]; X int i, size; X X if (iflag) X { X fprintf(stderr, "%s: instance_of can't be used in an instance def.\n", X my_name); X return (1); X } X X /* get the instance name */ X info_ptr = Get_token(info_ptr, name); X X for (i = 0; i < num_instance; i++) X if (!strcmp(instances[i]->name, name)) X break; X X if (i == num_instance) X { X fprintf(stderr, "%s: instance '%s' was never defined.\n", my_name, X name); X return (1); X } X X inst = instances[i]; X X /* get the offset for this instance */ X if (sscanf(info_ptr, "%lg %lg %lg", &off.x, &off.y, &off.z) != 3) X { X fprintf(stderr, "%s: missing instance location.\n", my_name); X return (1); X } X X /* skip the first one */ X inst = inst->next; X X while (inst) X { X switch (inst->type) X { X case I_SURFACE: X cur_surface = (SURFACE *) inst->data; X break; X X case I_OBJECT: X switch (inst->subtype) X { X case T_POLYGON: X p1 = (POLYGON *) inst->data; X size = sizeof(POLYGON) + (sizeof(VECTOR) * (p1->npoints - 1)); X if ((p = (POLYGON *) malloc(size)) == NULL) X Bad_malloc(); X memcpy(p, p1, size); X X for (i = 0; i < p->npoints; i++) X { X VecAdd(off, p->points[i], p->points[i]); X } X Build_poly(p); X break; X X case T_SPHERE: X if ((s = (SPHERE *) malloc(sizeof(SPHERE))) == NULL) X Bad_malloc(); X X memcpy(s, inst->data, sizeof(SPHERE)); X X VecAdd(off, s->center, s->center); X Build_sphere(s); X break; X X case T_HSPHERE: X if ((hs = (HSPHERE *) malloc(sizeof(HSPHERE))) == NULL) X Bad_malloc(); X X memcpy(hs, inst->data, sizeof(HSPHERE)); X VecAdd(off, hs->center, hs->center); X Build_hsphere(hs); X break; X X case T_CONE: X if ((c = (CONE *) malloc(sizeof(CONE))) == NULL) X Bad_malloc(); X memcpy(c, inst->data, sizeof(CONE)); X X VecAdd(off, c->base, c->base); X VecAdd(off, c->apex, c->apex); X Build_cone(c); X break; X X case T_RING: X if ((r = (RING *) malloc(sizeof(RING))) == NULL) X Bad_malloc(); X memcpy(r, inst->data, sizeof(RING)); X X VecAdd(off, r->center, r->center); X VecAdd(off, r->point1, r->point1); X VecAdd(off, r->point2, r->point2); X X Build_ring(r); X break; X X case T_QUADRIC: X if ((q = (QUADRIC *) malloc(sizeof(QUADRIC))) == NULL) X Bad_malloc(); X memcpy(q, inst->data, sizeof(QUADRIC)); X X VecAdd(off, q->loc, q->loc); X VecAdd(off, q->min, q->min); X VecAdd(off, q->max, q->max); X X Build_quadric(q); X break; X X default: X fprintf(stderr, "%s: internal error 01.\n", my_name); X return (1); X } X break; X X default: X fprintf(stderr, "%s: internal error 02.\n", my_name); X return (1); X } X X inst = inst->next; X } X X return (0); X} X X X/* X * Add_to_ilist() X * X * Add the given object/surface to the end of the current instance link list. X */ X XAdd_to_ilist(data, type, subtype) Xvoid *data; Xint type; Xint subtype; X{ X INSTANCE *i1, *i2; X X /* allocate an instance structure */ X if ((i1 = (INSTANCE *) malloc(sizeof(INSTANCE))) == NULL) X Bad_malloc(); X X i2 = instances[num_instance]; X while (i2->next) X i2 = i2->next; X X i2->next = i1; X i1->next = (void *) 0; X i1->data = data; X i1->type = type; X i1->subtype = subtype; X X} END_OF_FILE if test 14772 -ne `wc -c <'input.c'`; then echo shar: \"'input.c'\" unpacked with wrong size! fi # end of 'input.c' fi echo shar: End of archive 3 \(of 3\). cp /dev/null ark3isdone MISSING="" for I in 1 2 3 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 3 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- ------------------------------------------------------------------------------- Kory Hamzeh UUCP: avatar!kory or ..!uunet!avatar!kory INTERNET: kory@avatar.com Brought to you by Super Global Mega Corp .com