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