rsalz@uunet.uu.net (Rich Salz) (02/08/90)
Submitted-by: Craig Kolb <craig@weedeater.math.yale.edu> Posting-number: Volume 21, Issue 11 Archive-name: rayshade/part04 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 4 (of 8)." # Contents: src/Makefile src/malloc.c src/noise.c src/poly.c # src/texture.c src/triangle.c PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'src/Makefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/Makefile'\" else echo shar: Extracting \"'src/Makefile'\" \(7691 characters\) sed "s/^X//" >'src/Makefile' <<'END_OF_FILE' X# X# Makefile for rayshade. X# X# Craig Kolb X# X# $Id: Makefile,v 3.0 89/10/27 02:05:45 craig Exp $ X# X# $Log: Makefile,v $ X# Revision 3.0 89/10/27 02:05:45 craig X# Baseline for first official release. X# X# Location of Utah-raster library and include files, if appropriate. X# If you are compiling with -DNORLE, leave these two undefined. X# XRLELIB = /usr/u/utah/lib/librle.a XRLEINC = /usr/u/utah/include X# X# Linda compiler, if appropriate. X# X#LCC = /homes/systems/carriero/linda/v2.2/bin/clc X# X# Temporary file directory, bin direction, and executable name. X# XTMPDIR = /tmp XBINDIR = /usr/u/craig/bin XSHADENAME = rayshade X# X# Compiler flags. X# X# GENERIC (BSD): CFLAGS = -I$(RLEINC) -DTMPDIR=\"$(TMPDIR)\" X# SYSV: add -DSYSV X# X# Multimax (shared memory): X# add -DMULTIMAX X# Linda: add -DLINDA (and move raytrace.c to raytrace.cl) X# X# Long ago, rayshade was compiled on the Amiga using Aztec C and: X# CFLAGS = +fi +C +D +L -DTMPDIR="t:" -DAZTEC X# X# If you are not using the Utah Raster toolkit, add -DNORLE X# If your compiler doesn't understand the void type, add -DNOVOID X# X# If your compiler has trouble with the definitions of X# vecadd(), veccomb(), etc. in funcdefs.h, compile with -DDUMB_CPP X# X# Be sure to add any necessary floating-point hardware switches. X# XCFLAGS = -I$(RLEINC) -DTMPDIR=\"$(TMPDIR)\" -O -DSYSV X# X# Libraries: X# BSD: LIBS = $(RLELIB) -lm X# SYSV: LIBS = $(RLELIB) -lm X# AZTEC C (amiga): X# LIBS = $(RLELIB) -lUnixl32 -lmal32 -lml32 -lcl32 X# X# Multimax: LIBS = $(RLELIB) -lm -lpp X# X# If you have fast versions of malloc/free available, use them X# (e.g., -lmalloc on MIPS machines). X# XLIBS = $(RLELIB) -lm -lmalloc X# X# Uncomment the following line if you want the X# fast malloc routines in malloc.c to be used. X# X#MALLOC.O = malloc.o X X# X# Change "raytrace.o" to "raytrace.lo" below if using Linda. X# XOBJ = main.o ray_options.o setup.o input.o input_yacc.o input_lex.o \ X viewing.o object.o bounds.o voxels.o list.o surface.o \ X raymath.o matrix.o raytrace.o intersect.o grid.o box.o cone.o \ X cylinder.o hf.o plane.o poly.o sphere.o superq.o triangle.o \ X texture.o noise.o shade.o atmosphere.o light.o outputp.o \ X memory.o version.o $(MALLOC.O) X XSRC = main.c ray_options.c setup.c input.c input_yacc.c input_lex.c \ X viewing.c object.c bounds.c voxels.c list.c surface.c \ X raymath.c matrix.c raytrace.c intersect.c grid.c box.c cone.c \ X cylinder.c hf.c plane.c poly.c sphere.c superq.c triangle.c \ X texture.c noise.c shade.c atmosphere.c light.c outputp.c \ X memory.c version.c X# X# Change $(CC) below to $(LCC) if using Linda. X# X$(SHADENAME): $(OBJ) X $(CC) $(CFLAGS) -o $(SHADENAME) $(OBJ) $(LIBS) X X# X# Uncomment the following rule if using Linda. X# X#raytrace.lo: raytrace.cl X# $(LCC) $(CFLAGS) -c raytrace.cl X X# X# End of configuration section X# Xinstall: $(SHADENAME) X mv $(SHADENAME) $(BINDIR)/$(SHADENAME) X Xinput_yacc.c: input_yacc.y X yacc -d input_yacc.y X mv y.tab.c input_yacc.c X Xinput_lex.c: input_lex.l X lex -t input_lex.l > input_lex.c X Xclean: X @ /bin/rm -f $(OBJ) core X Xrealclean: X @ /bin/rm -f $(OBJ) core input_lex.c input_yacc.c y.tab.h X Xlint: X lint $(CFLAGS) $(SRC) X Xdepend: X (sed '/^# DO NOT DELETE THIS LINE/q' Makefile && \ X cc -M ${CFLAGS} ${SRC} | sed 's/\.\///; /\//d' \ X ) >Makefile.new X cp Makefile Makefile.bak X cp Makefile.new Makefile X rm -f Makefile.new X Xarchive: X (cd .. ; tar cvf ../rayshade.arch.tar .) X Xkit: X (cd .. ; makekit -iPACKING_LIST -oMANIFEST) X X# DO NOT DELETE THIS LINE Xmain.o: main.c Xmain.o: constants.h Xmain.o: typedefs.h Xmain.o: datatypes.h Xmain.o: primobj.h Xmain.o: defaults.h Xray_options.o: ray_options.c Xray_options.o: constants.h Xray_options.o: typedefs.h Xray_options.o: datatypes.h Xray_options.o: primobj.h Xsetup.o: setup.c Xsetup.o: constants.h Xsetup.o: defaults.h Xsetup.o: typedefs.h Xsetup.o: datatypes.h Xsetup.o: primobj.h Xsetup.o: funcdefs.h Xinput.o: input.c Xinput.o: constants.h Xinput.o: typedefs.h Xinput.o: datatypes.h Xinput.o: primobj.h Xinput_yacc.o: input_yacc.c Xinput_yacc.o: constants.h Xinput_yacc.o: typedefs.h Xinput_yacc.o: datatypes.h Xinput_yacc.o: primobj.h Xinput_yacc.o: funcdefs.h Xinput_yacc.o: texture.h Xinput_lex.o: input_lex.c Xinput_lex.o: typedefs.h Xinput_lex.o: datatypes.h Xinput_lex.o: primobj.h Xinput_lex.o: y.tab.h Xviewing.o: viewing.c Xviewing.o: constants.h Xviewing.o: typedefs.h Xviewing.o: datatypes.h Xviewing.o: primobj.h Xviewing.o: funcdefs.h Xobject.o: object.c Xobject.o: constants.h Xobject.o: typedefs.h Xobject.o: datatypes.h Xobject.o: primobj.h Xobject.o: funcdefs.h Xobject.o: texture.h Xbounds.o: bounds.c Xbounds.o: constants.h Xbounds.o: typedefs.h Xbounds.o: datatypes.h Xbounds.o: primobj.h Xbounds.o: funcdefs.h Xvoxels.o: voxels.c Xvoxels.o: constants.h Xvoxels.o: typedefs.h Xvoxels.o: datatypes.h Xvoxels.o: primobj.h Xvoxels.o: funcdefs.h Xlist.o: list.c Xlist.o: constants.h Xlist.o: typedefs.h Xlist.o: datatypes.h Xlist.o: primobj.h Xlist.o: funcdefs.h Xsurface.o: surface.c Xsurface.o: constants.h Xsurface.o: typedefs.h Xsurface.o: datatypes.h Xsurface.o: primobj.h Xsurface.o: funcdefs.h Xraymath.o: raymath.c Xraymath.o: typedefs.h Xraymath.o: datatypes.h Xraymath.o: primobj.h Xraymath.o: constants.h Xraymath.o: funcdefs.h Xmatrix.o: matrix.c Xmatrix.o: typedefs.h Xmatrix.o: datatypes.h Xmatrix.o: primobj.h Xmatrix.o: constants.h Xmatrix.o: funcdefs.h Xraytrace.o: raytrace.c Xraytrace.o: typedefs.h Xraytrace.o: datatypes.h Xraytrace.o: primobj.h Xraytrace.o: constants.h Xraytrace.o: funcdefs.h Xraytrace.o: raytrace.h Xintersect.o: intersect.c Xintersect.o: typedefs.h Xintersect.o: datatypes.h Xintersect.o: primobj.h Xintersect.o: funcdefs.h Xintersect.o: constants.h Xgrid.o: grid.c Xgrid.o: constants.h Xgrid.o: typedefs.h Xgrid.o: datatypes.h Xgrid.o: primobj.h Xgrid.o: funcdefs.h Xbox.o: box.c Xbox.o: constants.h Xbox.o: typedefs.h Xbox.o: datatypes.h Xbox.o: primobj.h Xbox.o: funcdefs.h Xcone.o: cone.c Xcone.o: typedefs.h Xcone.o: datatypes.h Xcone.o: primobj.h Xcone.o: funcdefs.h Xcone.o: constants.h Xcylinder.o: cylinder.c Xcylinder.o: typedefs.h Xcylinder.o: datatypes.h Xcylinder.o: primobj.h Xcylinder.o: funcdefs.h Xcylinder.o: constants.h Xhf.o: hf.c Xhf.o: typedefs.h Xhf.o: datatypes.h Xhf.o: primobj.h Xhf.o: funcdefs.h Xhf.o: constants.h Xplane.o: plane.c Xplane.o: constants.h Xplane.o: typedefs.h Xplane.o: datatypes.h Xplane.o: primobj.h Xplane.o: funcdefs.h Xpoly.o: poly.c Xpoly.o: constants.h Xpoly.o: typedefs.h Xpoly.o: datatypes.h Xpoly.o: primobj.h Xpoly.o: funcdefs.h Xsphere.o: sphere.c Xsphere.o: constants.h Xsphere.o: typedefs.h Xsphere.o: datatypes.h Xsphere.o: primobj.h Xsphere.o: funcdefs.h Xsuperq.o: superq.c Xsuperq.o: constants.h Xsuperq.o: typedefs.h Xsuperq.o: datatypes.h Xsuperq.o: primobj.h Xsuperq.o: funcdefs.h Xtriangle.o: triangle.c Xtriangle.o: constants.h Xtriangle.o: typedefs.h Xtriangle.o: datatypes.h Xtriangle.o: primobj.h Xtriangle.o: funcdefs.h Xtexture.o: texture.c Xtexture.o: constants.h Xtexture.o: typedefs.h Xtexture.o: datatypes.h Xtexture.o: primobj.h Xtexture.o: funcdefs.h Xtexture.o: texture.h Xnoise.o: noise.c Xnoise.o: constants.h Xnoise.o: typedefs.h Xnoise.o: datatypes.h Xnoise.o: primobj.h Xnoise.o: funcdefs.h Xshade.o: shade.c Xshade.o: constants.h Xshade.o: typedefs.h Xshade.o: datatypes.h Xshade.o: primobj.h Xshade.o: funcdefs.h Xatmosphere.o: atmosphere.c Xatmosphere.o: typedefs.h Xatmosphere.o: datatypes.h Xatmosphere.o: primobj.h Xatmosphere.o: constants.h Xatmosphere.o: funcdefs.h Xlight.o: light.c Xlight.o: typedefs.h Xlight.o: datatypes.h Xlight.o: primobj.h Xlight.o: funcdefs.h Xlight.o: constants.h Xoutputp.o: outputp.c Xoutputp.o: typedefs.h Xoutputp.o: datatypes.h Xoutputp.o: primobj.h Xoutputp.o: constants.h Xoutputp.o: funcdefs.h Xmemory.o: memory.c Xmemory.o: typedefs.h Xmemory.o: datatypes.h Xmemory.o: primobj.h Xmemory.o: funcdefs.h Xversion.o: version.c Xversion.o: patchlevel.h END_OF_FILE if test 7691 -ne `wc -c <'src/Makefile'`; then echo shar: \"'src/Makefile'\" unpacked with wrong size! fi # end of 'src/Makefile' fi if test -f 'src/malloc.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/malloc.c'\" else echo shar: Extracting \"'src/malloc.c'\" \(9119 characters\) sed "s/^X//" >'src/malloc.c' <<'END_OF_FILE' X#ifndef lint Xstatic char sccsid[] = "@(#)malloc.c 4.3 (Berkeley) 9/16/83"; X#endif X X/* X * malloc.c (Caltech) 2/21/82 X * Chris Kingsley, kingsley@cit-20. X * X * This is a very fast storage allocator. It allocates blocks of a small X * number of different sizes, and keeps free lists of each size. Blocks that X * don't exactly fit are passed up to the next larger size. In this X * implementation, the available sizes are 2^n-4 (or 2^n-12) bytes long. X * This is designed for use in a program that uses vast quantities of memory, X * but bombs when it runs out. X */ X X#include <sys/types.h> X X#define NULL 0 X X/* X * The overhead on a block is at least 4 bytes. When free, this space X * contains a pointer to the next free block, and the bottom two bits must X * be zero. When in use, the first byte is set to MAGIC, and the second X * byte is the size index. The remaining bytes are for alignment. X * If range checking is enabled and the size of the block fits X * in two bytes, then the top two bytes hold the size of the requested block X * plus the range checking words, and the header word MINUS ONE. X */ Xunion overhead { X union overhead *ov_next; /* when free */ X struct { X u_char ovu_magic; /* magic number */ X u_char ovu_index; /* bucket # */ X#ifdef RCHECK X u_short ovu_size; /* actual block size */ X u_int ovu_rmagic; /* range magic number */ X#endif X } ovu; X#define ov_magic ovu.ovu_magic X#define ov_index ovu.ovu_index X#define ov_size ovu.ovu_size X#define ov_rmagic ovu.ovu_rmagic X}; X X#define MAGIC 0xff /* magic # on accounting info */ X#define RMAGIC 0x55555555 /* magic # on range info */ X#ifdef RCHECK X#define RSLOP sizeof (u_int) X#else X#define RSLOP 0 X#endif X X/* X * nextf[i] is the pointer to the next free block of size 2^(i+3). The X * smallest allocatable block is 8 bytes. The overhead information X * precedes the data area returned to the user. X */ X#define NBUCKETS 30 Xstatic union overhead *nextf[NBUCKETS]; Xextern char *sbrk(); X X#ifdef MSTATS X/* X * nmalloc[i] is the difference between the number of mallocs and frees X * for a given block size. X */ Xstatic u_int nmalloc[NBUCKETS]; X#include <stdio.h> X#endif X X#ifdef debug X#define ASSERT(p) if (!(p)) botch("p"); else Xstatic Xbotch(s) X char *s; X{ X X printf("assertion botched: %s\n", s); X abort(); X} X#else X#define ASSERT(p) X#endif X Xchar * Xmalloc(nbytes) X register unsigned nbytes; X{ X register union overhead *p; X register int bucket = 0; X register unsigned shiftr; X X /* X * Convert amount of memory requested into X * closest block size stored in hash buckets X * which satisfies request. Account for X * space used per block for accounting. X */ X nbytes += sizeof (union overhead) + RSLOP; X nbytes = (nbytes + 3) &~ 3; X shiftr = (nbytes - 1) >> 2; X /* apart from this loop, this is O(1) */ X while (shiftr >>= 1) X bucket++; X /* X * If nothing in hash bucket right now, X * request more memory from the system. X */ X if (nextf[bucket] == NULL) X morecore(bucket); X if ((p = (union overhead *)nextf[bucket]) == NULL) X return (NULL); X /* remove from linked list */ X nextf[bucket] = nextf[bucket]->ov_next; X p->ov_magic = MAGIC; X p->ov_index= bucket; X#ifdef MSTATS X nmalloc[bucket]++; X#endif X#ifdef RCHECK X /* X * Record allocated size of block and X * bound space with magic numbers. X */ X if (nbytes <= 0x10000) X p->ov_size = nbytes - 1; X p->ov_rmagic = RMAGIC; X *((u_int *)((caddr_t)p + nbytes - RSLOP)) = RMAGIC; X#endif X return ((char *)(p + 1)); X} X X/* X * Allocate more memory to the indicated bucket. X */ Xstatic Xmorecore(bucket) X register bucket; X{ X register union overhead *op; X register int rnu; /* 2^rnu bytes will be requested */ X register int nblks; /* become nblks blocks of the desired size */ X register int siz; X X if (nextf[bucket]) X return; X /* X * Insure memory is allocated X * on a page boundary. Should X * make getpageize call? X */ X op = (union overhead *)sbrk(0); X if ((int)op & 0x3ff) X sbrk(1024 - ((int)op & 0x3ff)); X /* take 2k unless the block is bigger than that */ X rnu = (bucket <= 8) ? 11 : bucket + 3; X nblks = 1 << (rnu - (bucket + 3)); /* how many blocks to get */ X if (rnu < bucket) X rnu = bucket; X op = (union overhead *)sbrk(1 << rnu); X /* no more room! */ X if ((int)op == -1) { X for (rnu=bucket; rnu < NBUCKETS; rnu++) { X if (nextf[rnu]) break; X } X if (rnu >= NBUCKETS) X return; X /* Split into halves until bucket-sized */ X op = nextf[rnu]; X nextf[rnu] = op->ov_next; X while (--rnu > bucket) { X siz = 1 << (rnu + 3); X op->ov_next = nextf[rnu]; /* == NULL */ X nextf[rnu] = op; X op = (union overhead *)((caddr_t) op + siz); X } X nblks = 2; X } X /* X * Round up to minimum allocation size boundary X * and deduct from block count to reflect. X */ X if ((int)op & 7) { X op = (union overhead *)(((int)op + 8) &~ 7); X nblks--; X } X /* X * Add new memory allocated to that on X * free list for this hash bucket. X */ X nextf[bucket] = op; X siz = 1 << (bucket + 3); X while (--nblks > 0) { X op->ov_next = (union overhead *)((caddr_t)op + siz); X op = (union overhead *)((caddr_t)op + siz); X } X op->ov_next = NULL; X} X Xfree(cp) X char *cp; X{ X register int size; X register union overhead *op; X X if (cp == NULL) X return; X op = (union overhead *)((caddr_t)cp - sizeof (union overhead)); X#ifdef debug X ASSERT(op->ov_magic == MAGIC); /* make sure it was in use */ X#else X if (op->ov_magic != MAGIC) X return; /* sanity */ X#endif X#ifdef RCHECK X ASSERT(op->ov_rmagic == RMAGIC); X if (op->ov_index <= 13) X ASSERT(*(u_int *)((caddr_t)op + op->ov_size + 1 - RSLOP) == RMAGIC); X#endif X ASSERT(op->ov_index < NBUCKETS); X size = op->ov_index; X op->ov_next = nextf[size]; X nextf[size] = op; X#ifdef MSTATS X nmalloc[size]--; X#endif X} X X/* X * When a program attempts "storage compaction" as mentioned in the X * old malloc man page, it realloc's an already freed block. Usually X * this is the last block it freed; occasionally it might be farther X * back. We have to search all the free lists for the block in order X * to determine its bucket: 1st we make one pass thru the lists X * checking only the first block in each; if that fails we search X * ``realloc_srchlen'' blocks in each list for a match (the variable X * is extern so the caller can modify it). If that fails we just copy X * however many bytes was given to realloc() and hope it's not huge. X */ Xint realloc_srchlen = -1; /* -1 => search whole list */ X Xchar * Xrealloc(cp, nbytes) X char *cp; X unsigned nbytes; X{ X register u_int onb; X union overhead *op; X char *res; X register int i; X int was_alloced = 0; X X if (cp == NULL) X return (malloc(nbytes)); X op = (union overhead *)((caddr_t)cp - sizeof (union overhead)); X if (op->ov_magic == MAGIC) { X was_alloced++; X i = op->ov_index; X } else { X /* X * Already free, doing "compaction". X * X * Search for the old block of memory on the X * free list. First, check the most common X * case (last element free'd), then (this failing) X * the last ``realloc_srchlen'' items free'd. X * If all lookups fail, then assume the size of X * the memory block being realloc'd is the X * smallest possible. X */ X if ((i = findbucket(op, 1)) < 0 && X (i = findbucket(op, realloc_srchlen)) < 0) X i = 0; X } X onb = (1 << (i + 3)) - sizeof (*op) - RSLOP; X /* avoid the copy if same size block */ X if (was_alloced && X nbytes <= onb && nbytes > (onb >> 1) - sizeof(*op) - RSLOP) { X#ifdef RCHECK X op->ov_size = ((nbytes + sizeof(union overhead) + RSLOP) + 3 & ~3) -1; X *((u_int *)((caddr_t)op + op->ov_size + 1 - RSLOP)) = RMAGIC; X#endif X return(cp); X } X if ((res = malloc(nbytes)) == NULL) X return (NULL); X if (cp != res) /* common optimization */ X bcopy(cp, res, (nbytes < onb) ? nbytes : onb); X if (was_alloced) X free(cp); X return (res); X} X X/* X * Search ``srchlen'' elements of each free list for a block whose X * header starts at ``freep''. If srchlen is -1 search the whole list. X * Return bucket number, or -1 if not found. X */ Xstatic Xfindbucket(freep, srchlen) X union overhead *freep; X int srchlen; X{ X register union overhead *p; X register int i, j; X X for (i = 0; i < NBUCKETS; i++) { X j = 0; X for (p = nextf[i]; p && j != srchlen; p = p->ov_next) { X if (p == freep) X return (i); X j++; X } X } X return (-1); X} X X#ifdef MSTATS X/* X * mstats - print out statistics about malloc X * X * Prints two lines of numbers, one showing the length of the free list X * for each size category, the second showing the number of mallocs - X * frees for each size category. X */ Xmstats(s) X char *s; X{ X register int i, j; X register union overhead *p; X int totfree = 0, X totused = 0; X X fprintf(stderr, "Memory allocation statistics %s\nfree:\t", s); X for (i = 0; i < NBUCKETS; i++) { X for (j = 0, p = nextf[i]; p; p = p->ov_next, j++) X ; X fprintf(stderr, " %d", j); X totfree += j * (1 << (i + 3)); X } X fprintf(stderr, "\nused:\t"); X for (i = 0; i < NBUCKETS; i++) { X fprintf(stderr, " %d", nmalloc[i]); X totused += nmalloc[i] * (1 << (i + 3)); X } X fprintf(stderr, "\n\tTotal in use: %d, total free: %d\n", X totused, totfree); X} X#endif END_OF_FILE if test 9119 -ne `wc -c <'src/malloc.c'`; then echo shar: \"'src/malloc.c'\" unpacked with wrong size! fi # end of 'src/malloc.c' fi if test -f 'src/noise.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/noise.c'\" else echo shar: Extracting \"'src/noise.c'\" \(9494 characters\) sed "s/^X//" >'src/noise.c' <<'END_OF_FILE' X/* X * noise.c X * X * Copyright (C) 1989, Robert Skinner, Craig E. Kolb, F. Kenton Musgrave X * X * This software may be freely copied, modified, and redistributed, X * provided that this copyright notice is preserved on all copies. X * X * There is no warranty or other guarantee of fitness for this software, X * it is provided solely "as is". Bug reports or fixes may be sent X * to the author, who may or may not act on them as he desires. X * X * You may not include this software in a program or other software product X * without supplying the source, or without informing the end-user that the X * source is available for no extra charge. X * X * If you modify this software, you should include a notice giving the X * name of the person performing the modification, the date of modification, X * and the reason for such modification. X * X * $Id: noise.c,v 3.0 89/10/27 02:05:57 craig Exp $ X * X * $Log: noise.c,v $ X * Revision 3.0 89/10/27 02:05:57 craig X * Baseline for first official release. X * X */ X#include <stdio.h> X#include <math.h> X#include "constants.h" X#include "typedefs.h" X#include "funcdefs.h" X X#define MINX -10000 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 Xdouble RTable[MAXSIZE]; Xstatic short *hashTable; 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 Xdouble Chaos(), Marble(); X XInitTextureTable() X{ X int i, j, temp; X X#ifdef SYSV X (void)srand48(0); X#else X (void)srandom(0); X#endif X X hashTable = (short int *) 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 X XInitRTable() 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 = (double)i; X RTable[i] = R(&rp)*REALSCALE - 1.0; X } X} X X 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 double 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 */ Xint 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's Skinner's Perlin-style "Noise" function X */ Xdouble XNoise(point) XVector *point; X{ X register int ix, iy, iz, jx, jy, jz; X double x, y, z; X double sx, sy, sz, tx, ty, tz; X double 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} /* Noise() */ X X/* X * Vector-valued "Noise" X */ XDNoise(point, result) XVector *point, *result; X{ X register int ix, iy, iz, jx, jy, jz; X double x, y, z; X double px, py, pz, s; X double 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} X Xdouble XMarble(vec) XVector *vec; X{ X double i; X X i = sin(8. * Chaos(vec, 6) + 7. * vec->z) + 1; X i *= 0.5; X i = pow(i, 0.77); X return i; X} X Xdouble XChaos(vec, octaves) XVector *vec; Xint octaves; X{ X double f, s, t; X int n; X Vector tp; X X s = f = 1.0; X t = 0.; X X for (n = 0; n < octaves; n++) { X tp.x = f * vec->x; X tp.y = f * vec->y; X tp.z = f * vec->z; X t += Noise(&tp) * s; X f *= 2.0; X s *= 0.5; X } X X return t; X} X XVfBm(vec, omega, lambda, octaves, ans) XVector *vec, *ans; Xdouble omega, lambda; Xint octaves; X{ X register int i; X double l, o; X Vector tp, n; X X ans->x = ans->y = ans->z = 0.; X X l = o = 1.; X for (i = 0; i < octaves; i++) { X tp.x = l * vec->x; X tp.y = l * vec->y; X tp.z = l * vec->z; X DNoise(&tp, &n); X ans->x += o * n.x; X ans->y += o * n.y; X ans->z += o * n.z; X l *= lambda; X o *= omega; X if (o < EPSILON) X break; X } X} X Xdouble XfBm(vec, omega, lambda, octaves) Xregister Vector *vec; Xdouble omega, lambda; Xint octaves; X{ X register int i; X double l, n, a, o; X Vector tp; X X a = 0; l = o = 1.; X for (i = 0; i < octaves; i++) { X tp.x = l * vec->x; X tp.y = l * vec->y; X tp.z = l * vec->z; X n = o * Noise(&tp); X a += n; X l *= lambda; X o *= omega; X } X return a; X} END_OF_FILE if test 9494 -ne `wc -c <'src/noise.c'`; then echo shar: \"'src/noise.c'\" unpacked with wrong size! fi # end of 'src/noise.c' fi if test -f 'src/poly.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/poly.c'\" else echo shar: Extracting \"'src/poly.c'\" \(7502 characters\) sed "s/^X//" >'src/poly.c' <<'END_OF_FILE' X/* X * poly.c X * X * Copyright (C) 1989, Craig E. Kolb X * X * This software may be freely copied, modified, and redistributed, X * provided that this copyright notice is preserved on all copies. X * X * There is no warranty or other guarantee of fitness for this software, X * it is provided solely . Bug reports or fixes may be sent X * to the author, who may or may not act on them as he desires. X * X * You may not include this software in a program or other software product X * without supplying the source, or without informing the end-user that the X * source is available for no extra charge. X * X * If you modify this software, you should include a notice giving the X * name of the person performing the modification, the date of modification, X * and the reason for such modification. X * X * $Id: poly.c,v 3.0 89/10/27 02:05:59 craig Exp $ X * X * $Log: poly.c,v $ X * Revision 3.0 89/10/27 02:05:59 craig X * Baseline for first official release. X * X */ X#include <stdio.h> X#include <math.h> X#include "constants.h" X#include "typedefs.h" X#include "funcdefs.h" X X/* X * Create a reference to a polygon with vertices equal to those X * on the linked-list "plist." X */ XObject * Xmakpoly(surf, plist, npoints) Xchar *surf; XPointList *plist; Xint npoints; X{ X Polygon *poly; X Primitive *prim; X Object *newobj; X double indexval; X Vector edge1, edge2, anorm; X PointList *cur; X int i; X extern int yylineno, TrashBadPoly, Quiet; X X prim = mallocprim(); X prim->type = POLY; X prim->surf = find_surface(surf); X poly = (Polygon *)Malloc(sizeof(Polygon)); X prim->objpnt.p_poly = poly; X newobj = new_object(NULL, POLY, (char *)prim, (Trans *)NULL); 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(cur = plist;cur;cur = cur->next) { X poly->points[i--] = cur->vec; X free((char *)cur); X } X free((char *)plist); X X /* X * Find normal to polygon. Check all edges before giving X * up, just to be relatively nice about things. X */ X vecsub(poly->points[1], poly->points[0], &edge1); X for(i = 1;i < poly->npoints;i++) { X if(dotp(&edge1, &edge1) == 0.) { X if (TrashBadPoly) { X free((char *)poly->points); X free((char *)poly); X free((char *)prim); X free((char *)newobj); X return (Object *)0; X } X } X vecsub(poly->points[(i+1)%npoints], poly->points[i], &edge2); X if(crossp(&poly->norm, &edge1, &edge2) != 0.) X break; X edge1 = edge2; X } X X if(i >= poly->npoints) { X /* X * If we walked all the way through the list, X * then we didn't find a valid normal vector -- we X * must have a degenerate polygon of some sort. X */ X fprintf(stderr,"Degenerate polygon (line %d).\n", yylineno); X free((char *)poly->points); X free((char *)poly); X free((char *)prim); X free((char *)newobj); X return (Object *)0; X } X X /* X * Compute and store the plane constant. X */ X poly->d = dotp(&poly->norm, &poly->points[0]); X X /* X * Find which part of the normal vector is "dominant." This X * is used to turn the point-in-polygon test into a 2D problem. X */ X anorm.x = abs(poly->norm.x); X anorm.y = abs(poly->norm.y); X anorm.z = abs(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 newobj; X} X X/* X * Quadrants are defined as: X * | X * 1 | 0 X * | X * -------c-------- X * | X * 2 | 3 X * | X */ X#define quadrant(p, c) ((p.u<c.u) ? ((p.v<c.v) ? 2 : 1) : ((p.v<c.v) ? 3 : 0)) X X/* X * Project a point in 3-space to the plane whose normal is indicated by "i." X */ X#define project(r, p, i) {switch(i) { \ X case XNORMAL: \ X r.u = p.y; \ X r.v = p.z; \ X break; \ X case YNORMAL: \ X r.u = p.x; \ X r.v = p.z; \ X break; \ X case ZNORMAL: \ X r.u = p.x; \ X r.v = p.y; \ X break; \ X } } X/* X * Perform ray-polygon intersection test. X */ Xdouble Xintpoly(pos, ray, obj) XVector *pos, *ray; XPrimitive *obj; X{ X register Polygon *poly; X register int winding, i; X int quad, lastquad; X double dist, left, right; X Vec2d center, cur, last; X extern unsigned long primtests[]; X X primtests[POLY]++; X poly = obj->objpnt.p_poly; 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, ray); X if(dist == 0.) X /* X * No intersection with polygon plane. X */ X return 0.; X X dist = (poly->d - dotp(&poly->norm, pos)) / dist; X if(dist <= 0.) X /* X * The intersection point is behind the ray origin. X */ X return 0.; X X /* X * Compute the point of intersection, projected appropriately. X */ X if(poly->index == XNORMAL) { X center.u = pos->y + dist * ray->y; X center.v = pos->z + dist * ray->z; X } else if(poly->index == YNORMAL) { X center.v = pos->z + dist * ray->z; X center.u = pos->x + dist * ray->x; X } else { X center.u = pos->x + dist * ray->x; X center.v = pos->y + dist * ray->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, which X * is the "dominant" part of the polygon's normal vector. X */ X winding = 0; X project(last, poly->points[poly->npoints -1], poly->index); X lastquad = quadrant(last, center); X for(i = 0;i < poly->npoints; i++) { X project(cur, poly->points[i], poly->index); X quad = quadrant(cur, center); X if(quad != lastquad) { 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; X left *= 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 last = cur; X X } X return (winding == 0 ? 0. : dist); X} X X/* X * Return the normal to the polygon surface. X */ X/*ARGSUSED*/ Xnrmpoly(pos, obj, nrm) XVector *pos, *nrm; XPrimitive *obj; X{ X *nrm = obj->objpnt.p_poly->norm; X} X X/* X * Compute the extent of a polygon X */ Xpolyextent(obj, bounds) XPrimitive *obj; Xdouble bounds[2][3]; X{ X register Polygon *poly; X register int i; X X poly = obj->objpnt.p_poly; 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} END_OF_FILE if test 7502 -ne `wc -c <'src/poly.c'`; then echo shar: \"'src/poly.c'\" unpacked with wrong size! fi # end of 'src/poly.c' fi if test -f 'src/texture.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/texture.c'\" else echo shar: Extracting \"'src/texture.c'\" \(7557 characters\) sed "s/^X//" >'src/texture.c' <<'END_OF_FILE' X/* X * texture.c X * X * Copyright (C) 1989, Craig E. Kolb X * X * This software may be freely copied, modified, and redistributed, X * provided that this copyright notice is preserved on all copies. X * X * There is no warranty or other guarantee of fitness for this software, X * it is provided solely . Bug reports or fixes may be sent X * to the author, who may or may not act on them as he desires. X * X * You may not include this software in a program or other software product X * without supplying the source, or without informing the end-user that the X * source is available for no extra charge. X * X * If you modify this software, you should include a notice giving the X * name of the person performing the modification, the date of modification, X * and the reason for such modification. X * X * $Id: texture.c,v 3.0 89/10/27 02:06:05 craig Exp $ X * X * $Log: texture.c,v $ X * Revision 3.0 89/10/27 02:06:05 craig X * Baseline for first official release. X * X */ X#include <stdio.h> X#include <math.h> X#include "constants.h" X#include "typedefs.h" X#include "funcdefs.h" X#include "texture.h" X X/* X * Array of texturing functions indexed by type. X */ Xint (*textures[])() = X {CheckerText, BlotchText, BumpText, MarbleText, fBmText, fBmBumpText, X WoodText}; Xextern double Chaos(), Marble(), fBm(), Noise(); XColor *read_colormap(); X X/* X * Return pointer to new texture structure. X */ XTexture * Xnew_texture(type) Xchar type; X{ X Texture *new; X X new = (Texture *)Malloc(sizeof(Texture)); X new->type = type; X new->surf1 = (Surface *)NULL; X new->next = (Texture *)NULL; X new->trans = (Trans *)NULL; X return new; X} X X/* X * Apply appropriate textures to a surface. X */ Xapply_textures(hitinfo, list) XHitInfo *hitinfo; XTexture *list; X{ X Texture *ttmp; X Vector ptmp; X X for (ttmp = list; ttmp; ttmp = ttmp->next) { X ptmp = hitinfo->pos; X if (ttmp->trans) { X /* X * Transform position and normal to texture space. X */ X transform_point(&ptmp,&ttmp->trans->world2obj); X TransformNormal(&hitinfo->norm,&ttmp->trans->obj2world); X } X /* X * Make sure to use a normalized normal. X */ X (void)normalize(&hitinfo->norm); X (*textures[(int)ttmp->type]) X (ttmp,&ptmp,&hitinfo->norm,&hitinfo->surf); X if (ttmp->trans) { X /* X * Transform the normal back to world-space. X */ X TransformNormal(&hitinfo->norm,&ttmp->trans->world2obj); X } X } X} X XTexture * XNewWoodText() X{ X Texture *text; X X text = new_texture(WOOD); X return text; X} X XWoodText(text, pos, norm, surf) XTexture *text; XVector *pos, *norm; XSurface *surf; X{ X double red, grn, blu; X double chaos, midBrown, brownLayer, greenLayer; X double perturb, brownPerturb, greenPerturb, grnPerturb; X double t; X X chaos = Chaos(pos, 7); X t = sin(sin(8.*chaos + 7*pos->x +3.*pos->y)); X X greenLayer = brownLayer = abs(t); X X perturb = fabs(sin(40.*chaos + 50*pos->z)); X X brownPerturb = .6*perturb + 0.3; X greenPerturb = .2*perturb + 0.8; X grnPerturb = .15*perturb + 0.85; X grn = 0.5 * pow(abs(brownLayer), 0.3); X brownLayer = pow(0.5 * (brownLayer+1.0), 0.6) * brownPerturb; X greenLayer = pow(0.5 * (greenLayer+1.0), 0.6) * greenPerturb; X X red = (0.5*brownLayer + 0.35*greenLayer)*2.*grn; X blu = (0.25*brownLayer + 0.35*greenLayer)*2.0*grn; X grn *= max(brownLayer, greenLayer) * grnPerturb; X X surf->diff.r *= red; X surf->diff.g *= grn; X surf->diff.b *= blu; X X ScaleColor(0.3, surf->diff, &surf->amb); X} X X/* X * Create and return a reference to a "checker" texture. X */ XTexture * XNewCheckText(surf) Xchar *surf; X{ X Texture *text; X X text = new_texture(CHECKER); X text->surf1 = find_surface(surf); X X return text; X} X XTexture * XNewfBmBumpText(offset, scale, h, lambda, octaves) Xdouble h, lambda, scale, offset; Xint octaves; X{ X Texture *text; X X text = NewfBmText(offset, scale, h, lambda, octaves, 0., (char *)0); X X text->type = FBMBUMP; X X return text; X} X XTexture * XNewfBmText(offset, scale, h, lambda, octaves, thresh, mapname) Xdouble h, lambda, scale, offset, thresh; Xint octaves; Xchar *mapname; X{ X double beta; X Texture *text; X X text = new_texture(FBM); X X text->args = (double *)Malloc(5 * sizeof(double)); X beta = 1. + 2 * h; X text->args[0] = pow(lambda, -0.5 * beta); /* omega */ X text->args[1] = lambda; X text->args[2] = scale; X text->args[3] = offset; X text->args[4] = thresh; X text->size = (double)octaves; X if (mapname != (char *)0) X text->colormap = read_colormap(mapname); X X return text; X} X X/* X * Create and return a reference to a "bump" texture. X */ XTexture * XNewBumpText(size) Xdouble size; X{ X Texture *text; X X text = new_texture(BUMP); X text->size = size; X X return text; X} X X/* X * Create and return a reference to a "blotch" texture. X */ XTexture * XNewBlotchText(scale, surf) Xdouble scale; Xchar *surf; X{ X Texture *text; X X text = new_texture(BLOTCH); X text->size = scale; X text->surf1 = find_surface(surf); X X return text; X} X XTexture * XNewMarbleText(mapname) Xchar *mapname; X{ X Texture *text; X X text = new_texture(MARBLE); X if (mapname) X text->colormap = read_colormap(mapname); X return text; X} X X/* X * Apply "blotch" texture. X */ XBlotchText(text, pos, norm, surf) XTexture *text; XVector *pos, *norm; XSurface *surf; X{ X double val; X X /* X * "size" represents the 'average' noise value at a point. X */ X val = Noise(pos); X if (val > text->size) { X val = (val - text->size) / (1. - text->size); X blend_surface(surf, text->surf1, 1. - val, val); X } X} X XfBmText(text, pos, norm, surf) XTexture *text; XVector *pos, *norm; XSurface *surf; X{ X double val; X int index; X X val = fBm(pos, text->args[0], text->args[1], (int)text->size); X if (val < text->args[4]) X val = 0.; X else X val = text->args[3] + text->args[2] * (val - text->args[4]); X if (text->colormap) { X index = 255. * val; X if (index > 255) index = 255; X if (index < 0) index = 0; X surf->diff = text->colormap[index]; X ScaleColor(.2, surf->diff, &surf->amb); X } else { X ScaleColor(val, surf->diff, &surf->diff); X ScaleColor(val, surf->amb, &surf->amb); X } X} X X/* X * Apply a "checker" texture. X */ XCheckerText(text, pos, norm, surf) XTexture *text; XVector *pos, *norm; XSurface *surf; X{ X int xp, yp, zp; X X xp = pos->x > 0. ? pos->x : 1. - pos->x; X yp = pos->y > 0. ? pos->y : 1. - pos->y; X zp = pos->z > 0. ? pos->z : 1. - pos->z; X X if ((xp + yp + zp) % 2) X *surf = *text->surf1; X /* else surface stays the same. */ X} X XfBmBumpText(text, pos, norm, surf) XTexture *text; XVector *pos, *norm; XSurface *surf; X{ X Vector disp; X double w; X X VfBm(pos, text->args[0], text->args[1], (int)text->size, &disp); X w = text->args[2]; X norm->x += text->args[3] + disp.x * w; X norm->y += text->args[3] + disp.y * w; X norm->z += text->args[3] + disp.z * w; X} X X/* X * Apply a "bump" texture. X */ XBumpText(text, pos, norm, surf) XTexture *text; XVector *pos, *norm; XSurface *surf; X{ X Vector disp; X X DNoise(pos, &disp); X norm->x += disp.x * text->size; X norm->y += disp.y * text->size; X norm->z += disp.z * text->size; X (void)normalize(norm); X} X XMarbleText(text, pos, norm, surf) XTexture *text; XVector *pos, *norm; XSurface *surf; X{ X double val; X int index; X X val = Marble(pos); X if (text->colormap) { X index = (int)(255. * val); X surf->diff = text->colormap[index]; X } else { X ScaleColor(val, surf->amb, &surf->amb); X ScaleColor(val, surf->diff, &surf->diff); X } X} X XColor * Xread_colormap(filename) Xchar *filename; X{ X FILE *fp; X Color *map; X char buf[BUFSIZ]; X int i; X X fp = fopen(filename, "r"); X if (fp == (FILE *)NULL) X yyerror("Cannot open colormap file."); X X map = (Color *)Calloc(256, sizeof(Color)); X X for (i = 0; fgets(buf,BUFSIZ,fp) != NULL && i < 256; i++) { X sscanf(buf,"%lf %lf %lf",&map[i].r, &map[i].g, &map[i].b); X ScaleColor(1. / 255., map[i], &map[i]); X } X return map; X} END_OF_FILE if test 7557 -ne `wc -c <'src/texture.c'`; then echo shar: \"'src/texture.c'\" unpacked with wrong size! fi # end of 'src/texture.c' fi if test -f 'src/triangle.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/triangle.c'\" else echo shar: Extracting \"'src/triangle.c'\" \(7297 characters\) sed "s/^X//" >'src/triangle.c' <<'END_OF_FILE' X/* X * triangle.c X * X * Copyright (C) 1989, Craig E. Kolb X * X * This software may be freely copied, modified, and redistributed, X * provided that this copyright notice is preserved on all copies. X * X * There is no warranty or other guarantee of fitness for this software, X * it is provided solely . Bug reports or fixes may be sent X * to the author, who may or may not act on them as he desires. X * X * You may not include this software in a program or other software product X * without supplying the source, or without informing the end-user that the X * source is available for no extra charge. X * X * If you modify this software, you should include a notice giving the X * name of the person performing the modification, the date of modification, X * and the reason for such modification. X * X * $Id: triangle.c,v 3.0 89/10/27 02:06:07 craig Exp $ X * X * $Log: triangle.c,v $ X * Revision 3.0 89/10/27 02:06:07 craig X * Baseline for first official release. X * X */ X#include <stdio.h> X#include <math.h> X#include "constants.h" X#include "typedefs.h" X#include "funcdefs.h" X X#define within(x, a) (((a) <= 0 && (x) >= (a) && (x) <= 0) || \ X ((a) > 0 && (x) >= 0 && (x) <= (a))) X/* X * Create and return reference to a triangle. X */ XObject * Xmaktri(type, surf, p1, p2, p3, n1, n2, n3) Xint type; Xchar *surf; XVector *p1, *p2, *p3, *n1, *n2, *n3; X{ X Triangle *triangle; X Primitive *prim; X Vector vc1, vc2, vc3, ptmp, anorm; X Object *newobj; X double indexval; X extern int yylineno, Quiet; X X prim = mallocprim(); X triangle = (Triangle *)Malloc(sizeof(Triangle)); X prim->objpnt.p_triangle = triangle; X newobj = new_object(NULL, (char)type, (char *)prim, (Trans *)NULL); X prim->surf = find_surface(surf); X X if (type == PHONGTRI) { X prim->type = PHONGTRI; X (void)normalize(n1); X (void)normalize(n2); X (void)normalize(n3); X triangle->vnorm = (Vector *)Malloc(3 * sizeof(Vector)); X triangle->vnorm[0] = *n1; X triangle->vnorm[1] = *n2; X triangle->vnorm[2] = *n3; X triangle->b = (double *)Malloc(3 * sizeof(double)); X } X else X prim->type = TRIANGLE; X X vecsub(*p2, *p1, &vc1); X vecsub(*p3, *p2, &vc2); X vecsub(*p1, *p3, &vc3); X X /* Find plane normal. */ X rawcrossp(&triangle->nrm, &vc1, &vc2); X ptmp = triangle->nrm; X if (normalize(&ptmp) == 0.) { X if (!Quiet) X fprintf(stderr,"Degenerate triangle (line %d).\n", X yylineno); X free((char *)prim); X free((char *)triangle); X free((char *)newobj); X return (Object *)0; X } X X triangle->d = dotp(&triangle->nrm, p1); X X triangle->p1 = *p1; X triangle->p2 = *p2; X triangle->p3 = *p3; X X triangle->e1 = vc1; X triangle->e2 = vc2; X triangle->e3 = vc3; X X if (type == PHONGTRI && dotp(&triangle->vnorm[0], &ptmp) < 0.) { X /* X * Reverse direction of surface normal on Phong X * triangle if the surface normal points "away" X * from the first vertex normal. X */ X scalar_prod(-1., triangle->nrm, &triangle->nrm); X triangle->d = -triangle->d; X scalar_prod(-1., triangle->e1, &triangle->e1); X scalar_prod(-1., triangle->e2, &triangle->e2); X scalar_prod(-1., triangle->e3, &triangle->e3); X } X /* X * Find "dominant" part of normal vector. X */ X anorm.x = abs(triangle->nrm.x); X anorm.y = abs(triangle->nrm.y); X anorm.z = abs(triangle->nrm.z); X indexval = max(anorm.y, anorm.z); X indexval = max(anorm.x, indexval); X if (indexval == anorm.x) X triangle->index = XNORMAL; X else if (indexval == anorm.y) X triangle->index = YNORMAL; X else X triangle->index = ZNORMAL; X X return newobj; X} X X/* X * Intersect ray with triangle. See Snyder & Barr for details on X * how this works. X */ Xdouble Xinttri(pos, ray, obj) Xregister Vector *pos, *ray; XPrimitive *obj; X{ X register Triangle *triangle; X double qi1, qi2, s, k, b1, b2, b3; X extern unsigned long primtests[]; X X primtests[obj->type]++; X X triangle = obj->objpnt.p_triangle; X /* X * Plane intersection. X */ X k = dotp(&triangle->nrm, ray); X if (k == 0.) X return 0.; X s = (triangle->d - dotp(&triangle->nrm, pos)) / k; X if (s <= 0.) X return 0.; X X if (triangle->index == XNORMAL) { X qi1 = pos->y + s * ray->y; X qi2 = pos->z + s * ray->z; X b1 = triangle->e2.y * (qi2 - triangle->p2.z) - X triangle->e2.z * (qi1 - triangle->p2.y); X if (!within(b1, triangle->nrm.x)) X return 0.; X b2 = triangle->e3.y * (qi2 - triangle->p3.z) - X triangle->e3.z * (qi1 - triangle->p3.y); X if (!within(b2, triangle->nrm.x)) X return 0.; X b3 = triangle->e1.y * (qi2 - triangle->p1.z) - X triangle->e1.z * (qi1 - triangle->p1.y); X if (!within(b3, triangle->nrm.x)) X return 0.; X } else if (triangle->index == YNORMAL) { X qi1 = pos->x + s * ray->x; X qi2 = pos->z + s * ray->z; X b1 = triangle->e2.z * (qi1 - triangle->p2.x) - X triangle->e2.x * (qi2 - triangle->p2.z); X if (!within(b1, triangle->nrm.y)) X return 0.; X b2 = triangle->e3.z * (qi1 - triangle->p3.x) - X triangle->e3.x * (qi2 - triangle->p3.z); X if (!within(b2, triangle->nrm.y)) X return 0.; X b3 = triangle->e1.z * (qi1 - triangle->p1.x) - X triangle->e1.x * (qi2 - triangle->p1.z); X if (!within(b3, triangle->nrm.y)) X return 0.; X } else { X qi1 = pos->x + s * ray->x; X qi2 = pos->y + s * ray->y; X b1 = triangle->e2.x * (qi2 - triangle->p2.y) - X triangle->e2.y * (qi1 - triangle->p2.x); X if (!within(b1, triangle->nrm.z)) X return 0.; X X b2 = triangle->e3.x * (qi2 - triangle->p3.y) - X triangle->e3.y * (qi1 - triangle->p3.x); X if (!within(b2, triangle->nrm.z)) X return 0.; X X b3 = triangle->e1.x * (qi2 - triangle->p1.y) - X triangle->e1.y * (qi1 - triangle->p1.x); X if (!within(b3, triangle->nrm.z)) X return 0.; X } X /* X * Take abs value if there was an intersection. X */ X if (obj->type == PHONGTRI) { X triangle->b[0] = abs(b1); X triangle->b[1] = abs(b2); X triangle->b[2] = abs(b3); X } X return s; X} X Xnrmtri(pos, obj, nrm) XVector *pos, *nrm; XPrimitive *obj; X{ X Triangle *tri; X X /* X * Normals will be normalized later... X */ X if (obj->type == TRIANGLE) { X *nrm = obj->objpnt.p_triangle->nrm; X } else { X /* X * Interpolate normals of Phong-shaded triangles. X */ X tri = obj->objpnt.p_triangle; X nrm->x = tri->b[0]*tri->vnorm[0].x+tri->b[1]*tri->vnorm[1].x+ X tri->b[2]*tri->vnorm[2].x; X nrm->y = tri->b[0]*tri->vnorm[0].y+tri->b[1]*tri->vnorm[1].y+ X tri->b[2]*tri->vnorm[2].y; X nrm->z = tri->b[0]*tri->vnorm[0].z+tri->b[1]*tri->vnorm[1].z+ X tri->b[2]*tri->vnorm[2].z; X } X} X Xtriextent(o, bounds) XPrimitive *o; Xdouble bounds[2][3]; X{ X Triangle *tri; X X tri = o->objpnt.p_triangle; X X bounds[LOW][X] = bounds[HIGH][X] = tri->p1.x; X bounds[LOW][Y] = bounds[HIGH][Y] = tri->p1.y; X bounds[LOW][Z] = bounds[HIGH][Z] = tri->p1.z; X X if (tri->p2.x < bounds[LOW][X]) bounds[LOW][X] = tri->p2.x; X if (tri->p2.x > bounds[HIGH][X]) bounds[HIGH][X] = tri->p2.x; X if (tri->p3.x < bounds[LOW][X]) bounds[LOW][X] = tri->p3.x; X if (tri->p3.x > bounds[HIGH][X]) bounds[HIGH][X] = tri->p3.x; X X if (tri->p2.y < bounds[LOW][Y]) bounds[LOW][Y] = tri->p2.y; X if (tri->p2.y > bounds[HIGH][Y]) bounds[HIGH][Y] = tri->p2.y; X if (tri->p3.y < bounds[LOW][Y]) bounds[LOW][Y] = tri->p3.y; X if (tri->p3.y > bounds[HIGH][Y]) bounds[HIGH][Y] = tri->p3.y; X X if (tri->p2.z < bounds[LOW][Z]) bounds[LOW][Z] = tri->p2.z; X if (tri->p2.z > bounds[HIGH][Z]) bounds[HIGH][Z] = tri->p2.z; X if (tri->p3.z < bounds[LOW][Z]) bounds[LOW][Z] = tri->p3.z; X if (tri->p3.z > bounds[HIGH][Z]) bounds[HIGH][Z] = tri->p3.z; X} END_OF_FILE if test 7297 -ne `wc -c <'src/triangle.c'`; then echo shar: \"'src/triangle.c'\" unpacked with wrong size! fi # end of 'src/triangle.c' fi echo shar: End of archive 4 \(of 8\). cp /dev/null ark4isdone MISSING="" for I in 1 2 3 4 5 6 7 8 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 8 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net. Use a domain-based address or give alternate paths, or you may lose out.