#! /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 11 (of 19)."
# Contents:  libray/liblight/shadow.c libray/libobj/poly.c
#   libray/libtext/noise.c libshade/picture.c libshade/viewing.c
#   raypaint/xgraphics.c
# Wrapped by kolb@woody on Wed Jul 17 17:56:50 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'libray/liblight/shadow.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'libray/liblight/shadow.c'\"
else
echo shar: Extracting \"'libray/liblight/shadow.c'\" \(7457 characters\)
sed "s/^X//" >'libray/liblight/shadow.c' <<'END_OF_FILE'
X/*
X * shadow.c
X *
X * Copyright (C) 1989, 1991, Craig E. Kolb
X * All rights reserved.
X *
X * This software may be freely copied, modified, and redistributed
X * provided that this copyright notice is preserved on all copies.
X *
X * You may not distribute this software, in whole or in part, as part of
X * any commercial product without the express consent of the authors.
X *
X * There is no warranty or other guarantee of fitness of this software
X * for any purpose.  It is provided solely "as is".
X *
X * $Id: shadow.c,v 4.0 91/07/17 14:35:34 kolb Exp Locker: kolb $
X *
X * $Log:	shadow.c,v $
X * Revision 4.0  91/07/17  14:35:34  kolb
X * Initial version.
X * 
X */
X#include "libobj/geom.h"
X#include "libsurf/surface.h"
X#include "light.h"
X
X/*
X * Shadow stats.
X * External functions have read access via ShadowStats().
X */
Xstatic unsigned long	ShadowRays, ShadowHits, CacheMisses, CacheHits;
X/*
X * Options controlling how shadowing information is determined.
X * Set by external modules via ShadowSetOptions().
X */
Xstatic long		ShadowOptions;
X
Xvoid LightCacheHit();
X
X/*
X * Trace ray from point of intersection to a light.  If an intersection
X * occurs at a distance less than "dist" (the distance to the
X * light source), then the point is in shadow, and TRUE is returned.
X * Otherwise, the brightness/color of the light is computed ('result'),
X * and FALSE is returned.
X */
Xint
XShadowed(result, color, cache, ray, dist, noshadow)
XColor *result, *color;	/* resultant intensity, light color */
XShadowCache *cache;	/* shadow cache for light */
XRay *ray;		/* ray, origin on surface, dir towards light */
XFloat dist;		/* distance from pos to light source */
Xint noshadow;		/* If TRUE, no shadow ray is cast. */
X{
X	int i, smooth, enter;
X	HitList hitlist;
X	Ray tmpray;
X	ShadowCache *cp;
X	Vector hitpos, norm, gnorm;
X	Surface surf, *sptr, *prevsurf;
X	Float s, totaldist, statten;
X	Color res;
X
X	if (noshadow || NOSHADOWS(ShadowOptions)) {
X		*result = *color;
X		return FALSE;
X	}
X
X	ShadowRays++;
X	s = dist;
X	cp = &cache[ray->depth];
X	/*
X	 * Check shadow cache.  SHADOWCACHE() is implied.
X	 */
X	if (cp->obj) {
X		/*
X		 * Transform ray to the space of the cached primitive.
X		 */
X		tmpray = *ray;
X		if (cp->dotrans)
X			s *= RayTransform(&tmpray, &cp->trans);
X		/*
X		 * s = distance to light source in 'primitive space'.
X		 * Intersect ray with cached object.
X		 */
X		if (cp->obj->animtrans) {
X			/*
X			 * Geom has animated transformation --
X			 * call intersect so that the transformation
X			 * is resolved properly.
X			 */
X			if (intersect(cp->obj, &tmpray, &hitlist,
X			    SHADOW_EPSILON, &s)) {
X				CacheHits++;
X				return TRUE;
X			}
X		} else if (IsAggregate(cp->obj)) {
X			if ((*cp->obj->methods->intersect)(cp->obj->obj,
X				&tmpray, &hitlist, SHADOW_EPSILON, &s)) {
X				CacheHits++;
X				return TRUE;
X			}
X		} else if ((*cp->obj->methods->intersect)(cp->obj->obj,
X					&tmpray, SHADOW_EPSILON, &s)) {
X			/* Hit cached object. */
X			CacheHits++;
X			return TRUE;
X		}
X		/*
X		 * Did not hit anything -- zero out the cache.
X		 */
X		CacheMisses++;
X		/*
X		 * Transformed -- reset s for use below.
X		 */
X		s = dist;
X		cp->obj = (Geom *)NULL;
X		cp->dotrans = FALSE;
X	}
X
X	hitlist.nodes = 0;
X	if (!TraceRay(ray, &hitlist, SHADOW_EPSILON, &s)) {
X		/* Shadow ray didn't hit anything. */
X		*result = *color;
X		return FALSE;
X	}
X
X	/*
X	 * Otherwise, we've hit something.
X	 */
X	ShadowHits++;
X
X	/*
X	 * If we're not worrying about transparent objects...
X	 * This is ugly due to the fact that we have to find
X	 * the surface associated with the object that was hit.
X	 * GetShadingSurf() will always return a non-null value.
X	 *
X	 * ***NOTE**
X	 * The transparency of the surface is checked below without
X	 * applying textures, if any, to it.  This means that if
X	 * an object may be made trasparent by a texture, its
X	 * surface should have non-zero transparency *before* texturing
X	 * as well.
X	 */
X	if (!SHADOWTRANSP(ShadowOptions)) {
X		if (SHADOWCACHE(ShadowOptions))
X			LightCacheHit(&hitlist, cp);
X		return TRUE;
X	}
X
X	/*
X	 * We've hit a transparent object.  Attenuate the color of the light
X	 * source and continue the ray until we hit background or a
X	 * non-transparent object.  Note that this is incorrect if DefIndex or
X	 * any of the indices of refraction of the surfaces differ.
X	 */
X
X	totaldist = 0.;
X	prevsurf = (Surface *)NULL;
X	res = *color;
X
X	do {
X		/*
X		 * Get a pointer to the surface to be used
X		 * for shading...
X		 */
X		sptr = GetShadingSurf(&hitlist);
X		if (sptr->transp < EPSILON) {
X			if (SHADOWCACHE(ShadowOptions))
X				LightCacheHit(&hitlist, cp);
X			return TRUE;
X		}
X		/*
X		 * Take specular transmission attenuation from
X		 * previous intersection into account.
X		 */
X		if (prevsurf) {
X			if (prevsurf->statten != 1.) {
X				statten = pow(prevsurf->statten, s - totaldist);
X				ColorScale(statten, res, &res);
X			}
X		}
X		/*
X		 * Perform texturing and the like in case surface
X		 * transparency is modulated.
X		 */
X		/* copy the surface to be used... */
X		surf = *sptr;
X		enter = ComputeSurfProps(&hitlist, ray, &hitpos,
X			&norm, &gnorm, &surf, &smooth);
X		if (enter)
X			prevsurf = &surf;
X		else
X			prevsurf = (Surface *)NULL;
X		/*
X		 * Attenuate light source by body color of surface.
X		 */
X		ColorScale(surf.transp, res, &res);
X		ColorMultiply(res, surf.body, &res);
X		/*
X		 * Return if attenuation becomes large.
X		 * In this case, the light was attenuated to nothing,
X		 * so we can't cache anything...
X		 */
X		if (res.r < EPSILON && res.g < EPSILON && res.b < EPSILON)
X			return TRUE;
X		/*
X		 * Min distance is previous max.
X		 */
X		totaldist = s + EPSILON;
X		/*
X		 * Max distance is dist to light source
X		 */
X		s = dist;
X		/*
X		 * Trace ray starting at new origin and in the
X		 * same direction.
X		 */
X		hitlist.nodes = 0;
X	} while (TraceRay(ray, &hitlist, totaldist, &s));
X
X	*result = res;
X	return FALSE;
X}
X
Xvoid
XShadowStats(shadowrays, shadowhit, cachehit, cachemiss)
Xunsigned long *shadowrays, *shadowhit, *cachehit, *cachemiss;
X{
X	*shadowrays = ShadowRays;
X	*shadowhit = ShadowHits;
X	*cachehit = CacheHits;
X	*cachemiss = CacheMisses;
X}
X
Xvoid
XShadowSetOptions(options)
X{
X	ShadowOptions = options;
X}
X
Xvoid
XLightCacheHit(hitlist, cache)
XHitList *hitlist;
XShadowCache *cache;
X{
X	HitNode *np;
X	int i, n;
X	extern int ShadowOptions;
X
X	i = 0;
X
X	if (SHADOWCSG(ShadowOptions)) {
X		/*
X		 * There's possibly a CSG object in the
X		 * hitlist, so we can't simply cache the
X		 * primitive that was hit.  Find the
X		 * object lowest in hit that's not part
X		 * of a CSG object, and cache it.
X		 */
X		i = FirstCSGGeom(hitlist);
X	}
X
X	if (SHADOWBLUR(ShadowOptions)) {
X		/*
X		 * Something might be animated --
X		 * gotta cache the puppy.
X		 */
X		n = FirstAnimatedGeom(hitlist);
X		if (n > i)
X			i = n;
X	}
X
X	/*
X	 * Compute total world-->cached object
X	 * transformation and store in cache->trans.
X	 */
X	/*
X	 * Find the first transformation...
X	 */
X	np = &hitlist->data[i];
X	cache->obj = np->obj;
X	/*
X	 * If the cached object is animated, then we don't
X	 * want to include the object's transformation(s)
X	 * in cache->trans (it's taken care of in shadowed()
X	 * by calling intersect).
X	 */
X	if (cache->obj->animtrans) {
X		i++;
X		np++;
X	}
X	cache->dotrans = FALSE;
X	while (i < hitlist->nodes -1) {
X		if (np->obj->trans) {
X			if (cache->dotrans) {
X				MatrixMult(
X				    &np->obj->trans->itrans,
X				    &cache->trans,
X				    &cache->trans);
X			} else {
X				MatrixCopy(
X				    &np->obj->trans->itrans,
X				    &cache->trans);
X				cache->dotrans = TRUE;
X			}
X		}
X		i++;
X		np++;
X	}
X}
END_OF_FILE
if test 7457 -ne `wc -c <'libray/liblight/shadow.c'`; then
    echo shar: \"'libray/liblight/shadow.c'\" unpacked with wrong size!
fi
# end of 'libray/liblight/shadow.c'
fi
if test -f 'libray/libobj/poly.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'libray/libobj/poly.c'\"
else
echo shar: Extracting \"'libray/libobj/poly.c'\" \(7872 characters\)
sed "s/^X//" >'libray/libobj/poly.c' <<'END_OF_FILE'
X/*
X * poly.c
X *
X * Copyright (C) 1989, 1991, Craig E. Kolb
X * All rights reserved.
X *
X * This software may be freely copied, modified, and redistributed
X * provided that this copyright notice is preserved on all copies.
X *
X * You may not distribute this software, in whole or in part, as part of
X * any commercial product without the express consent of the authors.
X *
X * There is no warranty or other guarantee of fitness of this software
X * for any purpose.  It is provided solely "as is".
X *
X * $Id: poly.c,v 4.0 91/07/17 14:39:00 kolb Exp Locker: kolb $
X *
X * $Log:	poly.c,v $
X * Revision 4.0  91/07/17  14:39:00  kolb
X * Initial version.
X * 
X */
X#include "geom.h"
X#include "poly.h"
X
Xstatic Methods *iPolygonMethods = NULL;
Xstatic char polyName[] = "polygon";
X
Xunsigned long PolyTests, PolyHits;
X
X/*
X * Create a reference to a polygon with vertices equal to those
X * on the linked-list "plist."
X */
XPolygon *
XPolygonCreate(plist, npoints, flipflag)
XPointList *plist;
Xint npoints, flipflag;
X{
X	Polygon *poly;
X	Float indexval;
X	Vector *prev, *cur, anorm;
X	PointList *curp, *pltmp;
X	int i;
X
X	poly = (Polygon *)share_malloc(sizeof(Polygon));
X	/*
X	 * Allocate space for the vertices.
X	 */
X	poly->points = (Vector *)Malloc((unsigned)(npoints*sizeof(Vector)));
X	poly->npoints = npoints;
X
X	/*
X	 * Copy the vertices from the linked list to the array, freeing
X	 * the linked list as we go so that the caller doesn't have
X	 * to worry about doing so.
X	 */
X	i = npoints -1;
X	for(curp = plist; curp != (PointList *)0; curp = pltmp) {
X		poly->points[i--] = curp->vec;
X		pltmp = curp->next;
X		free((voidstar)curp);
X	}
X
X	/*
X	 * Find normal to polygon.
X	 */
X	poly->norm.x = poly->norm.y = poly->norm.z = 0.;
X	prev = &poly->points[poly->npoints -1];
X	for(i = 0,cur = poly->points;i < poly->npoints;i++, prev = cur, cur++) {
X		poly->norm.x += (prev->y - cur->y) * (prev->z + cur->z);
X		poly->norm.y += (prev->z - cur->z) * (prev->x + cur->x);
X		poly->norm.z += (prev->x - cur->x) * (prev->y + cur->y);
X	}
X
X	if (VecNormalize(&poly->norm) == 0.) {
X		/*
X		 * Degenerate normal --> degenerate polygon
X		 */
X		RLerror(RL_WARN, "Degenerate polygon.\n");
X		free((voidstar)poly->points);
X		return (Polygon *)NULL;
X	}
X
X	/*
X	 * If filflag is true, flip the normal.
X	 */
X	if (flipflag)
X		VecScale(-1, poly->norm, &poly->norm);
X
X	/*
X	 * Compute and store the plane constant.
X	 */
X	poly->d = dotp(&poly->norm, &poly->points[0]);
X
X	/*
X	 * Find the "dominant" part of the normal vector.  This
X	 * is used to turn the point-in-polygon test into a 2D problem.
X	 */
X	anorm.x = fabs(poly->norm.x);
X	anorm.y = fabs(poly->norm.y);
X	anorm.z = fabs(poly->norm.z);
X	indexval = max(anorm.y, anorm.z);
X	indexval = max(anorm.x, indexval);
X
X	if (indexval == anorm.x)
X		poly->index = XNORMAL;
X	else if (indexval == anorm.y)
X		poly->index = YNORMAL;
X	else
X		poly->index = ZNORMAL;
X
X	return poly;
X}
X
XMethods *
XPolygonMethods()
X{
X	if (iPolygonMethods == (Methods *)NULL) {
X		iPolygonMethods = MethodsCreate();
X		iPolygonMethods->create = (GeomCreateFunc *)PolygonCreate;
X		iPolygonMethods->methods = PolygonMethods;
X		iPolygonMethods->name = PolygonName;
X		iPolygonMethods->intersect = PolygonIntersect;
X		iPolygonMethods->normal = PolygonNormal;
X		iPolygonMethods->uv = PolygonUV;
X		iPolygonMethods->bounds = PolygonBounds;
X		iPolygonMethods->stats = PolygonStats;
X		iPolygonMethods->checkbounds = TRUE;
X		iPolygonMethods->closed = FALSE;
X	}
X	return iPolygonMethods;
X}
X
X/*
X * Quadrants are defined as:
X *        |
X *   1    |   0
X *        |
X * -------c--------
X *        |
X *   2    |   3
X *        |
X */
X#define quadrant(p, c) ((p.u<c.u) ? ((p.v<c.v) ? 2 : 1) : ((p.v<c.v) ? 3 : 0))
X
X/*
X * Perform ray-polygon intersection test.
X */
Xint
XPolygonIntersect(poly, ray, mindist, maxdist)
XPolygon *poly;
XRay *ray;
XFloat mindist, *maxdist;
X{
X	register int winding, i;
X	Vector dir, pos;
X	int quad, lastquad;
X	Float dist, left, right;
X	Vec2d center, cur, last;
X
X	PolyTests++;
X	pos = ray->pos;
X	dir = ray->dir;
X	/*
X	 * First, find where ray hits polygon plane, projecting
X	 * along the polygon's dominant normal component.
X	 */
X
X	dist = dotp(&poly->norm, &dir);
X	if(fabs(dist) < EPSILON)
X		/*
X	 	 * No intersection with polygon plane.
X		 */
X		return FALSE;
X
X	dist = (poly->d - dotp(&poly->norm, &pos)) / dist;
X	if(dist < mindist || dist > *maxdist)
X		/*
X		 * Intersection point behind origin or too far.
X		 */
X		return FALSE;
X
X	/*
X	 * Compute the point of intersection, projected appropriately.
X	 */
X	if(poly->index == XNORMAL) {
X		center.u = pos.y + dist * dir.y;
X		center.v = pos.z + dist * dir.z;
X	} else if(poly->index == YNORMAL) {
X		center.v = pos.z + dist * dir.z;
X		center.u = pos.x + dist * dir.x;
X	} else  {
X		center.u = pos.x + dist * dir.x;
X		center.v = pos.y + dist * dir.y;
X	}	
X
X	/*
X	 * Is the point inside the polygon?
X	 *
X	 * Compute the winding number by finding the quadrant each
X	 * polygon point lies in with respect to the the point in
X	 * question, and computing a "delta" (winding number).  If we
X	 * end up going around in a complete circle around
X	 * the point (winding number is non-zero at the end), then
X	 * we're inside.  Otherwise, the point is outside.
X	 *
X	 * Note that we can turn this into a 2D problem by projecting
X	 * all the points along the axis defined by poly->index,
X	 * the "dominant" part of the polygon's normal vector.
X	 */
X	winding = 0;
X	VecProject(last, poly->points[poly->npoints -1], poly->index);
X	lastquad = quadrant(last, center);
X	for(i = 0; i < poly->npoints; i++, last = cur) {
X		VecProject(cur, poly->points[i], poly->index);
X		quad = quadrant(cur, center);
X		if (quad == lastquad)
X			continue;
X		if(((lastquad + 1) & 3) == quad)
X			winding++;
X		else if(((quad + 1) & 3) == lastquad)
X			winding--;
X		else {
X			/*
X			 * Find where edge crosses
X			 * center's X axis.
X			 */
X			right = last.u - cur.u;
X			left = (last.v - cur.v) * (center.u - last.u);
X			if(left + last.v * right > right * center.v)
X				winding += 2;
X			else
X				winding -= 2;
X		}
X		lastquad = quad;
X	}
X
X	if (winding != 0) {
X		*maxdist = dist;
X		PolyHits++;
X		return TRUE;
X	}
X	return FALSE;
X}
X
X/*
X * Return the normal to the polygon surface.
X */
X/*ARGSUSED*/
Xint
XPolygonNormal(poly, pos, nrm, gnrm)
XPolygon *poly;
XVector *pos, *nrm, *gnrm;
X{
X	*gnrm = *nrm = poly->norm;
X	return FALSE;
X}
X
X/*ARGSUSED*/
Xvoid
XPolygonUV(poly, pos, norm, uv, dpdu, dpdv)
XPolygon *poly;
XVector *pos, *norm, *dpdu, *dpdv;
XVec2d *uv;
X{
X	/*
X	 * Since there's no nice way to do this, we wimp out and
X	 * do the following...
X	 *
X	 * Of course, we could force the user to specify U and V
X	 * axes, but forcing them to use X and Y as U and V is
X	 * just as arbitrary and much simpler to deal with.
X	 */
X	uv->u = pos->x;
X	uv->v = pos->y;
X	if (dpdu) {
X		dpdu->x = 1.;
X		dpdu->y = dpdu->z = 0.;
X		dpdv->x = dpdv->z = 0.;
X		dpdv->y = 1.;
X	}
X}
X
X/*
X * Compute the extent of a polygon
X */
Xvoid
XPolygonBounds(poly, bounds)
XPolygon *poly;
XFloat bounds[2][3];
X{
X	register int i;
X
X	bounds[LOW][X] = bounds[HIGH][X] = poly->points[0].x;
X	bounds[LOW][Y] = bounds[HIGH][Y] = poly->points[0].y;
X	bounds[LOW][Z] = bounds[HIGH][Z] = poly->points[0].z;
X
X	for (i = 1 ;i < poly->npoints; i++) {
X		if (poly->points[i].x < bounds[LOW][X])
X			bounds[LOW][X] = poly->points[i].x;
X		if (poly->points[i].x > bounds[HIGH][X])
X			bounds[HIGH][X] = poly->points[i].x;
X		if (poly->points[i].y < bounds[LOW][Y])
X			bounds[LOW][Y] = poly->points[i].y;
X		if (poly->points[i].y > bounds[HIGH][Y])
X			bounds[HIGH][Y] = poly->points[i].y;
X		if (poly->points[i].z < bounds[LOW][Z])
X			bounds[LOW][Z] = poly->points[i].z;
X		if (poly->points[i].z > bounds[HIGH][Z])
X			bounds[HIGH][Z] = poly->points[i].z;
X	}
X}
X
Xchar *
XPolygonName()
X{
X	return polyName;
X}
X
Xvoid
XPolygonStats(tests, hits)
Xunsigned long *tests, *hits;
X{
X	*tests = PolyTests;
X	*hits = PolyHits;
X}
X
Xvoid
XPolygonMethodRegister(meth)
XUserMethodType meth;
X{
X	if (iPolygonMethods)
X		iPolygonMethods->user = meth;
X}
END_OF_FILE
if test 7872 -ne `wc -c <'libray/libobj/poly.c'`; then
    echo shar: \"'libray/libobj/poly.c'\" unpacked with wrong size!
fi
# end of 'libray/libobj/poly.c'
fi
if test -f 'libray/libtext/noise.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'libray/libtext/noise.c'\"
else
echo shar: Extracting \"'libray/libtext/noise.c'\" \(7883 characters\)
sed "s/^X//" >'libray/libtext/noise.c' <<'END_OF_FILE'
X/*
X * noise.c
X *
X * Copyright (C) 1989, 1991, Robert Skinner, Craig E. Kolb
X * All rights reserved.
X *
X * This software may be freely copied, modified, and redistributed
X * provided that this copyright notice is preserved on all copies.
X *
X * You may not distribute this software, in whole or in part, as part of
X * any commercial product without the express consent of the authors.
X *
X * There is no warranty or other guarantee of fitness of this software
X * for any purpose.  It is provided solely "as is".
X *
X * $Id: noise.c,v 4.0 91/07/17 14:43:38 kolb Exp Locker: kolb $
X *
X * $Log:	noise.c,v $
X * Revision 4.0  91/07/17  14:43:38  kolb
X * Initial version.
X * 
X */
X#include "libcommon/common.h"
X
X#define MINX		-1000000
X#define MINY		MINX
X#define MINZ		MINX
X
X#define SCURVE(a) ((a)*(a)*(3.0-2.0*(a)))
X#define REALSCALE ( 2.0 / 65536.0 )
X#define NREALSCALE ( 2.0 / 4096.0 )
X#define Hash3d(a,b,c) hashTable[hashTable[hashTable[(a) & 0xfff] ^ ((b) & 0xfff)] ^ ((c) & 0xfff)]
X#define Hash(a,b,c) (xtab[(xtab[(xtab[(a) & 0xff] ^ (b)) & 0xff] ^ (c)) & 0xff] & 0xff)
X
X#define INCRSUM(m,s,x,y,z)	((s)*(RTable[m]*0.5		\
X					+ RTable[m+1]*(x)	\
X					+ RTable[m+2]*(y)	\
X					+ RTable[m+3]*(z)))	\
X
X
X#define MAXSIZE 267
X
XFloat		RTable[MAXSIZE];
Xstatic short	*hashTable;
Xstatic int	R(), Crc16();
X
Xstatic unsigned short xtab[256] =
X{
X   0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
X   0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
X   0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
X   0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
X   0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
X   0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
X   0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
X   0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
X   0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
X   0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
X   0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
X   0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
X   0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
X   0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
X   0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
X   0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
X   0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
X   0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
X   0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
X   0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
X   0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
X   0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
X   0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
X   0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
X   0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
X   0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
X   0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
X   0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
X   0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
X   0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
X   0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
X   0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
X};
X
XFloat Chaos(), Marble();
X
Xvoid
XInitTextureTable()
X{
X	int i, j, temp;
X
X	seednrand(1);
X	hashTable = (short *) Malloc(4096*sizeof(short int));
X	for (i = 0; i < 4096; i++)
X		hashTable[i] = i;
X	for (i = 4095; i > 0; i--) {
X		j = (int)(nrand() * 4096);
X		temp = hashTable[i];
X		hashTable[i] = hashTable[j];
X		hashTable[j] = temp;
X	}
X}
X
Xvoid
XNoiseInit()
X{
X	int i;
X	Vector rp;
X
X	InitTextureTable();
X
X	for (i = 0; i < MAXSIZE; i++) {
X	   	rp.x = rp.y = rp.z = (Float)i;
X	   	RTable[i] = R(&rp)*REALSCALE - 1.0;
X 	}
X}
X
Xstatic int
XR(v)
XVector *v;
X{
X	v->x *= .12345;
X	v->y *= .12345;
X	v->z *= .12345;
X
X	return Crc16(v, sizeof(Vector));
X}
X
X/*
X * Note that passing a Float to Crc16 and interpreting it as
X * an array of chars means that machines with different floating-point
X * representation schemes will evaluate Noise(point) differently.
X */
Xstatic int
XCrc16(buf, count)
Xregister char *buf;
Xregister int  count;
X{
X	register unsigned int crc = 0;
X
X	while (count--)
X		crc = (crc >> 8) ^ xtab[ (unsigned char) (crc ^ *buf++) ];
X
X	return crc;
X}
X
X
X/*
X * Robert Skinner's Perlin-style "Noise" function
X */
XFloat
XNoise3(point)
XVector *point;
X{
X	register int	ix, iy, iz, jx, jy, jz;
X	Float		x, y, z;
X	Float	sx, sy, sz, tx, ty, tz;
X	Float	sum;
X	short	m;
X
X
X	/* ensures the values are positive. */
X	x = point->x - MINX; y = point->y - MINY; z = point->z - MINZ;
X
X	/* its equivalent integer lattice point. */
X	ix = (int)x; iy = (int)y; iz = (int)z;
X	jx = ix+1; jy = iy + 1; jz = iz + 1;
X
X	sx = SCURVE(x - ix); sy = SCURVE(y - iy); sz = SCURVE(z - iz);
X
X	/* the complement values of sx,sy,sz */
X	tx = 1.0 - sx; ty = 1.0 - sy; tz = 1.0 - sz;
X
X	/*
X	 *  interpolate!
X	 */
X	m = Hash3d( ix, iy, iz ) & 0xFF;
X	sum = INCRSUM(m,(tx*ty*tz),(x-ix),(y-iy),(z-iz));
X
X	m = Hash3d( jx, iy, iz ) & 0xFF;
X	sum += INCRSUM(m,(sx*ty*tz),(x-jx),(y-iy),(z-iz));
X
X	m = Hash3d( ix, jy, iz ) & 0xFF;
X	sum += INCRSUM(m,(tx*sy*tz),(x-ix),(y-jy),(z-iz));
X
X	m = Hash3d( jx, jy, iz ) & 0xFF;
X	sum += INCRSUM(m,(sx*sy*tz),(x-jx),(y-jy),(z-iz));
X
X	m = Hash3d( ix, iy, jz ) & 0xFF;
X	sum += INCRSUM(m,(tx*ty*sz),(x-ix),(y-iy),(z-jz));
X
X	m = Hash3d( jx, iy, jz ) & 0xFF;
X	sum += INCRSUM(m,(sx*ty*sz),(x-jx),(y-iy),(z-jz));
X
X	m = Hash3d( ix, jy, jz ) & 0xFF;
X	sum += INCRSUM(m,(tx*sy*sz),(x-ix),(y-jy),(z-jz));
X
X	m = Hash3d( jx, jy, jz ) & 0xFF;
X	sum += INCRSUM(m,(sx*sy*sz),(x-jx),(y-jy),(z-jz));
X
X	return sum;
X
X}
X
X/*
X * Vector-valued "Noise"
X */
Xvoid
XDNoise3(point, result)
XVector *point, *result;
X{
X	register int	ix, iy, iz, jx, jy, jz;
X	Float		x, y, z;
X	Float px, py, pz, s;
X	Float	sx, sy, sz, tx, ty, tz;
X	short	m;
X
X	/* ensures the values are positive. */
X	x = point->x - MINX; y = point->y - MINY; z = point->z - MINZ;
X
X	/* its equivalent integer lattice point. */
X	ix = (int)x; iy = (int)y; iz = (int)z;
X	jx = ix+1; jy = iy + 1; jz = iz + 1;
X
X	sx = SCURVE(x - ix); sy = SCURVE(y - iy); sz = SCURVE(z - iz);
X
X	/* the complement values of sx,sy,sz */
X	tx = 1.0 - sx; ty = 1.0 - sy; tz = 1.0 - sz;
X
X	/*
X	 *  interpolate!
X	 */
X	m = Hash3d( ix, iy, iz ) & 0xFF;
X	px = x-ix;  py = y-iy;  pz = z-iz;
X	s = tx*ty*tz;
X	result->x = INCRSUM(m,s,px,py,pz);
X	result->y = INCRSUM(m+4,s,px,py,pz);
X	result->z = INCRSUM(m+8,s,px,py,pz);
X
X	m = Hash3d( jx, iy, iz ) & 0xFF;
X	px = x-jx;
X	s = sx*ty*tz;
X	result->x += INCRSUM(m,s,px,py,pz);
X	result->y += INCRSUM(m+4,s,px,py,pz);
X	result->z += INCRSUM(m+8,s,px,py,pz);
X
X	m = Hash3d( jx, jy, iz ) & 0xFF;
X	py = y-jy;
X	s = sx*sy*tz;
X	result->x += INCRSUM(m,s,px,py,pz);
X	result->y += INCRSUM(m+4,s,px,py,pz);
X	result->z += INCRSUM(m+8,s,px,py,pz);
X
X	m = Hash3d( ix, jy, iz ) & 0xFF;
X	px = x-ix;
X	s = tx*sy*tz;
X	result->x += INCRSUM(m,s,px,py,pz);
X	result->y += INCRSUM(m+4,s,px,py,pz);
X	result->z += INCRSUM(m+8,s,px,py,pz);
X
X	m = Hash3d( ix, jy, jz ) & 0xFF;
X	pz = z-jz;
X	s = tx*sy*sz;
X	result->x += INCRSUM(m,s,px,py,pz);
X	result->y += INCRSUM(m+4,s,px,py,pz);
X	result->z += INCRSUM(m+8,s,px,py,pz);
X
X	m = Hash3d( jx, jy, jz ) & 0xFF;
X	px = x-jx;
X	s = sx*sy*sz;
X	result->x += INCRSUM(m,s,px,py,pz);
X	result->y += INCRSUM(m+4,s,px,py,pz);
X	result->z += INCRSUM(m+8,s,px,py,pz);
X
X	m = Hash3d( jx, iy, jz ) & 0xFF;
X	py = y-iy;
X	s = sx*ty*sz;
X	result->x += INCRSUM(m,s,px,py,pz);
X	result->y += INCRSUM(m+4,s,px,py,pz);
X	result->z += INCRSUM(m+8,s,px,py,pz);
X
X	m = Hash3d( ix, iy, jz ) & 0xFF;
X	px = x-ix;
X	s = tx*ty*sz;
X	result->x += INCRSUM(m,s,px,py,pz);
X	result->y += INCRSUM(m+4,s,px,py,pz);
X	result->z += INCRSUM(m+8,s,px,py,pz);
X}
END_OF_FILE
if test 7883 -ne `wc -c <'libray/libtext/noise.c'`; then
    echo shar: \"'libray/libtext/noise.c'\" unpacked with wrong size!
fi
# end of 'libray/libtext/noise.c'
fi
if test -f 'libshade/picture.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'libshade/picture.c'\"
else
echo shar: Extracting \"'libshade/picture.c'\" \(7560 characters\)
sed "s/^X//" >'libshade/picture.c' <<'END_OF_FILE'
X/*
X * picture.c
X *
X * Copyright (C) 1989, 1991, Craig E. Kolb, Rod G. Bogart
X * All rights reserved.
X *
X * This software may be freely copied, modified, and redistributed
X * provided that this copyright notice is preserved on all copies.
X *
X * You may not distribute this software, in whole or in part, as part of
X * any commercial product without the express consent of the authors.
X *
X * There is no warranty or other guarantee of fitness of this software
X * for any purpose.  It is provided solely "as is".
X *
X * $Id: picture.c,v 4.0 91/07/17 14:47:00 kolb Exp Locker: kolb $
X *
X * $Log:	picture.c,v $
X * Revision 4.0  91/07/17  14:47:00  kolb
X * Initial version.
X * 
X */
X#include "rayshade.h"
X#include "picture.h"
X#include "viewing.h"
X#include "options.h"
X#include "stats.h"
X
X#ifdef URT
Xunsigned char **outptr;		/* Output buffer */
Xstatic int count_rle_rows();
X#endif
X
X/*
X * Convert floating-point (0.-1.) to unsigned char (0-255), with no gamma
X * correction.
X */
Xunsigned char
Xcorrect(x)
XFloat x;
X{
X	/*
X	 * Truncate values < 0 or > 1.
X	 */
X	if (x < 0)
X		return 0;
X	if (x > 1.)
X		return 255;
X	return (unsigned char)(x * 255.);
X}
X
X#ifdef URT
X/*
X * Open image file and write RLE header.
X */
Xvoid
XPictureStart(argv)
Xchar **argv;
X{
X	char gammacom[40];
X
X	if (Options.framenum != Options.startframe) {
X		/*
X		 * We've been here before;
X		 * write a new header and return.
X		 */
X		rle_put_setup(&rle_dflt_hdr);
X		return;
X	}
X	/*
X	 * If Appending, then we know that outfile is valid, 'cause
X	 * we've already read its header.
X	 */
X	if (Options.appending) {
X		Options.pictfile = fopen(Options.imgname, "a");
X		if (Options.pictfile == (FILE *)0)
X			RLerror(RL_PANIC, "Cannot append to %s?!\n",
X					Options.imgname);
X		rle_dflt_hdr.rle_file = Options.pictfile;
X		rle_put_init(&rle_dflt_hdr);
X	} else {
X		/*
X		 * Starting image from scatch.
X		 */
X		if (Options.imgname) {
X			Options.pictfile = fopen(Options.imgname, "w");
X			if (Options.pictfile == (FILE *)NULL)
X				RLerror(RL_PANIC,"Cannot open %s for writing.",
X					Options.imgname);
X		} else
X			Options.pictfile = stdout;
X
X		rle_dflt_hdr.xmax = Screen.maxx;
X		rle_dflt_hdr.ymax = Screen.maxy;
X		rle_dflt_hdr.xmin = Screen.minx;
X		rle_dflt_hdr.ymin = Screen.miny;
X		rle_dflt_hdr.alpha = Options.alpha;
X		if (Options.alpha)
X			RLE_SET_BIT(rle_dflt_hdr, RLE_ALPHA);
X		if (Options.exp_output) {
X			RLE_SET_BIT(rle_dflt_hdr, RLE_BLUE + 1);
X			rle_dflt_hdr.ncolors = 4;
X			rle_putcom("exponential_data", &rle_dflt_hdr);
X		}
X		else
X			rle_dflt_hdr.ncolors = 3;
X		/*
X	 	 * Document image gamma in RLE comment area.
X		 * Options.gamma has been inverted.
X	 	 */
X		(void)sprintf(gammacom, "display_gamma=%g", 1./Options.gamma);
X		rle_putcom(gammacom, &rle_dflt_hdr);
X		/*
X	 	 * Document command line in RLE history.
X	 	 */
X		rle_addhist(argv, (rle_hdr *)0, &rle_dflt_hdr);
X		rle_dflt_hdr.rle_file = Options.pictfile;
X		rle_put_setup(&rle_dflt_hdr);
X		/*
X	 	 * Flush the header.  If we don't, and LINDA forks off
X	 	 * a bunch of workers, strange things will happen (they'll
X	 	 * all flush the buffer when they die, and you end up with
X	 	 * lots of headers at the end of the file).
X	 	 */
X		(void)fflush(rle_dflt_hdr.rle_file);
X	}
X
X	if (rle_row_alloc(&rle_dflt_hdr, &outptr) < 0)
X		RLerror(RL_PANIC, "Unable to allocate image memory.\n");
X}
X
X/*
X * Read RLE header to which we are appending in order determine
X * old resolution, window location, and the like.
X */
Xvoid
XPictureSetWindow()
X{
X	if (Options.imgname == (char *)NULL)
X		RLerror(RL_PANIC,
X			"No partially-completed image file specified.\n");
X
X	/*
X	 * Open image and read RLE header.
X	 */
X	Options.pictfile = fopen(Options.imgname, "r");
X	rle_dflt_hdr.rle_file = Options.pictfile;
X	rle_get_setup_ok(&rle_dflt_hdr, "rayshade", Options.imgname);
X
X	/*
X	 * If user specified a window that does not match what's in
X	 * the header, complain.
X	if (Screen.minx != UNSET && Screen.minx != rle_dflt_hdr.xmin ||
X	    Screen.miny != UNSET && Screen.miny != rle_dflt_hdr.ymin ||
X	    Screen.maxx != UNSET && Screen.maxx != rle_dflt_hdr.xmax ||
X	    Screen.maxy != UNSET && Screen.maxy != rle_dflt_hdr.ymax)
X		RLerror(RL_ADVISE, "Image window: %d - %d, %d - %d.\n",
X			rle_dflt_hdr.xmin, rle_dflt_hdr.xmax,
X			rle_dflt_hdr.ymin, rle_dflt_hdr.ymax);
X	 */
X	/*
X	 * Set window.
X	 */
X	Screen.minx = rle_dflt_hdr.xmin;
X	Screen.miny = rle_dflt_hdr.ymin;
X	Screen.maxx = rle_dflt_hdr.xmax;
X	Screen.maxy = rle_dflt_hdr.ymax;
X
X	/*
X	 * Set alpha.  Warn the user if the alpha option doesn't reflect
X	 * what's already been rendered.
X	 */
X	if (Options.alpha != rle_dflt_hdr.alpha)
X		RLerror(RL_WARN, "Image %s %s an alpha channel.\n",
X			Options.imgname,
X			rle_dflt_hdr.alpha ? "has" : "does not have");
X
X	Options.alpha = rle_dflt_hdr.alpha;
X
X	/*
X	 * Determine number of scanlines written to file.
X	 */
X	Screen.miny += count_rle_rows(&rle_dflt_hdr);
X	if (Screen.miny >= Screen.maxy) {
X		fprintf(stderr, "\"%s\" is a complete image.\n",
X			Options.imgname);
X		exit(0);
X	}
X	fprintf(Stats.fstats,"Continuing \"%s\" at scanline #%d.\n",
X		Options.imgname, Screen.miny);
X	(void)fclose(Options.pictfile);
X}
X
Xstatic int
Xcount_rle_rows( hdr )
Xrle_hdr *hdr;
X{
X	rle_op **raw;
X	int **nraw, y, ynext;
X
X	if (rle_raw_alloc( hdr, &raw, &nraw ) < 0)  {
X		RLerror(RL_PANIC,
X			"Unable to allocate memory in count_rle_rows.\n");
X	}
X
X	y = hdr->ymin;
X	while ((ynext = rle_getraw( hdr, raw, nraw )) != 32768) {
X		y = ynext+1;
X		rle_freeraw( hdr, raw, nraw );
X	}
X
X	/* Free memory. */
X	rle_raw_free( hdr, raw, nraw );
X
X	return y - hdr->ymin;
X}
X
X/*
X * Write a scanline of output.
X * "buf" is an array of Color structures of size Screen.xsize.  Each color
X * component is normalized to [0, 1.].
X */
Xvoid
XPictureWriteLine(buf)
XPixel *buf;
X{
X	register int i, chan;
X	float floats[3];
X	rle_pixel pixels[4];
X
X	for(i = 0; i < Screen.xsize; i++) {
X		if (!Options.exp_output) {
X			/*
X			 * Scale colors to fit unsigned char and check for
X			 * over/underflow.
X			 */
X			outptr[0][i] = CORRECT(buf[i].r);
X			outptr[1][i] = CORRECT(buf[i].g);
X			outptr[2][i] = CORRECT(buf[i].b);
X		} else {
X			/*
X			 * Convert 3 floats to 4 unsigned chars for
X			 * 'exponential_data' RLE file.
X			 */
X			floats[0] = GAMMACORRECT(buf[i].r);
X			floats[1] = GAMMACORRECT(buf[i].g);
X			floats[2] = GAMMACORRECT(buf[i].b);
X			float_to_exp( 3, floats, pixels );
X			for (chan = 0; chan <= 3; chan++)
X				outptr[chan][i] = pixels[chan];
X		}
X		if (Options.alpha)
X			/*
X			 * Don't gamma correct alpha channel.
X			 */
X			outptr[-1][i] = correct(buf[i].alpha);
X	}
X	rle_putrow(outptr, Screen.xsize, &rle_dflt_hdr);
X}
X
X/*
X * End the frame.
X */
Xvoid
XPictureFrameEnd()
X{
X	rle_puteof(&rle_dflt_hdr);
X}
X
X/*
X * Close image file.
X */
Xvoid
XPictureEnd()
X{
X	(void)fclose(Options.pictfile);
X}
X
X#else /* !URT */
Xvoid
XPictureStart(argv)
Xchar **argv;
X{
X	if (Options.imgname) {
X		Options.pictfile = fopen(Options.imgname, "w");
X		if (Options.pictfile == (FILE *)NULL)
X			RLerror(RL_PANIC, "Cannot open %s for writing.",
X				Options.imgname);
X	} else
X		Options.pictfile = stdout;
X
X	fprintf(Options.pictfile,"%d %d\n",Screen.xsize, Screen.ysize);
X
X	(void)fflush(Options.pictfile);
X}
X
Xvoid
XPictureWriteLine(buf)
XPixel *buf;
X{
X	register int i;
X
X	for (i = 0; i < Screen.xsize; i++) {
X		(void)fputc((int)CORRECT(buf[i].r), Options.pictfile);
X		(void)fputc((int)CORRECT(buf[i].g), Options.pictfile);
X		(void)fputc((int)CORRECT(buf[i].b), Options.pictfile);
X	}
X	(void)fflush(Options.pictfile);
X}
X
Xvoid
XPictureFrameEnd()
X{
X	/*
X	 * Don't do anything -- generic format has no end-of-image marker.
X	 */
X}
X
Xvoid
XPictureEnd()
X{
X	(void)fclose(Options.pictfile);
X}
X
X#endif /* URT */
END_OF_FILE
if test 7560 -ne `wc -c <'libshade/picture.c'`; then
    echo shar: \"'libshade/picture.c'\" unpacked with wrong size!
fi
# end of 'libshade/picture.c'
fi
if test -f 'libshade/viewing.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'libshade/viewing.c'\"
else
echo shar: Extracting \"'libshade/viewing.c'\" \(7193 characters\)
sed "s/^X//" >'libshade/viewing.c' <<'END_OF_FILE'
X/*
X * viewing.c
X *
X * Copyright (C) 1989, 1991, Craig E. Kolb, Rod G. Bogart
X * All rights reserved.
X *
X * This software may be freely copied, modified, and redistributed
X * provided that this copyright notice is preserved on all copies.
X *
X * You may not distribute this software, in whole or in part, as part of
X * any commercial product without the express consent of the authors.
X *
X * There is no warranty or other guarantee of fitness of this software
X * for any purpose.  It is provided solely "as is".
X *
X * $Id: viewing.c,v 4.0 91/07/17 14:48:18 kolb Exp Locker: kolb $
X *
X * $Log:	viewing.c,v $
X * Revision 4.0  91/07/17  14:48:18  kolb
X * Initial version.
X * 
X */
X#include "rayshade.h"
X#include "viewing.h"
X#include "libcommon/sampling.h"
X#include "options.h"
X#include "defaults.h"
X#include "picture.h"
X#include "stats.h"
X
XRSCamera	Camera;
XRSScreen	Screen;
X
Xvoid SampleScreen(), SampleScreenFiltered();
X
Xvoid
XRSViewing()
X{
X	Float magnitude;
X
X	VecSub(Camera.lookp, Camera.pos, &Camera.dir);
X	Screen.firstray = Camera.dir;
X
X	Camera.lookdist = VecNormalize(&Camera.dir);
X	if (VecNormCross(&Camera.dir, &Camera.up, &Screen.scrni) == 0.)
X		RLerror(RL_PANIC,
X			"The view and up directions are identical?\n");
X	(void)VecNormCross(&Screen.scrni, &Camera.dir, &Screen.scrnj);
X
X	/*
X	 * Add stereo separation if desired.
X	 */
X	if (Options.stereo) {
X		if (Options.stereo == LEFT)
X			magnitude = -.5 * Options.eyesep;
X		else
X			magnitude =  .5 * Options.eyesep;
X		Camera.pos.x += magnitude * Screen.scrni.x;
X		Camera.pos.y += magnitude * Screen.scrni.y;
X		Camera.pos.z += magnitude * Screen.scrni.z;
X		VecSub(Camera.lookp, Camera.pos, &Screen.firstray);
X		Camera.dir = Screen.firstray;
X		Camera.lookdist = VecNormalize(&Camera.dir);
X		(void)VecNormCross(&Camera.dir, &Camera.up, &Screen.scrni);
X		(void)VecNormCross(&Screen.scrni, &Camera.dir, &Screen.scrnj);
X	}
X
X	magnitude = 2.*Camera.lookdist * tan(deg2rad(0.5*Camera.hfov)) /
X				Screen.xres;
X
X	VecScale(magnitude, Screen.scrni, &Screen.scrnx);
X	magnitude = 2.*Camera.lookdist * tan(deg2rad(0.5*Camera.vfov)) /
X				Screen.yres;
X	VecScale(magnitude, Screen.scrnj, &Screen.scrny);
X
X	Screen.firstray.x -= 0.5*Screen.yres*Screen.scrny.x +
X			     0.5*Screen.xres*Screen.scrnx.x;
X	Screen.firstray.y -= 0.5*Screen.yres*Screen.scrny.y +
X			     0.5*Screen.xres*Screen.scrnx.y;
X	Screen.firstray.z -= 0.5*Screen.yres*Screen.scrny.z +
X			     0.5*Screen.xres*Screen.scrnx.z;
X
X	if (Camera.focaldist == UNSET)
X		Camera.focaldist = Camera.lookdist;
X}
X
X/*
X * Adjust the initial ray to account for an aperture and a focal
X * distance.  The ray argument is assumed to be an initial ray, and
X * always reset to the eye point.  It is assumed to be unit length.
X */
Xvoid
Xfocus_blur_ray(ray)
XRay *ray;
X{
X	Vector circle_point, aperture_inc;
X	extern void UnitCirclePoint();
X	/*
X	 * Find a point on a unit circle and scale by aperture size.
X	 * This simulates rays passing thru different parts of the aperture.
X	 * Treat the point as a vector and rotate it so the circle lies
X	 * in the plane of the screen.  Add the aperture increment to the
X	 * starting position of the ray.  Stretch the ray to be focaldist 
X	 * in length.  Subtract the aperture increment from the end of the
X	 * long ray.  This insures that the ray heads toward a point at
X	 * the specified focus distance, so that point will be in focus.
X	 * Normalize the ray, and that's it.  Really.
X	 */
X	UnitCirclePoint(&circle_point, ray->sample);
X	VecComb(Camera.aperture * circle_point.x, Screen.scrni,
X		    Camera.aperture * circle_point.y, Screen.scrnj,
X		    &aperture_inc);
X	VecAdd(aperture_inc, Camera.pos, &(ray->pos));
X	VecScale(Camera.focaldist, ray->dir, &(ray->dir));
X	VecSub(ray->dir, aperture_inc, &(ray->dir));
X	(void)VecNormalize(&ray->dir);
X}
X
Xvoid
XViewingSetup()
X{
X	if (Options.stereo && Options.eyesep == UNSET)
X		RLerror(RL_PANIC,
X			"No eye separation specified for stereo rendering.\n");
X	/*
X	 * Because we want the user to be able to override the input file
X	 * through the command line, we have to initialize some variables to
X	 * bogus values so that when the file is being parsed, it is
X	 * possible to tell if a given variable has been set on the
X	 * command line.
X	 *
X	 * If such variables are not set to legal values on the command
X	 * line or in the input file, we must do it here.
X	 */
X	if (Screen.xres == UNSET)
X		Screen.xres = XRESOLUTION;
X	if (Screen.yres == UNSET)
X		Screen.yres = YRESOLUTION;
X
X#ifdef URT
X	/*
X	 * If using the URT, we can use the RLE file header to
X	 * determine window size.  Screen size (Screen.xres, Screen.yres)
X	 * is determined as usual (from command line or input file).
X	 */
X	if (Options.appending) {
X		/*
X		 * Read image header to determine window size.
X		 */
X		PictureSetWindow();
X	} else {
X#endif
X	if (Options.xmin < 0.) Options.xmin = 0.;
X	if (Options.ymin < 0.) Options.ymin = 0.;
X	if (Options.xmax > 1.) Options.xmax = 1.;
X	if (Options.xmax > 1.) Options.xmax = 1.;
X
X	Screen.minx = (int)(Options.xmin * Screen.xres);
X	Screen.maxx = (int)(Options.xmax * Screen.xres -1);
X	Screen.miny = (int)(Options.ymin * Screen.yres);
X	Screen.maxy = (int)(Options.ymax * Screen.yres -1);
X#ifdef URT
X	}
X#endif
X
X	Screen.xsize = Screen.maxx - Screen.minx + 1;
X	Screen.ysize = Screen.maxy - Screen.miny + 1;
X
X	/*
X	 * Sanity check.
X	 */
X	if (Screen.minx < 0 || Screen.miny < 0 ||
X	    Screen.maxx >= Screen.xres || Screen.maxy >= Screen.yres)
X		RLerror(RL_PANIC, "Invalid window specification.\n");
X
X	/*
X	 * If not defined in the input file, calculate VFOV
X	 * by hand.  This assumes that pixels are square, which is
X	 * probably a bad idea.  ("aspect" option?)
X	 */
X	if (Camera.vfov == UNSET)
X		Camera.vfov = Camera.hfov * Screen.yres / Screen.xres;
X}
X
Xvoid
XSampleScreenFiltered(x, y, u, v, ray, color, sample)
XFloat x, y;
XRay *ray;
XPixel *color;
Xint sample, u, v;
X{
X	SampleScreen(x, y, ray, color, sample);
X	color->r *= Sampling.filter[u][v];
X	color->g *= Sampling.filter[u][v];
X	color->b *= Sampling.filter[u][v];
X	color->alpha *= Sampling.filter[u][v];
X}	
X
Xvoid
XSampleScreen(x, y, ray, color, sample)
XFloat x, y;		/* Screen position to sample */
XRay *ray;		/* ray, with origin and medium properly set */
XPixel *color;		/* resulting color */
Xint sample;		/* sample number */
X{
X	Float dist;
X	HitList hitlist;
X	Color ctmp, fullintens;
X	extern void focus_blur_ray(), ShadeRay();
X
X	/*
X	 * Calculate ray direction.
X	 */
X	Stats.EyeRays++;
X	ray->dir.x = Screen.firstray.x + x*Screen.scrnx.x + y*Screen.scrny.x;
X	ray->dir.y = Screen.firstray.y + x*Screen.scrnx.y + y*Screen.scrny.y;
X	ray->dir.z = Screen.firstray.z + x*Screen.scrnx.z + y*Screen.scrny.z;
X
X	(void)VecNormalize(&ray->dir);
X
X	ray->sample = sample;
X
X	if (Camera.aperture > 0.0) {
X		/*
X		 * If the aperture is open, adjust the initial ray
X		 * to account for depth of field.  
X		 */
X		focus_blur_ray(ray);
X	}
X
X	/*
X	 * Do the actual ray trace.
X	 */
X	fullintens.r = fullintens.g = fullintens.b = 1.;
X	dist = FAR_AWAY;
X	hitlist.nodes = 0;
X	(void)TraceRay(ray, &hitlist, EPSILON, &dist);
X	ShadeRay(&hitlist, ray, dist, &Screen.background, &ctmp, &fullintens);
X	color->r = ctmp.r;
X	color->g = ctmp.g;
X	color->b = ctmp.b;
X	if (hitlist.nodes != 0) {
X		color->alpha = 1.;
X	} else {
X		color->alpha = 0.;
X	}
X}
END_OF_FILE
if test 7193 -ne `wc -c <'libshade/viewing.c'`; then
    echo shar: \"'libshade/viewing.c'\" unpacked with wrong size!
fi
# end of 'libshade/viewing.c'
fi
if test -f 'raypaint/xgraphics.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'raypaint/xgraphics.c'\"
else
echo shar: Extracting \"'raypaint/xgraphics.c'\" \(7806 characters\)
sed "s/^X//" >'raypaint/xgraphics.c' <<'END_OF_FILE'
X/*
X * xgraphics.c
X *
X * Copyright (C) 1989, 1991 Craig E. Kolb, Rod G. Bogart
X *
X * This software may be freely copied, modified, and redistributed
X * provided that this copyright notice is preserved on all copies.
X *
X * You may not distribute this software, in whole or in part, as part of
X * any commercial product without the express consent of the authors.
X * 
X * There is no warranty or other guarantee of fitness of this software
X * for any purpose.  It is provided solely "as is".
X *
X * $Id: xgraphics.c,v 4.0 91/07/17 17:37:32 kolb Exp Locker: kolb $
X *
X * $Log:	xgraphics.c,v $
X * Revision 4.0  91/07/17  17:37:32  kolb
X * Initial version.
X * 
X */
X
X#include <stdio.h>
X#include <math.h>
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X
Xchar *display_name = NULL;
XDisplay *dpy = NULL;
XScreen *scrn;
XVisual *vis;
XColormap cmap;
XGC gc;
XWindow win;
Xint screen_height;
X
Xunsigned long graymap[256];
Xint max_colors;
Xdouble one_over_gamma = 0.4;
X
X/*****************************************************************
X * Sets the gray color map for the device.  A 2.5 gamma map is used
X * by default.
X */
Xsetup_gray_gamma_map()
X{
X    int cc, col;
X    int gamma_color;
X
X    XColor xcolor;
X
X    /* Use the default colormap if possible. */
X    if ( vis == DefaultVisualOfScreen( scrn ) )
X        cmap = DefaultColormapOfScreen( scrn );
X    else
X        cmap = XCreateColormap( dpy, RootWindowOfScreen( scrn ),
X                               vis, AllocNone );
X
X    /* try to share with current colormap */
X    for (max_colors = 256; max_colors >= 16; max_colors = max_colors >> 1) {
X        xcolor.flags= DoRed | DoGreen | DoBlue;
X        for(col=0; col < max_colors; col++) {
X            gamma_color = (pow((float) col / (float) max_colors,
X                               one_over_gamma) * 65536);
X            xcolor.red= gamma_color;
X            xcolor.green= gamma_color;
X            xcolor.blue= gamma_color;
X            if (!XAllocColor(dpy, cmap, &xcolor)) {
X                for (cc=0; cc < col; cc++)
X                    XFreeColors(dpy, cmap, &graymap[cc], 1, 0);
X                col = 0;
X                break;
X            }
X            graymap[col] = xcolor.pixel;
X        }
X        if (col)
X            return;
X    }
X
X    /* use new map */
X    cmap = XCreateColormap( dpy, RootWindowOfScreen( scrn ),
X                           vis, AllocNone );
X    if (cmap == NULL)  {
X        fprintf(stderr, "Could not create color map for visual\n");
X        exit(-2);
X    }
X    for(cc=0; cc < 256; cc++)
X        if (!XAllocColorCells(dpy, cmap, False, NULL, 0, &graymap[cc], 1))
X            break;
X    max_colors = cc;
X
X    xcolor.flags= DoRed | DoGreen | DoBlue;
X    for(col=0; col < max_colors; col++) {
X        xcolor.pixel= graymap[col];
X        gamma_color = (pow((float) col / (float) max_colors,
X                           one_over_gamma) * 65536);
X        xcolor.red= gamma_color;
X        xcolor.green= gamma_color;
X        xcolor.blue= gamma_color;
X        XStoreColor(dpy, cmap, &xcolor);
X    }
X}
X
XGraphicsInit(xsize, ysize, name)
Xint xsize, ysize;
Xchar *name;
X{
X    int win_size;
X    XSetWindowAttributes attrs;
X    XSizeHints sh;
X
X    /* Open the display. */
X    if ( ! dpy )
X    {
X        XVisualInfo vis_temp, *vis_list, *max_vis;
X        int n_ret, i;
X
X        dpy = XOpenDisplay( display_name );
X        if ( ! dpy )
X        {
X            fprintf( stderr, "rayview: Can't open display %s\n",
X                     XDisplayName( display_name ) );
X            exit(1);
X        }
X
X        /* Get a PseudoColor visual that has the maximum number of planes. */
X        vis_temp.class = PseudoColor;
X        vis_list = XGetVisualInfo( dpy, VisualClassMask, &vis_temp, &n_ret );
X        if ( n_ret == 0 )
X        {
X            fprintf(stderr,
X                    "Can't find any PseudoColor visual from display %s.\n",
X                    XDisplayName( display_name ));
X            exit(1);
X        }
X        max_vis = &vis_list[0];
X        for ( i = 1; i < n_ret; i++ )
X        {
X            if ( max_vis->depth < vis_list[i].depth )
X                max_vis = &vis_list[i];
X        }
X        vis = max_vis->visual;
X        scrn = ScreenOfDisplay( dpy, max_vis->screen );
X        gc = DefaultGCOfScreen( scrn );
X
X        setup_gray_gamma_map();
X
X        XFree( (char *)vis_list );
X    }
X
X    screen_height = ysize;
X
X    attrs.backing_store = Always;
X    attrs.colormap = cmap;
X    attrs.event_mask = ExposureMask;
X    attrs.background_pixel = BlackPixelOfScreen(scrn);
X    attrs.border_pixel = WhitePixelOfScreen(scrn);
X
X    win = XCreateWindow( dpy, RootWindowOfScreen( scrn ),
X                         0, 0, xsize, ysize, 2,
X                         0, 0, vis,
X                         CWBackingStore | CWColormap | CWEventMask |
X                         CWBackPixel | CWBorderPixel,
X                         &attrs );
X
X    sh.flags = PSize | PMinSize | PMaxSize;
X    sh.width = sh.min_width = sh.max_width = xsize;
X    sh.height = sh.min_height = sh.max_height = ysize;
X    XSetStandardProperties( dpy, win, name, name, None, NULL, 0, &sh );
X
X    XMapWindow( dpy, win );
X
X    XFlush( dpy );
X}
X
X/*
X * Draw the pixel at (xp, yp) in the color given by the rgb-triple,
X * 0 indicating 0 intensity, 255 max intensity.
X */
XGraphicsDrawPixel(xp, yp, color)
Xint xp, yp;
Xunsigned char color[3];
X{
X    float bwvalue;
X    int val;
X
X    bwvalue = ( 0.35*color[0] + 0.55*color[1] + 0.10*color[2] ) / 256.0;
X    val = (int) ( bwvalue * max_colors );
X    XSetForeground( dpy, gc, graymap[val] );
X    XFillRectangle( dpy, win, gc, xp, (screen_height - (yp + 1)),
X                    1, 1 );
X}
X
X/*
X * Draw the rect with lower left corner (xp, yp) and upper right
X * corner (xp+ys, yp+ys).  The colors of the l-l, l-r, u-r, and u-l
X * corners are given as arrays of unsigned chars as above.
X */
XGraphicsDrawRectangle(xp, yp, xs, ys, ll, lr, ur, ul)
Xint xp, yp, xs, ys;
Xunsigned char ll[3], lr[3], ur[3], ul[3];
X{
X    float bwvalue;
X    int val;
X
X    bwvalue = ( 0.35*ll[0] + 0.55*ll[1] + 0.10*ll[2] ) / 256.0;
X    val = (int) ( bwvalue * max_colors );
X    XSetForeground( dpy, gc, graymap[val] );
X    XFillRectangle( dpy, win, gc, xp, (screen_height - (yp + ys + 1)),
X                    xs+1, ys+1 );
X    XFlush( dpy );
X}
X
XGraphicsLeftMouseEvent()
X{
X    Window root_ret, child_ret;
X    int rx, ry, wx, wy;
X    unsigned int mask;
X
X    if (XQueryPointer(dpy, win, &root_ret, &child_ret,
X                      &rx, &ry, &wx, &wy, &mask)) {
X        return mask & Button1Mask;
X    }
X    else
X        return 0;
X}
X
XGraphicsMiddleMouseEvent()
X{
X    Window root_ret, child_ret;
X    int rx, ry, wx, wy;
X    unsigned int mask;
X
X    if (XQueryPointer(dpy, win, &root_ret, &child_ret,
X                      &rx, &ry, &wx, &wy, &mask)) {
X        return mask & Button2Mask;
X    }
X    else
X        return 0;
X}
X
XGraphicsRightMouseEvent()
X{
X    Window root_ret, child_ret;
X    int rx, ry, wx, wy;
X    unsigned int mask;
X
X    if (XQueryPointer(dpy, win, &root_ret, &child_ret,
X                      &rx, &ry, &wx, &wy, &mask)) {
X        return mask & Button3Mask;
X    }
X    else
X        return 0;
X}
X
XGraphicsGetMousePos(x, y)
Xint *x, *y;
X{
X    Window root_ret, child_ret;
X    int rx, ry, wx, wy;
X    unsigned int mask;
X
X    if (XQueryPointer(dpy, win, &root_ret, &child_ret,
X                      &rx, &ry, &wx, &wy, &mask)) {
X        *x = wx;
X        *y = screen_height - wy - 1;
X    }
X    else {
X        *x = 0;
X        *y = 0;
X    }
X}
X
XGraphicsRedraw()
X{
X        XEvent event;
X        if (XCheckTypedEvent(dpy, Expose, &event)) {
X                XSetForeground( dpy, gc, graymap[0] );
X                XFillRectangle( dpy, win, gc, event.xexpose.x, event.xexpose.y,
X                    event.xexpose.width, event.xexpose.height );
X                XFlush( dpy );
X                return 1;
X        }
X        else
X                return 0;
X}
X
END_OF_FILE
if test 7806 -ne `wc -c <'raypaint/xgraphics.c'`; then
    echo shar: \"'raypaint/xgraphics.c'\" unpacked with wrong size!
fi
# end of 'raypaint/xgraphics.c'
fi
echo shar: End of archive 11 \(of 19\).
cp /dev/null ark11isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 19 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
