home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-07-21 | 45.7 KB | 1,619 lines |
- Newsgroups: comp.sources.misc
- From: Rayshade Construction Co. <rayshade@weedeater.math.YALE.EDU>
- Subject: v21i016: rayshade - A raytracing package for UNIX, Part13/19
- Message-ID: <1991Jul21.033819.29294@sparky.IMD.Sterling.COM>
- X-Md4-Signature: 53f3ff77cd6fa10e38fc8bd025d16e01
- Date: Sun, 21 Jul 1991 03:38:19 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: Rayshade Construction Co. <rayshade@weedeater.math.YALE.EDU>
- Posting-number: Volume 21, Issue 16
- Archive-name: rayshade/part13
- Environment: UNIX, !16BIT
-
- #! /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 13 (of 19)."
- # Contents: Doc/Guide/surfaces.tex libray/libcommon/transform.c
- # libray/libobj/csg.c libshade/shade.c
- # Wrapped by kolb@woody on Wed Jul 17 17:56:52 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'Doc/Guide/surfaces.tex' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Doc/Guide/surfaces.tex'\"
- else
- echo shar: Extracting \"'Doc/Guide/surfaces.tex'\" \(10193 characters\)
- sed "s/^X//" >'Doc/Guide/surfaces.tex' <<'END_OF_FILE'
- X\chapter{Surfaces and Atmospheric Effects}
- X
- XSurfaces are used to control the interaction between light sources and
- Xobjects. A surface specification consists of information
- Xabout how the light interacts with both the exterior and
- Xinterior of an object .
- XFor non-closed objects, such as polygons,
- Xthe ``interior'' of an object is the ``other side'' of the object's surface
- Xrelative to the origin of a ray.
- X
- XRayshade usually ensures that a primitive's surface normal is pointing
- Xtowards the origin of the incident ray when performing shading
- Xcalculations. Exceptions to this rule are transparent primitives, for
- Xwhich rayshade uses the direction of the surface normal to determine if
- Xthe incident ray is entering or exiting the object.
- XAll non-transparent primitives will, in effect, be double-sided.
- X
- X\section{Surface Description}
- X
- XA surface definition consists of a number of component keywords, each
- Xof which is usually followed by either a single number or a red-green-blue
- Xcolor triple. Each of the values in the color triple are normalized,
- Xwith zero indicating zero intensity, and one indicating full intensity.
- X
- XIf any surface component is left unspecified, its value defaults to zero,
- Xwith the exception of the index of refraction, which is assigned the
- Xdefault index of refraction (normally 1.0).
- X
- XSurface descriptions are used in rayshade to compute the color of a ray
- Xthat strikes the surface at a point \evec{P}. The normal to the surface
- Xat \evec{P}, \evec{N}, is also computed.
- X
- X\begin{defkey}{ambient}{\evec{color}}
- X Use the given {\em color} to approximate those surface-surface
- X interactions (e.g., diffuse interreflection) not modeled by the
- X ray tracing process.
- X\end{defkey}
- XA surface's ambient color is always applied to a ray. The color
- Xapplied is computed by multiplying the ambient color by the intensity
- Xof the ambient light source.
- X
- XIf \evec{P} is in shadow with respect to a given light source,
- Xthat light source makes no contribution to the shading of \evec{P}.
- X
- X\begin{defkey}{diffuse}{\evec{color}}
- X Specifies the diffuse color.
- X\end{defkey}
- XThe diffuse contribution from each non-shadowed light source at \evec{P}
- Xis equal to the diffuse color of the surface scaled by the cosine of
- Xthe angle between \evec{N}
- Xand the vector from \evec{P} to the light source.
- X
- X\begin{defkey}{specular}{\evec{color}}
- X Specifies the base color of specular reflections.
- X\end{defkey}
- X
- X\begin{defkey}{specpow}{{\em exponent}}
- X Specifies the specular highlight) exponent.
- X\end{defkey}
- XThe intensity of specular highlights from light sources are
- Xscaled by the specular color of the surface.
- X
- X\begin{defkey}{reflect}{{\em reflectivity}}
- X Specifies the specular reflectivity of the surface. If non-zero,
- X reflected rays will be spawned.
- X\end{defkey}
- XThe intensity of specularly reflected rays will be proportional to
- Xthe specular color of the surface scaled by the reflectivity.
- X
- X\begin{defkey}{transp}{{\em transparency}}
- X Specifies the specular transmissivity of the surface. If
- X non-zero,
- X transmitted (refracted) rays will be spawned.
- X\end{defkey}
- X
- X\begin{defkey}{body}{\evec{color}}
- X Specifies the body color of the object. The body color
- X affects the color of rays that are transmitted through the
- X object.
- X\end{defkey}
- X
- X\begin{defkey}{extinct}{{\em coefficient}}
- X Specifies the extinction coefficient of the interior
- X of the object.
- X\end{defkey}
- XThe extinction coefficient is raised to a power equal to the distance
- Xthe transmitted ray travels through the object.
- XThe overall intensity of specularly transmitted rays will be proportional to
- Xthis factor multiplied by the surface's body color
- Xmultiplied by the transparency of the object.
- X
- X\begin{defkey}{index}{{\em N}}
- X Specifies the index of refraction. The default value is equal
- X to the index of refraction of the atmosphere surrounding the eye.
- X\end{defkey}
- X
- X\begin{defkey}{translucency}{{\em translu} \evec{color} {\em stexp}}
- X Specifies the translucency, diffusely transmitted color,
- X and Phong exponent for transmitted specular highlights.
- X\end{defkey}
- XIf a light source illuminates a translucent surface from the side opposite
- Xthat from which a ray approaches, illumination computations are performed,
- Xusing the given color as the surface's diffuse color, and the given
- Xexponent as the Phong highlight exponent. The resulting color is then
- Xscaled by the surface's translucency.
- X
- X\section{Atmospheric Effects}
- X
- XAny number of atmospheric effects may also be associated with a surface.
- XThese effects will be applied to those rays that are transmitted through
- Xthe surface. Applying atmospheric effects to opaque objects is a waste
- Xof input file.
- X
- X\begin{defkey}{fog}{\evec{color} \evec{thinness}}
- XAdd exponential fog with the specified {\em thinness} and {\em color}.
- X\end{defkey}
- XFog is simulated by blending the color of the fog with the color of
- Xeach ray. The amount of fog color blended into a ray color is an exponential
- Xfunction of the distance from the ray origin to the point of intersection
- Xdivided by the specified {\em thinness} for each color channel.
- XIf the distance is equal to {\em thinness},
- Xa ray's new color will be half of the fog color plus half its
- Xoriginal color.
- X
- X\begin{defkey}{mist}{\evec{color} \evec{thinness} {\em zero scale}}
- XAdd global low-altitude mist of the specified color. The color of
- Xa ray is modulated by a fog with density that varies linearly with
- Xthe difference in $z$ coordinate (altitude) between the ray origin and
- Xthe point of intersection. The thinness values specify the transmissivity
- Xof the fog for each color channel.
- XThe base altitude of the
- Xmist is given by {\em zero}, and the apparent height of the mist can
- Xbe modulated using {\em scale}, which scales the difference in
- Xaltitude used to compute the fog.
- X\end{defkey}
- X
- X\section {The Default Medium}
- X
- XThe default medium is the medium which surrounds and encompasses
- Xall of the objects in the scene; it is the ``air'' through which eye
- Xrays usually travel before hitting an object. The properties of
- Xthe default medium may be modified through the use of the {\tt atmosphere}
- Xkeyword.
- X
- X\begin{defkey}{atmosphere}{[{\em N\/}] [{\em atmospheric effects}]}
- XIf given, {\em N} specifies the index of refraction of the default
- Xmedium. The default is 1.0. Any atmospheric effects listed are applied
- Xto rays that are exterior to every object in the scene (e.g., rays
- Xemanating from the camera).
- X\end{defkey}
- X
- X\begin{verbatim}
- X /*
- X * Red sphere on a grey plane, with fog.
- X */
- X eyep 0. -10. 2.
- X atmosphere fog .8 .8 .8 14. 14. 14.
- X plane 0 0 0 0 0 1
- X sphere diffuse 0.8 0 0 1.5 0 0 1.5
- X\end{verbatim}
- X
- X\section {Surface Specification}
- X
- X{\em Rayshade} provides a number of ways to define surfaces and to
- Xbind these surfaces to objects. The most straight-forward method
- Xof surface specification is to simply list the surface properties to
- Xbe used.
- XAlternatively, one may associate a name with a given surface.
- XThis name may subsequently be used to refer to that surface.
- X
- X\begin{defkey}{surface}{{\em name\/} $<${\em Surface Definition}$>$}
- X Associate the given collection of surface attributes with the
- X given name.
- X\end{defkey}
- X
- XThe binding of a collection of surface properties to a given object
- Xis accomplished in a bottom-up manner; the surface that ``closest''
- Xin the modeling tree to the primitive being rendered is the one that
- Xis used to give the primitive its appearance.
- X
- XAn object that has no surface bound to it is assigned a default surface
- Xthat give an object the appearance of white plastic.
- X
- XThe first
- Xand most direct way to bind a surface to a primitive
- Xis by specifying the surface to be bound to
- Xthe primitive when it is instantiated.
- XThis is accomplished
- Xby inserting a list of surface attributes or a surface name after
- Xthe primitive's type keyword and before the actual primitive data.
- X
- X\begin{verbatim}
- X /*
- X * A red 'mud' colored sphere reseting on a
- X * white sphere. To the right is a sphere with
- X * default surface attributes.
- X */
- X surface mud ambient .03 0. 0. diffuse .7 .3 0.
- X sphere ambient .05 .05 .05 diffuse .7 .7 .7 1. 0 0 0
- X sphere mud 1. 0 0 2
- X sphere 1. 1.5 0 0
- X\end{verbatim}
- X
- XHere, we define a red surface named ``mud''. We then instantiate
- Xa sphere, which has a diffuse white surface bound to it. The
- Xnext line instantiates a sphere with the defined ``mud'' surface bound
- Xto it. The last line instantiates a sphere with no surface bound to it;
- Xit is assigned the default surface by {\em rayshade}.
- X
- XThe {\tt applysurf} keyword may be used to set the default surface
- Xcharacteristics for the aggregate object currently being defined.
- X
- X\begin{defkey}{applysurf}{$<${\em Surface Specification}$>$}
- XThe specified surface is applied to all following
- Xinstantiated objects that do not have surfaces associated with them.
- XThe scope of this keyword is limited to the aggregate currently
- Xbeing defined.
- X\end{defkey}
- X
- X\begin{verbatim}
- X /*
- X * Mirrored ball and cylinder sitting on 'default' plane.
- X */
- X surface mirror .01 .01 .01 diffuse .05 .05 .05
- X specular .8 .8 .8 speccoef 20 reflect 0.95
- X plane 0 0 0 0 0 1
- X applysurf mirror
- X sphere 1 0 0 0
- X cylinder 1 3 0 0 3 0 3
- X\end{verbatim}
- X
- XFor convenience, the name {\tt cursurf} may be used to refer to the
- Xcurrent default surface.
- X
- XThe utility of bottom-up binding of surfaces lies in the fact that
- Xone may be as adamant or as noncommittal about
- Xsurface binding as one sees fit when defining objects. For example,
- Xone could define a king chess piece consisting of triangles that have no
- Xsurface bound to them, save for the cross on top, which has
- Xa gold-colored surface associated with it. One may then instantiate
- Xthe king twice, once applying a black surface, and once applying
- Xa white surface. The result: a black king and a white king, each
- Xadorned with a golden cross.
- X
- X\begin{verbatim}
- X surface white ...
- X surface black ...
- X surface gold ...
- X ...
- X define cross
- X box x y z x y z
- X ...
- X defend
- X define king
- X triangle x y z x y z x y z
- X ...
- X object gold cross
- X defend
- X
- X object white king translate 1. 0 0
- X object black king
- X\end{verbatim}
- END_OF_FILE
- if test 10193 -ne `wc -c <'Doc/Guide/surfaces.tex'`; then
- echo shar: \"'Doc/Guide/surfaces.tex'\" unpacked with wrong size!
- fi
- # end of 'Doc/Guide/surfaces.tex'
- fi
- if test -f 'libray/libcommon/transform.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'libray/libcommon/transform.c'\"
- else
- echo shar: Extracting \"'libray/libcommon/transform.c'\" \(10691 characters\)
- sed "s/^X//" >'libray/libcommon/transform.c' <<'END_OF_FILE'
- X/*
- X * transform.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: transform.c,v 4.0 91/07/17 14:32:25 kolb Exp Locker: kolb $
- X *
- X * $Log: transform.c,v $
- X * Revision 4.0 91/07/17 14:32:25 kolb
- X * Initial version.
- X *
- X */
- X#include "common.h"
- X
- X/*
- X * Matrices are indexed row-first; that is:
- X * matrix[ROW][COLUMN]
- X */
- X/*
- X * Allocate new structure that holds both object-to-world and
- X * world-to-object space transformation structures. It probably
- X * should hold pointers to these structures.
- X */
- XTrans *
- XTransCreate(tr, meth)
- XTransRef tr;
- XTransMethods *meth;
- X{
- X Trans *res;
- X
- X res = (Trans *)share_malloc(sizeof(Trans));
- X res->tr = tr;
- X res->methods = meth;
- X res->animated = FALSE;
- X res->assoc = (ExprAssoc *)NULL;
- X res->prev = res->next = (Trans *)NULL;
- X MatrixInit(&res->trans);
- X MatrixInit(&res->itrans);
- X return res;
- X}
- X
- Xvoid
- XTransFree(trans)
- XTrans *trans;
- X{
- X if (trans->tr)
- X free((voidstar)trans->tr);
- X free((voidstar)trans);
- X}
- X
- Xvoid
- XTransAssoc(trans, ptr, expr)
- XTrans *trans;
- XFloat *ptr;
- XExpr *expr;
- X{
- X ExprAssoc *assoc;
- X
- X if (expr->timevary) {
- X /*
- X * Gotta store the sucker.
- X */
- X trans->assoc = AssocCreate(ptr, expr, trans->assoc);
- X trans->animated = TRUE;
- X } else {
- X *ptr = expr->value;
- X }
- X fflush(stderr);
- X}
- X
- X/*
- X * Allocate new transformation 'matrix'.
- X */
- XRSMatrix *
- XMatrixCreate()
- X{
- X RSMatrix *res;
- X
- X res = (RSMatrix *)share_malloc(sizeof(RSMatrix));
- X MatrixInit(res);
- X return res;
- X}
- X
- X/*
- X * Multiply m1 and m2, copy result into "res".
- X */
- Xvoid
- XMatrixMult(t1, t2, res)
- XRSMatrix *t1, *t2, *res;
- X{
- X register int i;
- X RSMatrix tmp;
- X
- X for (i = 0; i < 3; i++) {
- X tmp.matrix[i][0] = t1->matrix[i][0] * t2->matrix[0][0] +
- X t1->matrix[i][1] * t2->matrix[1][0] +
- X t1->matrix[i][2] * t2->matrix[2][0];
- X tmp.matrix[i][1] = t1->matrix[i][0] * t2->matrix[0][1] +
- X t1->matrix[i][1] * t2->matrix[1][1] +
- X t1->matrix[i][2] * t2->matrix[2][1];
- X tmp.matrix[i][2] = t1->matrix[i][0] * t2->matrix[0][2] +
- X t1->matrix[i][1] * t2->matrix[1][2] +
- X t1->matrix[i][2] * t2->matrix[2][2];
- X }
- X
- X tmp.translate.x = t1->translate.x * t2->matrix[0][0] +
- X t1->translate.y * t2->matrix[1][0] +
- X t1->translate.z * t2->matrix[2][0] + t2->translate.x;
- X tmp.translate.y = t1->translate.x * t2->matrix[0][1] +
- X t1->translate.y * t2->matrix[1][1] +
- X t1->translate.z * t2->matrix[2][1] + t2->translate.y;
- X tmp.translate.z = t1->translate.x * t2->matrix[0][2] +
- X t1->translate.y * t2->matrix[1][2] +
- X t1->translate.z * t2->matrix[2][2] + t2->translate.z;
- X MatrixCopy(&tmp, res);
- X}
- X
- X/*
- X * Return transformation information to map the "coordinate system"
- X * with the given origin, "up" vector, radius, and up axis lengths to
- X * one in which the "up" vector is the Z axis and the x/y/up axes
- X * have unit length. This is useful for transforming a general
- X * form of a primitive into a canonical, Z-axis aligned, unit size
- X * primitive, facilitating intersection testing.
- X */
- Xvoid
- XCoordSysTransform(origin, up, r, len, trans)
- XVector *origin, *up;
- XFloat r, len;
- XTrans *trans;
- X{
- X RSMatrix tmp;
- X Vector atmp;
- X
- X ScaleMatrix(r, r, len, &trans->trans);
- X if (fabs(up->z) == 1.) {
- X atmp.x = 1.;
- X atmp.y = atmp.z = 0.;
- X } else {
- X atmp.x = up->y;
- X atmp.y = -up->x;
- X atmp.z= 0.;
- X }
- X /*
- X * Might want to make sure that |up->z| is < 1.
- X */
- X RotationMatrix(atmp.x, atmp.y, atmp.z, -acos(up->z), &tmp);
- X MatrixMult(&trans->trans, &tmp, &trans->trans);
- X TranslationMatrix(origin->x, origin->y, origin->z, &tmp);
- X MatrixMult(&trans->trans, &tmp, &trans->trans);
- X MatrixInvert(&trans->trans, &trans->itrans);
- X}
- X
- Xvoid
- XTransCopy(from, into)
- XTrans *into, *from;
- X{
- X MatrixCopy(&from->trans, &into->trans);
- X MatrixCopy(&from->itrans, &into->itrans);
- X}
- X
- Xvoid
- XTransInvert(from, into)
- XTrans *into, *from;
- X{
- X RSMatrix ttmp;
- X /*
- X * In case into == from...
- X */
- X if (from == into) {
- X ttmp = from->trans;
- X into->trans = from->itrans;
- X into->itrans = ttmp;
- X } else {
- X into->trans = from->itrans;
- X into->itrans = from->trans;
- X }
- X}
- X
- X/*
- X * Copy a given transformation structure.
- X */
- Xvoid
- XMatrixCopy(from, into)
- XRSMatrix *into, *from;
- X{
- X into->matrix[0][0] = from->matrix[0][0];
- X into->matrix[0][1] = from->matrix[0][1];
- X into->matrix[0][2] = from->matrix[0][2];
- X into->matrix[1][0] = from->matrix[1][0];
- X into->matrix[1][1] = from->matrix[1][1];
- X into->matrix[1][2] = from->matrix[1][2];
- X into->matrix[2][0] = from->matrix[2][0];
- X into->matrix[2][1] = from->matrix[2][1];
- X into->matrix[2][2] = from->matrix[2][2];
- X into->translate = from->translate;
- X}
- X
- Xvoid
- XTransInit(trans)
- XTrans *trans;
- X{
- X MatrixInit(&trans->trans);
- X MatrixInit(&trans->itrans);
- X}
- X
- Xvoid
- XTransCompose(t1, t2, res)
- XTrans *t1, *t2, *res;
- X{
- X MatrixMult(&t1->trans, &t2->trans, &res->trans);
- X MatrixMult(&t2->itrans, &t1->itrans, &res->itrans);
- X}
- X
- X/*
- X * Initialize transformation structure.
- X */
- Xvoid
- XMatrixInit(trans)
- XRSMatrix *trans;
- X{
- X trans->matrix[0][0] = trans->matrix[1][1] = trans->matrix[2][2] = 1.;
- X trans->matrix[0][1] = trans->matrix[0][2] = trans->matrix[1][0] =
- X trans->matrix[1][2] = trans->matrix[2][0] = trans->matrix[2][1] = 0.;
- X trans->translate.x = trans->translate.y = trans->translate.z = 0.;
- X}
- X
- X/*
- X * Calculate inverse of the given transformation structure.
- X */
- Xvoid
- XMatrixInvert(trans, inverse)
- XRSMatrix *inverse, *trans;
- X{
- X RSMatrix ttmp;
- X int i;
- X Float d;
- X extern int yylineno;
- X
- X ttmp.matrix[0][0] = trans->matrix[1][1]*trans->matrix[2][2] -
- X trans->matrix[1][2]*trans->matrix[2][1];
- X ttmp.matrix[1][0] = trans->matrix[1][0]*trans->matrix[2][2] -
- X trans->matrix[1][2]*trans->matrix[2][0];
- X ttmp.matrix[2][0] = trans->matrix[1][0]*trans->matrix[2][1] -
- X trans->matrix[1][1]*trans->matrix[2][0];
- X
- X ttmp.matrix[0][1] = trans->matrix[0][1]*trans->matrix[2][2] -
- X trans->matrix[0][2]*trans->matrix[2][1];
- X ttmp.matrix[1][1] = trans->matrix[0][0]*trans->matrix[2][2] -
- X trans->matrix[0][2]*trans->matrix[2][0];
- X ttmp.matrix[2][1] = trans->matrix[0][0]*trans->matrix[2][1] -
- X trans->matrix[0][1]*trans->matrix[2][0];
- X
- X ttmp.matrix[0][2] = trans->matrix[0][1]*trans->matrix[1][2] -
- X trans->matrix[0][2]*trans->matrix[1][1];
- X ttmp.matrix[1][2] = trans->matrix[0][0]*trans->matrix[1][2] -
- X trans->matrix[0][2]*trans->matrix[1][0];
- X ttmp.matrix[2][2] = trans->matrix[0][0]*trans->matrix[1][1] -
- X trans->matrix[0][1]*trans->matrix[1][0];
- X
- X d = trans->matrix[0][0]*ttmp.matrix[0][0] -
- X trans->matrix[0][1]*ttmp.matrix[1][0] +
- X trans->matrix[0][2]*ttmp.matrix[2][0];
- X
- X if (fabs(d) < EPSILON*EPSILON)
- X RLerror(RL_PANIC, "Singular matrix.\n",yylineno);
- X
- X ttmp.matrix[0][0] /= d;
- X ttmp.matrix[0][2] /= d;
- X ttmp.matrix[1][1] /= d;
- X ttmp.matrix[2][0] /= d;
- X ttmp.matrix[2][2] /= d;
- X
- X d = -d;
- X
- X ttmp.matrix[0][1] /= d;
- X ttmp.matrix[1][0] /= d;
- X ttmp.matrix[1][2] /= d;
- X ttmp.matrix[2][1] /= d;
- X
- X ttmp.translate.x = -(ttmp.matrix[0][0]*trans->translate.x +
- X ttmp.matrix[1][0]*trans->translate.y +
- X ttmp.matrix[2][0]*trans->translate.z);
- X ttmp.translate.y = -(ttmp.matrix[0][1]*trans->translate.x +
- X ttmp.matrix[1][1]*trans->translate.y +
- X ttmp.matrix[2][1]*trans->translate.z);
- X ttmp.translate.z = -(ttmp.matrix[0][2]*trans->translate.x +
- X ttmp.matrix[1][2]*trans->translate.y +
- X ttmp.matrix[2][2]*trans->translate.z);
- X
- X MatrixCopy(&ttmp, inverse);
- X}
- X
- X/*
- X * Apply a transformation to a point (translation affects the point).
- X */
- Xvoid
- XPointTransform(vec, trans)
- XVector *vec;
- XRSMatrix *trans;
- X{
- X Vector tmp;
- X
- X tmp.x = vec->x * trans->matrix[0][0] + vec->y * trans->matrix[1][0] +
- X vec->z * trans->matrix[2][0] + trans->translate.x;
- X tmp.y = vec->x * trans->matrix[0][1] + vec->y * trans->matrix[1][1] +
- X vec->z * trans->matrix[2][1] + trans->translate.y;
- X tmp.z = vec->x * trans->matrix[0][2] + vec->y * trans->matrix[1][2] +
- X vec->z * trans->matrix[2][2] + trans->translate.z;
- X *vec = tmp;
- X}
- X
- X/*
- X * 'c1x' is the X (0th) component of the first column, and so on.
- X */
- Xvoid
- XArbitraryMatrix(c1x, c2x, c3x, c1y, c2y, c3y, c1z, c2z, c3z, tx, ty, tz, trans)
- XFloat c1x, c1y, c1z, c2x, c2y, c2z, c3x, c3y, c3z, tx, ty, tz;
- XRSMatrix *trans;
- X{
- X trans->matrix[0][0] = c1x;
- X trans->matrix[1][0] = c1y;
- X trans->matrix[2][0] = c1z;
- X
- X trans->matrix[0][1] = c2x;
- X trans->matrix[1][1] = c2y;
- X trans->matrix[2][1] = c2z;
- X
- X trans->matrix[0][2] = c3x;
- X trans->matrix[1][2] = c3y;
- X trans->matrix[2][2] = c3z;
- X
- X trans->translate.x = tx;
- X trans->translate.y = ty;
- X trans->translate.z = tz;
- X}
- X
- X/*
- X * Apply transformation to a vector (translations have no effect).
- X */
- Xvoid
- XVecTransform(vec, trans)
- XVector *vec;
- XRSMatrix *trans;
- X{
- X Vector tmp;
- X
- X tmp.x = vec->x*trans->matrix[0][0] +
- X vec->y*trans->matrix[1][0] + vec->z*trans->matrix[2][0];
- X tmp.y = vec->x*trans->matrix[0][1] +
- X vec->y*trans->matrix[1][1] + vec->z*trans->matrix[2][1];
- X tmp.z = vec->x*trans->matrix[0][2] +
- X vec->y*trans->matrix[1][2] + vec->z*trans->matrix[2][2];
- X
- X *vec = tmp;
- X}
- X
- X/*
- X * Transform normal -- multiply by the transpose of the given
- X * matrix (which is the inverse of the 'desired' transformation).
- X */
- Xvoid
- XNormalTransform(norm, it)
- XVector *norm;
- XRSMatrix *it;
- X{
- X Vector onorm;
- X
- X onorm = *norm;
- X
- X norm->x = onorm.x*it->matrix[0][0] + onorm.y*it->matrix[0][1] +
- X onorm.z*it->matrix[0][2];
- X norm->y = onorm.x*it->matrix[1][0] + onorm.y*it->matrix[1][1] +
- X onorm.z*it->matrix[1][2];
- X norm->z = onorm.x*it->matrix[2][0] + onorm.y*it->matrix[2][1] +
- X onorm.z*it->matrix[2][2];
- X (void)VecNormalize(norm);
- X}
- X
- X/*
- X * Transform "ray" by transforming the origin point and direction vector.
- X */
- XFloat
- XRayTransform(ray, trans)
- XRay *ray;
- XRSMatrix *trans;
- X{
- X PointTransform(&ray->pos, trans);
- X VecTransform(&ray->dir, trans);
- X return VecNormalize(&ray->dir);
- X}
- X
- Xvoid
- XTransPropagate(trans)
- XTrans *trans;
- X{
- X (*trans->methods->propagate)(trans->tr, &trans->trans, &trans->itrans);
- X}
- X
- Xvoid
- XTransResolveAssoc(trans)
- XTrans *trans;
- X{
- X Trans *curtrans;
- X ExprAssoc *curassoc;
- X
- X for (curtrans = trans; curtrans; curtrans = curtrans->next) {
- X for (curassoc = curtrans->assoc; curassoc; curassoc = curassoc->next) {
- X *curassoc->lhs = ExprEval(curassoc->expr);
- X }
- X if (curtrans->assoc)
- X TransPropagate(curtrans);
- X }
- X}
- X
- Xvoid
- XTransComposeList(list, result)
- XTrans *list, *result;
- X{
- X TransCopy(list, result);
- X for (list = list->next; list; list = list->next)
- X TransCompose(list, result, result);
- X}
- END_OF_FILE
- if test 10691 -ne `wc -c <'libray/libcommon/transform.c'`; then
- echo shar: \"'libray/libcommon/transform.c'\" unpacked with wrong size!
- fi
- # end of 'libray/libcommon/transform.c'
- fi
- if test -f 'libray/libobj/csg.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'libray/libobj/csg.c'\"
- else
- echo shar: Extracting \"'libray/libobj/csg.c'\" \(10585 characters\)
- sed "s/^X//" >'libray/libobj/csg.c' <<'END_OF_FILE'
- X/*
- X * csg.c
- X *
- X * Copyright (C) 1991, Rod G. Bogart, 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: csg.c,v 4.0 91/07/17 14:37:00 kolb Exp Locker: kolb $
- X *
- X * $Log: csg.c,v $
- X * Revision 4.0 91/07/17 14:37:00 kolb
- X * Initial version.
- X *
- X */
- X#include "geom.h"
- X#include "csg.h"
- X
- X#define csg_set_enter(l, f) ((l)->data[0].enter = (f) + 1)
- X
- Xstatic Methods *iCsgMethods = NULL;
- Xstatic char csgName[] = "csg";
- X
- Xstatic int CsgUnionInt(), CsgDifferenceInt(),
- X CsgIntersectInt();
- Xstatic void CsgHitlistCopy(), CsgSetBounds();
- X
- XCsg *
- XCsgCreate(op)
- Xint op;
- X{
- X Csg *csg;
- X
- X csg = (Csg *)share_malloc(sizeof(Csg));
- X csg->operator = op;
- X csg->obj1 = csg->obj2 = (Geom *)NULL;
- X
- X
- X switch(op) {
- X case CSG_UNION:
- X csg->intmeth = CsgUnionInt;
- X break;
- X case CSG_INTERSECT:
- X csg->intmeth = CsgIntersectInt;
- X break;
- X case CSG_DIFFERENCE:
- X csg->intmeth = CsgDifferenceInt;
- X break;
- X default:
- X RLerror(RL_ABORT, "Unknown csg op type %d?\n",op);
- X }
- X return csg;
- X}
- X
- XMethods *
- XCsgMethods()
- X{
- X if (iCsgMethods== (Methods *)NULL) {
- X iCsgMethods = MethodsCreate();
- X iCsgMethods->create = (GeomCreateFunc *)CsgCreate;
- X iCsgMethods->convert = CsgConvert;
- X iCsgMethods->methods = CsgMethods;
- X iCsgMethods->name = CsgName;
- X iCsgMethods->intersect = CsgIntersect;
- X iCsgMethods->bounds = CsgBounds;
- X iCsgMethods->checkbounds = FALSE;
- X iCsgMethods->closed = TRUE;
- X }
- X return iCsgMethods;
- X}
- X
- Xchar *
- XCsgName()
- X{
- X return csgName;
- X}
- X
- Xcsg_intersect_objs(csg, ray, hit1, hit2, mindist, dist1, dist2)
- XCsg *csg;
- XRay *ray;
- XHitList *hit1, *hit2;
- XFloat mindist, *dist1, *dist2;
- X{
- X int operator;
- X
- X hit1->nodes = 0;
- X hit2->nodes = 0;
- X *dist1 = FAR_AWAY;
- X *dist2 = FAR_AWAY;
- X operator = csg->operator;
- X
- X if (!intersect(csg->obj1, ray, hit1, mindist, dist1) &&
- X ((operator == CSG_INTERSECT) || (operator == CSG_DIFFERENCE))) {
- X /*
- X * Intersection and Difference cases: if you miss the first
- X * object, you missed the whole thing.
- X */
- X return FALSE;
- X }
- X
- X if (!intersect(csg->obj2, ray, hit2, mindist, dist2) &&
- X ((operator == CSG_INTERSECT) ||
- X (hit1->nodes == 0) && (operator == CSG_UNION))) {
- X /*
- X * Intersect case: if you miss either object, you miss whole
- X * Union case: if you miss both object, you miss whole
- X */
- X return FALSE;
- X }
- X
- X return TRUE;
- X}
- X
- Xint
- Xcsg_enter_obj(hitp)
- XHitList *hitp;
- X{
- X if (hitp->data[0].enter)
- X return hitp->data[0].enter - 1;
- X
- X return PrimEnter(hitp->data[0].obj, &hitp->data[0].ray,
- X hitp->data[0].mindist, hitp->data[0].dist);
- X}
- X
- Xstatic int
- XCsgUnionInt(ray, hit1p, hit2p, dist1, dist2, hitclose, distclose)
- XRay *ray;
- XHitList *hit1p, *hit2p, **hitclose;
- XFloat dist1, dist2, *distclose;
- X{
- X Float distnext;
- X HitList hitnext, *hittmp;
- X
- X while (TRUE) {
- X if (hit2p->nodes == 0 ||
- X csg_enter_obj(hit2p)) {
- X /* return hit1 */
- X *hitclose = hit1p;
- X *distclose = dist1;
- X csg_set_enter(hit1p, csg_enter_obj(hit1p));
- X return TRUE;
- X } else {
- X distnext = FAR_AWAY;
- X hitnext.nodes = 0;
- X if (!intersect(hit1p->data[hit1p->nodes-1].obj,
- X ray, &hitnext, dist2+EPSILON, &distnext)) {
- X /*
- X * None of obj1 beyond, return hit2 (leaving)
- X */
- X *hitclose = hit2p;
- X *distclose = dist2;
- X csg_set_enter(hit2p, FALSE);
- X return TRUE;
- X } else {
- X /*
- X * Since hit1 is supposed to be the close one,
- X * swap them and copy hitnext into hit2.
- X */
- X hittmp = hit1p;
- X hit1p = hit2p;
- X hit2p = hittmp;
- X dist1 = dist2;
- X CsgHitlistCopy(&hitnext, hit2p);
- X dist2 = distnext;
- X /* and continue */
- X }
- X }
- X }
- X}
- X
- Xstatic int
- XCsgIntersectInt(ray, hit1p, hit2p, dist1, dist2, hitclose, distclose)
- XRay *ray;
- XHitList *hit1p, *hit2p, **hitclose;
- XFloat dist1, dist2, *distclose;
- X{
- X HitList *hittmp, hitnext;
- X Float distnext;
- X
- X while (TRUE) {
- X if (!csg_enter_obj(hit2p)) {
- X /* Ray is leaving obj2 */
- X /* Return hit1 info */
- X *hitclose = hit1p;
- X *distclose = dist1;
- X csg_set_enter(hit1p, csg_enter_obj(hit1p));
- X return TRUE;
- X } else {
- X distnext = FAR_AWAY;
- X hitnext.nodes = 0;
- X if (!intersect(hit1p->data[hit1p->nodes-1].obj,
- X ray, &hitnext, dist2+EPSILON, &distnext)) {
- X /*
- X * None of obj1 beyond, so return miss
- X */
- X return FALSE;
- X } else {
- X /*
- X * Since hit1 is supposed to be the
- X * close one, swap them and copy
- X * hitnext into hit2.
- X */
- X hittmp = hit1p;
- X hit1p = hit2p;
- X hit2p = hittmp;
- X dist1 = dist2;
- X CsgHitlistCopy(&hitnext, hit2p);
- X dist2 = distnext;
- X /* and continue */
- X }
- X }
- X }
- X}
- X
- Xstatic int
- XCsgDifferenceInt(ray, hit1p, hit2p, dist1, dist2, hitclose, distclose)
- XRay *ray;
- XHitList *hit1p, *hit2p, **hitclose;
- XFloat dist1, dist2, *distclose;
- X{
- X Float distnext;
- X HitList hitnext;
- X
- X while (TRUE) {
- X if (dist1 < dist2) {
- X if (hit2p->nodes == 0 ||
- X csg_enter_obj(hit2p)) {
- X /* return hit1 */
- X *hitclose = hit1p;
- X *distclose = dist1;
- X csg_set_enter(hit1p, csg_enter_obj(hit1p));
- X return TRUE;
- X } else {
- X distnext = FAR_AWAY;
- X hitnext.nodes = 0;
- X if (!intersect(hit1p->data[hit1p->nodes-1].obj,
- X ray, &hitnext, dist2+EPSILON, &distnext)) {
- X /*
- X * None of obj1 beyond, so
- X * return miss
- X */
- X return FALSE;
- X } else {
- X dist1 = distnext;
- X CsgHitlistCopy(&hitnext, hit1p);
- X /* and continue */
- X }
- X }
- X } else { /* dist1 <= dist2 */
- X if (hit1p->nodes == 0) {
- X /* return a miss */
- X return FALSE;
- X }
- X if (!csg_enter_obj(hit1p)) {
- X /*
- X * return hit2, but invert hit2
- X * Enter/Leave flag
- X */
- X *hitclose = hit2p;
- X *distclose = dist2;
- X csg_set_enter(hit2p, !csg_enter_obj(hit2p));
- X return TRUE;
- X } else {
- X distnext = FAR_AWAY;
- X hitnext.nodes = 0;
- X if (!intersect(hit2p->data[hit2p->nodes-1].obj,
- X ray, &hitnext, dist1+EPSILON, &distnext)) {
- X /*
- X * None of obj2 beyond, so
- X * return hit1
- X */
- X *hitclose = hit1p;
- X *distclose = dist1;
- X /* we know we're entering obj1 */
- X csg_set_enter(hit1p, TRUE);
- X return TRUE;
- X } else {
- X dist2 = distnext;
- X CsgHitlistCopy(&hitnext, hit2p);
- X /* and continue */
- X }
- X }
- X }
- X }
- X}
- X
- Xint
- XCsgIntersect(csg, ray, hitlist, mindist, maxdist)
- XCsg *csg;
- XRay *ray;
- XHitList *hitlist;
- XFloat mindist, *maxdist;
- X{
- X Float dist1, dist2, disttmp, distclose;
- X HitList hit1, hit2, *hit1p, *hit2p, *hitclose;
- X
- X hit1p = &hit1;
- X hit2p = &hit2;
- X if (!csg_intersect_objs(csg, ray, hit1p, hit2p, mindist,
- X &dist1, &dist2)) {
- X /* missed the csg object */
- X return FALSE;
- X }
- X
- X if ((dist1 > dist2) &&
- X (csg->operator == CSG_UNION || csg->operator == CSG_INTERSECT)) {
- X /* swap so 1 is closest (except in difference case) */
- X disttmp = dist2;
- X dist2 = dist1;
- X dist1 = disttmp;
- X hit1p = &hit2;
- X hit2p = &hit1;
- X }
- X
- X /*
- X * Call appropriate intersection method. If FALSE is return,
- X * no hit of any kind was found.
- X */
- X if (!(*csg->intmeth)(ray, hit1p, hit2p, dist1, dist2,
- X &hitclose, &distclose))
- X return FALSE;
- X
- X /*
- X * At this time, the closest hit is in hitclose and
- X * distclose.
- X */
- X if (distclose < mindist || distclose > *maxdist)
- X return FALSE;
- X
- X CsgHitlistCopy(hitclose, hitlist);
- X *maxdist = distclose;
- X return TRUE;
- X}
- X
- Xstatic void
- XCsgHitlistCopy(from, to)
- XHitList *from, *to;
- X{
- X int i;
- X
- X to->nodes = from->nodes;
- X for (i = 0; i < from->nodes; i++)
- X to->data[i] = from->data[i];
- X}
- X
- Xstatic void
- XCsgSetBounds(csg, bounds)
- XCsg *csg;
- XFloat bounds[2][3];
- X{
- X GeomComputeBounds(csg->obj1);
- X GeomComputeBounds(csg->obj2);
- X
- X switch (csg->operator) {
- X case CSG_UNION:
- X bounds[LOW][X] = min(csg->obj1->bounds[LOW][X], csg->obj2->bounds[LOW][X]);
- X bounds[HIGH][X] = max(csg->obj1->bounds[HIGH][X], csg->obj2->bounds[HIGH][X]);
- X bounds[LOW][Y] = min(csg->obj1->bounds[LOW][Y], csg->obj2->bounds[LOW][Y]);
- X bounds[HIGH][Y] = max(csg->obj1->bounds[HIGH][Y], csg->obj2->bounds[HIGH][Y]);
- X bounds[LOW][Z] = min(csg->obj1->bounds[LOW][Z], csg->obj2->bounds[LOW][Z]);
- X bounds[HIGH][Z] = max(csg->obj1->bounds[HIGH][Z], csg->obj2->bounds[HIGH][Z]);
- X break;
- X case CSG_INTERSECT:
- X bounds[LOW][X] = max(csg->obj1->bounds[LOW][X], csg->obj2->bounds[LOW][X]);
- X bounds[HIGH][X] = min(csg->obj1->bounds[HIGH][X], csg->obj2->bounds[HIGH][X]);
- X bounds[LOW][Y] = max(csg->obj1->bounds[LOW][Y], csg->obj2->bounds[LOW][Y]);
- X bounds[HIGH][Y] = min(csg->obj1->bounds[HIGH][Y], csg->obj2->bounds[HIGH][Y]);
- X bounds[LOW][Z] = max(csg->obj1->bounds[LOW][Z], csg->obj2->bounds[LOW][Z]);
- X bounds[HIGH][Z] = min(csg->obj1->bounds[HIGH][Z], csg->obj2->bounds[HIGH][Z]);
- X break;
- X case CSG_DIFFERENCE:
- X bounds[LOW][X] = csg->obj1->bounds[LOW][X];
- X bounds[HIGH][X] = csg->obj1->bounds[HIGH][X];
- X bounds[LOW][Y] = csg->obj1->bounds[LOW][Y];
- X bounds[HIGH][Y] = csg->obj1->bounds[HIGH][Y];
- X bounds[LOW][Z] = csg->obj1->bounds[LOW][Z];
- X bounds[HIGH][Z] = csg->obj1->bounds[HIGH][Z];
- X break;
- X default:
- X RLerror(RL_ABORT, "Unknown csg operator type %d?\n",
- X csg->operator);
- X }
- X}
- X
- X/*
- X * Return index of hitlist node closest to the leaf and not below any
- X * CSG object.
- X */
- Xint
- XFirstCSGGeom(hitlist)
- XHitList *hitlist;
- X{
- X int i;
- X
- X /*
- X * UUUUGLY -- detect if obj is a CsgGeom by comparing
- X * methods with iCsgMethods.
- X */
- X for (i = hitlist->nodes -1; i; i--)
- X if (hitlist->data[i].obj->methods == iCsgMethods)
- X return i;
- X return 0;
- X}
- X
- Xvoid
- XCsgBounds(csg, bounds)
- XCsg *csg;
- XFloat bounds[2][3];
- X{
- X CsgSetBounds(csg, csg->bounds);
- X BoundsCopy(csg->bounds, bounds);
- X}
- X
- Xint
- XCsgConvert(csg, list)
- XCsg *csg;
- XGeom *list;
- X{
- X static int OpenAdvised = FALSE;
- X /*
- X * Currently, this only handles two objects.
- X * Will be fixed in the future.
- X * No really we promise.
- X */
- X if (!list || !list->next) {
- X RLerror(RL_WARN, "CSG needs at least two objects.\n");
- X return 0;
- X }
- X if (list->next->next) {
- X RLerror(RL_WARN, "Currently, CSG only handles two objects.\n");
- X return 0;
- X }
- X /*
- X * Things are put into lists backwards....
- X */
- X csg->obj2 = list;
- X csg->obj1 = list->next;
- X if ((!csg->obj1->methods->closed || !csg->obj2->methods->closed) &&
- X !OpenAdvised) {
- X RLerror(RL_ADVISE,
- X "Performing CSG with non-closed object(s).\n");
- X OpenAdvised = TRUE;
- X }
- X return csg->obj1->prims + csg->obj2->prims;
- X}
- X
- Xvoid
- XCsgMethodRegister(meth)
- XUserMethodType meth;
- X{
- X if (iCsgMethods)
- X iCsgMethods->user = meth;
- X}
- END_OF_FILE
- if test 10585 -ne `wc -c <'libray/libobj/csg.c'`; then
- echo shar: \"'libray/libobj/csg.c'\" unpacked with wrong size!
- fi
- # end of 'libray/libobj/csg.c'
- fi
- if test -f 'libshade/shade.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'libshade/shade.c'\"
- else
- echo shar: Extracting \"'libshade/shade.c'\" \(10451 characters\)
- sed "s/^X//" >'libshade/shade.c' <<'END_OF_FILE'
- X/*
- X * shade.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: shade.c,v 4.0 91/07/17 14:47:36 kolb Exp Locker: kolb $
- X *
- X * $Log: shade.c,v $
- X * Revision 4.0 91/07/17 14:47:36 kolb
- X * Initial version.
- X *
- X */
- X#include "rayshade.h"
- X#include "libtext/texture.h"
- X#include "libsurf/surface.h"
- X#include "liblight/light.h"
- X#include "libsurf/atmosphere.h"
- X#include "options.h"
- X#include "stats.h"
- X
- XMedium TopMedium;
- XAtmosphere *AtmosEffects;
- X
- Xstatic void shade(), LightRay(), Lighting(), ReflectRay();
- Xstatic int TransmitRay();
- X
- X/*
- X * Calculate color of ray.
- X */
- Xvoid
- XShadeRay(hitlist, ray, dist, back, color, contrib)
- XHitList *hitlist; /* Information about point of intersection. */
- XRay *ray; /* Direction and origin of ray. */
- XFloat dist; /* Distance from origin of intersection. */
- XColor *back, /* "Background" color */
- X *color, /* Color to assign current ray. */
- X *contrib; /* Contribution of this ray to final color */
- X{
- X Vector norm, gnorm, pos; /* surface normal, point of intersection */
- X Surface surf, *stmp; /* surface properties */
- X int enter, smooth; /* entering ?, gnorm != snorm ?*/
- X
- X if (hitlist->nodes == 0) {
- X /*
- X * No valid intersection. Set distance for atmospheric
- X * effects and set color of ray to background.
- X */
- X *color = *back;
- X VecAddScaled(ray->pos, FAR_AWAY, ray->dir, &pos);
- X if (!ray->media && AtmosEffects)
- X Atmospherics(AtmosEffects, ray, FAR_AWAY, &pos, color);
- X return;
- X }
- X
- X /*
- X * Compute normal, surface properties, etc.
- X */
- X stmp = GetShadingSurf(hitlist);
- X surf = *stmp;
- X enter = ComputeSurfProps(hitlist, ray, &pos, &norm, &gnorm, &surf,
- X &smooth);
- X Stats.HitRays++;
- X
- X /*
- X * Calculate ray color.
- X */
- X shade(&pos, ray, &norm, &gnorm, smooth, enter, &surf, back, color,
- X contrib);
- X if (!ray->media && AtmosEffects)
- X Atmospherics(AtmosEffects, ray, dist, &pos, color);
- X}
- X
- X/*
- X * Perform lighting calculations based on surface normal & other properties,
- X * incident ray direction and position, and light source properties.
- X * Spawn any necessary reflected and transmitted rays.
- X */
- Xstatic void
- Xshade(pos, ray, nrm, gnrm, smooth, enter, surf, back, color, contrib)
- XVector *pos, *nrm, *gnrm; /* hit pos, shade normal, geo normal */
- Xint smooth; /* true if shading norm and geo norm differ */
- Xint enter; /* TRUE if entering surface */
- XRay *ray; /* indicent ray */
- XSurface *surf; /* properties of hit surface */
- XColor *back, *color; /* background color, computed color */
- XColor *contrib; /* contribution to final pixel value */
- X{
- X Float k; /* -ray . normal */
- X Color newcontrib;
- X Vector refl; /* reflected direction */
- X Color reflectivity, /* effective surface reflectivity */
- X intens; /* reflected/transmitted intensity */
- X Light *lp; /* current light source */
- X extern Light *Lights; /* list of defined sources */
- X
- X /*
- X * Ambient color is always included.
- X */
- X ColorMultiply(surf->amb, Options.ambient, color);
- X
- X /*
- X * Calculate direction of reflected ray.
- X */
- X k = -dotp(&ray->dir, nrm);
- X VecAddScaled(ray->dir, 2.*k, *nrm, &refl);
- X
- X /*
- X * Calculate intensity contributed by each light source.
- X */
- X for (lp = Lights; lp; lp = lp->next)
- X LightRay(lp, pos, nrm, gnrm, smooth, &refl, surf,
- X ray->depth, ray->sample, ray->time, color);
- X
- X if (ray->depth >= Options.maxdepth)
- X /*
- X * Don't spawn any transmitted/reflected rays.
- X */
- X return;
- X /*
- X * Specular transmission (refraction).
- X */
- X ColorScale(surf->reflect, surf->spec, &reflectivity);
- X
- X if (surf->transp > EPSILON) {
- X ColorScale(surf->transp, surf->body, &intens);
- X ColorMultiply(intens, *contrib, &newcontrib);
- X if (newcontrib.r > Options.cutoff.r ||
- X newcontrib.g > Options.cutoff.g ||
- X newcontrib.b > Options.cutoff.b)
- X /*
- X * Transmit ray. If TIR occurs, add transmitted
- X * component to reflected component. Kinda strange, but...
- X */
- X if (TransmitRay(ray, pos, nrm, k, surf->index,
- X surf->statten, enter, back, &newcontrib, &intens, color))
- X ColorAdd(reflectivity, intens, &reflectivity);
- X }
- X
- X if (reflectivity.r > EPSILON ||
- X reflectivity.g > EPSILON ||
- X reflectivity.b > EPSILON) {
- X ColorMultiply(reflectivity, *contrib, &newcontrib);
- X if (newcontrib.r > Options.cutoff.r ||
- X newcontrib.g > Options.cutoff.g ||
- X newcontrib.b > Options.cutoff.b)
- X ReflectRay(ray, pos, &refl, back, &reflectivity,
- X &newcontrib, color);
- X }
- X}
- X
- X/*
- X * Lighting calculations
- X */
- Xstatic void
- XLightRay(lp, pos, norm, gnorm, smooth, reflect, surf, depth, samp, time, color)
- XLight *lp; /* Light source */
- XVector *pos, *norm, *gnorm; /* hit pos, shade norm, geo norm */
- Xint smooth; /* true if shade and geo norm differ */
- XVector *reflect; /* reflection direction */
- XSurface *surf; /* surface characteristics */
- Xint depth, samp; /* ray depth, sample # */
- XFloat time;
- XColor *color; /* resulting color */
- X{
- X Color lcolor;
- X Ray newray;
- X Float costheta, cosalpha, dist;
- X
- X newray.pos = *pos;
- X newray.depth = depth;
- X newray.sample = samp;
- X newray.time = time;
- X newray.media = (Medium *)NULL;
- X
- X LightDirection(lp, pos, &newray.dir, &dist);
- X
- X costheta = dotp(&newray.dir, norm);
- X
- X if (smooth) {
- X cosalpha = dotp(&newray.dir, gnorm);
- X /*
- X * If shading normal indicates self-shadowing
- X * and geom normal indicates no self-shadowing,
- X * trust the geom normal.
- X */
- X if (costheta <= 0. && cosalpha > 0.)
- X costheta = cosalpha;
- X /*
- X * If geom normal indicates self-shadowing and
- X * geom normal doesn't, then have to do something
- X * clever ala Snyder & Barr.
- X */
- X }
- X
- X if (costheta <= 0.) {
- X /*
- X * Light source is on opposite side of surface,
- X * hence light must be transmitted through...
- X */
- X if (surf->translucency < EPSILON)
- X return;
- X if (!LightIntens(lp, &newray, dist,
- X (int)surf->noshadow, &lcolor))
- X return;
- X cosalpha = -dotp(reflect, &newray.dir);
- X Lighting(-costheta, cosalpha, &lcolor, &surf->translu,
- X &surf->body, surf->stexp, color);
- X ColorScale(surf->translucency, *color, color);
- X } else {
- X if (!LightIntens(lp, &newray, dist,
- X (int)surf->noshadow, &lcolor))
- X return; /* prim is in shadow w.r.t light source */
- X
- X cosalpha = dotp(reflect, &newray.dir);
- X Lighting(costheta, cosalpha, &lcolor, &surf->diff,
- X &surf->spec, surf->srexp, color);
- X }
- X}
- X
- X/*
- X * Compute shading function (diffuse reflection and specular highlight)
- X *
- X * This function *adds* the computed color to "color".
- X */
- Xstatic void
- XLighting(costheta, cosalpha, lcolor, diff, spec, coef, color)
- XFloat costheta, cosalpha, coef;
- XColor *diff, *spec, *color, *lcolor;
- X{
- X Float intens;
- X
- X /*
- X * Diffuse reflection.
- X * Falls off as the cosine of the angle between
- X * the normal and the ray to the light (costheta).
- X */
- X color->r += diff->r * costheta * lcolor->r;
- X color->g += diff->g * costheta * lcolor->g;
- X color->b += diff->b * costheta * lcolor->b;
- X /*
- X * Specularly reflected highlights.
- X * Fall off as the cosine of the angle
- X * between the reflected ray and the ray to the light source.
- X */
- X if (coef < EPSILON || cosalpha <= 0.)
- X return;
- X /*
- X * Specular highlight = cosine of the angle raised to the
- X * appropriate power.
- X */
- X intens = pow(cosalpha, coef);
- X color->r += spec->r * intens * lcolor->r;
- X color->g += spec->g * intens * lcolor->g;
- X color->b += spec->b * intens * lcolor->b;
- X}
- X
- X/*
- X * Spawn a transmitted ray. Returns TRUE if total internal reflection
- X * occurs, FALSE otherwise.
- X */
- Xstatic int
- XTransmitRay(ray, pos, norm, k, index, statten, enter, back, contrib, intens, color)
- XRay *ray;
- XVector *pos, *norm;
- XFloat k, index, statten;
- Xint enter;
- XColor *back, *contrib, *intens, *color;
- X{
- X int total_int_refl = FALSE;
- X Ray NewRay;
- X Float dist;
- X Color newcol;
- X HitList hittmp; /* Geom intersection record */
- X
- X NewRay.pos = *pos; /* Origin == hit point */
- X NewRay.media = ray->media; /* Media == old media */
- X NewRay.sample = ray->sample;
- X NewRay.time = ray->time;
- X NewRay.depth = ray->depth + 1;
- X
- X if (enter) {
- X /*
- X * Entering surface.
- X */
- X if (Refract(&NewRay.dir,
- X NewRay.media ? NewRay.media->index :
- X TopMedium.index, index, &ray->dir, norm, k)) {
- X total_int_refl = TRUE;
- X } else {
- X /*
- X * Push information for new medium.
- X */
- X NewRay.media = MediumPush(index, statten, NewRay.media);
- X }
- X } else {
- X /*
- X * Exiting surface
- X * Pop medium from stack.
- X */
- X if (NewRay.media != (Medium *)0)
- X NewRay.media = NewRay.media->next;
- X if (Refract(&NewRay.dir, index,
- X NewRay.media ? NewRay.media->index :
- X TopMedium.index, &ray->dir, norm, k)) {
- X total_int_refl = TRUE;
- X }
- X }
- X
- X /*
- X * At this point, NewRay.media is the medium into which
- X * the new ray is entering.
- X */
- X
- X if (!total_int_refl) {
- X Stats.RefractRays++;
- X hittmp.nodes = 0;
- X dist = FAR_AWAY;
- X TraceRay(&NewRay, &hittmp, EPSILON, &dist);
- X ShadeRay(&hittmp, &NewRay, dist, back, &newcol, contrib);
- X ColorMultiply(newcol, *intens, &newcol);
- X /*
- X * Attenuate transmitted color. Note that
- X * if the transmitted ray hit nothing, we still
- X * perform this computation, as it's possible
- X * that 'air' has a non-unit statten.
- X */
- X statten = NewRay.media ? NewRay.media->statten :
- X TopMedium.statten;
- X if (statten != 1.0) {
- X statten = pow(statten, dist);
- X ColorScale(statten, newcol, &newcol);
- X }
- X ColorAdd(*color, newcol, color);
- X /* Free pushed medium */
- X if (enter)
- X free((voidstar)NewRay.media);
- X }
- X
- X return total_int_refl;
- X}
- X
- Xstatic void
- XReflectRay(ray, pos, dir, back, intens, contrib, color)
- XRay *ray;
- XVector *pos, *dir;
- XColor *back, *intens, *contrib, *color;
- X{
- X Ray NewRay;
- X HitList hittmp; /* Geom intersection record */
- X Color newcol;
- X Float dist;
- X
- X NewRay.pos = *pos; /* Origin == hit point */
- X NewRay.dir = *dir; /* Direction == reflection */
- X NewRay.media = ray->media; /* Medium == old medium */
- X NewRay.sample = ray->sample;
- X NewRay.time = ray->time;
- X NewRay.depth = ray->depth + 1;
- X Stats.ReflectRays++;
- X hittmp.nodes = 0;
- X dist = FAR_AWAY;
- X (void)TraceRay(&NewRay, &hittmp, EPSILON, &dist);
- X ShadeRay(&hittmp, &NewRay, dist, back, &newcol, contrib);
- X ColorMultiply(newcol, *intens, &newcol);
- X ColorAdd(*color, newcol, color);
- X}
- END_OF_FILE
- if test 10451 -ne `wc -c <'libshade/shade.c'`; then
- echo shar: \"'libshade/shade.c'\" unpacked with wrong size!
- fi
- # end of 'libshade/shade.c'
- fi
- echo shar: End of archive 13 \(of 19\).
- cp /dev/null ark13isdone
- 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
-
- exit 0 # Just in case...
-