#! /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 '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.upos; 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 X#include X#include X#include 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