prt: a parallel raytracer. Part 3 of 3.
Kory Hamzeh
kory at avatar.avatar.com
Thu Dec 6 14:40:23 AEST 1990
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 <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 3 (of 3)."
# Contents: input.c
# Wrapped by kory at avatar on Wed Dec 5 18:23:23 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'input.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'input.c'\"
else
echo shar: Extracting \"'input.c'\" \(14772 characters\)
sed "s/^X//" >'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 <stdio.h>
X#include <malloc.h>
X#include <ctype.h>
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 at avatar.com
More information about the Alt.sources
mailing list