v21i011: A ray tracing program, Part04/08
Rich Salz
rsalz at uunet.uu.net
Thu Feb 8 07:49:47 AEST 1990
Submitted-by: Craig Kolb <craig at 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 at 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 at uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.
More information about the Comp.sources.unix
mailing list