home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume21
/
rayshade
/
part11
< prev
next >
Wrap
Text File
|
1991-07-21
|
52KB
|
1,903 lines
Newsgroups: comp.sources.misc
From: Rayshade Construction Co. <rayshade@weedeater.math.YALE.EDU>
Subject: v21i014: rayshade - A raytracing package for UNIX, Part11/19
Message-ID: <1991Jul21.033720.29170@sparky.IMD.Sterling.COM>
X-Md4-Signature: b8ad240ecf5d0fee5bec675087c3931a
Date: Sun, 21 Jul 1991 03:37:20 GMT
Approved: kent@sparky.imd.sterling.com
Submitted-by: Rayshade Construction Co. <rayshade@weedeater.math.YALE.EDU>
Posting-number: Volume 21, Issue 14
Archive-name: rayshade/part11
Environment: UNIX, !16BIT
#! /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
exit 0 # Just in case...