home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-07-21 | 50.6 KB | 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...
-