prt: a parallel raytracer. Part 2 of 3.

Kory Hamzeh kory at avatar.avatar.com
Thu Dec 6 14:39:17 AEST 1990


Archive-name: prt/Part02


#! /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 2 (of 3)."
# Contents:  FORMAT cone.c example2.dat nff.y prt.c rt.h shade.c
# Wrapped by kory at avatar on Wed Dec  5 18:23:19 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'FORMAT' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'FORMAT'\"
else
echo shar: Extracting \"'FORMAT'\" \(5595 characters\)
sed "s/^X//" >'FORMAT' <<'END_OF_FILE'
X
X                           PRT INPUT FILE FORMAT
X                                 Version 1.0
X                        Copyright (C) Kory Hamzeh, 1990.
X
XInitially prt used the NFF file format. Then I started adding features to it,
Xand decided not to call it NFF since it wasn't NFF anymore (makes sense,
Xdoesn't it?).
X
XHere is a list of keywords:
X
X	from
X	at
X	up
X	angle
X	resolution
X	light
X	background
X	surface
X	cone
X	sphere
X	hsphere
X	polygon
X	ring
X	quadric
X	instance
X	end_instance
X	instance_of
X
XHere is an explanation of each keyword:
X
X----------
X
XEach input file must begin with the following keywords:
X
X    from %g %g %g
X    at %g %g %g
X    up %g %g %g
X    angle %g
X    resolution %d %d
X
XThe parameters are:
X
X    From:  the eye location in XYZ.
X    At:    a position to be at the center of the image, in XYZ world
X	   coordinates.  A.k.a. "lookat".
X    Up:    a vector defining which direction is up, as an XYZ vector.
X    Angle: in degrees, defined as from the center of top pixel row to
X	   bottom pixel row and left column to right column.
X    Resolution: in pixels, in x and in y.
X
X----------
X
XLight sources:
X
X	light X Y Z
X
XFormat:
X
X	light %g %g %g
X
XThis keyword defines the position of the light sources. All light sources
Xmust be defined before any objects are defined.
X
X----------
X
XBackground color:
X
X	background R G B y
X
XFormat:
X
X	background %g %g %g y
X
XThe background color in RGB. The last field is used for color cueing which
Xis not implemented yet and must always be 'y'.
X
X----------
X
XSurface properties:
X
X	surface Rr Rg Rb Ks  Fr Fg Fb T  Ar Ag Ab  Dr Dg Db  Sr Sg Sb P Ior
X
XFormat:
X
X	surface %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g
X
XThe parameters are:
X
X	Rr Rg Rb	The reflective color triplet. This value should always
X			be 1 1 1 unless you want this surface to reflect 
X			different percentage per color component.
X	Ks		The specular component. This value is the percentage
X			of light that is reflected from this object. A value
X			of 0 means no reflection, and a value of 1 means a 
X			perfect reflector (mirror).
X	Fr Fg Fb	The refractive color triplet. This value should always
X			be 1 1 1 unless you want this surface to refract
X			different percentage per color component.
X	T		Transparency value. The amount of light that can go
X			through this object. A value of 0 means a totally opaque
X			object. A value of 1 means a totally transparent object.
X	Ar Ag Ab	The ambient color for this object. This means the color
X			of an object if it were fully shadowed. All objects are
X			assigned this color before any shading algorithm is
X			started. 
X	Dr Dg Db	The diffuse color component.
X	Sr Sg Sb	This value is the color of the specular highlights.
X			Usually it should be 1 1 1.
X	P		The Phong cosine power for highlights. The higher the
X			number (for example 100), the smaller the highlight.
X	Ior		Index of refraction.
X
X---------
X
XCylinder or cone:
X
X	cone
X	base.x base.y base.z base_radius
X	apex.x apex.y apex.z apex_radius
X
XFormat:
X
X    cone
X    %g %g %g %g
X    %g %g %g %g
X
X
X--------
X
XSphere:
X
X	sphere center.x center.y center.z radius
X
XFormat:
X
X	sphere %g %g %g %g
X
X
X--------
X
XHollow sphere:
X
X	sphere center.x center.y center.z radius thickness
X
XFormat:
X
X	sphere %g %g %g %g %g
X
X--------
X
XPolygon:  A polygon is defined by a set of vertices.  With these databases,
X	a polygon is defined to have all points coplanar.  A polygon has only
X	one side, with the order of the vertices being counterclockwise as you
X	face the polygon (right-handed coordinate system).  The first two edges
X	must form a non-zero convex angle, so that the normal and side 
X	visibility can be determined.  Description:
X
X	polygon total_vertices
X	vert1.x vert1.y vert1.z
X	[etc. for total_vertices vertices]
X
XFormat:
X
X	polygon %d
X	[ %g %g %g ] <-- for total_vertices vertices
X
X--------
X
XRing:
X	A ring is a flat coplaner round shaped object. For a ring object,
X	you must specify the center, 2 points on the surface of the ring,
X	the inner radius, and the outer radius. If the inner radius is non-zero,
X	then the ring will have a hole in the middle with the given radius.
X
X	ring center.x center.y center.z p1.x p1.y p1.z p2.x p2.y p2.z or ir
X
XFormat:
X
X	ring %g %g %g  %g %g %g  %g %g %g  %g  %g
X
X----------
X
XQuadratic:
X
X	You can raytrace any quadratic object by specifying the center,
X	min, max, and coefficients. This is a very powerful object type.
X	It can do ellipsoids, hyperbolas, and any other quadratic surface.
X
X	quadric center.x center.y center.Z
X	min.x min.y min.z max.x max.y max.z
X	a b c d e 
X	f g h i j
X
X	The fields "a" through "j" are the coefficients.
X
XFormat:
X
X	quadric %g %g %g
X	%g %g %g  %g %g %g
X	%g %g %g %g %g
X	%g %g %g %g %g
X
X----------
X
XObject instances.
X
XDefining an object instance:
X
X	You may define a group of objects (and surface properties) to an 
X	instance and assign a name to that instance. When the instance
X	is then used, all the objects in that instance will be placed
X	relative to the given origin. Note that instances by themselves
X	do not create any objects; the objects are created when the 
X	instance is referenced. Instances can not be nested.
X
X	Instances are used as follows:
X
X		instance nameofthisinstance
X
X			[ objects and surface properties ]
X
X		end_instance
X
X	where "nameofthisinstance" is a user assigned name such
X	as, for example, "tile_pattern".
X
X	An instance is referenced as follows:
X
X		instance_of nameofinstance loc.x loc.y loc.z
X
X	where
X
X		nameofinstance is the name assigned to a previously
X		defined object instance.
X		loc.x, loc.y, loc.z, the location of this object group.
X
X
X----------
X
X                       ** END OF DOCUMENT **
X
END_OF_FILE
if test 5595 -ne `wc -c <'FORMAT'`; then
    echo shar: \"'FORMAT'\" unpacked with wrong size!
fi
# end of 'FORMAT'
fi
if test -f 'cone.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'cone.c'\"
else
echo shar: Extracting \"'cone.c'\" \(5612 characters\)
sed "s/^X//" >'cone.c' <<'END_OF_FILE'
X
X/*
X * cone.c
X * 
X * This module conatins all of the code which relates to cones and cylinders.
X * 
X * I must admit, MTV's code helped to "inspire" this module.
X *
X * Copyright (C) 1990, Kory Hamzeh.
X */
X
X
X#include <stdio.h>
X#include <math.h>
X#include "rt.h"
X#include "externs.h"
X
X
Xint             Cone_intersect(), Cone_normal();
X
X
X
XBuild_cone(cd)
XCONE           *cd;
X{
X	OBJECT         *obj;
X	double          dmin, dmax, d, ftmp;
X	VECTOR          tmp;
X	int             i;
X
X	if (nobjects == MAX_PRIMS)
X	{
X		fprintf(stderr, "%s: too many objects specified\n", my_name);
X		exit(1);
X	}
X
X	if ((obj = (OBJECT *) malloc(sizeof(OBJECT))) == NULL)
X	{
X		fprintf(stderr, "%s: malloc failed\n", my_name);
X		exit(1);
X	}
X
X	objects[nobjects++] = obj;
X
X	obj->type = T_CONE;
X	obj->inter = Cone_intersect;
X	obj->normal = Cone_normal;
X	obj->surf = cur_surface;
X
X	VecSub(cd->apex, cd->base, cd->w);
X	cd->height = VecNormalize(&cd->w);
X	cd->slope = (cd->apex_radius - cd->base_radius) / (cd->height);
X	cd->base_d = -VecDot(cd->base, cd->w);
X
X	tmp.x = 0;
X	tmp.y = 0;
X	tmp.z = 1;
X
X	if (1.0 - fabs(VecDot(tmp, cd->w)) < MIN_T)
X	{
X		tmp.y = 1;
X		tmp.x = 0;
X	}
X
X	/*
X	 * find two axes which are at right angles to cone_w
X	 */
X
X	VecCross(cd->w, tmp, cd->u);
X	VecCross(cd->u, cd->w, cd->v);
X
X	VecNormalize(&cd->u);
X	VecNormalize(&cd->v);
X
X	cd->min_d = VecDot(cd->w, cd->base);
X	cd->max_d = VecDot(cd->w, cd->apex);
X
X	if (cd->max_d < cd->min_d)
X	{
X		ftmp = cd->max_d;
X		cd->max_d = cd->min_d;
X		cd->min_d = ftmp;
X	}
X
X	obj->obj = cd;
X
X	/*
X	 * Create the bounding box for this puppy.
X	 */
X
X	dmin = HUGE;
X	dmax = -HUGE;
X
X	/* first the X plane */
X	d = cd->base.x - cd->base_radius;
X
X	if (d < dmin)
X		dmin = d;
X	if (d > dmax)
X		dmax = d;
X
X	d = cd->base.x + cd->base_radius;
X
X	if (d < dmin)
X		dmin = d;
X	if (d > dmax)
X		dmax = d;
X
X	d = cd->apex.x - cd->apex_radius;
X	if (d < dmin)
X		dmin = d;
X	if (d > dmax)
X		dmax = d;
X
X	d = cd->apex.x + cd->apex_radius;
X	if (d < dmin)
X		dmin = d;
X	if (d > dmax)
X		dmax = d;
X
X	obj->b_min.x = dmin;
X	obj->b_max.x = dmax;
X
X	/* now the Y plane */
X	dmin = HUGE;
X	dmax = -HUGE;
X
X	d = cd->base.y - cd->base_radius;
X
X	if (d < dmin)
X		dmin = d;
X	if (d > dmax)
X		dmax = d;
X
X	d = cd->base.y + cd->base_radius;
X
X	if (d < dmin)
X		dmin = d;
X	if (d > dmax)
X		dmax = d;
X
X	d = cd->apex.y - cd->apex_radius;
X	if (d < dmin)
X		dmin = d;
X	if (d > dmax)
X		dmax = d;
X
X	d = cd->apex.y + cd->apex_radius;
X	if (d < dmin)
X		dmin = d;
X	if (d > dmax)
X		dmax = d;
X
X	obj->b_min.y = dmin;
X	obj->b_max.y = dmax;
X
X	/* and finally the Z plane */
X	dmin = HUGE;
X	dmax = -HUGE;
X
X	d = cd->base.z - cd->base_radius;
X
X	if (d < dmin)
X		dmin = d;
X	if (d > dmax)
X		dmax = d;
X
X	d = cd->base.z + cd->base_radius;
X
X	if (d < dmin)
X		dmin = d;
X	if (d > dmax)
X		dmax = d;
X
X	d = cd->apex.z - cd->apex_radius;
X	if (d < dmin)
X		dmin = d;
X	if (d > dmax)
X		dmax = d;
X
X	d = cd->apex.z + cd->apex_radius;
X	if (d < dmin)
X		dmin = d;
X	if (d > dmax)
X		dmax = d;
X
X	obj->b_min.z = dmin;
X	obj->b_max.z = dmax;
X}
X
X
XCone_intersect(obj, ray, inter)
XOBJECT         *obj;
XRAY            *ray;
XINTERSECT      *inter;
X{
X	RAY             tray;
X	CONE           *cd;
X	VECTOR          v, p;
X	double          a, b, c, d, disc;
X	double          t1, t2;
X	int             nroots;
X
X	cd = (CONE *) (obj->obj);
X
X	/*
X	 * First, we get the coordinates of the ray origin in the objects
X	 * space....
X	 */
X
X	VecSub(ray->pos, cd->base, v);
X
X	tray.pos.x = VecDot(v, cd->u);
X	tray.pos.y = VecDot(v, cd->v);
X	tray.pos.z = VecDot(v, cd->w);
X
X	tray.dir.x = VecDot(ray->dir, cd->u);
X	tray.dir.y = VecDot(ray->dir, cd->v);
X	tray.dir.z = VecDot(ray->dir, cd->w);
X
X
X	a = tray.dir.x * tray.dir.x
X		+ tray.dir.y * tray.dir.y
X		- cd->slope * cd->slope * tray.dir.z * tray.dir.z;
X
X	b = 2.0 * (tray.pos.x * tray.dir.x + tray.pos.y * tray.dir.y -
X		   cd->slope * cd->slope * tray.pos.z * tray.dir.z
X		   - cd->base_radius * cd->slope * tray.dir.z);
X
X	c = cd->slope * tray.pos.z + cd->base_radius;
X	c = tray.pos.x * tray.pos.x + tray.pos.y * tray.pos.y - (c * c);
X
X	disc = b * b - 4.0 * a * c;
X
X	if (disc < 0.0)
X		return (0);
X
X	disc = sqrt(disc);
X	t1 = (-b - disc) / (2.0 * a);
X	t2 = (-b + disc) / (2.0 * a);
X
X	if (t2 < MIN_T)
X		return (0);
X
X	if (t1 < MIN_T)
X	{
X		nroots = 1;
X		t1 = t2;
X	}
X	else
X	{
X		nroots = 2;
X	}
X
X	/*
X	 * ensure that the points are between the two bounding planes...
X	 */
X
X	switch (nroots)
X	{
X	case 1:
X		VecAddS(t1, ray->dir, ray->pos, p);
X		d = VecDot(cd->w, p);
X
X		if (d >= cd->min_d && d <= cd->max_d)
X		{
X			inter->t = t1;
X			inter->obj = obj;
X			inter->inside = 1;
X			return (1);
X		}
X		else
X		{
X			return (0);
X		}
X		break;
X
X	case 2:
X		VecAddS(t1, ray->dir, ray->pos, p);
X		d = VecDot(cd->w, p);
X
X		if (d >= cd->min_d && d <= cd->max_d)
X		{
X			inter->t = t1;
X			inter->obj = obj;
X			inter->inside = 0;
X			return (1);
X		}
X		else
X		{
X			VecAddS(t2, ray->dir, ray->pos, p);
X			d = VecDot(cd->w, p);
X			if (d >= cd->min_d && d <= cd->max_d)
X			{
X				inter->t = t2;
X				inter->obj = obj;
X				inter->inside = 1;
X				return (1);
X			}
X		}
X		return (0);
X	}
X	return (0);
X}
X
X
XCone_normal(cone, ray, ip, normal)
XCONE           *cone;
XRAY            *ray;
XVECTOR         *ip;
XVECTOR         *normal;
X{
X	VECTOR          v;
X	double          t;
X
X	/*
X	 * fill in the real normal... Project the point onto the base plane.
X	 * The normal is a vector from the basepoint through this point, plus
X	 * the slope times the cone_w vector...
X	 */
X
X	t = -(VecDot(*ip, cone->w) + cone->base_d);
X	VecAddS(t, cone->w, *ip, v);
X	VecSub(v, cone->base, *normal);
X	VecNormalize(normal);
X	VecAddS(-cone->slope, cone->w, *normal, *normal);
X	VecNormalize(normal);
X	if (VecDot(ray->dir, *normal) >= 0)
X		VecNegate(*normal);
X}
END_OF_FILE
if test 5612 -ne `wc -c <'cone.c'`; then
    echo shar: \"'cone.c'\" unpacked with wrong size!
fi
# end of 'cone.c'
fi
if test -f 'example2.dat' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'example2.dat'\"
else
echo shar: Extracting \"'example2.dat'\" \(5604 characters\)
sed "s/^X//" >'example2.dat' <<'END_OF_FILE'
X#
Xfrom 2 2 5
Xat 2 2 0
Xup 0 1 0
Xangle 40 
Xresolution 512 512 
Xbackground .3 .3 .9 n
Xlight 6 6 8 
Xlight -4 7 8
X#
X#
Xinstance tile
Xpolygon 4
X0 0 0
X0.25 0 0
X0.25 0 0.25
X0 0 0.25
Xpolygon 4
X0.25 0 0.25
X0.50 0 0.25
X0.50 0 0.50
X0.25 0 0.50
Xend_instance
X#
X# floor
X#
Xsurface 1 1 1 .9  0 0 0 0  .4 .4 .4   .5 .5 .5  1 1 1  30 0
Xsphere 1.8 2.4 1 0.7
Xsurface 1 1 1 .7  0 0 0 0  .1 .1 .1  .1 .1 .1   1 1 1  30 0
Xcone 
X3.5 1.5 1 0.3   
X2.5 1.5 -0.5 0.3
Xsurface 1 1 1 0.2 1 1 1 0.9 0 0 0 0 0 0 1 1 1 40 1.5
Xsphere 0.8 1.5 1 0.4
X#
Xsurface 0 0 0 0  0 0 0 0  0 .4 .4  0 .5 .5  0 0 0 0 0
Xpolygon 4
X-1 0.999 -4
X5 0.999 -4
X5 0.999 4
X-1 0.999 4
Xsurface 0 0 0 0  0 0 0 0  .4 0 0    .55 0 0  0 0 0 0 0
Xinstance_of tile -1 1 -4
Xinstance_of tile -0.5 1 -4
Xinstance_of tile 0 1 -4
Xinstance_of tile 0.5 1 -4
Xinstance_of tile 1 1 -4
Xinstance_of tile 1.5 1 -4
Xinstance_of tile 2 1 -4
Xinstance_of tile 2.5 1 -4
Xinstance_of tile 3 1 -4
Xinstance_of tile 3.5 1 -4
Xinstance_of tile 4 1 -4
Xinstance_of tile 4.5 1 -4
Xinstance_of tile -1 1 -3.5
Xinstance_of tile -0.5 1 -3.5
Xinstance_of tile 0 1 -3.5
Xinstance_of tile 0.5 1 -3.5
Xinstance_of tile 1 1 -3.5
Xinstance_of tile 1.5 1 -3.5
Xinstance_of tile 2 1 -3.5
Xinstance_of tile 2.5 1 -3.5
Xinstance_of tile 3 1 -3.5
Xinstance_of tile 3.5 1 -3.5
Xinstance_of tile 4 1 -3.5
Xinstance_of tile 4.5 1 -3.5
Xinstance_of tile -1 1 -3
Xinstance_of tile -0.5 1 -3
Xinstance_of tile 0 1 -3
Xinstance_of tile 0.5 1 -3
Xinstance_of tile 1 1 -3
Xinstance_of tile 1.5 1 -3
Xinstance_of tile 2 1 -3
Xinstance_of tile 2.5 1 -3
Xinstance_of tile 3 1 -3
Xinstance_of tile 3.5 1 -3
Xinstance_of tile 4 1 -3
Xinstance_of tile 4.5 1 -3
Xinstance_of tile -1 1 -2.5
Xinstance_of tile -0.5 1 -2.5
Xinstance_of tile 0 1 -2.5
Xinstance_of tile 0.5 1 -2.5
Xinstance_of tile 1 1 -2.5
Xinstance_of tile 1.5 1 -2.5
Xinstance_of tile 2 1 -2.5
Xinstance_of tile 2.5 1 -2.5
Xinstance_of tile 3 1 -2.5
Xinstance_of tile 3.5 1 -2.5
Xinstance_of tile 4 1 -2.5
Xinstance_of tile 4.5 1 -2.5
Xinstance_of tile -1 1 -2
Xinstance_of tile -0.5 1 -2
Xinstance_of tile 0 1 -2
Xinstance_of tile 0.5 1 -2
Xinstance_of tile 1 1 -2
Xinstance_of tile 1.5 1 -2
Xinstance_of tile 2 1 -2
Xinstance_of tile 2.5 1 -2
Xinstance_of tile 3 1 -2
Xinstance_of tile 3.5 1 -2
Xinstance_of tile 4 1 -2
Xinstance_of tile 4.5 1 -2
Xinstance_of tile -1 1 -1.5
Xinstance_of tile -0.5 1 -1.5
Xinstance_of tile 0 1 -1.5
Xinstance_of tile 0.5 1 -1.5
Xinstance_of tile 1 1 -1.5
Xinstance_of tile 1.5 1 -1.5
Xinstance_of tile 2 1 -1.5
Xinstance_of tile 2.5 1 -1.5
Xinstance_of tile 3 1 -1.5
Xinstance_of tile 3.5 1 -1.5
Xinstance_of tile 4 1 -1.5
Xinstance_of tile 4.5 1 -1.5
Xinstance_of tile -1 1 -1
Xinstance_of tile -0.5 1 -1
Xinstance_of tile 0 1 -1
Xinstance_of tile 0.5 1 -1
Xinstance_of tile 1 1 -1
Xinstance_of tile 1.5 1 -1
Xinstance_of tile 2 1 -1
Xinstance_of tile 2.5 1 -1
Xinstance_of tile 3 1 -1
Xinstance_of tile 3.5 1 -1
Xinstance_of tile 4 1 -1
Xinstance_of tile 4.5 1 -1
Xinstance_of tile -1 1 -0.5
Xinstance_of tile -0.5 1 -0.5
Xinstance_of tile 0 1 -0.5
Xinstance_of tile 0.5 1 -0.5
Xinstance_of tile 1 1 -0.5
Xinstance_of tile 1.5 1 -0.5
Xinstance_of tile 2 1 -0.5
Xinstance_of tile 2.5 1 -0.5
Xinstance_of tile 3 1 -0.5
Xinstance_of tile 3.5 1 -0.5
Xinstance_of tile 4 1 -0.5
Xinstance_of tile 4.5 1 -0.5
Xinstance_of tile -1 1 0
Xinstance_of tile -0.5 1 0
Xinstance_of tile 0 1 0
Xinstance_of tile 0.5 1 0
Xinstance_of tile 1 1 0
Xinstance_of tile 1.5 1 0
Xinstance_of tile 2 1 0
Xinstance_of tile 2.5 1 0
Xinstance_of tile 3 1 0
Xinstance_of tile 3.5 1 0
Xinstance_of tile 4 1 0
Xinstance_of tile 4.5 1 0
Xinstance_of tile -1 1 0.5
Xinstance_of tile -0.5 1 0.5
Xinstance_of tile 0 1 0.5
Xinstance_of tile 0.5 1 0.5
Xinstance_of tile 1 1 0.5
Xinstance_of tile 1.5 1 0.5
Xinstance_of tile 2 1 0.5
Xinstance_of tile 2.5 1 0.5
Xinstance_of tile 3 1 0.5
Xinstance_of tile 3.5 1 0.5
Xinstance_of tile 4 1 0.5
Xinstance_of tile 4.5 1 0.5
Xinstance_of tile -1 1 1
Xinstance_of tile -0.5 1 1
Xinstance_of tile 0 1 1
Xinstance_of tile 0.5 1 1
Xinstance_of tile 1 1 1
Xinstance_of tile 1.5 1 1
Xinstance_of tile 2 1 1
Xinstance_of tile 2.5 1 1
Xinstance_of tile 3 1 1
Xinstance_of tile 3.5 1 1
Xinstance_of tile 4 1 1
Xinstance_of tile 4.5 1 1
Xinstance_of tile -1 1 1.5
Xinstance_of tile -0.5 1 1.5
Xinstance_of tile 0 1 1.5
Xinstance_of tile 0.5 1 1.5
Xinstance_of tile 1 1 1.5
Xinstance_of tile 1.5 1 1.5
Xinstance_of tile 2 1 1.5
Xinstance_of tile 2.5 1 1.5
Xinstance_of tile 3 1 1.5
Xinstance_of tile 3.5 1 1.5
Xinstance_of tile 4 1 1.5
Xinstance_of tile 4.5 1 1.5
Xinstance_of tile -1 1 2
Xinstance_of tile -0.5 1 2
Xinstance_of tile 0 1 2
Xinstance_of tile 0.5 1 2
Xinstance_of tile 1 1 2
Xinstance_of tile 1.5 1 2
Xinstance_of tile 2 1 2
Xinstance_of tile 2.5 1 2
Xinstance_of tile 3 1 2
Xinstance_of tile 3.5 1 2
Xinstance_of tile 4 1 2
Xinstance_of tile 4.5 1 2
Xinstance_of tile -1 1 2.5
Xinstance_of tile -0.5 1 2.5
Xinstance_of tile 0 1 2.5
Xinstance_of tile 0.5 1 2.5
Xinstance_of tile 1 1 2.5
Xinstance_of tile 1.5 1 2.5
Xinstance_of tile 2 1 2.5
Xinstance_of tile 2.5 1 2.5
Xinstance_of tile 3 1 2.5
Xinstance_of tile 3.5 1 2.5
Xinstance_of tile 4 1 2.5
Xinstance_of tile 4.5 1 2.5
Xinstance_of tile -1 1 3
Xinstance_of tile -0.5 1 3
Xinstance_of tile 0 1 3
Xinstance_of tile 0.5 1 3
Xinstance_of tile 1 1 3
Xinstance_of tile 1.5 1 3
Xinstance_of tile 2 1 3
Xinstance_of tile 2.5 1 3
Xinstance_of tile 3 1 3
Xinstance_of tile 3.5 1 3
Xinstance_of tile 4 1 3
Xinstance_of tile 4.5 1 3
Xinstance_of tile -1 1 3.5
Xinstance_of tile -0.5 1 3.5
Xinstance_of tile 0 1 3.5
Xinstance_of tile 0.5 1 3.5
Xinstance_of tile 1 1 3.5
Xinstance_of tile 1.5 1 3.5
Xinstance_of tile 2 1 3.5
Xinstance_of tile 2.5 1 3.5
Xinstance_of tile 3 1 3.5
Xinstance_of tile 3.5 1 3.5
Xinstance_of tile 4 1 3.5
Xinstance_of tile 4.5 1 3.5
END_OF_FILE
if test 5604 -ne `wc -c <'example2.dat'`; then
    echo shar: \"'example2.dat'\" unpacked with wrong size!
fi
# end of 'example2.dat'
fi
if test -f 'nff.y' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'nff.y'\"
else
echo shar: Extracting \"'nff.y'\" \(9364 characters\)
sed "s/^X//" >'nff.y' <<'END_OF_FILE'
X%{
X#include <stdio.h>
X#include <math.h>
X
Xtypedef double Flt ;
Xtypedef Flt Vec[3] ;
Xtypedef Vec Point ;
Xtypedef Vec Color ;
X
Xchar *Progname;
Xint yylinecount = 1;
Xextern char yytext[] ;
Xextern FILE * yyin ;
XVec * pl, * plist ;
X%}
X
X%token VIEWPOINT FROM AT UP ANGLE HITHER RESOLUTION LIGHT
X%token BACKGROUND SURFACE CONE SPHERE POLYGON PATCH NUM TOKEN
X
X%union {
X	Vec	vec ;
X	Vec *	vecl ;
X	double	flt ;
X} ;
X
X%type <vec>	point primcolor TOKEN
X%type <obj>	cone sphere polygon ppatch
X%type <flt>	num 
X
X%%
X
Xscene:
X	camera elementlist ;
X
Xelementlist:
X	elementlist element
X	|  ;
X
Xelement:
X	light
X	| background
X	| surface
X	| object ;
X
Xobject:	  cone
X	| sphere
X	| polygon
X	| ppatch ;
X
Xcamera:
X	VIEWPOINT			/* $1      */
X	FROM point			/* $2-$3   */
X	AT point			/* $4-$5   */
X	UP point			/* $6-$7   */
X	ANGLE num 			/* $8-$9   */
X	HITHER num			/* $10-$11 */
X	RESOLUTION num num		/* $12-$14 */
X	{
X		printf("from %g %g %g\n", $3[0], $3[1], $3[2]);
X		printf("at %g %g %g\n", $5[0], $5[1], $5[2]);
X		printf("up %g %g %g\n", $7[0], $7[1], $7[2]);
X		printf("angle %g\n", $11);
X		printf("resolution %d %d\n", (int) $13, (int) $14);
X	} ;
X
Xlight:
X	LIGHT point 
X	{
X		printf("light %g %g %g\n", $2[0], $2[1], $2[2]);
X	} ;
X
Xbackground:
X	BACKGROUND primcolor
X	{
X		printf("background %g %g %g n\n", $2[0], $2[1], $2[2]);
X	} ;
X
Xsurface:
X	SURFACE primcolor num num num num num 
X	{
X		printf("surface 1 1 1 %g  1 1 1 %g ", $4, $6);
X		printf("%g %g %g   %g %g %g  1 1 1  %g %g\n",
X			$2[0] * 0.3, $2[1] * 0.3, $2[2] * 0.3,
X			$2[0] * 0.7, $2[1] * 0.7, $2[2] * 0.7,
X			$5, $7);
X	} ;
X
Xcone:
X	CONE point num point num 
X	{
X		printf("cone %g %g %g  %g  %g %g %g  %g\n",
X			$2[0], $2[1], $2[2], $3, $4[0], $4[1], $4[2], $5);
X	} ;
X
Xsphere:
X	SPHERE point num 
X	{
X		printf("sphere %g %g %g  %g\n",
X			$2[0], $2[1], $2[2], $3);
X	} ;
X
Xpolygon:
X	POLYGON num 
X	{
X		printf("polygon %d\n", (int) $2);
X	} 
X	pointlist 
X	{
X
X	} ;
X
Xppatch:
X	PATCH num
X        {
X		fprintf(stderr, "%s: sorry, rt doesn't support polygon patches.\n",
X			Progname);
X	} ;
X
Xprimcolor:
X	num num num 
X	{
X		$$[0] = $1 ;
X		$$[1] = $2 ;
X		$$[2] = $3 ;
X	} 
X	| TOKEN
X	{
X		char buf[80] ;
X
X		if (LookupColorByName(yytext, $$) == 0) {
X			sprintf(buf, "cannot find color \"%s\"\n",
X				yytext) ;
X			yyerror(buf) ;
X		}
X	} ;
X
X
Xpoint:
X	num num num
X	{
X		$$[0] = $1 ;
X		$$[1] = $2 ;
X		$$[2] = $3 ;
X	} ;
X
Xpointlist:
X	pointlist point
X	{
X		printf("%g %g %g\n", $2[0], $2[1], $2[2]);
X	}
X	| ;
X	
X
Xnum:
X	NUM
X		{
X			$$ = atof(yytext) ;
X		} ;
X
X%%
X
Xyyerror(str)
X char * str ;
X{
X	fprintf(stderr, "%s: error at line %d\n", 
X		Progname, yylinecount) ;
X	fprintf(stderr, "%s: %s\n", Progname, str) ;
X	exit(-1) ;
X}
X
X
Xmain(argc, argv)
X int argc;
X char *argv[] ;
X{
X	Progname = argv[0];
X
X	yyin = stdin ;
X	if (yyparse() == 1) {
X		fprintf(stderr, "%s: invalid input specification\n", Progname);
X		exit(-1) ;
X	}
X}
X
X
X#define		NCOLORS		(142)
X
Xtypedef struct t_color_entry {
X	char *	ce_name ;
X	Vec 	ce_color ;
X} ColorEntry ;
X
X#define LESS_THAN -1
X#define GREATER_THAN 1
X#define EQUAL_TO 0
X
X/*
X * Note: These colors must be in sorted order, because we binary search
X * for them.
X *
X * They were swiped from the X-11 distribution.  Sorry....
X */
X
XColorEntry Colors[] = {
X	"Aquamarine", {.439216, .858824, .576471},
X	"Black", {0, 0, 0},
X	"Blue", {0, 0, 1},
X	"BlueViolet", {.623529, .372549, .623529},
X	"Brown", {.647059, .164706, .164706},
X	"CadetBlue", {.372549, .623529, .623529},
X	"Coral", {1, .498039, 0},
X	"CornflowerBlue", {.258824, .258824, .435294},
X	"Cyan", {0, 1, 1},
X	"DarkGreen", {.184314, .309804, .184314},
X	"DarkOliveGreen", {.309804, .309804, .184314},
X	"DarkOrchid", {.6, .196078, .8},
X	"DarkSlateBlue", {.419608, .137255, .556863},
X	"DarkSlateGray", {.184314, .309804, .309804},
X	"DarkSlateGrey", {.184314, .309804, .309804},
X	"DarkTurquoise", {.439216, .576471, .858824},
X	"DimGray", {.329412, .329412, .329412},
X	"DimGrey", {.329412, .329412, .329412},
X	"Firebrick", {.556863, .137255, .137255},
X	"ForestGreen", {.137255, .556863, .137255},
X	"Gold", {.8, .498039, .196078},
X	"Goldenrod", {.858824, .858824, .439216},
X	"Gray", {.752941, .752941, .752941},
X	"Green", {0, 1, 0},
X	"GreenYellow", {.576471, .858824, .439216},
X	"Grey", {.752941, .752941, .752941},
X	"IndianRed", {.309804, .184314, .184314},
X	"Khaki", {.623529, .623529, .372549},
X	"LightBlue", {.74902, .847059, .847059},
X	"LightGray", {.658824, .658824, .658824},
X	"LightGrey", {.658824, .658824, .658824},
X	"LightSteelBlue", {.560784, .560784, .737255},
X	"LimeGreen", {.196078, .8, .196078},
X	"Magenta", {1, 0, 1},
X	"Maroon", {.556863, .137255, .419608},
X	"MediumAquamarine", {.196078, .8, .6},
X	"MediumBlue", {.196078, .196078, .8},
X	"MediumForestGreen", {.419608, .556863, .137255},
X	"MediumGoldenrod", {.917647, .917647, .678431},
X	"MediumOrchid", {.576471, .439216, .858824},
X	"MediumSeaGreen", {.258824, .435294, .258824},
X	"MediumSlateBlue", {.498039, 0, 1},
X	"MediumSpringGreen", {.498039, 1, 0},
X	"MediumTurquoise", {.439216, .858824, .858824},
X	"MediumVioletRed", {.858824, .439216, .576471},
X	"MidnightBlue", {.184314, .184314, .309804},
X	"Navy", {.137255, .137255, .556863},
X	"NavyBlue", {.137255, .137255, .556863},
X	"Orange", {.8, .196078, .196078},
X	"OrangeRed", {1, 0, .498039},
X	"Orchid", {.858824, .439216, .858824},
X	"PaleGreen", {.560784, .737255, .560784},
X	"Pink", {.737255, .560784, .560784},
X	"Plum", {.917647, .678431, .917647},
X	"Red", {1, 0, 0},
X	"Salmon", {.435294, .258824, .258824},
X	"SeaGreen", {.137255, .556863, .419608},
X	"Sienna", {.556863, .419608, .137255},
X	"SkyBlue", {.196078, .6, .8},
X	"SlateBlue", {0, .498039, 1},
X	"SpringGreen", {0, 1, .498039},
X	"SteelBlue", {.137255, .419608, .556863},
X	"Tan", {.858824, .576471, .439216},
X	"Thistle", {.847059, .74902, .847059},
X	"Turquoise", {.678431, .917647, .917647},
X	"Violet", {.309804, .184314, .309804},
X	"VioletRed", {.8, .196078, .6},
X	"Wheat", {.847059, .847059, .74902},
X	"White", {.988235, .988235, .988235},
X	"Yellow", {1, 1, 0},
X	"YellowGreen", {.6, .8, .196078},
X	"aquamarine", {.439216, .858824, .576471},
X	"black", {0, 0, 0},
X	"blue", {0, 0, 1},
X	"blue_violet", {.623529, .372549, .623529},
X	"brown", {.647059, .164706, .164706},
X	"cadet_blue", {.372549, .623529, .623529},
X	"coral", {1, .498039, 0},
X	"cornflower_blue", {.258824, .258824, .435294},
X	"cyan", {0, 1, 1},
X	"dark_green", {.184314, .309804, .184314},
X	"dark_olive_green", {.309804, .309804, .184314},
X	"dark_orchid", {.6, .196078, .8},
X	"dark_slate_blue", {.419608, .137255, .556863},
X	"dark_slate_gray", {.184314, .309804, .309804},
X	"dark_slate_grey", {.184314, .309804, .309804},
X	"dark_turquoise", {.439216, .576471, .858824},
X	"dim_gray", {.329412, .329412, .329412},
X	"dim_grey", {.329412, .329412, .329412},
X	"firebrick", {.556863, .137255, .137255},
X	"forest_green", {.137255, .556863, .137255},
X	"gold", {.8, .498039, .196078},
X	"goldenrod", {.858824, .858824, .439216},
X	"gray", {.752941, .752941, .752941},
X	"green", {0, 1, 0},
X	"green_yellow", {.576471, .858824, .439216},
X	"grey", {.752941, .752941, .752941},
X	"indian_red", {.309804, .184314, .184314},
X	"khaki", {.623529, .623529, .372549},
X	"light_blue", {.74902, .847059, .847059},
X	"light_gray", {.658824, .658824, .658824},
X	"light_grey", {.658824, .658824, .658824},
X	"light_steel_blue", {.560784, .560784, .737255},
X	"lime_green", {.196078, .8, .196078},
X	"magenta", {1, 0, 1},
X	"maroon", {.556863, .137255, .419608},
X	"medium_aquamarine", {.196078, .8, .6},
X	"medium_blue", {.196078, .196078, .8},
X	"medium_forest_green", {.419608, .556863, .137255},
X	"medium_goldenrod", {.917647, .917647, .678431},
X	"medium_orchid", {.576471, .439216, .858824},
X	"medium_sea_green", {.258824, .435294, .258824},
X	"medium_slate_blue", {.498039, 0, 1},
X	"medium_spring_green", {.498039, 1, 0},
X	"medium_turquoise", {.439216, .858824, .858824},
X	"medium_violet_red", {.858824, .439216, .576471},
X	"midnight_blue", {.184314, .184314, .309804},
X	"navy", {.137255, .137255, .556863},
X	"navy_blue", {.137255, .137255, .556863},
X	"orange", {.8, .196078, .196078},
X	"orange_red", {1, 0, .498039},
X	"orchid", {.858824, .439216, .858824},
X	"pale_green", {.560784, .737255, .560784},
X	"pink", {.737255, .560784, .560784},
X	"plum", {.917647, .678431, .917647},
X	"red", {1, 0, 0},
X	"salmon", {.435294, .258824, .258824},
X	"sea_green", {.137255, .556863, .419608},
X	"sienna", {.556863, .419608, .137255},
X	"sky_blue", {.196078, .6, .8},
X	"slate_blue", {0, .498039, 1},
X	"spring_green", {0, 1, .498039},
X	"steel_blue", {.137255, .419608, .556863},
X	"tan", {.858824, .576471, .439216},
X	"thistle", {.847059, .74902, .847059},
X	"turquoise", {.678431, .917647, .917647},
X	"violet", {.309804, .184314, .309804},
X	"violet_red", {.8, .196078, .6},
X	"wheat", {.847059, .847059, .74902},
X	"white", {.988235, .988235, .988235},
X	"yellow", {1, 1, 0},
X	"yellow_green", {.6, .8, .196078}
X} ;
X
Xint
XLookupColorByName(name, color)
X char * name ;
X Vec color ;
X{
X	int rc ;
X	rc = BinarySearch(name, 0, NCOLORS - 1 , Colors) ;
X	if (rc < 0) {
X		return(0) ;
X	}
X
X	color[0] = Colors[rc].ce_color[0];
X	color[1] = Colors[rc].ce_color[1];
X	color[2] = Colors[rc].ce_color[2];
X	return 1 ;
X}
X
X
Xint 
XBinarySearch(name, l, h, array)
X char * name ;
X int l, h ;
X ColorEntry array[] ;
X{
X	int m, rc ;
X	if (l > h)
X		return(-1) ;
X	
X	m = (l + h) / 2 ;
X
X	rc = strcmp(name, array[m].ce_name) ;
X	if (rc == 0)
X		return m ;
X	else if (rc < 0)
X		return BinarySearch(name, l, m-1, array) ;
X	else
X		return BinarySearch(name, m + 1, h, array) ;
X}
END_OF_FILE
if test 9364 -ne `wc -c <'nff.y'`; then
    echo shar: \"'nff.y'\" unpacked with wrong size!
fi
# end of 'nff.y'
fi
if test -f 'prt.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'prt.c'\"
else
echo shar: Extracting \"'prt.c'\" \(10451 characters\)
sed "s/^X//" >'prt.c' <<'END_OF_FILE'
X/*
X * prt - Paralel Ray Tracer
X *
X * Copyright (C) 1990, Kory Hamzeh.
X *
X * This program acts as a front-end to 'rt'. It takes the user given list
X * of hostnames, and using rsh, it spawns off copys of rt running on different
X * machines. It will gather up the image fragments that each sub-process sends
X * it, and builds one final image. The usage syntax is as follows:
X *
X * 	prt input-file output-file host [host ... ]
X */
X
X#include <sys/types.h>
X#include <sys/fcntl.h>
X#include <sys/errno.h>
X#include <signal.h>
X#include <stdio.h>
X
X#define MAX_HOSTS	64
X
Xtypedef struct rt_info {
X	char	hostname[32];
X	int	pid;
X	int	cur_bytes;
X	int	tot_bytes;
X	int	offset;
X	int	bld_offset;
X	long	time_st;
X	long	time_en;
X	int	out_pipe[2];
X	int	err_pipe[2];
X	} RT_INFO;
X
XRT_INFO rt_tab[MAX_HOSTS];
X
Xint num_hosts = 0;
Xint tot_bytes = 0;
Xint cur_bytes = 0;
Xint percent_done = 0;
Xint verbose = 0;
Xint in_file[64];
Xint out_file[64];
XFILE *in_fp;
XFILE *out_fp;
Xint image_x;
Xint image_y;
Xchar *image;
Xchar *my_name;
Xfd_set work_fds;
Xfd_set orig_fds;
Xlong time_st;
Xlong time_en;
Xchar *rt_args[32];
X
Xint Dead_baby();
X
X/*
X** Main startup code.
X*/
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	int i, pix1, pix2;
X
X	time(&time_st);
X
X	my_name = argv[0];
X	++argv;
X	--argc;
X
X	if(argc < 3)
X		Usage();
X
X	/*
X	** Check for the verbose option.
X	*/
X
X	if(!strcmp(argv[0], "-v"))
X	{
X		verbose = 1;
X		++argv;
X		--argc;
X	}
X
X	if(argc < 2)
X		Usage();
X
X	rt_args[0] = "rsh";
X	rt_args[2] = "rt";
X	rt_args[3] = "-z";
X	rt_args[4] = "-y";
X
X	i = 7;
X	rt_args[i] = NULL;
X	while(argc > 2 && *argv[0] == '-')
X	{
X		rt_args[i] = *argv;
X		rt_args[i + 1] = NULL;
X		i++;
X		++argv;
X		--argc;
X	}
X
X	strcpy(in_file, argv[0]);
X	++argv;
X	--argc;
X
X	strcpy(out_file, argv[0]);
X	++argv;
X	--argc;
X
X	signal(SIGCLD, Dead_baby);
X
X	/*
X	** Get the list of hosts from the command line.
X	*/
X
X	while(argc > 0 && num_hosts < MAX_HOSTS)
X	{
X		strcpy(rt_tab[num_hosts].hostname, argv[0]);
X
X		rt_tab[num_hosts].cur_bytes = 0;
X		rt_tab[num_hosts].tot_bytes = 0;
X
X		++argv;
X		--argc;
X		++num_hosts;
X	}
X
X	if(num_hosts == 0)
X	{
X		fprintf(stderr, "%s: no host were specified.\n", my_name);
X		exit(0);
X	}
X
X	/*
X	** Check to see if too many hosts were specified.
X	*/
X
X	if(num_hosts == MAX_HOSTS)
X	{
X		fprintf(stderr, "%s: Too many hosts. Max is %d.\n", 
X			my_name, MAX_HOSTS);
X		exit(1);
X	}
X
X	/*
X	** Check the image size.
X	*/
X
X	Get_image_size();
X
X	if(verbose)
X	{
X		fprintf(stderr, "%s: image size is %d x %d\n", 
X			my_name, image_x, image_y);
X	}
X
X	/*
X	** Allocate an image buffer.
X	*/
X
X	if((image = (char *) malloc(image_x * image_y * 3)) == NULL)
X	{
X		fprintf(stderr, "%s: malloc of %d failed.\n", my_name,
X			image_x, image_y);
X		exit(1);
X	}
X
X	/*
X	** Open the output file.
X	*/
X
X	if((out_fp = fopen(out_file, "w")) == NULL)
X	{
X		fprintf(stderr, "%s: unable to create file '%s'.\n", my_name, out_file);
X		exit(1);
X	}
X
X	/*
X	** Calculate the total number of pixels that each sub-process
X	** must render.
X	*/
X
X	pix1 = image_y / num_hosts;
X	pix2 = image_y % num_hosts;
X
X	for(i = 0; i < num_hosts; i++)
X		rt_tab[i].tot_bytes = pix1 * (image_x * 3);
X
X	for(i = 0; i < pix2; i++)
X		rt_tab[i].tot_bytes += image_x * 3;
X
X	/*
X	** Calculate the offset into the image buffer which each host
X	** will use.
X	*/
X
X	for(i = 0, pix1 = 0; i < num_hosts; i++, pix1 += rt_tab[i].tot_bytes)
X		rt_tab[i].offset  = rt_tab[i].bld_offset = pix1;
X
X	/*
X	** Start the sub-processes.
X	*/
X
X	Start_tracers();
X
X	/*
X	** Gather bits of image and build one final big image.
X	*/
X
X	Gather_image();
X
X	/*
X	** Exit and go home.
X	*/
X
X	time(&time_en);
X
X	if(verbose)
X		fprintf(stderr, "%s: Total execution time: %02d:%02d.\n",
X			my_name, (time_en - time_st) / 60, (time_en - time_st) % 60);
X
X	fclose(out_fp);
X	exit(0);
X}
X
X
X/*
X** Get_image_size()
X**
X** Scan the object database looking for the resolution key word to figure
X** out how big this image will be.
X*/
X
XGet_image_size()
X{
X	int found = 0;
X	int line = 1;
X	char buf[512];
X
X	if((in_fp = fopen(in_file, "r")) == NULL)
X	{
X		fprintf(stderr, "%s: unable to open input file '%s'\n", 
X			my_name, in_file);
X		exit(1);
X	}
X
X	/*
X	** Scan the file looking for 'resolution xxx yyy'.
X	*/
X
X	while(fgets(buf, sizeof(buf), in_fp))
X	{
X		if(!strncmp(buf, "resolution", 10))
X		{
X			if(sscanf(buf + 10, "%d %d", &image_x, &image_y) != 2)
X			{
X				fprintf(stderr, "%s: invalid resolution specified in input file on line %d.\n", my_name, line);
X				fclose(in_fp);
X				exit(1);
X			}
X
X			found = 1;
X			break;
X		}
X
X		++line;
X	}
X
X	fclose(in_fp);
X	if(!found)
X	{
X		fprintf(stderr, "%s: image resolution not found in file '%s'.\n",
X			my_name, in_file);
X		exit(1);
X	}
X}
X
X/*
X** Start_tracers()
X**
X** This routine is a bit hairy. It creates the input, output, and error
X** pipe, and then rsh's rt.
X*/
X
XStart_tracers()
X{
X	int rc, h, in_fd, i;
X	char starty[32], incy[32];
X
X
X	for(h = 0; h < num_hosts; h++)
X	{
X		/* First, create the pipe. */
X		rc = pipe(rt_tab[h].out_pipe);
X		rc += pipe(rt_tab[h].err_pipe);
X
X		if(rc != 0)
X		{
X			fprintf(stderr, "%s: pipe() failed.\n", my_name);
X			Kill_tracers(h);
X		}
X
X		if(verbose)
X			fprintf(stderr, "%s: starting rt on host %s.\n", my_name,
X				rt_tab[h].hostname);
X		/* fork */
X		if((rt_tab[h].pid = fork()) < 0)
X		{
X			fprintf(stderr, "%s: fork() failed.\n", my_name);
X			Kill_tracers(h);
X		}
X
X		if(rt_tab[h].pid > 0)		/* parent */
X		{
X			/* Close the write end of the pipes. */
X			close(rt_tab[h].out_pipe[1]);
X			close(rt_tab[h].err_pipe[1]);
X			/* Set for no delay on read */
X			fcntl(rt_tab[h].out_pipe[0], F_SETFL, O_NDELAY);
X			fcntl(rt_tab[h].err_pipe[0], F_SETFL, O_NDELAY);
X			/* set the start time */
X			time(&rt_tab[h].time_st);
X		}
X		else
X		{
X			sprintf(starty, "%d", h);
X			sprintf(incy, "%d", num_hosts);
X
X			/* Close the read end of the pipe */
X			close(rt_tab[h].out_pipe[0]);
X			close(rt_tab[h].err_pipe[0]);
X
X			in_fd = open(in_file, O_RDONLY);
X			close(0);		/* the data file */
X			dup(in_fd);
X			close(1);
X			dup(rt_tab[h].out_pipe[1]);
X
X			close(2);
X			dup(rt_tab[h].err_pipe[1]);
X
X			for(i = 3; i < 100; i++)
X				close(i);
X
X			rt_args[1] = rt_tab[h].hostname;
X			rt_args[5] = starty;
X			rt_args[6] = incy;
X
X			/* exec the sucker */
X			execvp("rsh", rt_args);
X
X			fprintf(stderr, "%s: rsh on host %s failed.\n", my_name,
X				rt_tab[h].hostname); 
X			exit(1);
X		}
X	}
X}
X
X/*
X** Gather_image()
X**
X** This routine gathers the bits of images flying back from the various 
X** sub-processes, and build one big final image.
X*/
X
XGather_image()
X{
X	int h, width, rc;
X	extern int errno;
X
X	/*
X	** Build fd list for select.
X	*/
X
X	Build_fd_set();
X
X	/*
X	** Write the image header.
X	*/
X
X	fprintf(out_fp, "%d %d\n", image_x, image_y);
X	tot_bytes = image_x * image_y * 3;
X	cur_bytes = 0;
X	percent_done = 0;
X	width = MAX_HOSTS * 2;
X
X	/*
X	** Main loop.
X	*/
X
X	if(verbose)
X		fprintf(stderr, "%s: %d%% done         ", my_name, percent_done);
X
X	while(cur_bytes < tot_bytes)
X	{
X		Build_fd_set();
X		work_fds = orig_fds;
X		rc = select(width, &work_fds, NULL, NULL, NULL);
X		if(rc < 0)
X			continue;
X
X		for(h = 0; h < num_hosts; h++)
X		{
X			if(rt_tab[h].pid == 0)
X				continue;
X
X			if(FD_ISSET(rt_tab[h].out_pipe[0], &work_fds))
X			{
X				Get_image_frag(h);
X				FD_CLR(rt_tab[h].out_pipe[0], &work_fds);
X			}
X
X			if(FD_ISSET(rt_tab[h].err_pipe[0], &work_fds))
X			{
X				Tracer_error_report(h);
X				FD_CLR(rt_tab[h].err_pipe[0], &work_fds);
X			}
X
X		}
X
X		if(verbose)
X		{
X			if(((cur_bytes * 100) / tot_bytes) != percent_done)
X			{
X				percent_done = (cur_bytes * 100) / tot_bytes;
X				fprintf(stderr, "\r%s: %d%% done        ", my_name, 
X					percent_done);
X			}
X		}
X	}
X
X	/* Write out the image */
X	Write_image();
X
X}
X
X/*
X** Get_image_frag(host)
X**
X** Get the image fragment which just came form one of the tracers. Just store
X** it in the buffer for now, and we'll sort it out later.
X*/
X
XGet_image_frag(h)
Xint h;
X{
X	int fd, count;
X	char *p;
X	extern int errno;
X
X	if(rt_tab[h].pid == 0)
X		return;
X
X	fd = rt_tab[h].out_pipe[0];
X	p = image + rt_tab[h].offset + rt_tab[h].cur_bytes;
X
X	while((count = read(fd, p, image_x * 3)) > 0)
X	{
X		p += count;
X		rt_tab[h].cur_bytes += count;
X		cur_bytes += count;
X		if(rt_tab[h].cur_bytes == rt_tab[h].tot_bytes)
X		{
X			if(verbose)
X				Rt_done(h);
X			rt_tab[h].pid = 0;
X			return ;
X		}
X	}
X
X	if(count == 0 && errno != EWOULDBLOCK && errno != EINTR)
X	{
X		rt_tab[h].pid = 0;	/* this guy is done */
X		if(verbose)
X			fprintf(stderr, "\n%s: rt on host %s is done.\n", my_name,
X				rt_tab[h].hostname);
X	}
X
X}
X
X
X/*
X** Tracer_error_report()
X**
X** A rt sub-process sent us a message through its stderr pipe. Display the
X** message and kill them all.
X*/
X
XTracer_error_report(h)
Xint h;
X{
X	char ebuf[512];
X	int count;
X
X	if(rt_tab[h].pid == 0)
X		return ;
X
X	count = read(rt_tab[h].err_pipe[0], ebuf, sizeof(ebuf));
X	if(count > 0)
X	{
X		fprintf(stderr, "\n%s: Error from rt on host %s\007\n", my_name,
X			rt_tab[h].hostname);
X		ebuf[count] = 0;
X		fprintf(stderr, "%s", ebuf);
X		Kill_tracers(num_hosts);
X		exit(0);
X	}
X}
X
X
X/*
X** Write_image()
X**
X** Take the image fragments that came back from all of the tracers and
X** write one big image.
X*/
X
XWrite_image()
X{
X	int h, rs;
X	char *p;
X
X	if(verbose)
X		fprintf(stderr, "\n%s: writing image ... ", my_name);
X
X	cur_bytes = 0;
X	rs = image_x * 3;
X	h = 0;
X
X	while(cur_bytes < tot_bytes)
X	{
X		p = image + rt_tab[h].bld_offset;
X		fwrite(p, rs, 1, out_fp);
X		rt_tab[h].bld_offset += rs;
X		cur_bytes += rs;
X
X		h++;
X		if(h == num_hosts)
X			h = 0;
X	}
X
X	if(verbose)
X		fprintf(stderr, "\n");
X}
X
X
X/*
X** Usage()
X**
X** Print usage message.
X*/
X
X
XUsage()
X{
X	fprintf(stderr, "Usage: %s [-v] input-file output-file host [host ..]\n",
X		my_name);
X	exit(1);
X}
X
X
X/*
X** Kill_tracers()
X**
X*/
X
XKill_tracers(count)
Xint count;
X{
X	int h;
X
X	for(h = 0; h < count; h++)
X		kill(rt_tab[h].pid, 9); 	/* a sure kill */
X}
X
X/*
X** Dead_baby()
X**
X** Death of a child signal is vectored here.
X*/
X
XDead_baby()
X{
X	int status;
X
X	wait(&status);
X	signal(SIGCLD, Dead_baby);
X}
X
X/*
X** Build_fd_set() - Build an fd_set for select()
X*/
X
XBuild_fd_set()
X{
X	int h;
X
X	FD_ZERO(&orig_fds);
X
X	for(h = 0; h < num_hosts; h++)
X	{
X		if(rt_tab[h].pid == 0)
X			continue;
X
X		FD_SET(rt_tab[h].out_pipe[0], &orig_fds);
X		FD_SET(rt_tab[h].err_pipe[0], &orig_fds); 
X	}
X}
X
X
X/*
X** Rt_done()
X**
X** A rt sub-process fisnished, let the user know.
X*/
X
XRt_done(h)
Xint h;
X{
X	int min, sec;
X
X	time(&rt_tab[h].time_en);
X	min = (rt_tab[h].time_en - rt_tab[h].time_st) / 60;
X	sec = (rt_tab[h].time_en - rt_tab[h].time_st) % 60;
X
X	fprintf(stderr, "\n%s: rt on host %s is done. Execution time: %02d:%02d.\n", 
X			my_name, rt_tab[h].hostname, min, sec);
X}
X
END_OF_FILE
if test 10451 -ne `wc -c <'prt.c'`; then
    echo shar: \"'prt.c'\" unpacked with wrong size!
fi
# end of 'prt.c'
fi
if test -f 'rt.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'rt.h'\"
else
echo shar: Extracting \"'rt.h'\" \(7836 characters\)
sed "s/^X//" >'rt.h' <<'END_OF_FILE'
X/*
X * rt.h - General information file for rt
X * 
X * Copyright (C) 1990, Kory Hamzeh
X */
X
X/*
X * Define some stuff
X */
X
X#define	MAX_LIGHTS	8	/* maximum number of light sources */
X#define	MAX_PRIMS	80000	/* maximum number of primitives	 */
X#define MAX_INSTANCE	64	/* maximum number of instances	   */
X#define MAX_TOKENS	17
X#define MIN_T		1e-12
X#define MAX_LEVEL	5	/* maxmimum recursion level	   */
X#define GROUP_SIZE	4
X#define STACK_SIZE	512
X
X/*
X * Object types
X */
X
X#define T_COMPOSITE	0
X#define T_POLYGON	1
X#define	T_SPHERE	2
X#define T_HSPHERE	3
X#define T_CONE		4
X#define T_RING		5
X#define T_QUADRIC	6
X
X/*
X * Instance type flags
X */
X
X#define I_OBJECT	0	/* object type			 */
X#define I_SURFACE	1	/* surface properties		 */
X#define I_LIGHT		2	/* light sources		 */
X
X/*
X * Structures
X */
X
X/* vector */
X
Xtypedef struct vector
X{
X	double          x;
X	double          y;
X	double          z;
X}               VECTOR;
X
X
X/* color pixel info */
X
Xtypedef struct color
X{
X	double          r;
X	double          g;
X	double          b;
X}               COLOR;
X
X/* surface properties */
X
Xtypedef struct surface
X{
X	double          p_reflect;	/* percentage of reflection	 */
X	double          p_refract;	/* percentage of refraction	 */
X	COLOR           c_reflect;	/* reflect color		 */
X	COLOR           c_refract;	/* refract color		 */
X	COLOR           c_ambient;	/* ambient color		 */
X	COLOR           c_diffuse;	/* diffues color		 */
X	COLOR           c_specular;	/* specular color		 */
X	double          spec_width;	/* specular width factor	 */
X	double          i_refraction;	/* index of refraction		 */
X	double          refl_diffuse;	/* circle of diffusion in refl.	 */
X	double          refr_diffuse;	/* circle of diffusion in refr.	 */
X}               SURFACE;
X
X/* composite (slab) data */
X
Xtypedef struct composite
X{
X	int             num;	/* number of object in this group */
X	struct object  *child[GROUP_SIZE];	/* pointer to members		 */
X}               COMPOSITE;
X
X/* n-point polygon */
X
Xtypedef struct polygon
X{
X	int             npoints;/* number of points		 */
X	VECTOR          normal;	/* surface normal (normalized)	 */
X	double          d;	/* the D coefficient		 */
X	int             p1, p2;	/* the dominant normals		 */
X	VECTOR          points[1];	/* actual points		 */
X}               POLYGON;
X
X
X/* sphere */
X
Xtypedef struct sphere
X{
X	VECTOR          center;	/* center of sphere		 */
X	double          radius;	/* and its radius		 */
X	double          radius2;/* radius * radius		 */
X}               SPHERE;
X
X/* hallow sphere */
X
Xtypedef struct hsphere
X{
X	VECTOR          center;	/* center of sphere		 */
X	double          radius;	/* and its radius		 */
X	double          radius2;/* radius * radius		 */
X	double          i_radius;	/* inner_radius = outer - tickness */
X	double          i_radius2;	/* i_radius * i_radius		 */
X}               HSPHERE;
X
X
X/* cone */
X
Xtypedef struct cone
X{
X	VECTOR          base;	/* center of base		 */
X	double          base_radius;	/* base radius			 */
X	double          base_d;	/* base D coefficient		 */
X	VECTOR          apex;	/* center of apex		 */
X	double          apex_radius;	/* apex radius			 */
X	VECTOR          u;
X	VECTOR          v;
X	VECTOR          w;
X	double          height;	/* apex - base			 */
X	double          slope;	/* slope of the damn thing	 */
X	double          min_d;
X	double          max_d;
X}               CONE;
X
X/* ring */
X
Xtypedef struct ring
X{
X	VECTOR          center;	/* center of ring		 */
X	VECTOR          point1;	/* one point on surface		 */
X	VECTOR          point2;	/* another point on surface	 */
X	VECTOR          normal;	/* surface normal		 */
X	double          d;	/* the D coefficient		 */
X	double          o_radius;	/* outer radius			 */
X	double          i_radius;	/* inner radius			 */
X	double          o_radius2;	/* o_radius * o_radius		 */
X	double          i_radius2;	/* i_radius * i_radius		 */
X}               RING;
X
X/*
X * General form quadratic data type.
X */
X
Xtypedef struct quadric
X{
X	VECTOR          loc;	/* location of the quadratic	 */
X	VECTOR          min;	/* minumum extent		 */
X	VECTOR          max;	/* maximum extent		 */
X	double          a, b, c, d, e;	/* coefficients a to J follow	 */
X	double          f, g, h, i, j;
X	double          a2, b2, c2, d2;	/* a2 = A * 2, etc...		 */
X	double          f2, g2, i2;
X}               QUADRIC;
X
X/*
X * The OBJECT data type is built from all of the previous types.
X */
X
Xtypedef struct object
X{
X	int             type;	/* T_* goes here		 */
X	void           *obj;	/* actually point to type CONE, etc. */
X	VECTOR          b_min;	/* bounding box in values	 */
X	VECTOR          b_max;	/* bounding box max values	 */
X	int             active;	/* TRUE if on active hit list	 */
X	SURFACE        *surf;	/* object surface properties	 */
X	int             (*inter) ();	/* pointer to intersect routine  */
X	int             (*normal) ();	/* pointer to normal routine	 */
X}               OBJECT;
X
X/*
X * This data type contains info about object intersection
X */
X
Xtypedef struct intersect
X{
X	OBJECT         *obj;	/* object that caused the intersect */
X	double          t;	/* distance				 */
X	int             inside;	/* 1 = ray is inside object		 */
X}               INTERSECT;
X
X/*
X * This date type conatins info about the image and observer.
X */
X
Xtypedef struct view_info
X{
X	VECTOR          from;	/* observer's location			 */
X	VECTOR          look_at;/* looking at here		 */
X	VECTOR          up;	/* which way is up?		 */
X	double          angle;	/* field of view		 */
X	int             x_res;	/* x resolution			 */
X	int             y_res;	/* y res			 */
X}               VIEW_INFO;
X
X/*
X * This data type contains info about background colors and cueing.
X */
X
Xtypedef struct background
X{
X	COLOR           col;
X	char            cue;
X}               BACKGROUND;
X
X/*
X * This data type contains info about lights.
X */
X
Xtypedef struct light
X{
X	VECTOR          pos;	/* light position		 */
X	COLOR           col;	/* color of light		 */
X	double          intensity;	/* light intensity		 */
X	OBJECT         *cache[MAX_LEVEL];	/* shadow cache			 */
X}               LIGHT;
X
X/*
X * This data type contains info about rays.
X */
X
Xtypedef struct ray
X{
X	VECTOR          pos;	/* ray origin			 */
X	VECTOR          dir;	/* ray direction		 */
X}               RAY;
X
X/*
X * Instance info holder
X */
X
Xtypedef struct instance
X{
X	char           *name;	/* name of instance		 */
X	void           *next;	/* next object pointer		 */
X	void           *data;	/* points to object data	 */
X	int             type;	/* I_* type			 */
X	int             subtype;/* T_* type			 */
X}               INSTANCE;
X
X/* vector math stuff */
X
X#define MakeVector(x, y, z, v)		(v).x=(x),(v).y=(y),(v).z=(z)
X
X#define VecNegate(a)			{(a).x=0-(a).x;\
X					(a).y=0-(a).y;\
X					(a).z=0-(a).z;}
X
X#define VecDot(a,b)			((a).x*(b).x+(a).y*(b).y+(a).z*(b).z)
X
X#define VecLen(a)			(sqrt(VecDot(a,a)))
X
X#define VecCopy(a,b)	 		{(b).x=(a).x;(b).y=(a).y;(b).z=(a).z;}
X
X#define VecAdd(a,b,c)	 		{(c).x=(a).x+(b).x;\
X			 		(c).y=(a).y+(b).y;\
X			 		(c).z=(a).z+(b).z;}
X
X#define VecSub(a,b,c)	 		{(c).x=(a).x-(b).x;\
X			 		(c).y=(a).y-(b).y;\
X			 		(c).z=(a).z-(b).z;}
X
X#define VecComb(A,a,B,b,c)		{(c).x=(A)*(a).x+(B)*(b).x;\
X					(c).y=(A)*(a).y+(B)*(b).y;\
X			 		(c).z=(A)*(a).z+(B)*(b).z;}
X
X#define VecAddS(A,a,b,c)	 	{(c).x=(A)*(a).x+(b).x;\
X				 	(c).y=(A)*(a).y+(b).y;\
X				 	(c).z=(A)*(a).z+(b).z;}
X
X#define VecSProd(A,a,b)	 		{(b).x=(A)*(a).x;\
X				 	(b).y=(A)*(a).y;\
X				 	(b).z=(A)*(a).z;}
X
X#define VecCross(a,b,c)	 		{(c).x=(a).y*(b).z-(a).z*(b).y;\
X			 		(c).y=(a).z*(b).x-(a).x*(b).z;\
X			 		(c).z=(a).x*(b).y-(a).y*(b).x;};
X
X#define MIN(a, b)			((a) < (b) ? (a) : (b))
X#define MAX(a, b)			((a) > (b) ? (a) : (b))
X
Xdouble          VecNormalize();
XOBJECT         *Pop_object();
X
X/*
X * This macro returns a random number between 0 and 1.0. It probably is not
X * portable!!
X */
X
X#define RAND()				((double) rand() / 32767.0)
END_OF_FILE
if test 7836 -ne `wc -c <'rt.h'`; then
    echo shar: \"'rt.h'\" unpacked with wrong size!
fi
# end of 'rt.h'
fi
if test -f 'shade.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'shade.c'\"
else
echo shar: Extracting \"'shade.c'\" \(5265 characters\)
sed "s/^X//" >'shade.c' <<'END_OF_FILE'
X/*
X * shade.c - This module contains the illumination model.
X * 
X * Copyright (C) 1990, Kory Hamzeh
X */
X
X#include <stdio.h>
X#include <math.h>
X
X#include "rt.h"
X#include "externs.h"
X
X
X
XCOLOR           Illuminate(), Trace_a_ray();
X
X/*
X * Illuminate()
X * 
X * Apply the proper illumination model to determine the color of the object at
X * the given point.
X */
X
X
XCOLOR 
XIlluminate(inter, ray, ip, n)
XINTERSECT      *inter;
XRAY            *ray;
XVECTOR         *ip;
Xint             n;		/* Level of recursion */
X{
X	COLOR           col, c;
X	OBJECT         *obj, *scache;
X	SURFACE        *surf, *surf2;
X	VECTOR          normal, l_dir, h, refl;
X	INTERSECT       test_inter;
X	RAY             ray2;
X	double          t, l_dist, incident, spec;
X	double          n1, n2, intensity;
X	int             in_shadow, l;
X
X	/*
X	 * If the maximum level of recusion has been reached, then return
X	 * peacefully.
X	 */
X
X	if (n >= MAX_LEVEL)
X	{
X		col.r = col.g = col.b = 0;
X		return (col);
X	}
X
X	obj = inter->obj;
X	surf = obj->surf;
X	t = inter->t;
X
X	/* get the surface normal */
X	(*obj->normal) (obj->obj, ray, ip, &normal);
X
X	/* first set the color to ambient color */
X	col = surf->c_ambient;
X
X	/* foreach light source */
X	for (l = 0; l < nlights; l++)
X	{
X		/*
X		 * get the vector from the light source to the intersection
X		 * point
X		 */
X		VecSub(lights[l]->pos, *ip, l_dir);
X
X		intensity = lights[l]->intensity;
X
X		/*
X		 * Calculate the angle of incident.
X		 */
X
X		if (VecDot(normal, l_dir) >= 0)
X		{
X			/*
X			 * Test to see if any object is casting a shadow on
X			 * this point by firing a test ray from the light
X			 * source to this spot. If there is a hit and the
X			 * object is not the current object, then a shadow is
X			 * casted. In such a case, we don't need to calculate
X			 * the diffuse color.
X			 */
X
X			l_dist = VecNormalize(&l_dir);
X			in_shadow = 0;
X			if (shadow)
X			{
X				ray2.pos = *ip;
X				ray2.dir = l_dir;
X				++n_shadows;
X
X				/*
X				 * If we do have a shadow cache entry for
X				 * this light at this level, try that first.
X				 * If it hits, then a shadow is casted. If it
X				 * doesn't hit, then try all of the other
X				 * primitives.
X				 */
X
X				if ((scache = lights[l]->cache[n]) != NULL)
X				{
X					if ((*scache->inter) (scache, &ray2, &test_inter) &&
X					    inter->obj != test_inter.obj &&
X					    test_inter.t < l_dist - MIN_T)
X					{
X						++n_shadinter;
X						continue;
X					}
X				}
X
X				if (Intersect(&ray2, &test_inter) &&
X				    inter->obj != test_inter.obj &&
X				    test_inter.t < l_dist - MIN_T)
X				{
X					lights[l]->cache[n] = test_inter.obj;
X					++n_shadinter;
X					continue;
X				}
X				else
X				{
X					lights[l]->cache[n] = NULL;
X				}
X			}
X
X			incident = VecDot(normal, l_dir);
X			/* calculate the diffuse color */
X			col.r += incident * surf->c_diffuse.r * intensity;
X			col.g += incident * surf->c_diffuse.g * intensity;
X			col.b += incident * surf->c_diffuse.b * intensity;
X
X			/*
X			 * Add some specular highlights. This is accomplished
X			 * by calculating the angle of reflection and getting
X			 * the dot product of it with the ray direction.
X			 */
X
X			if (surf->spec_width != 0.0)
X			{
X				Reflect(&ray->dir, &normal, &ray2.dir);
X				spec = pow(VecDot(l_dir, ray2.dir), surf->spec_width);
X
X				col.r += spec * surf->c_specular.r * intensity;
X				col.g += spec * surf->c_specular.g * intensity;
X				col.b += spec * surf->c_specular.b * intensity;
X			}
X		}
X	}
X
X	/*
X	 * If reflections are enabled, calculat the reflection color.
X	 */
X
X	if (reflect && surf->p_reflect != 0.0)
X	{
X		++n_reflect;
X		ray2.pos = *ip;
X		Reflect(&ray->dir, &normal, &ray2.dir);
X
X		/*
X		 * Send out reflection ray.
X		 */
X
X		c = Trace_a_ray(&ray2, n + 1);
X		col.r += c.r * surf->p_reflect * surf->c_reflect.r;
X		col.g += c.g * surf->p_reflect * surf->c_reflect.g;
X		col.b += c.b * surf->p_reflect * surf->c_reflect.b;
X	}
X
X	/*
X	 * If refraction are enable, calculate the refracted color.
X	 */
X
X	if (refract && surf->p_refract != 0.0)
X	{
X		/*
X		 * determine the this ray is inside or outside the object so
X		 * that we can determine the proper index of refraction to
X		 * use.
X		 */
X
X		if (inter->inside)
X		{
X			n1 = surf->i_refraction;
X			n2 = 1.0;
X		}
X		else
X		{
X			n1 = 1.0;
X			n2 = surf->i_refraction;
X		}
X
X		ray2.pos = *ip;
X		if (Refract(n1, n2, &ray->dir, &normal, &ray2.dir))
X		{
X			++n_refract;
X			c = Trace_a_ray(&ray2, n + 1);
X
X			col.r += c.r * surf->p_refract * surf->c_refract.r;
X			col.g += c.g * surf->p_refract * surf->c_refract.g;
X			col.b += c.b * surf->p_refract * surf->c_refract.b;
X		}
X	}
X
X	/* return that color */
X	return (col);
X
X}
X
X
X/*
X * Reflect()
X * 
X * Calculate the reflected vector.
X */
X
XReflect(v, norm, refl)
XVECTOR         *v;
XVECTOR         *norm;
XVECTOR         *refl;
X{
X	double          nl;
X
X	nl = 1 / fabs(VecDot(*v, *norm));
X
X	VecComb(nl, *v, 2.0, *norm, *refl);
X	VecNormalize(refl);
X}
X
X/*
X * Refract()
X * 
X * Calculate the refraction vector.
X */
X
XRefract(n1, n2, i, n, r)
Xdouble          n1;
Xdouble          n2;
XVECTOR         *i;
XVECTOR         *n;
XVECTOR         *r;
X{
X	double          eta, c1, c2, c3;
X
X	eta = n1 / n2;
X	c1 = -VecDot(*i, *n);
X	c2 = 1.0 - eta * eta * (1.0 - (c1 * c1));
X	if (c2 < 0.0)
X		return (0);	/* total internal reflection */
X
X	c3 = (eta * c1) - sqrt(c2);
X
X	VecComb(eta, *i, c3, *n, *r);
X	return (1);
X}
END_OF_FILE
if test 5265 -ne `wc -c <'shade.c'`; then
    echo shar: \"'shade.c'\" unpacked with wrong size!
fi
# end of 'shade.c'
fi
echo shar: End of archive 2 \(of 3\).
cp /dev/null ark2isdone
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