CCL Home Page
Up Directory CCL Part10
#! /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 'Doc/Guide/camera.tex' <<'END_OF_FILE'
X\chapter{Specifying a View}
X
XWhen designing a {\rayshade} input file, there are two main
Xissues that must be considered.  The first and more complex
Xis the selection of the objects to be rendered and the appearances
Xthey should be assigned.  The second and usually easier issue is
Xthe choice of viewing parameters.  This chapter deals with the
Xlatter problem; the majority of the following chapters
Xdiscuss aspects of objects and their appearances.
X
X{\Rayshade} uses a camera model to describe
Xthe geometric relationship between the objects to be rendered
Xand the image that is produced.  This relationship describes
Xa perspective projection from world space onto the image plane.
X
XThe geometry of the perspective projection
Xmay be thought of as an
Xinfinite pyramid, known as the viewing {\em frustum}.
XThe apex of the frustum is defined by the camera's position,
Xand the main axis of the frustum by a ``look'' vector.
XThe four sides of
Xthe pyramid are differentiated by their relationship to a
Xreference ``up'' vector from the camera's position.
X
XThe image
Xultimately produced by {\rayshade} may then be thought of as
Xthe projection of the objects closest to the eye onto
Xa rectangular screen formed by the intersection of the pyramid with
Xa plane orthogonal to the pyramid's axis.  The overall shape
Xof the frustum (the lengths of the top and bottom sides compared
Xto left and right)
Xis described by the horizontal and vertical fields
Xof view.
X
X\section{Camera Position}
X
XThe three basic camera properties are its position, the direction
Xin which it is pointing, and its orientation.  The keywords for
Xspecifying these values are described below.
XThe default values
Xare designed to provide a reasonable view of a sphere of radius 2
Xlocated at origin.  If these default values are used,
Xthe origin is projected onto the center of the image plane, with
Xthe world $x$ axis  running left-to-right, the $z$ axis bottom-to-top,
Xand the $y$ axis going ``into'' the screen.
X
X\begin{defkey}{eyep}{\evec{pos}}
X	Place the virtual camera at the given position.
X\end{defkey}
XThe default camera position is (0, -8, 0).
X
X\begin{defkey}{lookp}{\evec{pos}}
X	Point the virtual camera toward the given position.
X\end{defkey}
XThe default look point is the origin (0, 0, 0).  The look point
Xand camera position must not be coincident.
X
X\begin{defkey}{up}{\evec{direction}}
X	The ``up'' vector from the camera point is set to the
X	given direction.
X\end{defkey}
XThis up vector need not be orthogonal to
Xthe view vector, nor need it be normalized.  The default up
Xdirection is (0, 0, 1).
X
XAnother popular standard viewing geometry, with the $x$ axis running
Xleft-to-right,
Xthe $y$ axis bottom-to-top, and the $z$ axis pointing out of the screen,
Xmay be obtained by setting the up vector to (0, 1, 0) and by placing
Xthe camera on the positive $z$ axis.
X
X\section{Field of View}
X
XAnother important choice to be made is that of the 
Xfield of view of the camera.  The size of this field describes
Xthe angles between the left and right sides and top and bottom sides
Xof the frustum.
X
X\begin{defkey}{fov}{{\em hfov} [{\em vfov}]}
X	Specify
X	the horizontal and vertical field of view, in degrees.
X\end{defkey}
XThe default horizontal field of view is 45 degrees.
XIf {\em vfov} is omitted, as is the general practice,
Xthe vertical field of view is computed using the horizontal
Xfield of view, the output image resolution, and the assumption
Xthat a pixel samples a square area.  Thus,
Xthe values passed via the
X{\tt screen} keyword define the shape of the final image.
XIf you are
Xdisplaying on a non-square pixeled device,
Xyou must set the vertical field of view
Xto compensate for the ``squashing'' that will result.
X
X\section{Depth of Field}
X
XUnder many circumstances,
Xit is desirable to render
Xobjects in the image such that they are in sharp
Xfocus on the image plane.  This is achieved by using the default
X``pinhole' camera.  In this mode, the camera's aperture is a single
Xpoint, and all light rays are focused on the image plane.
X
XAlternatively, one may widen the aperture in order to
Xsimulate depth of field. In this case, rays are cast from various places on
Xthe aperture disk towards a point whose distance from the
Xcamera is equal to the
X{\em focus distance}.  Objects that lay in the focal plane will be
Xin sharp focus.  The farther an object is from the image plane,
Xthe more out-of-focus it will appear to be.
XA wider aperture will lead to a greater blurring of
Xobjects that do not lay in the focal plane.
XWhen using a non-zero aperture radius, it is best to use jittered
Xsampling in order to reduce aliasing.
X
X\begin{defkey}{aperture}{{\em radius}}
X	Use an aperture with the given {\em radius}.
X\end{defkey}
XThe default radius is zero, resulting in a pinhole camera model.
X
X\begin{defkey}{focaldist}{{\em distance}}
X	Set the focal plane to be {\em distance} units from the camera.
X\end{defkey}
XBy default, the focal distance is equal to the distance from the
Xcamera to the look point.
X
X\section{Stereo Rendering}
X
XProducing a stereo pair is a relatively simple process; rather than
Xsimply rendering a single image, one creates two related images which
Xmay then be viewed on a stereo monitor, in a stereo slide viewer, or
Xby using colored glasses and an appropriate display filter.
X
X{\Rayshade} facilitates the rendering of stereo pairs by allowing you
Xto specify the distance between the camera positions used in
Xcreating the two images.  The camera position given in the
X{\rayshade} input file
Xdefines
Xthe midpoint between the two camera positions used to generate the
Ximages.
XGenerally, the remainder of the viewing parameters are kept constant.
X
X\begin{defkey}{eyesep}{{\em separation}}
X	Specifies the camera separation to be used in rendering stereo
X	pairs.
X\end{defkey}
XThere is no default value.
XThe separation may also be specified on the command line through
Xthe {\em -E} option.
XThe view to be rendered (left or right)
Xmust be specified on the command line by using
Xthe {\tt -l} or {\tt -r} options.
X
XThere are several things to keep in mind when generating stereo
Xpairs.  Firstly, those objects that lie in from of the focal plane will
Xappear to protrude from the screen when viewed in stereo, while objects
Xfarther
Xthan the focal plane will recede into the screen.  As it is usually
Xeasier to look at stereo images that recede into the screen, you will
Xusually
Xwant to place the look point closer to the camera than the object
Xof primary interest.
X
XThe degree of stereo effect is a
Xfunction of the camera separation and the distance from the camera
Xto the look point. Too large a separation will result in a hyperstereo
Xeffect that will be hard to resolve, while too little a value will result
Xin no stereo effect
Xat all.  A separation equal to one tenth the distance from the
Xcamera to the look point is often a good choice.
END_OF_FILE
if test 6817 -ne `wc -c <'Doc/Guide/camera.tex'`; then
    echo shar: \"'Doc/Guide/camera.tex'\" unpacked with wrong size!
fi
# end of 'Doc/Guide/camera.tex'
fi
if test -f 'Doc/Guide/options.tex' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Doc/Guide/options.tex'\"
else
echo shar: Extracting \"'Doc/Guide/options.tex'\" \(6858 characters\)
sed "s/^X//" >'Doc/Guide/options.tex' <<'END_OF_FILE'
X\chapter{Options}
X
XThis appendix describes the command-line arguments accepted by {\rayshade}.
XThese options override defaults
Xas well as any values or flags given in the input file,
Xand are thus useful for generating test and other unusual, ``non-standard''
Xrenderings.
X
XThe general form of a {\rayshade} command line is:
X\begin{quote}
X{\tt rayshade} [{\em Options}] [{\em filename}]
X\end{quote}
X
XIf given, the input file is read from {\em filename}.  By default,
Xthe input file is read from the standard input.
XRecall that, by default, the image file is written to the standard
Xoutput; you will need to redirect the standard output if you have not
Xchosen to write the image to a file directly.  The name of the input
Xfile may be given anywhere on the command line.
X
XCommand-line options fall into two broad categories: those that set
Xnumerical or other values and thus must be followed by further arguments,
Xand those that simply turn features on and off.  {\Rayshade}'s
Xconvention is to denote the value-setting arguments using capital letters,
Xand feature-toggling arguments using lower-case letters.
X
X\begin{defkey}{-A}{{\em frame}}
X	Begin rendering (action) on the given frame.
X\end{defkey}
XThe default starting frame is number zero.
X
X\begin{defkey}{-a}{}
X	Toggle writing of alpha channel.
X\end{defkey}
XThis option is only available when the Utah Raster Toolkit is
Xbeing used.
X
X\begin{defkey}{-C}{{\em R G B}}
X	Set the adaptive ray tree pruning color.  If all
X	channel contributions falls below the given cutoff
X	values, no further rays are spawned.
X\end{defkey}
XOverrides the value specified via the {\tt cutoff} keyword.
X
X\begin{defkey}{-c}{}
X	Continue an interrupted rendering.
X\end{defkey}
XWhen given, this option indicates that the image file being written
Xto contains a partially-completed image.  {\Rayshade} will read the
Ximage to determine the scanline from which to continue the rendering.
XThis option is only available with the Utah Raster Toolkit.
XThe {\tt -O} option must also be used.
X
X\begin{defkey}{-D}{{\em depth}}
X	Set maximum ray tree depth.
X\end{defkey}
XOverrides the value specified in the input file via the {\tt maxdepth}
Xkeyword.
X
X\begin{defkey}{-E}{{\em separation}}
X	Set eye separation for rendering of stereo pairs.
X\end{defkey}
XOverrides the value specified via the {\tt eyesep} keyword.
X
X\begin{defkey}{-e}{}
X	Write exponential RLE file.
X\end{defkey}
XThis option is only available for use with the Utah Raster Toolkit.
XSee the Utah Raster Toolkit's {\em unexp} manual page for details on
Xexponential RLE files.
X
X\begin{defkey}{-F}{{\em freq}}
X	Set frequency of status report.
X\end{defkey}
XOverrides the value given using the {\tt report} keyword.
X
X\begin{defkey}{-f}{}
X	Flip all computed polygon (and triangle) normals.
X\end{defkey}
XThis option should be used when rendering polygons defined
Xby vertices given in {\em clockwise}
Xorder, rather than counter-clockwise order as
Xexpected by {\rayshade}.
X
X\begin{defkey}{-G}{{\em gamma}}
X	Use given gamma correction exponent writing writing
X	color information to the image file.
X\end{defkey}
XThe default value for {\em gamma} is 1.0.
X
X\begin{defkey}{-g}{}
X	Use a Gaussian pixel filter.
X\end{defkey}
XOverrides the filter selected through the use of the {\tt filter}
Xkeyword.
X
X\begin{defkey}{-h}{}
X	Print a short use message.
X\end{defkey}
X
X\begin{defkey}{-j}{}
X	Toggle the use of jittered sampling to perform antialiasing.
X	If disabled, a fixed sampling pattern is used.
X\end{defkey}
X
X\begin{defkey}{-l}{}
X	Render the left stereo pair image.
X\end{defkey}
X
X\begin{defkey}{-m}{}
X	Write a sampling map to the alpha channel.
X\end{defkey}
XRather than containing coverage information, the alpha channel values
Xwill be restricted to zero, indicating no supersampling, and full intensity,
Xindicating supersampling.  This option is only available if the Utah
XRaster Toolkit is being used.
X
X\begin{defkey}{-N}{{\em frames}}
X	Set the total number of frames to be rendered.
X\end{defkey}
XThis option overrides any value specified through the use of the
X{\tt frames} keyword.  By default, a single frame is rendered.
X
X\begin{defkey}{-n}{}
X	Do not render shadows.
X\end{defkey}
X
X\begin{defkey}{-O}{{\em outfile}}
X	Write the image to the named file.
X\end{defkey}
XThis option overrides the name given with the {\tt outfile} keyword,
Xif any,
Xin the input file.
X
X\begin{defkey}{-o}{}
X	Toggle the effect of object opacity on shadows.
X\end{defkey}
XThis option is equivalent to specifying {\tt shadowtransp}
Xin the input file.  By default, {\rayshade} traces shadow
Xrays through non-opaque objects.
X
X\begin{defkey}{-P}{{\em cpp-arguments}}
X	Specify the options that should be passed to the C
X	preprocessor.
X\end{defkey}
XThe C preprocessor, if available, is applied to all of the input
Xpassed to {\em rayshade}.
X
X\begin{defkey}{-p}{}
X	Perform preview-quality rendering.
X\end{defkey}
XThis option is equivalent to {\tt -n -S 1 -D 0}.
X
X\begin{defkey}{-q}{}
X	Do not print warning messages.
X\end{defkey}
X
X\begin{defkey}{-R}{{\em xsize ysize}}
X	Produce an image {\em xsize} pixels wide by
X	{\em ysize} pixels high.
X\end{defkey}
XThis option overrides any screen size set by use of
Xthe {\tt screen} keyword.
X
X\begin{defkey}{-r}{}
X	Render the right stereo pair image.
X\end{defkey}
X
X\begin{defkey}{-S}{{\em samples}}
X	Use $samples^2$ jittered samples.
X\end{defkey}
XThis option overrides any value set through the use of
Xthe {\tt samples} keyword in the input file.
X
X\begin{defkey}{-s}{}
X	Disable caching of  shadowing information.
X\end{defkey}
XIt should never be necessary to use this option.
X
X\begin{defkey}{-T}{{\em r g b}}
X	Set the contrast threshold in the three
X	color channels for use in adaptive supersampling.
X\end{defkey}
XThis option overrides any value given through the use of
Xthe {\em contrast} keyword.
X
X\begin{defkey}{-u}{}
X	Toggle the use of the C preprocessor.
X\end{defkey}
X{\Rayshade} usually feeds its input through a
XC preprocessor if one is available on your system.
XIf this option is given, unadulterated input files will
Xbe used.
X
X\begin{defkey}{-V}{{\em	filename}}
X	Write verbose output to the named file.
X\end{defkey}
XThis option overrides any file named through the use of
Xthe {\tt report} keyword.
X
X\begin{defkey}{-v}{}
X	Write verbose output.
X\end{defkey}
XWhen given, this option causes information about the options
Xselected and the objects defined to be included in the
Xreport file.
X
X\begin{defkey}{-W}{{\em minx maxx miny maxy}}
X	Render the specified window.
X\end{defkey}
XThe window must be properly contained within the screen.  This
Xoption overrides any window specified using the {\em window} keyword
Xin the input file.
X
X\begin{defkey}{-X}{{\em left right bottom top}}
X	Crop the rendering window using the given normalized values.
X\end{defkey}
XThis option is provided to facilitate changing and/or examining a
Xsmall portion of an image without having to re-render the entire
Ximage.
END_OF_FILE
if test 6858 -ne `wc -c <'Doc/Guide/options.tex'`; then
    echo shar: \"'Doc/Guide/options.tex'\" unpacked with wrong size!
fi
# end of 'Doc/Guide/options.tex'
fi
if test -f 'config.H' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'config.H'\"
else
echo shar: Extracting \"'config.H'\" \(6009 characters\)
sed "s/^X//" >'config.H' <<'END_OF_FILE'
X/* config.h
X * This file was produced by running the config.h.SH script, which
X * gets its values from config.sh, which is generally produced by
X * running Configure.
X *
X * Feel free to modify any of this as the need arises.  Note, however,
X * that running config.h.SH again will wipe out any changes you've made.
X * For a more permanent change edit config.sh and rerun config.h.SH.
X */
X
X
X/* EUNICE:
X *	This symbol, if defined, indicates that the program is being compiled
X *	under the EUNICE package under VMS.  The program will need to handle
X *	things like files that don't go away the first time you unlink them,
X *	due to version numbering.  It will also need to compensate for lack
X *	of a respectable link() command.
X */
X/* VMS:
X *	This symbol, if defined, indicates that the program is running under
X *	VMS.  It is currently only set in conjunction with the EUNICE symbol.
X */
X/* XENIX:
X *	This symbol, if defined, indicates thet the program is running under
X *	Xenix (at least 3.0 ?).
X */
X/* BSD:
X *	This symbol, if defined, indicates that the program is running under
X *	a BSD system.
X */
X/*#undef EUNICE		/**/
X/*#undef VMS		/**/
X/*#undef XENIX		/**/
X#define BSD		/**/
X
X/* CPPSTDIN:
X *	This symbol contains the first part of the string which will invoke
X *	the C preprocessor on the standard input and produce to standard
X *	output.	 Typical value of "cc -E" or "/lib/cpp".
X */
X/* CPPMINUS:
X *	This symbol contains the second part of the string which will invoke
X *	the C preprocessor on the standard input and produce to standard
X *	output.  This symbol will have the value "-" if CPPSTDIN needs a minus
X *	to specify standard input, otherwise the value is "".
X */
X#define CPPSTDIN "/usr/lib/cpp"
X#define CPPMINUS ""
X
X/* bzero:
X *	This symbol is maped to memset if the  bzero() routine is not
X *	available to set memory to 0.
X */
X/*#undef	bzero(s,l)	memset((s),0,(l))	;	/* mapped to memset */
X
X/* CBRT:
X *	This symbol, if defined, indicates that the cbrt() (cube root)
X *	function is available.
X */
X#define	CBRT		/**/
X
X/* index:
X *	This preprocessor symbol is defined, along with rindex, if the system
X *	uses the strchr and strrchr routines instead.
X */
X/* rindex:
X *	This preprocessor symbol is defined, along with index, if the system
X *	uses the strchr and strrchr routines instead.
X */
X#define	index strchr	/* cultural */
X#define	rindex strrchr	/*  differences? */
X
X/* MEMSET:
X *	This symbol, if defined, indicates that the memset routine is available
X *	to set blocks of memory. You should always use bzero() instead of
X *	memset() because bzero is remaped to memset if necessary. This means
X *	that a memset() routine must be provided in case MEMSET is not defined
X *	and no bzero() is found.
X */
X#define	MEMSET		/**/
X
X/* POPEN:
X *	This symbol, if defined, indicates that the popen routine is
X *	available to open a pipe from a process.
X */
X#define POPEN		/**/
X
X/* RUSAGE:
X *	This symbol, if defined, indicates that the getrusage() routine exists.
X *	Inclusion of  and  may be necessary.
X */
X#define	RUSAGE		/**/
X
X/* TIMES:
X *	This symbol, if defined, indicates that the times() routine exists.
X *	Note that this became obsolete on some systems (SUNOS), which now
X * use getrusage().
X */
X/* CLOCKTYPE:
X *	This symbol holds the type returned by times(). It can be long,
X *	or clock_t on BSD sites (in which case  should be
X *	included). Moreover, the Clock_t symbol is defined in common.h
X *	and should be used for easy clean reference.
X */
X#define TIMES		/**/
X#define CLOCKTYPE long		/**/
X
X/* I_STRING:
X *	This symbol, if defined, indicates to the C program that it should
X *	include  (USG systems) instead of  (BSD systems).
X */
X#define I_STRING		/**/
X
X/* I_SYSRESOURCE:
X *	This symbol, if defined, indicates to the C program that it should
X *	include .
X */
X#define	I_SYSRESOURCE		/**/
X
X/* I_SYSTYPES:
X *	This symbol, if defined, indicates to the C program that it should
X *	include .
X */
X#define	I_SYSTYPES		/**/
X
X/* I_TIME:
X *	This symbol, if defined, indicates to the C program that it should
X *	include .
X */
X/* I_SYSTIME:
X *	This symbol, if defined, indicates to the C program that it should
X *	include .
X */
X/* I_SYSTIMEKERNEL:
X *	This symbol, if defined, indicates to the C program that it should
X *	include  with KERNEL defined.
X */
X/*#undef I_TIME		/**/
X#define I_SYSTIME		/**/
X/*#undef I_SYSTIMEKERNEL		/**/
X
X/* nrand:
X *	This macro is to be used to generate uniformly distributed
X *	random numbers over the range [0., 1.].
X */
X/* seednrand:
X *	This symbol defines the macro to be used in seeding the
X *	random number generator (see nrand).
X */
X#define nrand()		drand48()		/**/
X#define seednrand(x)	srand48(x)	/**/
X
X/* VOIDFLAGS:
X *	This symbol indicates how much support of the void type is given by this
X *	compiler.  What various bits mean:
X *
X *	    1 = supports declaration of void
X *	    2 = supports arrays of pointers to functions returning void
X *	    4 = supports comparisons between pointers to void functions and
X *		    addresses of void functions
X *	    8 = suports declaration of generic void pointers
X *
X *	The package designer should define VOIDUSED to indicate the requirements
X *	of the package.  This can be done either by #defining VOIDUSED before
X *	including config.h, or by defining defvoidused in Myinit.U.  If the
X *	latter approach is taken, only those flags will be tested.  If the
X *	level of void support necessary is not present, defines void to int.
X */
X#ifndef VOIDUSED
X#define VOIDUSED 11
X#endif
X#define VOIDFLAGS 11
X#if (VOIDFLAGS & VOIDUSED) != VOIDUSED
X#define void int		/* is void to be avoided? */
X#define M_VOID		/* Xenix strikes again */
X#endif
X
X/* URT:
X *     This symbol, if defined, indicates that the Utah Raster
X *	Toolkit is being used.
X */
X#define       URT          /**/
X
X/* I_VARARGS:
X *	This symbol, if defined, indicates to the C program that it should
X *	include .
X */
X/*#undef I_STDLIB		/**/
X
END_OF_FILE
if test 6009 -ne `wc -c <'config.H'`; then
    echo shar: \"'config.H'\" unpacked with wrong size!
fi
# end of 'config.H'
fi
if test -f 'config.h.SH' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'config.h.SH'\"
else
echo shar: Extracting \"'config.h.SH'\" \(6456 characters\)
sed "s/^X//" >'config.h.SH' <<'END_OF_FILE'
Xcase $CONFIG in
X'')
X    if test ! -f config.sh; then
X	ln ../config.sh . || \
X	ln ../../config.sh . || \
X	ln ../../../config.sh . || \
X	(echo "Can't find config.sh."; exit 1)
X	echo "Using config.sh from above..."
X    fi
X    . ./config.sh
X    ;;
Xesac
Xecho "Extracting config.h (with variable substitutions)"
Xsed <config.h -e 's!^#undef!/\*#undef!'
X/* config.h
X * This file was produced by running the config.h.SH script, which
X * gets its values from config.sh, which is generally produced by
X * running Configure.
X *
X * Feel free to modify any of this as the need arises.  Note, however,
X * that running config.h.SH again will wipe out any changes you've made.
X * For a more permanent change edit config.sh and rerun config.h.SH.
X */
X
X
X/* EUNICE:
X *	This symbol, if defined, indicates that the program is being compiled
X *	under the EUNICE package under VMS.  The program will need to handle
X *	things like files that don't go away the first time you unlink them,
X *	due to version numbering.  It will also need to compensate for lack
X *	of a respectable link() command.
X */
X/* VMS:
X *	This symbol, if defined, indicates that the program is running under
X *	VMS.  It is currently only set in conjunction with the EUNICE symbol.
X */
X/* XENIX:
X *	This symbol, if defined, indicates thet the program is running under
X *	Xenix (at least 3.0 ?).
X */
X/* BSD:
X *	This symbol, if defined, indicates that the program is running under
X *	a BSD system.
X */
X#$d_eunice EUNICE		/**/
X#$d_eunice VMS		/**/
X#$d_xenix XENIX		/**/
X#$d_bsd BSD		/**/
X
X/* CPPSTDIN:
X *	This symbol contains the first part of the string which will invoke
X *	the C preprocessor on the standard input and produce to standard
X *	output.	 Typical value of "cc -E" or "/lib/cpp".
X */
X/* CPPMINUS:
X *	This symbol contains the second part of the string which will invoke
X *	the C preprocessor on the standard input and produce to standard
X *	output.  This symbol will have the value "-" if CPPSTDIN needs a minus
X *	to specify standard input, otherwise the value is "".
X */
X#define CPPSTDIN "$cppstdin"
X#define CPPMINUS "$cppminus"
X
X/* bzero:
X *	This symbol is maped to memset if the  bzero() routine is not
X *	available to set memory to 0.
X */
X#$d_bzero	bzero(s,l)	memset((s),0,(l))	;	/* mapped to memset */
X
X/* CBRT:
X *	This symbol, if defined, indicates that the cbrt() (cube root)
X *	function is available.
X */
X#$d_cbrt	CBRT		/**/
X
X/* index:
X *	This preprocessor symbol is defined, along with rindex, if the system
X *	uses the strchr and strrchr routines instead.
X */
X/* rindex:
X *	This preprocessor symbol is defined, along with index, if the system
X *	uses the strchr and strrchr routines instead.
X */
X#$d_index	index strchr	/* cultural */
X#$d_index	rindex strrchr	/*  differences? */
X
X/* MEMSET:
X *	This symbol, if defined, indicates that the memset routine is available
X *	to set blocks of memory. You should always use bzero() instead of
X *	memset() because bzero is remaped to memset if necessary. This means
X *	that a memset() routine must be provided in case MEMSET is not defined
X *	and no bzero() is found.
X */
X#$d_memset	MEMSET		/**/
X
X/* POPEN:
X *	This symbol, if defined, indicates that the popen routine is
X *	available to open a pipe from a process.
X */
X#$d_popen POPEN		/**/
X
X/* RUSAGE:
X *	This symbol, if defined, indicates that the getrusage() routine exists.
X *	Inclusion of  and  may be necessary.
X */
X#$d_rusage	RUSAGE		/**/
X
X/* TIMES:
X *	This symbol, if defined, indicates that the times() routine exists.
X *	Note that this became obsolete on some systems (SUNOS), which now
X * use getrusage().
X */
X/* CLOCKTYPE:
X *	This symbol holds the type returned by times(). It can be long,
X *	or clock_t on BSD sites (in which case  should be
X *	included). Moreover, the Clock_t symbol is defined in common.h
X *	and should be used for easy clean reference.
X */
X#$d_times TIMES		/**/
X#define CLOCKTYPE $clocktype		/**/
X
X/* I_STRING:
X *	This symbol, if defined, indicates to the C program that it should
X *	include  (USG systems) instead of  (BSD systems).
X */
X#$i_string I_STRING		/**/
X
X/* I_SYSRESOURCE:
X *	This symbol, if defined, indicates to the C program that it should
X *	include .
X */
X#$i_sysresrc	I_SYSRESOURCE		/**/
X
X/* I_SYSTYPES:
X *	This symbol, if defined, indicates to the C program that it should
X *	include .
X */
X#$i_systypes	I_SYSTYPES		/**/
X
X/* I_TIME:
X *	This symbol, if defined, indicates to the C program that it should
X *	include .
X */
X/* I_SYSTIME:
X *	This symbol, if defined, indicates to the C program that it should
X *	include .
X */
X/* I_SYSTIMEKERNEL:
X *	This symbol, if defined, indicates to the C program that it should
X *	include  with KERNEL defined.
X */
X#$i_time I_TIME		/**/
X#$i_systime I_SYSTIME		/**/
X#$i_systimek I_SYSTIMEKERNEL		/**/
X
X/* nrand:
X *	This macro is to be used to generate uniformly distributed
X *	random numbers over the range [0., 1.].
X */
X/* seednrand:
X *	This symbol defines the macro to be used in seeding the
X *	random number generator (see nrand).
X */
X#define nrand()		$mrand		/**/
X#define seednrand(x)	$seedfunc(x)	/**/
X
X/* VOIDFLAGS:
X *	This symbol indicates how much support of the void type is given by this
X *	compiler.  What various bits mean:
X *
X *	    1 = supports declaration of void
X *	    2 = supports arrays of pointers to functions returning void
X *	    4 = supports comparisons between pointers to void functions and
X *		    addresses of void functions
X *	    8 = suports declaration of generic void pointers
X *
X *	The package designer should define VOIDUSED to indicate the requirements
X *	of the package.  This can be done either by #defining VOIDUSED before
X *	including config.h, or by defining defvoidused in Myinit.U.  If the
X *	latter approach is taken, only those flags will be tested.  If the
X *	level of void support necessary is not present, defines void to int.
X */
X#ifndef VOIDUSED
X#define VOIDUSED $defvoidused
X#endif
X#define VOIDFLAGS $voidflags
X#if (VOIDFLAGS & VOIDUSED) != VOIDUSED
X#$define void int		/* is void to be avoided? */
X#$define M_VOID		/* Xenix strikes again */
X#endif
X
X/* URT:
X *     This symbol, if defined, indicates that the Utah Raster
X *	Toolkit is being used.
X */
X#$d_urt       URT          /**/
X
X/* I_VARARGS:
X *	This symbol, if defined, indicates to the C program that it should
X *	include .
X */
X#$i_stdlib I_STDLIB		/**/
X
X!GROK!THIS!
END_OF_FILE
if test 6456 -ne `wc -c <'config.h.SH'`; then
    echo shar: \"'config.h.SH'\" unpacked with wrong size!
fi
# end of 'config.h.SH'
fi
if test -f 'libray/libcommon/expr.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'libray/libcommon/expr.c'\"
else
echo shar: Extracting \"'libray/libcommon/expr.c'\" \(5942 characters\)
sed "s/^X//" >'libray/libcommon/expr.c' <<'END_OF_FILE'
X/*
X * expr.c
X *
X * Copyright (C) 1989, 1991, Craig E. Kolb, Rod G. Bogart
X * All rights reserved.
X *
X * This software may be freely copied, modified, and redistributed
X * provided that this copyright notice is preserved on all copies.
X *
X * You may not distribute this software, in whole or in part, as part of
X * any commercial product without the express consent of the authors.
X * 
X * There is no warranty or other guarantee of fitness of this software
X * for any purpose.  It is provided solely "as is".
X *
X * $Id: expr.c,v 4.0 91/07/17 14:30:36 kolb Exp Locker: kolb $
X *
X * $Log:	expr.c,v $
X * Revision 4.0  91/07/17  14:30:36  kolb
X * Initial version.
X * 
X */
X#include "common.h"
X
XExpr *TimeExpr, *FrameExpr;
X
Xstatic Expr *ExprCreate();
Xvoid ExprFree();
X
XExpr *
XExprFloatCreate(val, timevary)
XFloat val;
Xint timevary;
X{
X	Expr *res;
X
X	res = ExprCreate(FLOAT_EXPR, timevary);
X	res->value = val;
X	return res;
X}
X
XExpr *
XExprReuseFloatCreate(val)
XFloat val;
X{
X	Expr *res;
X
X	/* this should get the expr from a magic list
X	 * that will reuse the exprs.
X	 * But not yet...
X	 */
X	res = ExprCreate(FLOAT_EXPR, FALSE);
X	res->value = val;
X	return res;
X}
X
XExpr *
XExprMalloc()
X{
X	return (Expr *)Malloc(sizeof(Expr));
X}
X
Xstatic
XExpr *
XExprCreate(type, timevary)
Xint type, timevary;
X{
X	Expr *res;
X
X	res = ExprMalloc();
X	res->type = type;
X	res->timevary = timevary;
X	res->symtab = FALSE;
X	res->nparams = 0;
X	res->params = (Expr **)NULL;
X	res->function = (Float (*)())NULL;
X	res->value = 0.0;
X	res->timenow = -FAR_AWAY;
X	return res;	
X}
X
XFloat
XExprEval(expr)
XExpr *expr;	/* Expression to evaluate */
X{
X	/*
X	 * If the expression is a time-varying function,
X	 * and its time is incorrect, evaluate at
X	 * the current time.
X	 */
X	if (expr->timevary && expr->nparams && 
X	    !equal(TimeExpr->value, expr->timenow)) {
X		if (expr->nparams == 1) {
X			expr->value = (*expr->function)
X				(ExprEval(expr->params[0]));
X		} else if (expr->nparams == 2) {
X			expr->value = (*expr->function)
X				(ExprEval(expr->params[0]),
X				 ExprEval(expr->params[1]));
X		} else if (expr->nparams == 3) {
X			expr->value = (*expr->function)
X				(ExprEval(expr->params[0]),
X				 ExprEval(expr->params[1]),
X				 ExprEval(expr->params[2]));
X		} else if (expr->nparams == 4) {
X			expr->value = (*expr->function)
X				(ExprEval(expr->params[0]),
X				 ExprEval(expr->params[1]),
X				 ExprEval(expr->params[2]),
X				 ExprEval(expr->params[3]));
X		} else if (expr->nparams == 5) {
X			expr->value = (*expr->function)
X				(ExprEval(expr->params[0]),
X				 ExprEval(expr->params[1]),
X				 ExprEval(expr->params[2]),
X				 ExprEval(expr->params[3]),
X				 ExprEval(expr->params[4]));
X		} else if (expr->nparams > 5)
X			RLerror(RL_PANIC, "Expression with > 5 args?\n");
X		expr->timenow = TimeExpr->value;
X	}
X	return expr->value;
X}
X
XExpr *
XExprFunctionCreate(fp, nparams, params, timevary)
XFloat (*fp)();
Xint nparams, timevary;
XExpr **params;
X{
X	Expr *res;
X
X	res = ExprCreate(FLOAT_EXPR, timevary);
X	res->function = fp;
X	res->nparams = nparams;
X	res->params = params;
X
X	return res;
X}
X
XExpr *
XExprResolve1(a, fp, timevary)
XExpr *a;
XFloat (*fp)();
Xint timevary;
X{
X	Expr **params, *res;
X
X	if (!timevary && !a->timevary) {
X		res = ExprFloatCreate((*fp)(a->value), FALSE);
X		ExprFree(a);
X		return res;
X	} else {
X		params = (Expr **)Malloc(sizeof(Expr *));
X		params[0] = a;
X		return ExprFunctionCreate(fp, 1, params, TRUE);
X	}
X}
X
XExpr *
XExprResolve2(a, b, fp, timevary)
XExpr *a, *b;
XFloat (*fp)();
Xint timevary;
X{
X	Expr **params, *res;
X	if (!timevary && !a->timevary && !b->timevary) {
X		res = ExprFloatCreate((*fp)(a->value, b->value), FALSE);
X		ExprFree(a);
X		ExprFree(b);
X		return res;
X	} else {
X		params = (Expr **)Malloc(2 * sizeof(Expr *));
X		params[0] = a;
X		params[1] = b;
X		return ExprFunctionCreate(fp, 2, params, TRUE);
X	}
X}
X
XExpr *
XExprResolve3(a, b, c, fp, timevary)
XExpr *a, *b, *c;
XFloat (*fp)();
Xint timevary;
X{
X	Expr **params, *res;
X	if (!timevary && !a->timevary && !b->timevary && !c->timevary) {
X		res = ExprFloatCreate((*fp)(a->value, b->value, c->value), 
X				      FALSE);
X		ExprFree(a);
X		ExprFree(b);
X		ExprFree(c);
X		return res;
X	} else {
X		params = (Expr **)Malloc(3 * sizeof(Expr *));
X		params[0] = a;
X		params[1] = b;
X		params[2] = c;
X		return ExprFunctionCreate(fp, 3, params, TRUE);
X	}
X}
X
XExpr *
XExprResolve4(a, b, c, d, fp, timevary)
XExpr *a, *b, *c, *d;
XFloat (*fp)();
Xint timevary;
X{
X	Expr **params, *res;
X	if (!timevary && !a->timevary && !b->timevary && !c->timevary &&
X	    !d->timevary) {
X		res = ExprFloatCreate((*fp)(a->value, b->value, c->value, 
X					    d->value), FALSE);
X		ExprFree(a);
X		ExprFree(b);
X		ExprFree(c);
X		ExprFree(d);
X		return res;
X	} else {
X		params = (Expr **)Malloc(4 * sizeof(Expr *));
X		params[0] = a;
X		params[1] = b;
X		params[2] = c;
X		params[3] = d;
X		return ExprFunctionCreate(fp, 4, params, TRUE);
X	}
X}
X
XExpr *
XExprResolve5(a, b, c, d, e, fp, timevary)
XExpr *a, *b, *c, *d, *e;
XFloat (*fp)();
Xint timevary;
X{
X	Expr **params, *res;
X	if (!timevary && !a->timevary && !b->timevary && !c->timevary &&
X	    !d->timevary && !e->timevary) {
X		res = ExprFloatCreate((*fp)(a->value, b->value, c->value, 
X					    d->value, e->value), FALSE);
X		ExprFree(a);
X		ExprFree(b);
X		ExprFree(c);
X		ExprFree(d);
X		ExprFree(e);
X		return res;
X	} else {
X		params = (Expr **)Malloc(5 * sizeof(Expr *));
X		params[0] = a;
X		params[1] = b;
X		params[2] = c;
X		params[3] = d;
X		params[4] = e;
X		return ExprFunctionCreate(fp, 5, params, TRUE);
X	}
X}
X
XExprAssoc *
XAssocCreate(lhs, expr, next)
XFloat *lhs;
XExpr *expr;
XExprAssoc *next;
X{
X	ExprAssoc *new;
X
X	new = (ExprAssoc *)Malloc(sizeof(ExprAssoc));
X	new->lhs = lhs;
X	new->expr = expr;
X	new->next = next;
X	return new;
X}
X
Xvoid
XTimeSet(time)
XFloat time;
X{
X	TimeExpr->value = time;
X}
X
Xvoid
XFrameSet(frame)
XFloat frame;
X{
X	FrameExpr->value = frame;
X}
X
Xvoid
XExprFree(expr)
XExpr *expr;
X{
X	if (!expr->symtab) {
X		if (expr->type == BUILTIN_EXPR && expr->params)
X			free((voidstar)expr->params);
X		free((voidstar)expr);
X	}
X}
END_OF_FILE
if test 5942 -ne `wc -c <'libray/libcommon/expr.c'`; then
    echo shar: \"'libray/libcommon/expr.c'\" unpacked with wrong size!
fi
# end of 'libray/libcommon/expr.c'
fi
if test -f 'libray/libobj/cone.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'libray/libobj/cone.c'\"
else
echo shar: Extracting \"'libray/libobj/cone.c'\" \(6723 characters\)
sed "s/^X//" >'libray/libobj/cone.c' <<'END_OF_FILE'
X/*
X * cone.c
X *
X * Copyright (C) 1989, 1991, Craig E. Kolb
X * All rights reserved.
X *
X * This software may be freely copied, modified, and redistributed
X * provided that this copyright notice is preserved on all copies.
X *
X * You may not distribute this software, in whole or in part, as part of
X * any commercial product without the express consent of the authors.
X *
X * There is no warranty or other guarantee of fitness of this software
X * for any purpose.  It is provided solely "as is".
X *
X * $Id: cone.c,v 4.0 91/07/17 14:36:46 kolb Exp Locker: kolb $
X *
X * $Log:	cone.c,v $
X * Revision 4.0  91/07/17  14:36:46  kolb
X * Initial version.
X * 
X */
X#include "geom.h"
X#include "cone.h"
X
Xstatic Methods *iConeMethods = NULL;
Xstatic char coneName[] = "cone";
X
Xunsigned long ConeTests, ConeHits;
X
XCone *
XConeCreate(br, bot, ar, apex)
XVector *bot, *apex;
XFloat br, ar;
X{
X	Cone *cone;
X	Float tantheta, lprime, tlen, len, dtmp;
X	Vector axis, base, tmp;
X
X	/*
X	 * The passed basepoint must be closer to the origin of the
X	 * cone than the apex point, implying that the base radius
X	 * must be smaller than the apex radius.  If the values passed
X	 * reflect the opposite, we switch everything.
X	 */
X	if(ar < br) {
X		tmp = *bot;
X		*bot = *apex;
X		*apex = tmp;
X		dtmp = br;
X		br = ar;
X		ar = dtmp;
X	} else if (equal(ar, br)) {
X		RLerror(RL_WARN, "Cone is a cylinder -- discarding.\n");
X		return (Cone *)NULL;
X	}
X	/*
X	 * Find the axis and axis length.
X	 */
X	VecSub(*apex, *bot, &axis);
X	len = VecNormalize(&axis);
X	if (len < EPSILON) {
X		RLerror(RL_WARN, "Degenerate cone.\n");
X		return (Cone *)NULL;
X	}
X
X	cone = (Cone *)share_malloc(sizeof(Cone));
X
X	/*
X	 * To render a cone, we transform the desired cone into
X	 * a canonical, Z-axis aligned, unit length, unit radius
X	 * at the apex cone.
X	 *
X	 * Here, we construct the transformation matrix to map
X	 * from cone<-->world space.
X	 */
X
X	/*
X	 * "tantheta" is the change in radius per unit length along
X	 * the cone axis.
X	 */
X	tantheta = (ar - br) / len;
X	/*
X	 * lprime defines the distance along the axis where the cone starts
X	 */
X	lprime = br / tantheta;
X	/*
X	 * Find the true base (origin) of the cone.
X	 */
X	VecScale(-lprime, axis, &base);
X	VecAdd(base, *bot, &base);
X	/*
X	 * tlen is the total length of the cone.
X	 */
X	tlen = lprime + len;
X	/*
X	 * start_dist is the distance from the origin of the canonical
X	 * cone at which the cone begins
X	 */
X	cone->start_dist = lprime / tlen;
X	CoordSysTransform(&base, &axis, ar, tlen, &cone->trans);
X	return cone;
X}
X
XMethods *
XConeMethods()
X{
X	if (iConeMethods == (Methods *)NULL) {
X		iConeMethods = MethodsCreate();
X		iConeMethods->name = ConeName;
X		iConeMethods->create = (GeomCreateFunc *)ConeCreate;
X		iConeMethods->methods = ConeMethods;
X		iConeMethods->intersect = ConeIntersect;
X		iConeMethods->normal = ConeNormal;
X		iConeMethods->uv = ConeUV;
X		iConeMethods->bounds = ConeBounds;
X		iConeMethods->stats = ConeStats;
X		iConeMethods->checkbounds = TRUE;
X		iConeMethods->closed = FALSE;
X	}
X	return iConeMethods;
X}
X
X/*
X * Ray-cone intersection test.  This routine is far from optimal, but
X * it's straight-forward and it works...
X */
Xint
XConeIntersect(cone, ray, mindist, maxdist)
XCone *cone;
XRay *ray;
XFloat mindist, *maxdist;
X{
X	Float t1, t2, a, b, c, disc, zpos, distfact;
X	Ray newray;
X	Vector nray, npos;
X	Float nmin;
X
X	ConeTests++;
X
X	/*
X	 * Transform ray from world to cone space.
X	 */
X	newray = *ray;
X	distfact = RayTransform(&newray, &cone->trans.itrans);
X	nray = newray.dir;
X	npos = newray.pos;
X	nmin = mindist * distfact;
X
X	a = nray.x * nray.x + nray.y * nray.y - nray.z*nray.z;
X	b = nray.x * npos.x + nray.y * npos.y - nray.z*npos.z;
X	c = npos.x*npos.x + npos.y*npos.y - npos.z*npos.z;
X
X	if (fabs(a) < EPSILON) {
X		/*
X		 * Only one intersection point...
X		 */
X		t1 = -0.5*c / b;
X		zpos = npos.z + t1 * nray.z;
X		if (t1 < nmin || zpos < cone->start_dist || zpos > 1.)
X			return FALSE;
X		t1 /= distfact;
X		if (t1 < *maxdist) {
X			*maxdist = t1;
X			ConeHits++;
X			return TRUE;
X		}
X		return FALSE;
X	} else {
X		disc = b*b - a*c;
X		if (disc < 0.)
X			return FALSE;		/* No possible intersection */
X		disc = sqrt(disc);
X		t1 = (-b + disc) / a;
X		t2 = (-b - disc) / a;
X		/*
X		 * Clip intersection points.
X		 */
X		zpos = npos.z + t1 * nray.z;
X		if (t1 < nmin || zpos < cone->start_dist || zpos > 1.) {
X			zpos = npos.z + t2 * nray.z;
X			if (t2 < nmin || zpos < cone->start_dist ||
X			    zpos > 1.)
X				return FALSE;
X			else
X				t1 = t2 / distfact;
X		} else {
X			zpos = npos.z + t2 * nray.z;
X			if (t2 < nmin || zpos < cone->start_dist ||
X			    zpos > 1.)
X				t1 /= distfact;
X			else
X				t1 = min(t1, t2) / distfact;
X		}
X		if (t1 < *maxdist) {
X			*maxdist = t1;
X			ConeHits++;
X			return TRUE;
X		}
X		return FALSE;
X	}
X}
X
X/*
X * Compute the normal to a cone at a given location on its surface.
X */
Xint
XConeNormal(cone, pos, nrm, gnrm)
XCone *cone;
XVector *pos, *nrm, *gnrm;
X{
X	Vector npos;
X
X	/*
X	 * Transform intersection point to cone space.
X	 */
X	npos = *pos;
X	PointTransform(&npos, &cone->trans.itrans);
X	
X	/*
X	 * The following is equal to
X	 * (pos X (0, 0, 1)) X pos
X	 */
X	nrm->x = npos.x * npos.z;
X	nrm->y = npos.y * npos.z;
X	nrm->z = -npos.x * npos.x - npos.y * npos.y;
X
X	/*
X	 * Transform normal back to world space.
X	 */
X	NormalTransform(nrm, &cone->trans.itrans);
X	*gnrm = *nrm;
X	return FALSE;
X}
X
Xvoid
XConeUV(cone, pos, norm, uv, dpdu, dpdv)
XCone *cone;
XVector *pos, *norm, *dpdu, *dpdv;
XVec2d *uv;
X{
X	Vector npos;
X	Float val;
X
X	npos = *pos;
X	PointTransform(&npos, &cone->trans.itrans);
X
X	uv->v = (npos.z - cone->start_dist) / (1. - cone->start_dist);
X	if (npos.z < EPSILON)
X		uv->u = 0.;
X	else {
X		val = npos.x / npos.z;
X		/*
X		 * Be careful not to feed |val| > 1 to acos
X		 */
X		if (val > 1.)
X			uv->u = 0.;
X		else if (val < -1.)
X			uv->u = 0.5;
X		else {
X			uv->u = acos(val) / TWOPI;
X			if (npos.y < 0.)
X				uv->u = 1. - uv->u;
X		}
X	}
X	/*
X	 * dpdv = pos
X	 * dpdu = dpdv X norm = (-norm->y, norm->x, 0.)
X	 */
X	if (dpdu) {
X		*dpdv = npos;
X		dpdu->x = -npos.y;
X		dpdu->y = npos.x;
X		dpdu->z = 0.;
X		VecTransform(dpdu, &cone->trans.trans);
X		VecTransform(dpdu, &cone->trans.trans);
X		(void)VecNormalize(dpdu);
X		(void)VecNormalize(dpdv);
X	}
X}
X
X/*
X * Return the extent of a cone.
X */
Xvoid
XConeBounds(cone, bounds)
XCone *cone;
XFloat bounds[2][3];
X{
X	bounds[LOW][X] = bounds[LOW][Y] = -1;
X	bounds[HIGH][X] = bounds[HIGH][Y] = 1;
X	bounds[LOW][Z] = cone->start_dist;
X	bounds[HIGH][Z] = 1;
X	/*
X	 * Transform bounding box to world space.
X	 */
X	BoundsTransform(&cone->trans.trans, bounds);
X}
X
Xchar *
XConeName()
X{
X	return coneName;
X}
X
Xvoid
XConeStats(tests, hits)
Xunsigned long *tests, *hits;
X{
X	*tests = ConeTests;
X	*hits = ConeHits;
X}
X
Xvoid
XConeMethodRegister(meth)
XUserMethodType meth;
X{
X	if (iConeMethods)
X		iConeMethods->user = meth;
X}
END_OF_FILE
if test 6723 -ne `wc -c <'libray/libobj/cone.c'`; then
    echo shar: \"'libray/libobj/cone.c'\" unpacked with wrong size!
fi
# end of 'libray/libobj/cone.c'
fi
if test -f 'libray/libtext/imagetext.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'libray/libtext/imagetext.c'\"
else
echo shar: Extracting \"'libray/libtext/imagetext.c'\" \(6113 characters\)
sed "s/^X//" >'libray/libtext/imagetext.c' <<'END_OF_FILE'
X/*
X * imagetext.c
X *
X * Copyright (C) 1989, 1991, Craig E. Kolb
X * All rights reserved.
X *
X * This software may be freely copied, modified, and redistributed
X * provided that this copyright notice is preserved on all copies.
X *
X * You may not distribute this software, in whole or in part, as part of
X * any commercial product without the express consent of the authors.
X *
X * There is no warranty or other guarantee of fitness of this software
X * for any purpose.  It is provided solely "as is".
X *
X * $Id: imagetext.c,v 4.0 91/07/17 14:42:42 kolb Exp Locker: kolb $
X *
X * $Log:	imagetext.c,v $
X * Revision 4.0  91/07/17  14:42:42  kolb
X * Initial version.
X * 
X */
X#include "texture.h"
X#include "libimage/image.h"
X#include "imagetext.h"
X
X#define INTERP(v)	(text->lo + (v)*(text->hi - text->lo))
X
X/*
X * Create Image texture.
X * Image texture has so many options that there's usually no
X * nice way to parse without resorting to additional keywords.
X * Thus the ImageTextCreate routine only reads the image to be used;
X * all but ->component must be set by hand.  The routine
X * ImageTextSetComponent is provided to set the component and
X * ensure that the image being used is appropriate. 
X */
XImageText *
XImageTextCreate(imagefile)
Xchar *imagefile;
X{
X	ImageText *text;
X
X	text = (ImageText *)Calloc(1, sizeof(ImageText));
X	text->component = COLOR; /* texture all colors by default*/
X	/*
X	 * Only apply one copy of the texture by default
X	 */
X	text->tileu = text->tilev = 0;
X	text->lo = 0.; text->hi = 1.;
X	text->smooth = FALSE;
X	text->mapping = UVMappingCreate();
X	text->image = ImageRead(imagefile);
X	return text;
X}
X
X/*
X * Set image texture to apply to given component,
X * ensuring that the image that is being used is compatible.
X */
Xvoid
XImageTextSetComponent(text, component)
XImageText *text;
Xint component;
X{
X	switch (component) {
X	case COLOR: /* usual case, texture on amb, diff, spec, body */
X	case AMBIENT:
X	case DIFFUSE:
X	case SPECULAR:
X	case BODY:
X		/* all of the above can use 1 or 3 channel images */
X		if (text->image->chan != 1 && text->image->chan != 3) {
X			RLerror(RL_ABORT,
X				"Image %s must have 1 or 3 channels\n", 
X				text->image->filename);
X		}
X		break;
X	case REFLECT:
X	case TRANSP:
X	case SPECPOW:
X	case BUMP:
X	case INDEX:
X		/* the above need 1 channel images */
X		if (text->image->chan != 1) {
X			RLerror(RL_ABORT, "Image %s must have 1 channel\n",
X				text->image->filename);
X		}
X		break;
X	}
X	text->component = component;
X}
X
Xvoid
XImageTextApply(text, prim, ray, pos, norm, gnorm, surf)
XImageText *text;
XGeom *prim;
XRay *ray;
XVector *pos, *norm, *gnorm;
XSurface *surf;
X{
X	Float fx, fy;
X	Float outval[4], outval_u[4], outval_v[4];
X	Float u, v;
X	Surface tmpsurf;
X	int ix, iy;
X	int rchan, gchan, bchan;
X	Vector dpdu, dpdv, ntmp;
X
X	/*
X	 * First, find the floating point location in image coords.
X	 * Then set ix, iy to the integer location in image coords and
X	 * use fx, fy to represent the subpixel position.
X	 */
X	if (text->component == BUMP)
X		TextToUV(text->mapping, prim, pos, gnorm, &u, &v,
X			 &dpdu, &dpdv);
X	else
X		TextToUV(text->mapping, prim, pos, gnorm, &u, &v, 
X			 (Vector *)NULL, (Vector *)NULL);
X	/*
X	 * Handle tiling at this point.
X	 */
X	if (TileValue(text->tileu, text->tilev, u, v))
X		return;
X	u -= floor(u);
X	v -= floor(v);
X	fx = u * (Float) text->image->width;
X	fy = v * (Float) text->image->height;
X	ix = fx;
X	iy = fy;
X	fx = fx - (Float) ix;
X	fy = fy - (Float) iy;
X
X	if (text->image->has_alpha) {
X		/* Alpha channel is 0 */
X		rchan = 1;
X		gchan = 2;
X		bchan = 3;
X	} else {
X		rchan = 0;
X		gchan = 1;
X		bchan = 2;
X	}
X
X	if (text->image->chan == 1) {
X		gchan = rchan;
X		bchan = rchan;
X	}
X
X	ImageIndex(text->image, ix, iy, fx, fy, text->smooth, outval);
X
X	/*
X	 * escape when alpha is zero, 'cause there is no change
X	 */
X	if (text->image->has_alpha && (outval[0] < 0.001))
X		return;
X
X	if (text->component != COLOR || text->surf == (Surface *)NULL) {
X		tmpsurf = *surf;
X	} else {
X		tmpsurf = *text->surf;
X	}
X
X	switch (text->component) {
X		case COLOR: /* amb, diff, spec */
X			tmpsurf.spec.r *= outval[rchan];
X			tmpsurf.spec.g *= outval[gchan];
X			tmpsurf.spec.b *= outval[bchan];
X			tmpsurf.diff.r *= outval[rchan];
X			tmpsurf.diff.g *= outval[gchan];
X			tmpsurf.diff.b *= outval[bchan];
X			tmpsurf.amb.r *= outval[rchan];
X			tmpsurf.amb.g *= outval[gchan];
X			tmpsurf.amb.b *= outval[bchan];
X			break;
X	 	case AMBIENT: /* ambient */
X			tmpsurf.amb.r *= INTERP(outval[rchan]);
X			tmpsurf.amb.g *= INTERP(outval[gchan]);
X			tmpsurf.amb.b *= INTERP(outval[bchan]);
X			break;
X		case DIFFUSE: /* diffuse */
X			tmpsurf.diff.r *= INTERP(outval[rchan]);
X			tmpsurf.diff.g *= INTERP(outval[gchan]);
X			tmpsurf.diff.b *= INTERP(outval[bchan]);
X			break;
X		case SPECULAR: /* specular */
X			tmpsurf.spec.r *= INTERP(outval[rchan]);
X			tmpsurf.spec.g *= INTERP(outval[gchan]);
X			tmpsurf.spec.b *= INTERP(outval[bchan]);
X			break;
X		case BODY: /* transmitted */
X			tmpsurf.body.r *= INTERP(outval[rchan]);
X			tmpsurf.body.g *= INTERP(outval[gchan]);
X			tmpsurf.body.b *= INTERP(outval[bchan]);
X			break;
X		case REFLECT: /* specular reflectivity */
X			tmpsurf.reflect *= INTERP(outval[rchan]);
X			break;
X		case TRANSP: /* specular transmittance */
X			tmpsurf.transp *= INTERP(outval[rchan]);
X			break;
X		case SPECPOW: /* specpow */
X			tmpsurf.srexp *= INTERP(outval[rchan]);
X			break;
X		case INDEX: /* index of refraction */
X			tmpsurf.index *= INTERP(outval[rchan]);
X			break;
X		case BUMP: /* bump map */
X			ImageIndex(text->image, 
X				    (ix == text->image->width - 1) ? 0 : ix+1,
X				    iy, fx, fy,
X				    text->smooth, outval_u);
X			ImageIndex(text->image, ix, 
X				    (iy == text->image->height - 1) ? 0 : iy+1,
X				    fx, fy,
X				    text->smooth, outval_v);
X			MakeBump(norm, &dpdu, &dpdv, 
X				 INTERP(outval_u[rchan] - outval[rchan]),
X				 INTERP(outval_v[rchan] - outval[rchan]));
X			return;
X	}
X
X	if (text->image->has_alpha && (outval[0] < 0.999)) {
X		/*
X		 * image partial coverage means blend surf and text->surf
X		 */
X		SurfaceBlend(surf, &tmpsurf, 1. - outval[0], outval[0]);
X	} else {
X		/*
X		 * image full coverage means use text->surf
X		 */
X		*surf = tmpsurf;
X	}
X}
END_OF_FILE
if test 6113 -ne `wc -c <'libray/libtext/imagetext.c'`; then
    echo shar: \"'libray/libtext/imagetext.c'\" unpacked with wrong size!
fi
# end of 'libray/libtext/imagetext.c'
fi
echo shar: End of archive 10 \(of 19\).
cp /dev/null ark10isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 19 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
Modified: Wed Dec 11 17:00:00 1996 GMT
Page accessed 1203 times since Sat Apr 17 21:59:32 1999 GMT