#! /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 'blurb.urt' <<'END_OF_FILE' X X THE UTAH RASTER TOOLKIT X XThe Utah Raster toolkit is a collection of programs and C routines for Xdealing with raster images commonly encountered in computer graphics. It Xprovides the following major functions: X X * A device and system independent image format for storing images X and information about them. Called the RLE format, it uses X run length encoding to reduce storage space for most images. X X * A library of C routines for reading, writing and manipulating X images stored in the RLE format. X X * A collections of programs for manipulating and displaying RLE X images. X X XThe Format: X X The device independent RLE file has two parts, the header, which stores X information about the image (size, position, channel information, X color maps, comments, etc), and the actual image data in a run length X encoded format. The RLE format often requires about a third of the X available space for most "image synthesis" style images. If the image X does not compress well, the RLE format stores it as straight pixel data X with little extra overhead. The format was first developed around X 1983 at the University of Utah. X XThe Library: X X C routines are provided for setting up and reading the image header, X and for reading and writing the image a scanline at a time. Images can X be read or written using two different methods. Using the "row" method, X the library performs the RLE encoding and decoding. With the "raw" method, X scanlines are constructed directly with RLE opcodes. Additional routines X are available for generating dither matrices (e.g., for display programs X running on devices with less than 24 bits of color). X XThe Tools: X applymap - Apply color map values to pixel values. X avg4 - Downfilter an image by 1/4, generating a matte channel if one X didn't previously exist X crop - Crop an image. X dvirle - Convert TeX output into anti-aliased images. X fant - Rotate and/or scale in image by an arbitrary (float) value. X mcut - Quantize an image from 24 to eight bits using the median cut X algorithm. X mergechan - Merge several channels from different files into a single X RLE file. X pyrmask - Blend images using Gaussian pyramids. X repos - Change the position in the RLE header. X rleClock - Generate an image of a clock. X rleaddcom - Add a comment to the RLE file's header. X rlebg - Generate a solid or variable background. X rlebox - Find the actual non-background area of an image. X rlecomp - Digital image compositor. Provides the operations over, atop, X in, out, xor, plus, minus and diff on two images. X rledither - Floyd-Steinberg to a given color map. X rleflip - Rotate an image by 90/180 degree increments. X rlehdr - Dump the contents of the RLE header in human readable form. X rlehisto - Generate the histogram of an RLE file. X rleldmap - Load a color map into an RLE file from a variety of sources. X rlemandl - Generate Mandlebrot sets as RLE files. X rlenoise - Adds random noise to an image. X rlepatch - Overlay several smaller images over a larger one. X rleprint - Print all pixel values. X rlequant - Variance-based color quantization. X rlescale - Generates gray scale and color scale RLE files. X rleselect - Select specific images from a file. X rlesetbg - Set the background color stored in the RLE header. X rleskel - A skeleton application, for rolling your own. X rlespiff - Simple contrast enhancement to "spiff up" images. X rlesplice - Splice images together horizontally or vertically. X rlesplit - Split a file containing several images into several files. X rleswap - Swap, copy or delete channels in an RLE file. X rlezoom - Enlarge or shrink an image with pixel replication. X smush - Perform a simple Gaussian filter on an image. X to8 - Convert a 24 bit RGB image to an eight bit dithered one. X tobw - Convert 24 bits to 8 bits black and white. X unexp - Convert an "exponential" image to a displayable one. X unslice - Quickly assemble an image from several horizontal strips X X Format conversion programs are provided for: X - Ascii (line printer pictures) (to) X - Cubicomp image format (from) X - GIF (to and from) X - MacPaint (to and from) X - PBMPLUS pgm (from) and ppm (to and from) X - PostScript (to) X - Sun rasterfiles (to and from) X - Targa image format (from) X - TIFF (to and from) X - Wasatch paint systems (from) X - Wavefront 'RLA' format (to and from) X - Simple pixel streams (color & B&W) (to and from) X X Display programs are provided for: X get4d - SGI Iris 4D workstation X get_orion - Orion displays X getap - Apollo workstations X getbob - HP Series 300 ("bobcat") running Windows 9000 X getcx3d - Chromatics CX1500 display X getfb - BRL "libfb" displays X getgmr - Grinnell GMR-27 (remember those?) X getiris - Iris in raw 24 bit mode. X getmac - Macintosh. X getmex - Iris running Mex X getqcr - Photograph images with the Matrix QCR-Z camera. X getren - HP 98721 "Renaissance" display X getsun - Suns running Suntools X getx10 - Workstations running the X10 window system X getx11 - Workstations running X11 X - [Note display programs for a particular device are X simple to add] X X All the tools are designed to pipe together, so they can be used as X filters on images much like the standard Unix tools filter text. X XPlus: X X The raster toolkit also includes Unix man pages for the library and X commands, some sample images, and additional documentation. X XSystem Requirements: X X We have successfully ported the Raster Toolkit to a number of Unix X systems, including 4.2/4.3bsd (Vax, Sun, etc), Apollo Domain/IX, HP X Series 300, SGI Iris, IBM RT and RS6000, Stardent GS-1000, Cray X running UNICOS. Display programs are included for several devices. X Creating display programs for additional devices is a X straightforward task. X XDistribution: X X For Internet sites, the toolkit may be obtained via anonymous FTP to X the sites listed below, in the file pub/urt-3.0.tar.Z. Some sample X images are in the file pub/urt-img.tar.Z, and the file X pub/urt-doc.tar.Z contains some (somewhat out-of-date) "papers" X describing the toolkit. We are still working out distribution X mechanisms for sites not connected to the Internet. We will X probably be adding other archive sites; please send mail to one of X the addresses below if you don't see a site near you (particularly X if you are on the other side of the Atlantic or Pacific). If you X would like to offer to be an archive site, please let us know, too. X X cs.utah.edu (128.110.4.21) X weedeater.math.yale.edu (130.132.23.17) X freebie.engin.umich.edu (35.2.68.23) X X Although the Raster Toolkit software is copyrighted, it may be freely X re-distributed on a "GNU-like" basis. X XIf you have further questions, please direct them to X toolkit-request@cs.utah.edu Xor urt-request@caen.engin.umich.edu X(but not both). END_OF_FILE if test 7019 -ne `wc -c <'blurb.urt'`; then echo shar: \"'blurb.urt'\" unpacked with wrong size! fi # end of 'blurb.urt' fi 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'\" \(7574 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.1.1 91/09/29 15:40:57 cek Exp Locker: cek $ X * X * $Log: shadow.c,v $ X * Revision 4.0.1.1 91/09/29 15:40:57 cek X * patch1: ShadowOptions was incorrectly externed. X * 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) Xlong 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 long 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 7574 -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/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'\" \(7990 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.1.2 92/02/07 09:22:20 cek Exp Locker: cek $ X * X * $Log: picture.c,v $ X * Revision 4.0.1.2 92/02/07 09:22:20 cek X * patch6: Fixed typo in MTV error message. X * X * Revision 4.0.1.1 92/01/10 16:28:28 cek X * patch3: Added check for nonexistent patial image file. X * patch3: Fixed declaration of nrow in count_rle_rows(). X * patch3: Changed level of several error messages. X * 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_ABORT,"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_ABORT, 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 if (Options.pictfile == (FILE *)NULL) { X RLerror(RL_ABORT, "Cannot open image file %s.\n", X Options.imgname); X } 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_ABORT, "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 7990 -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 '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 if test -f 'rayview/spheregen.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'rayview/spheregen.c'\" else echo shar: Extracting \"'rayview/spheregen.c'\" \(7060 characters\) sed "s/^X//" >'rayview/spheregen.c' <<'END_OF_FILE' X/* X * Routines to define a unit sphere Object. X * If you have a sphere library (-lsphere on most SGI machines), you can X * use that by defining SPHERELIB on the cc command line. Otherwise, X * we use Jon Leech's code to generate a sphere. X * C. Kolb 6/91 X */ X#ifdef SPHERELIB X#include X X/* X * Define unit sphere Object. Here, we make use of sgi's spherelib. X * If not available, undefine SPHERELIB, and the code below will be used. X */ XObject XGLSphereObjectDefine() X{ X int sphere; X X sphere = genobj(); X sphobj(sphere); X return sphere; X} X#else X X/* X * The following code has been slightly modified. The original sphere X * code is available via anonymous X * ftp from weedeater.math.yale.edu (130.132.23.17) in pub/sphere.c X * X * Modifications include changing print_triangle to draw a GL object, X * the inclusion of gl.h, X * the renaming of main() to GLSphereObjectDefine(), the nuking of anything X * phigs-related, and setting the ccw flag to be true. X * X * C. Kolb 6/91 X */ X X/*% cc -g sphere.c -o sphere -lm X * X * sphere - generate a triangle mesh approximating a sphere by X * recursive subdivision. First approximation is an octahedron; X * each level of refinement increases the number of triangles by X * a factor of 4. X * Level 3 (128 triangles) is a good tradeoff if gouraud X * shading is used to render the database. X * X * Usage: sphere [level] [-p] [-c] X * level is an integer >= 1 setting the recursion level (default 1). X * -p causes generation of a PPHIGS format ASCII archive X * instead of the default generic output format. X * -c causes triangles to be generated with vertices in counterclockwise X * order as viewed from the outside in a RHS coordinate system. X * The default is clockwise order. X * X * The subroutines print_object() and print_triangle() should X * be changed to generate whatever the desired database format is. X * X * Jon Leech (leech@cs.unc.edu) 3/24/89 X */ X#include X#include X X#include X Xtypedef struct { X double x, y, z; X} point; X Xtypedef struct { X point pt[3]; /* Vertices of triangle */ X double area; /* Unused; might be used for adaptive subdivision */ X} triangle; X Xtypedef struct { X int npoly; /* # of triangles in object */ X triangle *poly; /* Triangles */ X} object; X X/* Six equidistant points lying on the unit sphere */ X#define XPLUS { 1, 0, 0 } /* X */ X#define XMIN { -1, 0, 0 } /* -X */ X#define YPLUS { 0, 1, 0 } /* Y */ X#define YMIN { 0, -1, 0 } /* -Y */ X#define ZPLUS { 0, 0, 1 } /* Z */ X#define ZMIN { 0, 0, -1 } /* -Z */ X X/* Vertices of a unit octahedron */ Xtriangle octahedron[] = { X { { XPLUS, ZPLUS, YPLUS }, 0.0 }, X { { YPLUS, ZPLUS, XMIN }, 0.0 }, X { { XMIN , ZPLUS, YMIN }, 0.0 }, X { { YMIN , ZPLUS, XPLUS }, 0.0 }, X { { XPLUS, YPLUS, ZMIN }, 0.0 }, X { { YPLUS, XMIN , ZMIN }, 0.0 }, X { { XMIN , YMIN , ZMIN }, 0.0 }, X { { YMIN , XPLUS, ZMIN }, 0.0 } X}; X X/* A unit octahedron */ Xobject oct = { X sizeof(octahedron) / sizeof(octahedron[0]), X &octahedron[0] X}; X X/* Forward declarations */ Xpoint *normalize(/* point *p */); Xpoint *midpoint(/* point *a, point *b */); Xvoid print_object(/* object *obj, int level */); Xvoid print_triangle(/* triangle *t */); X X/*extern char *malloc(/* unsigned );*/ X XObject XGLSphereObjectDefine(maxlevel) Xint maxlevel; X{ X object *old, X *new; X int ccwflag = 1, /* Reverse vertex order if true */ X i, level; X Object sph; X X makeobj(sph = genobj()); X X if (ccwflag) { X /* Reverse order of points in each triangle */ X for (i = 0; i < oct.npoly; i++) { X point tmp; X tmp = oct.poly[i].pt[0]; X oct.poly[i].pt[0] = oct.poly[i].pt[2]; X oct.poly[i].pt[2] = tmp; X } X } X X old = &oct; X X /* Subdivide each starting triangle (maxlevel - 1) times */ X for (level = 1; level < maxlevel; level++) { X /* Allocate a new object */ X new = (object *)malloc(sizeof(object)); X if (new == NULL) { X fprintf(stderr, "GLSphereObjectDefine: out of memory, level %d\n", X level); X exit(1); X } X new->npoly = old->npoly * 4; X X /* Allocate 4* the number of points in the current approximation */ X new->poly = (triangle *)malloc(new->npoly * sizeof(triangle)); X if (new->poly == NULL) { X fprintf(stderr, "GLSphereObjectDefine: out of memory, level %d\n", X level); X exit(1); X } X X /* Subdivide each triangle in the old approximation and normalize X * the new points thus generated to lie on the surface of the unit X * sphere. X * Each input triangle with vertices labelled [0,1,2] as shown X * below will be turned into four new triangles: X * X * Make new points X * a = (0+2)/2 X * b = (0+1)/2 X * c = (1+2)/2 X * 1 X * /\ Normalize a, b, c X * / \ X * b/____\ c Construct new triangles X * /\ /\ [0,b,a] X * / \ / \ [b,1,c] X * /____\/____\ [a,b,c] X * 0 a 2 [a,c,2] X */ X for (i = 0; i < old->npoly; i++) { X triangle X *oldt = &old->poly[i], X *newt = &new->poly[i*4]; X point a, b, c; X X a = *normalize(midpoint(&oldt->pt[0], &oldt->pt[2])); X b = *normalize(midpoint(&oldt->pt[0], &oldt->pt[1])); X c = *normalize(midpoint(&oldt->pt[1], &oldt->pt[2])); X X newt->pt[0] = oldt->pt[0]; X newt->pt[1] = b; X newt->pt[2] = a; X newt++; X X newt->pt[0] = b; X newt->pt[1] = oldt->pt[1]; X newt->pt[2] = c; X newt++; X X newt->pt[0] = a; X newt->pt[1] = b; X newt->pt[2] = c; X newt++; X X newt->pt[0] = a; X newt->pt[1] = c; X newt->pt[2] = oldt->pt[2]; X } X X if (level > 1) { X free(old->poly); X free(old); X } X X /* Continue subdividing new triangles */ X old = new; X } X X /* Print out resulting approximation */ X X print_object(old, maxlevel); X closeobj(); X return sph; X} X X/* Normalize a point p */ Xpoint *normalize(p) Xpoint *p; X{ X static point r; X double mag; X X r = *p; X mag = r.x * r.x + r.y * r.y + r.z * r.z; X if (mag != 0.0) { X mag = 1.0 / sqrt(mag); X r.x *= mag; X r.y *= mag; X r.z *= mag; X } X X return &r; X} X X/* Return the midpoint on the line between two points */ Xpoint *midpoint(a, b) Xpoint *a, *b; X{ X static point r; X X r.x = (a->x + b->x) * 0.5; X r.y = (a->y + b->y) * 0.5; X r.z = (a->z + b->z) * 0.5; X X return &r; X} X X/* Write out all triangles in an object */ Xvoid print_object(obj, level) Xobject *obj; Xint level; X{ X int i; X X /* Spit out coordinates for each triangle */ X for (i = 0; i < obj->npoly; i++) X print_triangle(&obj->poly[i]); X} X X/* Output a triangle */ Xvoid print_triangle(t) Xtriangle *t; X{ X int i; X float p[3]; X X#ifdef sgi X bgnpolygon(); X#endif X X p[0] = t->pt[0].x; p[1] = t->pt[0].y; p[2] = t->pt[0].z; X n3f(p); X#ifdef sgi X v3f(p); X#else X pmv(p[0], p[1], p[2]); X#endif X p[0] = t->pt[1].x; p[1] = t->pt[1].y; p[2] = t->pt[1].z; X n3f(p); X#ifdef sgi X v3f(p); X#else X pdr(p[0], p[1], p[2]); X#endif X p[0] = t->pt[2].x; p[1] = t->pt[2].y; p[2] = t->pt[2].z; X n3f(p); X#ifdef sgi X v3f(p); X endpolygon(); X#else X pdr(p[0], p[1], p[2]); X pclos(); X#endif X} X X#endif END_OF_FILE if test 7060 -ne `wc -c <'rayview/spheregen.c'`; then echo shar: \"'rayview/spheregen.c'\" unpacked with wrong size! fi # end of 'rayview/spheregen.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