#! /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/running.tex' <<'END_OF_FILE' X\chapter{Running Rayshade} X X{\Rayshade} Xcan take anywhere from seconds to weeks to render an image. The exact Xtime required is a function of the speed of the Xmachine(s) on which Xyou're working, the complexity of the scene, and how ``good'' you want Xthe final image to be. \footnote{Appendix D describes some simple Xways to accelerate the rendering process.} X XCreating a finished ray-traced image is an iterative process. Usually, many Xtest renderings are made at low resolution and with Xnon-essential features turned off. After each test image is created, Xsurface definitions might be modified, the eye or look positions may be Xslightly changed, or the intensity of a light source changed. X XThis chapter describes the basic operation of {\rayshade} and some of Xthe options that control that operation. XSetting these options properly can greatly reduce Xrendering time, improve the quality of your images, and make you a better Xperson. X X{\Rayshade} usually works as a filter, reading a description from Xthe standard input and writing Xan image file to the standard output. As it is working, {\rayshade} reports Xon the progress of the rendering by writing messages to the standard Xerror. X X\section{The Input File} X XThe scene description read by {\rayshade} consists of a number of Xkeywords, each followed by a set of arguments. These keywords can Xbe thought of as commands that direct {\rayshade} to do various things, Xsuch as create objects, set the eye's position, and change an object's Xappearance. X XMany of the keywords have related command-line options for turning Xon special features and setting values. XThese options override the values given in the input file, Xand are explained in detail in Appendix A. X X{\Rayshade} is ``case sensitive,'' which means that typing X{\tt SPHERE} or {\tt Sphere} instead of {\tt sphere} won't work. X{\Rayshade} keywords are all lower-case. Many people choose to Xcapitalize the first letter of names that they give to objects Xor surfaces in order to make then ``stand out'' in an input file. X XKeywords, numbers and strings in the input file are separated by spaces, Xtabs, or new lines (carriage returns). These ``whitespace'' characters Xare handled identically by {\rayshade}, which means that you can separate Xkeywords from keywords, key words from arguments, and arguments from Xarguments using any combination of whitespace characters that you choose. X X\begin{table} X\centering X\begin{tabular}{|c|c|l|}\hline\hline XOperator & Use & Operation \\ \hline \hline X\verb+^+ & \verb!a ^ b! & Exponentiation \\ \hline X\verb+-+ & \verb! -a ! & Negation \\ \hline X\verb+*+ & \verb!a * b! & Multiplication \\ \hline X\verb+/+ & \verb!a / b! & Division \\ \hline X\verb+%+ & \verb!a % b! & Remainder \\ \hline X\verb-+- & \verb!a + b! & Addition \\ \hline X\verb+-+ & \verb!a - b! & Subtraction \\ \hline \hline X\end{tabular} X\caption{Operators, in order of decreasing precedence.} X\label{tab:operators} X\end{table} X XNumbers may be entered directly as reals or as parenthesized expressions. XReals may be written in exponential notation if you wish, and Xintegers may be written with or without a trailing decimal point. XWhen an integer value is called for and a real is given, Xthe real value is truncated and the resulting integer is used. XTable \ref{tab:operators} lists the available operators Xavailable for use in expressions, in order of decreasing precedence. X XThe upshot of all this is that the strings X{\tt 42}, {\tt 42.}, X{\tt (20 + 22)}, and {\tt (7\verb!^!2 - 7)} mean the same thing Xto {\rayshade}. X XVariables may also be defined and used in expressions. Several Xbuilt-in functions are also provided. See Appendix B for further details. X X{\Rayshade} will automatically run the input it receives Xthrough the C preprocessor if it is available. This Xallows you to use C preprocessor directives, such as {\tt \#include}, X{\tt \#define}, and {\tt \#ifdef} when designing your input files. X XComments may be included in {\rayshade} input files by enclosing Xtext between the strings \verb!/*! and \verb!*/!, as in the C Xprogramming Xlanguage. X X\section{Images} X XThe end result of running {\rayshade} is an image file. Depending upon Xhow it was installed, {\rayshade} writes images in either the Utah Raster X{\em RLE} format or a generic but easily-manipulated {\em mtv} format Xused by Mark VandeWettering in his {\em mtv} ray tracer. The {\em mtv} Xformat consists of a header giving the resolution of the image followed Xby interleaved red-green-blue values for each pixel. The {\em RLE} format Xsupports an arbitrary number of color channels, Xan alpha channel, comments, a history field, and the ability Xto treat images as windows into a larger image. As a result of this Xflexibility, a number of {\rayshade}'s features Xare not Xsupported if the {\em mtv} format is being used. You are thus strongly Xencouraged to obtain a copy of the Utah Raster Toolkit. X XIf the {\em mtv} Xformat is used, the image will (and must) consist of three eight-bit Xcolor channels. XIf the {\em RLE} format is used, the image file consists of three Xeight-bit color channels plus an eight-bit alpha channel. {\Rayshade} Xalso documents in the {\em RLE} header the command line and {\em gamma} Xvalue used in creating the image. X XIf more than one frame is rendered, the resulting images are appended Xin turn Xto the image file. The various utilities provided by the XUtah Raster Toolkit can be used to manipulate the resulting ``movie'' Xfiles. XIf the Toolkit is not being used, you will probably need to write Xutility programs to handle the decidedly non-standard multi-image {\em mtv} Xformat files. X XBy default, {\rayshade} writes the computed image to the standard output. XThe image file may be written to a file instead by specifying a file name Xin the input stream. X X\begin{defkey}{outfile}{{\em filename}} X Write the computed image to the named file. X\end{defkey} XThe output file name may also be specified on the command line by Xusing the {\tt -O} option. X XThe size of the output image is measured in pixels. The {\em x} size Xis the number of pixels left-to-right, while the {\em y} size is Xthe number of pixels bottom-to-top. X X\begin{defkey}{screen}{{\em xsize ysize}} X Use a screen {\em xsize} pixels wide by {\em ysize} pixels high. X\end{defkey} XThe screen size may also be set on the command line through Xthe {\tt -R} option. XThe default Xscreen size is 512 by 512 pixels. X XWhen rendering an image, it is often advantageous to split the image Xinto a number of disjoint windows, each of which is rendered Xon a different machine. One then combines the images corresponding to Xthe windows into a final image. X X\begin{defkey}{window}{{\em minx maxx miny maxy}} X Render the image in the given window. X\end{defkey} XThe window must be properly Xcontained within the screen, i.e., {\em minx} and {\em miny} must Xbe greater than or equal to zero, while {\em maxx} and X{\em maxy} must be less than {\em xsize} and {\em ysize}, respectively. XThe Utah Raster tool X{\em rlecomp\/} is useful for reconstructing the full image from Xsub-images. XBy default, the window Xis equivalent to the entire screen. X XIt is also convenient to be able to render a small portion Xof the window by specifying a subregion using normalized coordinates. X X\begin{defkey}{crop}{{\em left right bottom top}} X Crop the rendering window. X\end{defkey} XThe rendering window is cropped by rendering the screen Xarea that falls within $minx + left(maxx - minx)$ and X$minx + right(maxx - minx)$ in the $X$ direction, and similarly Xfor the $Y$ direction. X{\em Left} and {\em bottom} must be greater than or equal to zero. X{\em Right} and {\em top} must be less than or equal to one. XIf {\em left} is greater than {\em right}, the two values are Xswapped, and similarly for {\em bottom} and {\em top}. X X{\em Gamma correction} may also be applied to the three output color Xchannels. See Appendix A for more details. X X\section{Statistics Reporting} X XAs it is working, {\rayshade} informs you of its progress by writing Xmessages to a ``report file''. By default, the report file is the Xstandard error. The report itself consists of a number of Xprogress report lines consisting of the number of eye rays traced, Xthe total elapsed time, and the elapsed time since the last progress report. XThe end of the report contains detailed statistics about intersection Xtests performed, the number of rays traced, and the like. X X\begin{defkey}{report}{[{\tt verbose}] [{\tt quiet}] [{\em freq}] [{\em file}]} X Specify the kind of X information included in the report and to which X file it should be written. X If {\tt verbose} is specified, the X report will also include a listing of the options selected, X the X bounding volumes of each aggregate, X and the total number of primitives in each aggregate. X {\tt quiet} causes warning X messages to be suppressed. {\em freq} specifies the frequency, X in scanlines rendered, that progress reports are made. X If given, {\em file} names a file to which the report X will be written. X\end{defkey} XBy default, a non-verbose, non-quiet report is Xwritten to the standard error once every 10 lines. XThe {\tt -V} option may also be used to direct the report to a named file. X X\section{Antialiasing} X XGiven a screen of a fixed size, creating an image is accomplished by Xsampling each pixel one or more times in order to determine what can Xbe seen ``through'' that pixel by the camera. A pixel thus covers Xa square area of the image plane, not just a single point. X XIf a pixel is not sampled at the proper rate, aliasing will result. XAliasing usually appears as ``jaggies'' or ``stair steps'' in the image. XIn order to reduce these and other artifacts, {\rayshade} provides Xan adaptive jittered antialiasing scheme that attempts to detect where Xincreased sampling rates are needed. XIn jittered sampling, the location at which a sample is taken is Xperturbed by a random amount. This perturbation reduces aliasing Xbut adds noise to the image. Appendix B describes how jittered Xtime sampling is implemented in {\rayshade}. X XThe adaptive sampling scheme implemented in {\rayshade} begins Xby sampling each pixel on the current scanline once. XFor each pixel on the scanline, the contrast between it and its Xfour immediate neighbors is computed. If this contrast is greater Xthan a user-specified maximum in any color channel, Xthe pixel and its Xneighbors are all supersampled by firing an additional X{$numsamples^2 -1$} rays through those pixels that have not already been Xsupersampled. This process is repeated for the current scanline Xuntil a pass is made without any Xpixel being supersampled. X X\begin{defkey}{contrast}{{\em redcont greencont bluecont}} X Set the maximum allowed contrast between four color X samples when adaptive supersampling is used. X The contrast test is applied to each color X channel separately. X\end{defkey} XThe default maximum contrast values for the red, green, and blue Xchannels are 0.25, 0.2, and 0.4, respectively. X X\begin{defkey}{sample}{{\em n} [{\tt nojitter}]} X Use $n^{2} $ samples when performing jittered X sampling. The maximum legal value is 5. X If {\tt nojitter} is specified, sample locations X and times will not be jittered. X\end{defkey} XBy default, $3^{2}$ jittered samples are taken. X XA given set of sample values must be filtered Xin order to Xassign a color to a pixel. Ideally, when performing filtering Xfor a specific pixel, Xthe filter will consider samples from neighboring regions. In X{\rayshade}, the filtering applied to a pixel makes use of samples Xtaken for that pixel alone. However, one may increase the size Xof the filter that is applied in order to approximate the results Xa more robust filtering scheme. X X\begin{defkey}{filter}{{\em type} [{\em width}]} X Use the indicated filter type with the given width, X in pixels. X Supported filter types are {\tt gauss} (Gaussian) X and {\tt box} (the default). X\end{defkey} XThe default filter width is 1.0 for a box filter, 1.8 for a Gaussian Xfilter. The filter and pixel centers always coincide. XWhen sampling a pixel, samples are taken over the area of Xthe pixel filter, which is not necessarily the same as the area Xof the pixel itself. X XJittered sampling is used in {\rayshade} to sample extended light Xsources as well. A total of $samples^2$ samples are taken of Xeach extended light source in order to determine the extent of shadowing. X X\section{The Ray Tree} X XWhen ray tracing a scene, reflected or transmitted rays may strike Xother reflective or transparent objects. Further reflected or Xtransmitted rays will be spawned, and so on. Taken together, such Xa family of rays is termed the {\em ray tree}. Care must be taken Xto control the depth of this tree: If it is allowed to grow too deeply, Xone may spend a great deal of time computing rays that contribute little Xto the final picture; if it is not allowed to grow far enough, this Xpremature tree pruning may be evident in the image. X X{\Rayshade} provides two complementary methods for controlling the depth Xof the ray tree. One method sets an absolute maximum for the tree. The Xother allows one to adaptively prune a tree as it grows so that ``unimportant'' Xrays are not spawned. X X\begin{defkey}{maxdepth}{{\em level}} X Do not spawn rays deeper than those at the given {\em level}. X\end{defkey} XRays from the eye are of depth zero. The default value for X{\em level} is 15. XThis depth may also be set from the command line through the {\tt -D} option. X X\begin{defkey}{cutoff}{{\em threshold}} X Do not spawn rays whose contribution to the final color of X the eye ray is less than {\em threshold} for each color channel. X Threshold may be given as a single floating-point value, X or as a red-green-blue triple. X\end{defkey} XThe default value is 0.002. This threshold may also be set from Xthe command line through the {\tt -T} option. END_OF_FILE if test 13825 -ne `wc -c <'Doc/Guide/running.tex'`; then echo shar: \"'Doc/Guide/running.tex'\" unpacked with wrong size! fi # end of 'Doc/Guide/running.tex' fi if test -f 'Doc/Guide/texture.tex' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Doc/Guide/texture.tex'\" else echo shar: Extracting \"'Doc/Guide/texture.tex'\" \(13148 characters\) sed "s/^X//" >'Doc/Guide/texture.tex' <<'END_OF_FILE' X\chapter {Texturing} X XTextures are used to modify the appearance of an object through the Xuse of procedural functions. A texture may modify any surface characteristic, Xsuch as diffuse color, reflectivity, or transparency, or it may Xmodify the surface normal (``bump mapping'') in order to give the Xappearance of a rough surface. X XAny number of textures may be associated with an object. If more than Xone texture is specified, they are applied in the order given. This allows Xone to compose texturing functions and create, for example Xa tiled marble ground plane using the {\em checker} and {\em marble} Xtextures. X XTextures are associated with objects by following the object specification Xby a number of lines of the form: X X\begin{center} X{\tt texture} {\em name} $<${\em Texturing Arguments}$>$ [{\em Transformations}] X\end{center} X XTransformations may be applied to the texture in order to, for example, Xshrink or grow feature size, change the orientation of features, and Xchange the position of features. X XSeveral of the texturing functions take the name of a colormap as an Xargument. A colormap is 256-line ASCII file, with each line containing Xthree space-separated values ranging from 0 to 255. Each line gives Xthe red, green, and blue values for a single entry in the colormap. X X\section {Texturing Functions} X X\begin{defkey}{blotch}{{\em BlendFactor surface}} XProduces a mildly interesting blotchy-looking surface. X{\em BlendFactor} is used to control the interpolation between Xthe default surface characteristics and the characteristics of Xthe given surface. A value of 0 results in a roughly 50-50 mix Xof the two surfaces. Higher values result in a great portion of Xthe default surface characteristics. X\end{defkey} X X\begin{defkey}{bump}{{\em scale}} XApply a random bump map. The point of intersection is passed to X{\em DNoise()}. XThe returned normalized vector is weighted by {\em scale} Xand the result is added to the normal vector at the point of intersection. X\end{defkey} XUsing an image texture applied to the ``bump'' component offers a more Xdirect way to control the modification of surface normals (see below). X X\begin{defkey}{checker}{$<${\em Surface}$>$} XApplies a 3D checkerboard texture. Every point that falls within an X``even'' unit cube will be assigned the characteristics of the named surface Xapplied to it, while points that fall within ``odd'' cubes will have Xits usual surface characteristics. Be wary of strange effects due Xto roundoff error that occur when a planar checkered surface lies Xin a plane of constant integral value (e.g., $z=0$) in texture space. XIn such cases, Xsimply translate the texture to ensure that the planar surface is not Xcoincident with an integral plane in texture space X(e.g., {\tt translate 0 0 0.1}). X\end{defkey} X X\begin{defkey}{cloud}{{\em scale H $\lambda$ octaves cthresh lthresh tscale}} X This texture is a variant on Geoff Gardner's ellipsoid-texturing X algorithm. It should be applied to unit spheres centered X at the origin. These spheres may, of course, be transformed X at will to form the appropriately-shaped cloud or tree. X X A sample of normalized {\em fBm} (see the {\em fbm} texture) is X generated X at the point of intersection. This sample is used to X modulate the surface transparency. The final transparency X if a function of the sample value, the X the proximity of the point of intersection to the edge of X the sphere (as seen from the ray origin), and three parameters X to control the overall ``density.'' The proximity of the point X to the sphere edge is determined by evaluating a {\em limb} function, X which varies from 0 on the limb to 1 at the center of the sphere. X\[ Xtransp = 1. - \frac{fBm - cthresh - (lthresh - cthresh)(1 - limb)}{tscale} X\] X\end{defkey} X X\begin{defkey}{fbm}{{\em offset scale H $\lambda$ octaves thresh} X[{\em colormap}]} XGenerate a sample of discretized fractional Brownian motion (fBm) and Xuses it to scale the diffuse and ambient component of an object's surface. X{\em Scale} is used to scale the value Xreturned by the fBm function. {\em Offset} allows one to control the minimum Xvalue of the fBm function. {\em H} is the {\em Holder exponent} Xused in the fBm function (a value of 0.5 works well). $\lambda$ is Xused to control {\em lacunarity}, and specifies the the frequency Xdifference between successive samples of the fBm basis function (a Xvalue of 2.0 will suffice). {\em Octaves} specifies the number of Xoctaves (samples) to take of the fBm basis function (in this case, Noise()). XBetween five and seven octaves usually works well. {\em Thresh} is used Xto specify a lower bound onthe output of the fBm function. Any Xvalue lower than {\em thresh} is set to zero. X XIf a {\em colormap} is named, a 256-entry colormap is read from the named Xfile, and the sample of fBm is scaled by 255 and is used as an index into Xthe colormap. The resulting colormap entry Xis used to scale the ambient and diffuse components of the Xobject's surface. X\end{defkey} X X\begin{defkey}{fbmbump}{{\em offset scale H $\lambda$ octaves}} XSimilar to the {\em fbm} texture. Rather than modifying the color of Xa surface, this texture acts as a bump map. X\end{defkey} X X\begin{defkey}{gloss}{{\em glossiness}} XGives reflective surfaces a glossy appearance. This texture perturbs Xthe object's surface normal such that the normal ``samples'' a cone of Xunit height with radius $1. - glossiness$. A value of 1 results Xin perfect mirror-like reflections, while a value of 0 results Xin extremely fuzzy reflections. For best results, jittered sampling Xshould be used to render scenes that make use of this texture. X\end{defkey} X X\begin{defkey}{marble}{[{\em colormap}]} XGives a surface a marble-like appearance. The texture is implemented as Xroughly parallel alternating veins of marble, each of which is Xseparated by 1/7 of a unit and runs perpendicular to the Z axis. XIf a colormap is named, the surface's ambient and diffuse colors Xwill be scaled using the RGB values in the colormap. If no colormap is Xgiven, the diffuse and ambient components are simply scaled by the Xvalue of the marble function. One may transform the texture to Xcontrol the density and orientation of the marble veins. X\end{defkey} X X\begin{defkey}{sky}{{\em scale H $\lambda$ octaves cthresh ltresh}} X Similar to the {\em fbm} texture. Rather than modifying the X color of a surface, this texture modulates its transparency. X {\em cthresh} is the value of the {\em fBm} function above X which the surface is totally opaque. Below {\em lthresh}, X the surface is totally transparent. X\end{defkey} X X\begin{defkey}{stripe}{$<${\em Surface}$>$ {\em size bump} $<$Mapping$>$} X Apply a ``raised'' stripe pattern to the surface. X The surface properties used to color the stripe are those X of the given surface. The width of the stripe, as compared X to the unit interval, is given by {\em size}. The magnitude X of {\em bump} controls the extent to which the bump appears X to be displaced from the rest of the surface. If negative, X the stripe will appear to X sink into the surface; if positive, it will appear to stand X out of the surface. X\end{defkey} XMapping functions are described below. X X\begin{defkey}{wood}{} XGives a surface a wood-like appearance. The feature size of this texture Xis approximately $0.01$ of a unit, making it often necessary to Xscale the texture in order to achieve the desired appearance. X\end{defkey} X X\section {Image Texturing} X X{\Rayshade} also supports an {\tt image} texture. This texture Xallows you to use images to modify the characteristics of a surface. You Xcan use three-channel images to modify the any or all of Xthe ambient, diffuse, and specular colors of a surface. XIf you are using the Utah Raster Toolkit, Xyou can also use single-channel images to modify surface reflectance, Xtransparency, and the specular exponent. You can also use a single-channel Ximage to apply a bump map to a surface. X XIn all but the bump-mapping case, Xa component is modified by multiplying the given value by the value Xcomputed by the texturing function. When using the Utah Raster Toolkit, Xsurface characteristics are modified in proportion to the value of Xthe {\em alpha} channel in the image. If there is no {\em alpha} channel, Xor you are not using the Utah Raster Toolkit, {\em alpha} is assumed to be Xeverywhere Xequal to $1$. X X\begin{defkey}{component}{$<${\em Component}$>$} X The named component will be modified. X\end{defkey} XPossible surface components are: X{\tt ambient} (modify ambient color), X{\tt diffuse} (modify diffuse color), X{\tt specular} (modify specular color), X{\tt specpow}, (modify specular exponent), X{\tt reflect}, (modify reflectivity), X{\tt transp} (modify transparency), X{\tt bump}, (modify surface normal). XThe {\tt specpow}, {\tt reflect}, {\tt transp}, and {\tt bump} Xcomponents require the use of a single-channel image. X X\begin{defkey}{range}{{\em high low}} X Specify the range of values to which the values in the X image should be mapped. An value of $1$ will X be mapped {\em high}, $0$ to {\em low}. Intermediate X values will be linearly interpolated. X\end{defkey} X X\begin{defkey}{smooth}{} X When given, pixel averaging will be performed in order X to smooth the sampled image. If not specified, no averaging X will occur. X\end{defkey} X X\begin{defkey}{textsurf}{$<${\em Surface Specification}$>$} X For use when modifying surface colors, this keyword specifies X that the given surface should be used as the base X to be modified when the {\em alpha} value in the image X is non-zero. When {\em alpha} is zero, the object's X unmodified default surface characteristics are retained. X\end{defkey} XThe usual behavior is for the object's default surface properties to Xbe used. X X\begin{defkey}{tile}{{\em un vn}} X Specify how the image should be tiled (repeated) along the X $u$ and $v$ axes. X If positive, the value of {\em un} gives the number of X times the image should be repeated along the $u$ axis, starting X from the origin of the texture, and positive {\em vn} gives the X number of times it X should be repeated along the $v$ axis. If either value is zero, X the image is repeated infinitely along the appropriate axis. X\end{defkey} XTiling is usually only a concern when planar mapping is being used, Xthough it may also be used if image textures are being scaled. By default X{\em un} and {\em vn} are both zero. X X XA mapping function may also be associated with an image texture. X X\section {Mapping Functions} X XMapping functions are used to apply two-dimensional textures to Xsurfaces. Each mapping functions defines a different method of transforming Xa three dimensional point of intersection to a two dimensional $u-v$ pair Xtermed texturing coordinates. XTypically, the arguments to a mapping method define a center of Xa projection and two non-parallel axes that define a local coordinate system. X XThe default mapping method is termed $u-v$ mapping or {\em inverse mapping}. XNormally, there is a different inverse mapping method for each primitive type X(see chapter 5). XWhen inverse mapping is used, the point of intersection is passed to Xthe $uv$ method for the primitive that was hit. X X\begin{defkey}{map}{{\tt uv}} X Use the $uv$ (inverse mapping) method associated with the X object that was intersected in order to map from 3D to determine X texturing coordinates. X\end{defkey} XThe inverse mapping method for each primitive is described in Chapter 5. X X\begin{defkey}{map}{{\tt planar} [\evec{origin} \evec{vaxis} \evec{uaxis}]} X Use a planar mapping method. The 2D texture is transformed X so that its $u$ axis is given by \evec{uaxis} and its $v$ X axis by $vaxis$. The texture is projected along the vector X defined by the cross product of the $u$ and $v$ axes, with X the (0,0) in texture space mapped to \evec{origin}. X\end{defkey} X X\begin{defkey}{map}{{\tt cylindrical} [\evec{origin} \evec{vaxis} \evec{uaxis}]} X Use a cylindrical mapping method. The point of intersection X is projected onto an imaginary cylinder, and the location X of the projected point is used to determine the texture coordinates. X If given, \evec{origin} and X \evec{vaxis} define the cylinder's axis, and \evec{uaxis} defines X where $u=0$ is located. X\end{defkey} XSee the description of the inverse mapping method for the Xcylinder in Chapter 5. By default, the point of intersection is Xprojected onto a cylinder that runs through the origin along the $z$ Xaxis, with \evec{uaxis} equal to the $x$ axis. X X\begin{defkey}{map}{{\tt spherical} [\evec{origin} \evec{vaxis} \evec{uaxis}]} X Use a spherical mapping method. The intersection point is X projected onto an imaginary sphere, and the location of the X projected point is used to determine the texturing coordinates X in a manner identical to that used in the inverse mapping method X for the sphere primitive. X If given, the center of X the projection is \evec{origin}, \evec{vaxis} defines X the sphere axis, and the point where the X non-parallel \evec{uaxis} intersects the sphere X defines where $u=0$ is located. X\end{defkey} XBy default, a spherical mapping projects points towards the origin, Xwith \evec{vaxis} defined to be the $z$ axis and X\evec{uaxis} defined to be the $x$ axis. END_OF_FILE if test 13148 -ne `wc -c <'Doc/Guide/texture.tex'`; then echo shar: \"'Doc/Guide/texture.tex'\" unpacked with wrong size! fi # end of 'Doc/Guide/texture.tex' fi if test -f 'libray/libobj/triangle.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'libray/libobj/triangle.c'\" else echo shar: Extracting \"'libray/libobj/triangle.c'\" \(12047 characters\) sed "s/^X//" >'libray/libobj/triangle.c' <<'END_OF_FILE' X/* X * triangle.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: triangle.c,v 4.0.1.1 91/09/29 15:47:11 cek Exp Locker: cek $ X * X * $Log: triangle.c,v $ X * Revision 4.0.1.1 91/09/29 15:47:11 cek X * patch1: Potential roundoff problem in dPdU code. X * X * Revision 4.0 91/07/17 14:39:38 kolb X * Initial version. X * X */ X#include "geom.h" X#include "triangle.h" X Xstatic Methods *iTriangleMethods = NULL; Xstatic char triName[] = "triangle"; X Xunsigned long TriTests, TriHits; X Xstatic void TriangleSetdPdUV(); X X/* X * Create and return reference to a triangle. X */ XTriangle * XTriangleCreate(type, p1, p2, p3, n1, n2, n3, u1, u2, u3, flipflag) Xint type; XVector *p1, *p2, *p3, *n1, *n2, *n3; XVec2d *u1, *u2, *u3; Xint flipflag; X{ X Triangle *triangle; X Vector ptmp, anorm; X Float d; X X /* X * Allocate new triangle and primitive to point to it. X */ X triangle = (Triangle *)share_malloc(sizeof(Triangle)); X triangle->type = type; /* so inttri can tell the difference */ X X VecSub(*p2, *p1, &triangle->e[0]); X VecSub(*p3, *p2, &triangle->e[1]); X VecSub(*p1, *p3, &triangle->e[2]); X X /* Find plane normal. */ X VecCross(&triangle->e[0], &triangle->e[1], &ptmp); X triangle->nrm = ptmp; X if (VecNormalize(&triangle->nrm) == 0.) { X RLerror(RL_ADVISE, "Degenerate triangle.\n"); X return (Triangle *)NULL; X } X X if (flipflag) X VecScale(-1, triangle->nrm, &triangle->nrm); X X triangle->d = dotp(&triangle->nrm, p1); X X triangle->p[0] = *p1; X triangle->p[1] = *p2; X triangle->p[2] = *p3; X X if (type == PHONGTRI) { X if (VecNormalize(n1) == 0. || VecNormalize(n2) == 0. || X VecNormalize(n3) == 0.) { X RLerror(RL_WARN, "Degenerate vertex normal.\n"); X return (Triangle *)NULL; X } X triangle->vnorm = (Vector *)Malloc(3 * sizeof(Vector)); X triangle->vnorm[0] = *n1; X triangle->vnorm[1] = *n2; X triangle->vnorm[2] = *n3; X if (flipflag) { X /* Flip the vertex normals */ X VecScale(-1, triangle->vnorm[0], X &triangle->vnorm[0]); X VecScale(-1, triangle->vnorm[1], X &triangle->vnorm[1]); X VecScale(-1, triangle->vnorm[2], X &triangle->vnorm[2]); X } else if (dotp(&triangle->vnorm[0], &triangle->nrm) < 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 * Note that this means that we trust the vertex X * normals rather than trust that the user gave the X * vertices in the correct order. X */ X RLerror(RL_ADVISE, "Inconsistant triangle normals.\n"); X VecScale(-1., triangle->nrm, &triangle->nrm); X VecScale(-1., ptmp, &ptmp); X triangle->d = -triangle->d; X VecScale(-1., triangle->e[0], &triangle->e[0]); X VecScale(-1., triangle->e[1], &triangle->e[1]); X VecScale(-1., triangle->e[2], &triangle->e[2]); X } X } X X /* X * If UV coordinates are given for the vertices, allocate and X * store them. X */ X if (u1 && u2 && u3) { X triangle->uv = (Vec2d *)Malloc(3 * sizeof(Vec2d)); X triangle->uv[0] = *u1; X triangle->uv[1] = *u2; X triangle->uv[2] = *u3; X /* Calculate dpdu and dpdv vectors */ X triangle->dpdu = (Vector *)Malloc(sizeof(Vector)); X triangle->dpdv = (Vector *)Malloc(sizeof(Vector)); X TriangleSetdPdUV(triangle->p, triangle->uv, X triangle->dpdu, triangle->dpdv); X } else { X triangle->uv = (Vec2d *)NULL; X } X X /* X * Find "dominant" part of normal vector. X */ X anorm.x = fabs(ptmp.x); X anorm.y = fabs(ptmp.y); X anorm.z = fabs(ptmp.z); X X /* X * Scale edges by dominant part of normal. This makes intersection X * testing a bit faster. X */ X if (anorm.x > anorm.y && anorm.x > anorm.z) { X triangle->index = XNORMAL; X d = 1. / ptmp.x; X } else if (anorm.y > anorm.z) { X triangle->index = YNORMAL; X d = 1. / ptmp.y; X } else { X triangle->index = ZNORMAL; X d = 1. /ptmp.z; X } X X VecScale(d, triangle->e[0], &triangle->e[0]); X VecScale(d, triangle->e[1], &triangle->e[1]); X VecScale(d, triangle->e[2], &triangle->e[2]); X X return triangle; X} X XMethods * XTriangleMethods() X{ X if (iTriangleMethods == (Methods *)NULL) { X iTriangleMethods = MethodsCreate(); X iTriangleMethods->create = (GeomCreateFunc *)TriangleCreate; X iTriangleMethods->methods = TriangleMethods; X iTriangleMethods->name = TriangleName; X iTriangleMethods->intersect = TriangleIntersect; X iTriangleMethods->normal = TriangleNormal; X iTriangleMethods->uv = TriangleUV; X iTriangleMethods->bounds = TriangleBounds; X iTriangleMethods->stats = TriangleStats; X iTriangleMethods->checkbounds = TRUE; X iTriangleMethods->closed = FALSE; X } X return iTriangleMethods; X} X X/* X * Intersect ray with triangle. This is an optimized version of the X * intersection routine from Snyder and Barr's '87 SIGGRAPH paper. X */ Xint XTriangleIntersect(tri, ray, mindist, maxdist) XTriangle *tri; XRay *ray; XFloat mindist, *maxdist; X{ X Float qi1, qi2, s, k, b0, b1, b2; X Vector pos, dir; X X TriTests++; X pos = ray->pos; X dir = ray->dir; X /* X * Plane intersection. X */ X k = dotp(&tri->nrm, &dir); X if (fabs(k) < EPSILON) X return FALSE; X s = (tri->d - dotp(&tri->nrm, &pos)) / k; X if (s < mindist || s > *maxdist) X return FALSE; X X if (tri->index == XNORMAL) { X qi1 = pos.y + s * dir.y; X qi2 = pos.z + s * dir.z; X b0 = tri->e[1].y * (qi2 - tri->p[1].z) - X tri->e[1].z * (qi1 - tri->p[1].y); X if (b0 < 0. || b0 > 1.) X return FALSE; X b1 = tri->e[2].y * (qi2 - tri->p[2].z) - X tri->e[2].z * (qi1 - tri->p[2].y); X if (b1 < 0. || b1 > 1.) X return FALSE; X b2 = tri->e[0].y * (qi2 - tri->p[0].z) - X tri->e[0].z * (qi1 - tri->p[0].y); X if (b2 < 0. || b2 > 1.) X return FALSE; X } else if (tri->index == YNORMAL) { X qi1 = pos.x + s * dir.x; X qi2 = pos.z + s * dir.z; X b0 = tri->e[1].z * (qi1 - tri->p[1].x) - X tri->e[1].x * (qi2 - tri->p[1].z); X if (b0 < 0. || b0 > 1.) X return FALSE; X b1 = tri->e[2].z * (qi1 - tri->p[2].x) - X tri->e[2].x * (qi2 - tri->p[2].z); X if (b1 < 0. || b1 > 1.) X return FALSE; X b2 = tri->e[0].z * (qi1 - tri->p[0].x) - X tri->e[0].x * (qi2 - tri->p[0].z); X if (b2 < 0. || b2 > 1.) X return FALSE; X } else { X qi1 = pos.x + s * dir.x; X qi2 = pos.y + s * dir.y; X b0 = tri->e[1].x * (qi2 - tri->p[1].y) - X tri->e[1].y * (qi1 - tri->p[1].x); X if (b0 < 0. || b0 > 1.) X return FALSE; X b1 = tri->e[2].x * (qi2 - tri->p[2].y) - X tri->e[2].y * (qi1 - tri->p[2].x); X if (b1 < 0. || b1 > 1.) X return FALSE; X b2 = tri->e[0].x * (qi2 - tri->p[0].y) - X tri->e[0].y * (qi1 - tri->p[0].x); X if (b2 < 0. || b2 > 1.) X return FALSE; X } X X tri->b[0] = b0; X tri->b[1] = b1; X tri->b[2] = b2; X X TriHits++; X *maxdist = s; X return TRUE; X} X Xint XTriangleNormal(tri, pos, nrm, gnrm) XTriangle *tri; XVector *pos, *nrm, *gnrm; X{ X *gnrm = tri->nrm; X X if (tri->type == FLATTRI) { X *nrm = tri->nrm; X return FALSE; X } X X /* X * Interpolate normals of Phong-shaded triangles. X */ 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 (void)VecNormalize(nrm); X return TRUE; X} X X/*ARGSUSED*/ Xvoid XTriangleUV(tri, pos, norm, uv, dpdu, dpdv) XTriangle *tri; XVector *pos, *norm, *dpdu, *dpdv; XVec2d *uv; X{ X Float d; X X /* X * Normalize barycentric coordinates. X */ X d = tri->b[0]+tri->b[1]+tri->b[2]; X X tri->b[0] /= d; X tri->b[1] /= d; X tri->b[2] /= d; X X if (dpdu) { X if (tri->uv == (Vec2d *)NULL) { X *dpdu = tri->e[0]; X (void)VecNormalize(dpdu); X VecSub(tri->p[0], *pos, dpdv); X (void)VecNormalize(dpdv); X } else { X *dpdu = *tri->dpdu; X *dpdv = *tri->dpdv; X } X } X X if (tri->uv == (Vec2d *)NULL) { X uv->v = tri->b[2]; X if (equal(uv->v, 1.)) X uv->u = 0.; X else X uv->u = tri->b[1] / (tri->b[0] + tri->b[1]); X } else { X /* X * Compute UV by taking weighted sum of UV coordinates. X */ X uv->u = tri->b[0]*tri->uv[0].u + tri->b[1]*tri->uv[1].u + X tri->b[2]*tri->uv[2].u; X uv->v = tri->b[0]*tri->uv[0].v + tri->b[1]*tri->uv[1].v + X tri->b[2]*tri->uv[2].v; X } X} X Xvoid XTriangleBounds(tri, bounds) XTriangle *tri; XFloat bounds[2][3]; X{ X bounds[LOW][X] = bounds[HIGH][X] = tri->p[0].x; X bounds[LOW][Y] = bounds[HIGH][Y] = tri->p[0].y; X bounds[LOW][Z] = bounds[HIGH][Z] = tri->p[0].z; X X if (tri->p[1].x < bounds[LOW][X]) bounds[LOW][X] = tri->p[1].x; X if (tri->p[1].x > bounds[HIGH][X]) bounds[HIGH][X] = tri->p[1].x; X if (tri->p[2].x < bounds[LOW][X]) bounds[LOW][X] = tri->p[2].x; X if (tri->p[2].x > bounds[HIGH][X]) bounds[HIGH][X] = tri->p[2].x; X X if (tri->p[1].y < bounds[LOW][Y]) bounds[LOW][Y] = tri->p[1].y; X if (tri->p[1].y > bounds[HIGH][Y]) bounds[HIGH][Y] = tri->p[1].y; X if (tri->p[2].y < bounds[LOW][Y]) bounds[LOW][Y] = tri->p[2].y; X if (tri->p[2].y > bounds[HIGH][Y]) bounds[HIGH][Y] = tri->p[2].y; X X if (tri->p[1].z < bounds[LOW][Z]) bounds[LOW][Z] = tri->p[1].z; X if (tri->p[1].z > bounds[HIGH][Z]) bounds[HIGH][Z] = tri->p[1].z; X if (tri->p[2].z < bounds[LOW][Z]) bounds[LOW][Z] = tri->p[2].z; X if (tri->p[2].z > bounds[HIGH][Z]) bounds[HIGH][Z] = tri->p[2].z; X} X Xchar * XTriangleName() X{ X return triName; X} X Xvoid XTriangleStats(tests, hits) Xunsigned long *tests, *hits; X{ X *tests = TriTests; X *hits = TriHits; X} X X/* X * Given three vertices of a triangle and the uv coordinates associated X * with each, compute directions of u and v axes. X */ Xstatic void XTriangleSetdPdUV(p, t, dpdu, dpdv) XVector p[3]; /* Triangle vertices */ XVec2d t[3]; /* uv coordinates for each vertex */ XVector *dpdu, *dpdv; /* u and v axes (return values) */ X{ X Float scale; X int hi, mid, lo; X Vector base; X X /* sort u coordinates */ X if (t[2].u > t[1].u) { X if (t[1].u > t[0].u) { X hi = 2; mid = 1; lo = 0; X } else if (t[2].u > t[0].u) { X hi = 2; mid = 0; lo = 1; X } else { X hi = 0; mid = 2; lo = 1; X } X } else { X if (t[2].u > t[0].u) { X hi = 1; mid = 2; lo = 0; X } else if (t[1].u > t[0].u) { X hi = 1; mid = 0; lo = 2; X } else { X hi = 0; mid = 1; lo = 2; X } X } X if (fabs(t[hi].u - t[lo].u) < EPSILON) { X /* degenerate axis */ X dpdv->x = dpdv->y = dpdv->z = 0.; X } else { X /* X * Given u coordinates of vertices forming the X * 'long' edge, find where 'middle' X * vertex falls on that edge given its u coordinate. X */ X scale = (t[mid].u - t[lo].u) / (t[hi].u - t[lo].u); X VecComb(1.0 - scale, p[lo], scale, p[hi], &base); X /* X * v axis extends from computed basepoint to X * middle vertex -- but in which direction? X */ X if (t[mid].v < ((1.0 - scale)*t[lo].v + scale*t[hi].v)) X VecSub(base, p[mid], dpdv); X else X VecSub(p[mid], base, dpdv); X (void)VecNormalize(dpdv); X } X X /* sort v coordinates */ X if (t[2].v > t[1].v) { X if (t[1].v > t[0].v) { X hi = 2; mid = 1; lo = 0; X } else if (t[2].v > t[0].v) { X hi = 2; mid = 0; lo = 1; X } else { X hi = 0; mid = 2; lo = 1; X } X } else { X if (t[2].v > t[0].v) { X hi = 1; mid = 2; lo = 0; X } else if (t[1].v > t[0].v) { X hi = 1; mid = 0; lo = 2; X } else { X hi = 0; mid = 1; lo = 2; X } X } X if (fabs(t[hi].v - t[lo].v) < EPSILON) { X /* degenerate axis */ X dpdu->x = dpdu->y = dpdu->z = 0.; X } else { X /* X * Given v coordinates of vertices forming the X * 'long' edge, find where 'middle' X * vertex falls on that edge given its v coordinate. X */ X scale = (t[mid].v - t[lo].v) / (t[hi].v - t[lo].v); X VecComb(1.0 - scale, p[lo], scale, p[hi], &base); X /* X * u axis extends from computed basepoint to X * middle vertex -- but in which direction? X */ X if (t[mid].u < ((1.0 - scale)*t[lo].u + scale*t[hi].u)) X VecSub(base, p[mid], dpdu); X else X VecSub(p[mid], base, dpdu); X (void)VecNormalize(dpdu); X } X} X Xvoid XTriangleMethodRegister(meth) XUserMethodType meth; X{ X if (iTriangleMethods) X iTriangleMethods->user = meth; X} END_OF_FILE if test 12047 -ne `wc -c <'libray/libobj/triangle.c'`; then echo shar: \"'libray/libobj/triangle.c'\" unpacked with wrong size! fi # end of 'libray/libobj/triangle.c' fi echo shar: End of archive 15 \(of 19\). cp /dev/null ark15isdone 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