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