home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume21
/
rayshade
/
part08
(
.txt
)
< prev
next >
Wrap
LaTeX Document
|
1991-07-21
|
53KB
|
1,568 lines
Newsgroups: comp.sources.misc
From: Rayshade Construction Co. <rayshade@weedeater.math.YALE.EDU>
Subject: v21i011: rayshade - A raytracing package for UNIX, Part08/19
Message-ID: <1991Jul21.033530.28980@sparky.IMD.Sterling.COM>
X-Md4-Signature: 1ec025725cfa48faa06a8a934d79ef56
Date: Sun, 21 Jul 1991 03:35:30 GMT
Approved: kent@sparky.imd.sterling.com
Submitted-by: Rayshade Construction Co. <rayshade@weedeater.math.YALE.EDU>
Posting-number: Volume 21, Issue 11
Archive-name: rayshade/part08
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 8 (of 19)."
# Contents: Doc/Guide/animate.tex etc/rsconvert/lex.l
# libray/libobj/cylinder.c libray/libobj/disc.c
# libray/libobj/roots.c libray/libobj/sphere.c
# libray/libsurf/surfshade.c libray/libtext/texture.c
# libshade/misc.c libshade/stats.c
# Wrapped by kolb@woody on Wed Jul 17 17:56:47 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Doc/Guide/animate.tex' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Doc/Guide/animate.tex'\"
echo shar: Extracting \"'Doc/Guide/animate.tex'\" \(4147 characters\)
sed "s/^X//" >'Doc/Guide/animate.tex' <<'END_OF_FILE'
X\chapter{Animation}
X\Rayshade provides basic animation animation support by
Xallowing time-varying
Xtransformations to be associated with primitives and aggregate objects.
XCommands are provided for controlling the amount of time between each
Xframe, the speed of the camera shutter, and the total number of frames
Xto be rendered.
XBy default, rayshade renders a single frame, with the shutter open for
Xan instant (0 units of time, in fact). The shutter speed in no way
Xchanges the light-gathering properties of the camera, i.e. frames
Xrendered using
Xa longer exposure will not appear brighter than those with a shorter
Xexposure. The only change will be in the potential amount of movement
Xthat the
Xframe ``sees'' during the time that the shutter is open.
XEach ray cast by \rayshade samples a particular moment in time.
XThe time value assigned to a ray
Xranges from the starting time of the current frame to the starting
Xtime plus the amount of time the shutter is open. When
Xa ray encounters an object or texture that possesses an animated
Xtransformation, the transformed
Xentity is moved into whatever position is appropriate
Xfor the ray's current time value before intersection, shading, or texturing
Xcomputations are performed.
XThe starting time of the current frame is computed using the
Xlength of each frame
Xthe current frame number, and the starting time of the first frame.
X\begin{defkey}{shutter}{{\em t}}
X Specifies that the shutter is open for t units of
X time for each exposure.
X\end{defkey}
XA larger value of {\em t} will lead to more motion blur in the final
Ximage. Note that {\em t} may be greater than the actual length
Xof a frame. By default, {\em t} is zero, which prevents all motion blur.
X\begin{defkey}{framelength}{{\em frameinc}}
X Specifies the time increment between frames.
X\end{defkey}
XThe default time between frames is 1 unit.
X\begin{defkey}{starttime}{{\em time}}
X Specifies the starting time of the first frame.
X\end{defkey}
XBy default, {\em time} is zero.
XVariables may be defined thorugh the use of the {\tt define} keyword:
X\begin{defkey}{define}{{\em name value}}
X Associate {\em name} with the given {\em value}. Value may
X be a constant or a parenthesized expression.
X\end{defkey}
XThe variable {\em name} may thereafter be used in expressions in the
Xinput file.
XAn animated transformation is one for which animated expressions have
Xbeen used to define one or more of its parameters (e.g. the angle through
Xwhich a rotation occurs). An animated expression is one that makes
Xuse of a time-varying (``animated'') variable or function.
XThere are two supported animated variables.
XThe first, {\tt time}, is equal to the current time.
XWhen a ray encounters an animated
Xtransformation defined using an expression containing {\tt time}, the ray
Xsubstitutes its time value into the expression before evaluation.
XUsing the {\tt time} variable in an animated expression is the most
Xbasic way to create blur-causing motion.
XThe second animated variable, {\tt frame}, is equal to the current
Xframe number. Unlike the {\tt time} variable, {\tt frame} takes on
Xa single value for the duration of each frame. Thus, transforms
Xanimated through the use of the {\tt frame} variable will not exhibit
Xmotion blurring.
XAlso supported is the {\tt linear} function. This function uses
X{\tt time} implicitly to interplate between two values.
X\begin{defkey}{linear}{{\tt (} {\em Stime, Sval, Etime, Eval} {\tt )}}
X Linearly interpolate between {\em Sval} at time
X {\em Stime} and {\em Eval} at time {\em Etime}.
X If the current time is less than {\em Stime}, the function
X returns {\em Sval}. If the current time is greater than
X {\em Etime}, {\em Eval} is returned.
X\end{defkey}
XThe following example shows the use of the {\tt time} variable to
Xanimate a sphere by translating it downwards over five frames.
XNote thet the {\tt shutter} keyword is used to set the shutter duration
Xin order to induce motion blurring.
X\begin{verbatim}
X frames 5
X shutter 1
X sphere 1 0 0 2 translate 0 0 (-time)
X\end{verbatim}
XFurther examples of animation may be found in the Examples directory
Xof the \rayshade distribution.
END_OF_FILE
if test 4147 -ne `wc -c <'Doc/Guide/animate.tex'`; then
echo shar: \"'Doc/Guide/animate.tex'\" unpacked with wrong size!
# end of 'Doc/Guide/animate.tex'
if test -f 'etc/rsconvert/lex.l' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'etc/rsconvert/lex.l'\"
echo shar: Extracting \"'etc/rsconvert/lex.l'\" \(4148 characters\)
sed "s/^X//" >'etc/rsconvert/lex.l' <<'END_OF_FILE'
X/* lex.l */
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/* $Id: lex.l,v 4.0 91/07/17 14:29:16 kolb Exp Locker: kolb $ */
X#include "config.h"
X#include <stdio.h>
X#ifdef I_STRING
X#include <string.h>
X#else
X#include <strings.h>
X#endif
X#include "libcommon/common.h"
X#include "y.tab.h"
Xalpha [a-zA-Z]
Xspecial [\.\_-]
Xdigit [0-9]
Xexp [Ee][-+]?{digit}+
Xstring ({alpha}|"/")({alpha}|{digit}|{special}|"/")*
X%p 3000
X[\t\n] {WriteVerbatim(yytext);};
X" " {};
X^# {handlehash();}
X"/*" {skipcomments();}
Xadaptive {return(tADAPTIVE);}
Xaperture {return(tAPERTURE);}
Xbackground {return(tBACKGROUND);}
Xblotch {return(tBLOTCH);}
Xbox {return(tBOX);}
Xbump {return(tBUMP);}
Xchecker {return(tCHECKER);}
Xcone {return(tCONE);}
Xcontrast {return(tCONTRAST);}
Xcutoff {return(tCUTOFF);}
Xcylinder {return(tCYL);}
Xdefend {return(tENDDEF);}
Xdefine {return(tSTARTDEF);}
Xdirectional {return(tDIRECTIONAL);}
Xendfile {return(tENDFILE);}
Xextended {return(tEXTENDED);}
Xeyep {return(tEYEP);}
Xfbm {return(tFBM);}
Xfbmbump {return(tFBMBUMP);}
Xfocaldist {return(tFOCALDIST);}
Xfog {return(tFOG);}
Xfov {return(tFOV);}
Xgloss {return(tGLOSS);}
Xgrid {return(tGRID);}
Xheightfield {return(tHEIGHTFIELD);}
Xjittered {return(tJITTERED);}
Xlight {return(tLIGHT);}
Xlist {return(tLIST);}
Xlookp {return(tLOOKP);}
Xmarble {return(tMARBLE);}
Xmaxdepth {return(tMAXDEPTH);}
Xmist {return(tMIST);}
Xobject {return(tOBJECT);}
Xoutfile {return(tOUTFILE);}
Xplane {return(tPLANE);}
Xpoint {return(tPOINT);}
Xpoly {return(tPOLY);}
Xresolution {return(tRESOLUTION);}
Xrotate {return(tROTATE);}
Xsamples {return(tSAMPLES);}
Xscale {return(tSCALE);}
Xscreen {return(tSCREEN);}
Xsphere {return(tSPHERE);}
Xsuperq {return(tSUPERQ);}
Xsurface {return(tSURFACE);}
Xtexture {return(tTEXTURE);}
Xtransform {return(tTRANSFORM);}
Xtranslate {return(tTRANSLATE);}
Xtriangle {return(tTRIANGLE);}
Xup {return(tUP);}
Xwood {return(tWOOD);}
X{string} {yylval.c = strsave(yytext);
X return(tSTRING);}
X[+-]?{digit}+ {yylval.i = atoi(yytext);
X return(tINT);}
X[+-]?{digit}+"."{digit}*({exp})? |
X[+-]?{digit}*"."{digit}+({exp})? |
X[+-]?{digit}+{exp} {yylval.d = atof(yytext); return(tFLOAT);}
X. {return yytext[0];}
Xyywrap() {return(1);}
X * Skip over comments.
Xskipcomments()
X char c;
X WriteVerbatim("/*");
X while (1) {
X while ((c = input()) != '*')
X WriteChar(c);
X WriteChar(c);
X if ((c = input()) == '/') {
X WriteChar(c);
X return;
X unput(c);
X * Deal with ccp-produced lines of the form:
X * # n "filename"
X * and
X * # n
X * Where filename is the name of the file being processed, and n is
X * the current line number in that file.
Xhandlehash()
X char buf[BUFSIZ];
X int i;
X extern int yylineno;
X extern char yyfilename[];
X * Read the entire line into buf.
X */
X for (i = 0; (buf[i] = input()) != '\n'; i++)
X ;
X unput(buf[i]); /* To make sure consecutive # lines work. */
X buf[i] = (char)NULL; /* Replace newline with NULL. */
X * Check to see if it's #include or
X * #define.
X * If so just spit out the line.
X */
X if (strncmp("include", buf, 7) == 0 || strncmp("define", buf, 6) == 0) {
X WriteVerbatim("#");
X WriteVerbatim(buf);
X return;
X * Complain if the line was not of the form #n "filename"
X */
X if ((i = sscanf(buf, "%d \"%[^\"]s\"", &yylineno, yyfilename)) == 0) {
X yyerror("Unknown '#' control.");
X exit(1);
X if (i == 1) {
X#ifdef SYSV
X if (strchr(buf, '"') != (char *)0) {
X#else
X if (index(buf, '"') != (char *)0) {
X#endif
X /*
X * Filename was "", which means stdin.
X */
X strcpy(yyfilename, "stdin");
END_OF_FILE
if test 4148 -ne `wc -c <'etc/rsconvert/lex.l'`; then
echo shar: \"'etc/rsconvert/lex.l'\" unpacked with wrong size!
# end of 'etc/rsconvert/lex.l'
if test -f 'libray/libobj/cylinder.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'libray/libobj/cylinder.c'\"
echo shar: Extracting \"'libray/libobj/cylinder.c'\" \(4773 characters\)
sed "s/^X//" >'libray/libobj/cylinder.c' <<'END_OF_FILE'
X * cylinder.c
X * Copyright (C) 1989, 1991, Craig E. Kolb
X * All rights reserved.
X * This software may be freely copied, modified, and redistributed
X * provided that this copyright notice is preserved on all copies.
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 * There is no warranty or other guarantee of fitness of this software
X * for any purpose. It is provided solely "as is".
X * $Id: cylinder.c,v 4.0 91/07/17 14:37:12 kolb Exp Locker: kolb $
X * $Log: cylinder.c,v $
X * Revision 4.0 91/07/17 14:37:12 kolb
X * Initial version.
X#include "geom.h"
X#include "cylinder.h"
Xstatic Methods *iCylinderMethods = NULL;
Xstatic char cylName[] = "cylinder";
Xunsigned long CylTests, CylHits;
XCylinder *
XCylinderCreate(r, bot, top)
XFloat r;
XVector *bot, *top;
X Cylinder *cyl;
X Float len;
X Vector axis;
X if (r <= 0.) {
X RLerror(RL_WARN, "Invalid cylinder radius.\n");
X return (Cylinder*)NULL;
X VecSub(*top, *bot, &axis);
X len = VecNormalize(&axis);
X if (len < EPSILON) {
X RLerror(RL_WARN, "Degenerate cylinder.\n");
X return (Cylinder *)NULL;
X cyl = (Cylinder *)share_malloc(sizeof(Cylinder));
X CoordSysTransform(bot, &axis, r, len, &cyl->trans);
X return cyl;
XMethods *
XCylinderMethods()
X if (iCylinderMethods == (Methods *)NULL) {
X iCylinderMethods = MethodsCreate();
X iCylinderMethods->name = CylinderName;
X iCylinderMethods->create = (GeomCreateFunc *)CylinderCreate;
X iCylinderMethods->methods = CylinderMethods;
X iCylinderMethods->intersect = CylinderIntersect;
X iCylinderMethods->normal = CylinderNormal;
X iCylinderMethods->uv = CylinderUV;
X iCylinderMethods->bounds = CylinderBounds;
X iCylinderMethods->stats = CylinderStats;
X iCylinderMethods->checkbounds = TRUE;
X iCylinderMethods->closed = FALSE;
X return iCylinderMethods;
X * Ray-cylinder intersection test.
XCylinderIntersect(cyl, ray, mindist, maxdist)
XCylinder *cyl;
XRay *ray;
XFloat mindist, *maxdist;
X Float t1, t2, a, b, c, zpos1, zpos2, disc;
X Float distfact;
X Ray newray;
X Vector nray, npos;
X Float nmin;
X CylTests++;
X * Transform ray into canonical cylinder space.
X */
X newray = *ray;
X distfact = RayTransform(&newray, &cyl->trans.itrans);
X nray = newray.dir;
X npos = newray.pos;
X nmin = mindist * distfact;
X a = nray.x * nray.x + nray.y * nray.y;
X if (a < EPSILON*EPSILON)
X /* |nray.z| == 1. */
X return FALSE;
X b = nray.x * npos.x + nray.y * npos.y;
X c = npos.x*npos.x + npos.y*npos.y - 1;
X disc = b*b - a*c;
X if(disc < 0.)
X return FALSE;
X disc = sqrt(disc);
X t1 = (-b + disc) / a;
X t2 = (-b - disc) / a;
X if (t1 < nmin && t2 < nmin)
X return FALSE;
X zpos1 = npos.z + t1 * nray.z;
X zpos2 = npos.z + t2 * nray.z;
X if (t1 < nmin || zpos1 < 0. || zpos1 > 1.) {
X if (t2 < nmin || zpos2 < 0. || zpos2 > 1.)
X return FALSE;
X else
X t1 = t2 / distfact;
X } else {
X if (t2 < nmin || zpos2 < 0. || zpos2 > 1.)
X t1 /= distfact;
X else {
X t1 = min(t1, t2) / distfact;
X if (t1 < *maxdist) {
X *maxdist = t1;
X CylHits++;
X return TRUE;
X return FALSE;
XCylinderNormal(cyl, pos, nrm, gnrm)
XCylinder *cyl;
XVector *pos, *nrm, *gnrm;
X * Transform position into cylinder space.
X */
X *nrm = *pos;
X PointTransform(nrm, &cyl->trans.itrans);
X * The normal is equal to the point of intersection in cylinder
X * space, but with Z = 0.;
X */
X nrm->z = 0.;
X * Tranform normal back to world space.
X */
X NormalTransform(nrm, &cyl->trans.itrans);
X *gnrm = *nrm;
X return FALSE;
Xvoid
XCylinderUV(cyl, pos, norm, uv, dpdu, dpdv)
XCylinder *cyl;
XVector *pos, *norm, *dpdu, *dpdv;
XVec2d *uv;
X Vector npos;
X npos = *pos;
X PointTransform(&npos, &cyl->trans.itrans);
X uv->v = npos.z;
X * Due to roundoff error, |npos.x| may be > 1.
X */
X if (npos.x > 1.)
X uv->u = 0.;
X else if (npos.x < -1.)
X uv->u = 0.5;
X else
X uv->u = acos(npos.x) / TWOPI;
X if (npos.y < 0.)
X uv->u = 1. - uv->u;
X if (dpdu) {
X dpdv->x = dpdv->y = 0.;
X dpdv->z = 1.;
X dpdu->x = -npos.y;
X dpdu->y = npos.x;
X dpdu->z = 0.;
X VecTransform(dpdu, &cyl->trans.trans);
X VecTransform(dpdv, &cyl->trans.trans);
X (void)VecNormalize(dpdu);
X (void)VecNormalize(dpdv);
Xvoid
XCylinderBounds(cyl, bounds)
XCylinder *cyl;
XFloat bounds[2][3];
X bounds[LOW][X] = bounds[LOW][Y] = -1;
X bounds[HIGH][X] = bounds[HIGH][Y] = 1;
X bounds[LOW][Z] = 0.;
X bounds[HIGH][Z] = 1;
X * Transform bounding box to world space.
X */
X BoundsTransform(&cyl->trans.trans, bounds);
Xchar *
XCylinderName()
X return cylName;
Xvoid
XCylinderStats(tests, hits)
Xunsigned long *tests, *hits;
X *tests = CylTests;
X *hits = CylHits;
Xvoid
XCylinderMethodRegister(meth)
XUserMethodType meth;
X if (iCylinderMethods)
X iCylinderMethods->user = meth;
END_OF_FILE
if test 4773 -ne `wc -c <'libray/libobj/cylinder.c'`; then
echo shar: \"'libray/libobj/cylinder.c'\" unpacked with wrong size!
# end of 'libray/libobj/cylinder.c'
if test -f 'libray/libobj/disc.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'libray/libobj/disc.c'\"
echo shar: Extracting \"'libray/libobj/disc.c'\" \(4405 characters\)
sed "s/^X//" >'libray/libobj/disc.c' <<'END_OF_FILE'
X * disc.c
X * Copyright (C) 1989, 1991, Craig E. Kolb
X * All rights reserved.
X * This software may be freely copied, modified, and redistributed
X * provided that this copyright notice is preserved on all copies.
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 * There is no warranty or other guarantee of fitness of this software
X * for any purpose. It is provided solely "as is".
X * $Id: disc.c,v 4.0 91/07/17 14:37:23 kolb Exp Locker: kolb $
X * $Log: disc.c,v $
X * Revision 4.0 91/07/17 14:37:23 kolb
X * Initial version.
X#include "geom.h"
X#include "disc.h"
Xstatic Methods *iDiscMethods = NULL;
Xstatic char discName[] = "disc";
Xunsigned long DiscTests, DiscHits;
XDisc *
XDiscCreate(r, pos, norm)
XFloat r;
XVector *pos, *norm;
X Disc *disc; /* Pointer to new disc. */
X if (r < EPSILON) {
X RLerror(RL_WARN, "Degenerate disc.\n");
X /*
X * Don't create this primitive.
X */
X return (Disc *)NULL;
X if (VecNormalize(norm) == 0.) {
X RLerror(RL_WARN, "Degenerate disc normal.\n");
X return (Disc *)NULL;
X * Allocate new Disc.
X */
X disc = (Disc *)share_malloc(sizeof(Disc));
X * Initialize new disc.
X * We store the square of the radius to save us a sqrt().
X */
X disc->radius = r*r;
X disc->pos = *pos;
X disc->norm = *norm;
X * Compute plane constant.
X */
X disc->d = dotp(pos, norm);
X * Allocate new primitive
X */
X return disc;
XMethods *
XDiscMethods()
X if (iDiscMethods == (Methods *)NULL) {
X iDiscMethods = MethodsCreate();
X iDiscMethods->name = DiscName;
X iDiscMethods->create = (GeomCreateFunc *)DiscCreate;
X iDiscMethods->methods = DiscMethods;
X iDiscMethods->intersect = DiscIntersect;
X iDiscMethods->normal = DiscNormal;
X iDiscMethods->uv = DiscUV;
X iDiscMethods->bounds = DiscBounds;
X iDiscMethods->stats = DiscStats;
X iDiscMethods->checkbounds = FALSE;
X iDiscMethods->closed = FALSE;
X return iDiscMethods;
XDiscIntersect(disc, ray, mindist, maxdist)
XDisc *disc;
XRay *ray;
XFloat mindist, *maxdist;
X Vector hit;
X Float denom, dist;
X DiscTests++;
X denom = dotp(&disc->norm, &ray->dir);
X if (fabs(denom) < EPSILON)
X /* Edge-on intersection */
X return FALSE;
X dist = (disc->d - dotp(&disc->norm, &ray->pos)) / denom;
X if (dist < mindist || dist > *maxdist)
X /* Too close or too far */
X return FALSE;
X * Find difference between point of intersection and center of disc.
X */
X VecAddScaled(ray->pos, dist, ray->dir, &hit);
X VecSub(hit, disc->pos, &hit);
X * If hit point is <= disc->radius from center, we've hit the disc.
X */
X if (dotp(&hit, &hit) <= disc->radius) {
X *maxdist = dist;
X DiscHits++;
X return TRUE;
X return FALSE;
XDiscNormal(disc, pos, nrm, gnrm)
XDisc *disc;
XVector *pos, *nrm, *gnrm;
X *gnrm = *nrm = disc->norm;
X return FALSE;
Xvoid
XDiscUV(disc, pos, norm, uv, dpdu, dpdv)
XDisc *disc;
XVector *pos, *norm, *dpdu, *dpdv;
XVec2d *uv;
X Float dist, val;
X dist = (pos->x - disc->pos.x) * (pos->x - disc->pos.x) +
X (pos->y - disc->pos.y) * (pos->y - disc->pos.y) +
X (pos->z - disc->pos.z) * (pos->z - disc->pos.z);
X if (dist < EPSILON) {
X uv->u = uv->v = 0.;
X return;
X dist = sqrt(dist);
X uv->v = dist / sqrt(disc->radius); /* should store r and r*r */
X val = pos->x / dist;
X if (fabs(val) > 1.)
X uv->u = 0.5;
X else {
X uv->u = acos(val) / TWOPI;
X if (pos->y < 0.)
X uv->u = 1. - uv->u;
X if (dpdu) {
X VecSub(*pos, disc->pos, dpdv);
X /* dpdu = dpdv X norm */
X VecCross(dpdv, norm, dpdu);
Xvoid
XDiscBounds(disc, bounds)
XDisc *disc;
XFloat bounds[2][3];
X Float extent, rad;
X rad = sqrt(disc->radius);
X * Project disc along each of X, Y and Z axes.
X */
X extent = rad * sqrt(1. - disc->norm.x * disc->norm.x);
X bounds[LOW][X] = disc->pos.x - extent;
X bounds[HIGH][X] = disc->pos.x + extent;
X extent = rad * sqrt(1. - disc->norm.y * disc->norm.y);
X bounds[LOW][Y] = disc->pos.y - extent;
X bounds[HIGH][Y] = disc->pos.y + extent;
X extent = rad * sqrt(1. - disc->norm.z * disc->norm.z);
X bounds[LOW][Z] = disc->pos.z - extent;
X bounds[HIGH][Z] = disc->pos.z + extent;
Xchar *
XDiscName()
X return discName;
Xvoid
XDiscStats(tests, hits)
Xunsigned long *tests, *hits;
X *tests = DiscTests;
X *hits = DiscHits;
Xvoid
XDiscMethodRegister(meth)
XUserMethodType meth;
X if (iDiscMethods)
X iDiscMethods->user = meth;
END_OF_FILE
if test 4405 -ne `wc -c <'libray/libobj/disc.c'`; then
echo shar: \"'libray/libobj/disc.c'\" unpacked with wrong size!
# end of 'libray/libobj/disc.c'
if test -f 'libray/libobj/roots.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'libray/libobj/roots.c'\"
echo shar: Extracting \"'libray/libobj/roots.c'\" \(4798 characters\)
sed "s/^X//" >'libray/libobj/roots.c' <<'END_OF_FILE'
X * Roots3And4.c
X * Utility functions to find cubic and quartic roots,
X * coefficients are passed like this:
X * c[0] + c[1]*x + c[2]*x^2 + c[3]*x^3 + c[4]*x^4 = 0
X * The functions return the number of non-complex roots and
X * put the values into the s array.
X * Author: Jochen Schwarze (schwarze@isa.de)
X * Jan 26, 1990 Version for Graphics Gems
X * Oct 11, 1990 Fixed sign problem for negative q's in SolveQuartic
X * (reported by Mark Podlipec),
X * Old-style function definitions,
X * IsZero() as a macro
X * Nov 23, 1990 Some systems do not declare acos() and cbrt() in
X * <math.h>, though the functions exist in the library.
X * If large coefficients are used, EQN_EPS should be
X * reduced considerably (e.g. to 1E-30), results will be
X * correct but multiple roots might be reported more
X * than once.
X#include "libcommon/common.h"
Xextern double sqrt(), cbrt(), cos(), acos();
X/* epsilon surrounding for near zero values */
X * In case M_PI isn't defined in math.h
X#ifndef M_PI
X#define M_PI PI
X#endif
X#define EQN_EPS 1e-9
X#define IsZero(x) ((x) > -EQN_EPS && (x) < EQN_EPS)
X#ifndef CBRT
X#define cbrt(x) ((x) > 0.0 ? pow((double)(x), 1.0/3.0) : \
X ((x) < 0.0 ? -pow((double)-(x), 1.0/3.0) : 0.0))
X#endif
Xint SolveQuadric(c, s)
X double c[ 3 ];
X double s[ 2 ];
X double p, q, D;
X /* normal form: x^2 + px + q = 0 */
X p = c[ 1 ] / (2 * c[ 2 ]);
X q = c[ 0 ] / c[ 2 ];
X D = p * p - q;
X if (IsZero(D))
X {
X s[ 0 ] = - p;
X return 1;
X }
X else if (D > 0)
X {
X double sqrt_D = sqrt(D);
X s[ 0 ] = sqrt_D - p;
X s[ 1 ] = - sqrt_D - p;
X return 2;
X }
X else /* if (D < 0) */
X return 0;
Xint SolveCubic(c, s)
X double c[ 4 ];
X double s[ 3 ];
X int i, num;
X double sub;
X double A, B, C;
X double sq_A, p, q;
X double cb_p, D;
X /* normal form: x^3 + Ax^2 + Bx + C = 0 */
X A = c[ 2 ] / c[ 3 ];
X B = c[ 1 ] / c[ 3 ];
X C = c[ 0 ] / c[ 3 ];
X /* substitute x = y - A/3 to eliminate quadric term:
X x^3 +px + q = 0 */
X sq_A = A * A;
X p = 1.0/3 * (- 1.0/3 * sq_A + B);
X q = 1.0/2 * (2.0/27 * A * sq_A - 1.0/3 * A * B + C);
X /* use Cardano's formula */
X cb_p = p * p * p;
X D = q * q + cb_p;
X if (IsZero(D))
X {
X if (IsZero(q)) /* one triple solution */
X s[ 0 ] = 0;
X num = 1;
X else /* one single and one double solution */
X double u = cbrt(-q);
X s[ 0 ] = 2 * u;
X s[ 1 ] = - u;
X num = 2;
X }
X else if (D < 0) /* Casus irreducibilis: three real solutions */
X {
X double phi = 1.0/3 * acos(-q / sqrt(-cb_p));
X double t = 2 * sqrt(-p);
X s[ 0 ] = t * cos(phi);
X s[ 1 ] = - t * cos(phi + M_PI / 3);
X s[ 2 ] = - t * cos(phi - M_PI / 3);
X num = 3;
X }
X else /* one real solution */
X {
X double sqrt_D = sqrt(D);
X double u = cbrt(sqrt_D - q);
X double v = - cbrt(sqrt_D + q);
X s[ 0 ] = u + v;
X num = 1;
X }
X /* resubstitute */
X sub = 1.0/3 * A;
X for (i = 0; i < num; ++i)
X s[ i ] -= sub;
X return num;
Xint SolveQuartic(c, s)
X double c[ 5 ];
X double s[ 4 ];
X double coeffs[ 4 ];
X double z, u, v, sub;
X double A, B, C, D;
X double sq_A, p, q, r;
X int i, num;
X /* normal form: x^4 + Ax^3 + Bx^2 + Cx + D = 0 */
X A = c[ 3 ] / c[ 4 ];
X B = c[ 2 ] / c[ 4 ];
X C = c[ 1 ] / c[ 4 ];
X D = c[ 0 ] / c[ 4 ];
X /* substitute x = y - A/4 to eliminate cubic term:
X x^4 + px^2 + qx + r = 0 */
X sq_A = A * A;
X p = - 3.0/8 * sq_A + B;
X q = 1.0/8 * sq_A * A - 1.0/2 * A * B + C;
X r = - 3.0/256*sq_A*sq_A + 1.0/16*sq_A*B - 1.0/4*A*C + D;
X if (IsZero(r))
X {
X /* no absolute term: y(y^3 + py + q) = 0 */
X coeffs[ 0 ] = q;
X coeffs[ 1 ] = p;
X coeffs[ 2 ] = 0;
X coeffs[ 3 ] = 1;
X num = SolveCubic(coeffs, s);
X s[ num++ ] = 0;
X }
X else
X {
X /* solve the resolvent cubic ... */
X coeffs[ 0 ] = 1.0/2 * r * p - 1.0/8 * q * q;
X coeffs[ 1 ] = - r;
X coeffs[ 2 ] = - 1.0/2 * p;
X coeffs[ 3 ] = 1;
X (void) SolveCubic(coeffs, s);
X /* ... and take the one real solution ... */
X z = s[ 0 ];
X /* ... to build two quadric equations */
X u = z * z - r;
X v = 2 * z - p;
X if (IsZero(u))
X u = 0;
X else if (u > 0)
X u = sqrt(u);
X else
X return 0;
X if (IsZero(v))
X v = 0;
X else if (v > 0)
X v = sqrt(v);
X else
X return 0;
X coeffs[ 0 ] = z - u;
X coeffs[ 1 ] = q < 0 ? -v : v;
X coeffs[ 2 ] = 1;
X num = SolveQuadric(coeffs, s);
X coeffs[ 0 ]= z + u;
X coeffs[ 1 ] = q < 0 ? v : -v;
X coeffs[ 2 ] = 1;
X num += SolveQuadric(coeffs, s + num);
X }
X /* resubstitute */
X sub = 1.0/4 * A;
X for (i = 0; i < num; ++i)
X s[ i ] -= sub;
X return num;
END_OF_FILE
if test 4798 -ne `wc -c <'libray/libobj/roots.c'`; then
echo shar: \"'libray/libobj/roots.c'\" unpacked with wrong size!
# end of 'libray/libobj/roots.c'
if test -f 'libray/libobj/sphere.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'libray/libobj/sphere.c'\"
echo shar: Extracting \"'libray/libobj/sphere.c'\" \(4775 characters\)
sed "s/^X//" >'libray/libobj/sphere.c' <<'END_OF_FILE'
X * sphere.c
X * Copyright (C) 1989, 1991, Craig E. Kolb
X * All rights reserved.
X * This software may be freely copied, modified, and redistributed
X * provided that this copyright notice is preserved on all copies.
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 * There is no warranty or other guarantee of fitness of this software
X * for any purpose. It is provided solely "as is".
X * $Id: sphere.c,v 4.0 91/07/17 14:39:17 kolb Exp Locker: kolb $
X * $Log: sphere.c,v $
X * Revision 4.0 91/07/17 14:39:17 kolb
X * Initial version.
X#include "geom.h"
X#include "sphere.h"
Xstatic Methods *iSphereMethods = NULL;
Xstatic char sphereName[] = "sphere";
Xunsigned long SphTests, SphHits;
X * Create & return reference to a sphere.
XSphere *
XSphereCreate(r, pos)
XFloat r;
XVector *pos;
X Sphere *sphere;
X if (r < EPSILON) {
X RLerror(RL_WARN, "Degenerate sphere.\n");
X return (Sphere *)NULL;
X sphere = (Sphere *)share_malloc(sizeof(Sphere));
X * sphere->rsq holds the square of the radius.
X */
X sphere->r = r;
X sphere->rsq = r*r;
X sphere->x = pos->x;
X sphere->y = pos->y;
X sphere->z = pos->z;
X return sphere;
XMethods *
XSphereMethods()
X if (iSphereMethods == (Methods *)NULL) {
X iSphereMethods = MethodsCreate();
X iSphereMethods->create = (GeomCreateFunc *)SphereCreate;
X iSphereMethods->methods = SphereMethods;
X iSphereMethods->name = SphereName;
X iSphereMethods->intersect = SphereIntersect;
X iSphereMethods->normal = SphereNormal;
X iSphereMethods->uv = SphereUV;
X iSphereMethods->enter = SphereEnter;
X iSphereMethods->bounds = SphereBounds;
X iSphereMethods->stats = SphereStats;
X iSphereMethods->checkbounds = TRUE;
X iSphereMethods->closed = TRUE;
X return iSphereMethods;
X * Ray/sphere intersection test.
XSphereIntersect(sph, ray, mindist, maxdist)
XSphere *sph;
XRay *ray;
XFloat mindist, *maxdist;
X Float xadj, yadj, zadj;
X Float b, t, s;
X SphTests++;
X * Translate ray origin to object space and negate everything.
X * (Thus, we translate the sphere into ray space, which saves
X * us a couple of negations below.)
X */
X xadj = sph->x - ray->pos.x;
X yadj = sph->y - ray->pos.y;
X zadj = sph->z - ray->pos.z;
X * Solve quadratic equation.
X */
X b = xadj * ray->dir.x + yadj * ray->dir.y + zadj * ray->dir.z;
X t = b * b - xadj * xadj - yadj * yadj - zadj * zadj + sph->rsq;
X if (t < 0.)
X return FALSE;
X t = (Float)sqrt((double)t);
X s = b - t;
X if (s > mindist) {
X if (s < *maxdist) {
X *maxdist = s;
X SphHits++;
X return TRUE;
X return FALSE;
X s = b + t;
X if (s > mindist && s < *maxdist) {
X *maxdist = s;
X SphHits++;
X return TRUE;
X return FALSE;
X * Compute normal to sphere at pos
XSphereNormal(sphere, pos, nrm, gnrm)
XSphere *sphere;
XVector *pos, *nrm, *gnrm;
X nrm->x = (pos->x - sphere->x) / sphere->r;
X nrm->y = (pos->y - sphere->y) / sphere->r;
X nrm->z = (pos->z - sphere->z) / sphere->r;
X *gnrm = *nrm;
X return FALSE;
X * Determine if ray enters (TRUE) or leaves (FALSE) sphere at pos
XSphereEnter(sphere, ray, mind, hitd)
XSphere *sphere;
XRay *ray;
XFloat mind, hitd;
X Vector pos;
X VecAddScaled(ray->pos, mind, ray->dir, &pos);
X pos.x -= sphere->x;
X pos.y -= sphere->y;
X pos.z -= sphere->z;
X return dotp(&pos, &pos) > sphere->rsq;
X/*ARGSUSED*/
Xvoid
XSphereUV(sphere, pos, norm, uv, dpdu, dpdv)
XSphere *sphere;
XVector *pos, *norm, *dpdu, *dpdv;
XVec2d *uv;
X Float phi, theta;
X Vector realnorm;
X realnorm.x = pos->x - sphere->x;
X realnorm.y = pos->y - sphere->y;
X realnorm.z = pos->z - sphere->z;
X VecNormalize( &realnorm );
X if (realnorm.z > 1.) /* roundoff */
X phi = PI;
X else if (realnorm.z < -1.)
X phi = 0;
X else
X phi = acos(-realnorm.z);
X uv->v = phi / PI;
X if (fabs(uv->v) < EPSILON || equal(uv->v, 1.))
X uv->u = 0.;
X else {
X theta = realnorm.x / sin(phi);
X if (theta > 1.)
X theta = 0.;
X else if (theta < -1.)
X theta = 0.5;
X else
X theta = acos(theta) / TWOPI;
X if (realnorm.y > 0)
X uv->u = theta;
X else
X uv->u = 1 - theta;
X if (dpdu != (Vector *)0) {
X dpdu->x = -realnorm.y;
X dpdu->y = realnorm.x;
X dpdu->z = 0.;
X (void)VecNormalize(dpdu);
X (void)VecNormCross(&realnorm, dpdu, dpdv);
Xvoid
XSphereBounds(s, bounds)
XSphere *s;
XFloat bounds[2][3];
X bounds[LOW][X] = s->x - s->r;
X bounds[HIGH][X] = s->x + s->r;
X bounds[LOW][Y] = s->y - s->r;
X bounds[HIGH][Y] = s->y + s->r;
X bounds[LOW][Z] = s->z - s->r;
X bounds[HIGH][Z] = s->z + s->r;
Xchar *
XSphereName()
X return sphereName;
Xvoid
XSphereStats(tests, hits)
Xunsigned long *tests, *hits;
X *tests = SphTests;
X *hits = SphHits;
Xvoid
XSphereMethodRegister(meth)
XUserMethodType meth;
X if (iSphereMethods)
X iSphereMethods->user = meth;
END_OF_FILE
if test 4775 -ne `wc -c <'libray/libobj/sphere.c'`; then
echo shar: \"'libray/libobj/sphere.c'\" unpacked with wrong size!
# end of 'libray/libobj/sphere.c'
if test -f 'libray/libsurf/surfshade.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'libray/libsurf/surfshade.c'\"
echo shar: Extracting \"'libray/libsurf/surfshade.c'\" \(4829 characters\)
sed "s/^X//" >'libray/libsurf/surfshade.c' <<'END_OF_FILE'
X * surfshade.c
X * Copyright (C) 1989, 1991, Craig E. Kolb
X * All rights reserved.
X * This software may be freely copied, modified, and redistributed
X * provided that this copyright notice is preserved on all copies.
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 * There is no warranty or other guarantee of fitness of this software
X * for any purpose. It is provided solely "as is".
X * $Id: surfshade.c,v 4.0 91/07/17 14:41:15 kolb Exp Locker: kolb $
X * $Log: surfshade.c,v $
X * Revision 4.0 91/07/17 14:41:15 kolb
X * Initial version.
X#include "libobj/geom.h"
X#include "surface.h"
X * Compute surface properties from given hitlist
X * Returns TRUE if ray is entering object, FALSE otherwise.
XComputeSurfProps(hitlist, ray, pos, norm, gnorm, surf, smooth)
XHitList *hitlist; /* Hit information (path through DAG) */
XRay *ray; /* Ray in world space */
XVector *pos; /* Intersection point */
XVector *norm, *gnorm; /* shading normal, geometric normal (return values) */
XSurface *surf; /* Copy of surface to use, texture-modified */
Xint *smooth;
X HitNode *hp;
X int i;
X Ray rtmp;
X Geom *prim, *obj;
X Float k, kp;
X int texturing, transforming, entering;
X Trans prim2model, world2model;
X hp = hitlist->data;
X prim = hp->obj;
X * Compute point of intersection in "primitive space".
X */
X VecAddScaled(hp->ray.pos, hp->dist, hp->ray.dir, pos);
X * Find normal to primitive at point of intersection.
X */
X *smooth = PrimNormal(prim, pos, norm, gnorm);
X texturing = transforming = FALSE;
X * Walk down hit list, constructing world<-->primitive transformation
X * and determining if we need to perform texture mapping.
X * The last node is the World node, which cannot be textured or
X * transformed, so we skip it.
X */
X for (i = 0, hp = hitlist->data; i < hitlist->nodes -1; hp++, i++) {
X obj = hp->obj;
X if (hp->dotrans) {
X /*
X * Here we're actually computing prim2world.
X * When finished, we invert it.
X */
X if (transforming) {
X TransCompose(&hp->trans, &world2model,
X &world2model);
X } else {
X TransCopy(&hp->trans, &world2model);
X }
X transforming = TRUE;
X if (obj->texture)
X texturing = TRUE;
X * Determine if we're entering or exiting the surface,
X * flipping surface normals if necessary.
X */
X k = dotp(&hitlist->data[0].ray.dir, norm);
X if (*smooth) {
X /*
X * If gnorm and shading norm differ and
X * their dot products with the ray have
X * different signs, use the geometric normal
X * instead, ala Snyder & Barr's paper.
X */
X kp = dotp(&hitlist->data[0].ray.dir, gnorm);
X if (k <= 0. && kp > 0. || k >= 0. && kp < 0.)
X k = kp;
X if (k > 0.) {
X /* flip normals */
X VecScale(-1., *gnorm, gnorm);
X VecScale(-1., *norm, norm);
X /*
X * Normal indicates that we're exiting.
X * Only set entering to TRUE if csg has indicated
X * that the ray is, indeed, entering.
X */
X entering = (hitlist->data[0].enter == ENTERING);
X } else {
X /*
X * Normal indicates that we're entering.
X * Set entering flag as such unless csg has
X * told us that we're exiting.
X */
X entering = !(hitlist->data[0].enter == EXITING);
X * If there are no transformations, then world2model is identity.
X */
X if (!transforming)
X TransInit(&world2model);
X * If we're not performing texturing, we simply need to compute
X * the normal and point of intersection to world space.
X */
X if (!texturing) {
X /*
X * At this point 'world2model' is really 'prim2world'.
X */
X if (transforming) {
X NormalTransform(norm, &world2model.itrans);
X NormalTransform(gnorm, &world2model.itrans);
X VecAddScaled(ray->pos,
X hitlist->data[hitlist->nodes -1].dist,
X ray->dir, pos);
X return entering;
X * world2model currently transforms from primitive to world space.
X * Invert it to get transformation from world to primitive space.
X */
X TransInvert(&world2model, &world2model);
X TransInit(&prim2model);
X rtmp = hitlist->data[0].ray;
X * Walk down hitlist.
X */
X for (hp = hitlist->data, i = 0; i < hitlist->nodes -1; i++, hp++) {
X obj = hp->obj;
X if (hp->dotrans) {
X NormalTransform(norm, &hp->trans.itrans);
X if (texturing) {
X /*
X * Compose prim<-->model and world<-->model
X * with current transformation.
X */
X TransCompose(&hp->trans, &prim2model,
X &prim2model);
X TransCompose(&hp->trans, &world2model,
X &world2model);
X /*
X * Transform point and ray to model space.
X */
X PointTransform(pos, &hp->trans.trans);
X (void)RayTransform(&rtmp, &hp->trans.trans);
X }
X /*
X * Apply textures
X */
X if (obj->texture)
X TextApply(obj->texture, prim, &rtmp, pos, norm,
X gnorm, surf, &prim2model, &world2model);
X return entering;
END_OF_FILE
if test 4829 -ne `wc -c <'libray/libsurf/surfshade.c'`; then
echo shar: \"'libray/libsurf/surfshade.c'\" unpacked with wrong size!
# end of 'libray/libsurf/surfshade.c'
if test -f 'libray/libtext/texture.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'libray/libtext/texture.c'\"
echo shar: Extracting \"'libray/libtext/texture.c'\" \(4973 characters\)
sed "s/^X//" >'libray/libtext/texture.c' <<'END_OF_FILE'
X * texture.c
X * Copyright (C) 1989, 1991, Craig E. Kolb
X * All rights reserved.
X * This software may be freely copied, modified, and redistributed
X * provided that this copyright notice is preserved on all copies.
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 * There is no warranty or other guarantee of fitness of this software
X * for any purpose. It is provided solely "as is".
X * $Id: texture.c,v 4.0 91/07/17 14:44:11 kolb Exp Locker: kolb $
X * $Log: texture.c,v $
X * Revision 4.0 91/07/17 14:44:11 kolb
X * Initial version.
X#include "texture.h"
X * Transformation structures used to map from texture space to
X * model/primitive/world space.
XTrans prim2model, model2text, prim2text, world2text;
X#define ApplyMapping(m,o,p,n,c,u,v) (*m->method)(m, o, p, n, c, u, v)
XTexture *
XTextCreate(data, meth)
XTextRef data;
Xvoid (*meth)();
X Texture *res;
X res = (Texture *)share_calloc(1, sizeof(Texture));
X res->data = data;
X res->method = meth;
X res->trans = (Trans *)NULL;
X res->next = (Texture *)NULL;
X res->animtrans = FALSE;
X return res;
X * Apply appropriate textures to a surface.
Xvoid
XTextApply(tlist, prim, ray, pos, norm, gnorm, surf, p2model, world2model)
XTexture *tlist; /* Textures */
XGeom *prim;
XRay *ray;
XVector *pos, *norm, *gnorm; /* pos, shading norm, geo. norm */
XSurface *surf;
XTrans *p2model, *world2model;
X Vector ptmp;
X Texture *ttmp;
X prim2model = *p2model;
X * Walk down texture list, applying each in turn.
X */
X for (ttmp = tlist; ttmp; ttmp = ttmp->next) {
X /*
X * Make copies of pos & ray to pass to the texturing function.
X */
X ptmp = *pos;
X if (ttmp->trans) {
X /*
X * 'take' the inverse of ttmp->trans, since
X * transforming a texture means applying the
X * inverse of the transformation
X * to the point of intersection, etc.
X */
X if (ttmp->animtrans) {
X /*
X * Resolve animated associations.
X * We currently do not store a time
X * for the texture, so we can't know if
X * we're already resolved for the current
X * ray->time.
X */
X TransResolveAssoc(ttmp->trans);
X TransComposeList(ttmp->trans, &model2text);
X TransInvert(&model2text, &model2text);
X } else
X TransInvert(ttmp->trans, &model2text);
X /*
X * We compose ttmp->trans, which maps from model to
X * texture space, with prim2model and world2model
X * to get prim2text and world2text.
X */
X TransCompose(&model2text, &prim2model, &prim2text);
X TransCompose(&model2text, world2model, &world2text);
X /*
X * Transform intersection point to texture space.
X * Ray and normal are passed in model space.
X */
X ModelPointToText(&ptmp);
X } else {
X /*
X * By default, texture and model space are identical.
X */
X TransInit(&model2text);
X TransCopy(&prim2model, &prim2text);
X TransCopy(world2model, &world2text);
X /*
X * Call texture function.
X */
X (*ttmp->method) (ttmp->data,prim,ray,&ptmp,norm,gnorm,surf);
X * Compute UV at 'pos' on given primitive.
XTextToUV(mapping, prim, pos, norm, u, v, dpdu, dpdv)
XMapping *mapping;
XGeom *prim;
XVector *pos, *norm, *dpdu, *dpdv;
XFloat *u, *v;
X Vec2d uv;
X Vector ptmp;
X RSMatrix t;
X ptmp = *pos;
X if (mapping->flags & PRIMSPACE) {
X /*
X * Convert point and normal to primitive space.
X */
X TextPointToPrim(&ptmp);
X } else {
X /*
X * Convert point and normal to object space.
X */
X TextPointToModel(&ptmp);
X ApplyMapping(mapping, prim, &ptmp, norm, &uv, dpdu, dpdv);
X * Transform UV by model2text. We set X = u and Y = v,
X * while Z = 0.
X * Although the UV coordinates may be in prim space,
X * we treat them as if they are model-space coords.
X * This is due to the fact that we want the texture
X * to be applied in model space.
X */
X ptmp.x = uv.u;
X ptmp.y = uv.v;
X ptmp.z = 0.;
X PointTransform(&ptmp, &model2text.trans);
X *u = ptmp.x;
X *v = ptmp.y;
X if (dpdu == (Vector *)NULL || dpdv == (Vector *)NULL)
X return;
X * Here's the ugly part.
X * Build initial UVN-->XYZ matrix...
X */
X ArbitraryMatrix(dpdu->x, dpdu->y, dpdu->z,
X dpdv->x, dpdv->y, dpdv->z,
X norm->x, norm->y, norm->z, 0., 0., 0., &t);
X * ...transform to model space...
X */
X MatrixMult(&t, &prim2model.trans, &t);
X * ... apply model2text in UVN space.
X */
X MatrixMult(&model2text.itrans, &t, &t);
X dpdu->x = t.matrix[0][0];
X dpdu->y = t.matrix[0][1];
X dpdu->z = t.matrix[0][2];
X dpdv->x = t.matrix[1][0];
X dpdv->y = t.matrix[1][1];
X dpdv->z = t.matrix[1][2];
X (void)VecNormalize(dpdu);
X (void)VecNormalize(dpdv);
X * Append 'text' to the given linked list of textures.
X * Note that 'text' may be a list, too.
XTexture *
XTextAppend(text, list)
XTexture *text, *list;
X Texture *tp;
X if (list) {
X /*
X * Walk to the end of the list
X */
X for (tp = list;tp->next ;tp = tp->next)
X ;
X tp->next = text;
X return list;
X /* else */
X return text;
END_OF_FILE
if test 4973 -ne `wc -c <'libray/libtext/texture.c'`; then
echo shar: \"'libray/libtext/texture.c'\" unpacked with wrong size!
# end of 'libray/libtext/texture.c'
if test -f 'libshade/misc.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'libshade/misc.c'\"
echo shar: Extracting \"'libshade/misc.c'\" \(4080 characters\)
sed "s/^X//" >'libshade/misc.c' <<'END_OF_FILE'
X * misc.c
X * Copyright (C) 1989, 1991, Craig E. Kolb
X * All rights reserved.
X * This software may be freely copied, modified, and redistributed
X * provided that this copyright notice is preserved on all copies.
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 * There is no warranty or other guarantee of fitness of this software
X * for any purpose. It is provided solely "as is".
X * $Id: misc.c,v 4.0 91/07/17 14:46:31 kolb Exp Locker: kolb $
X * $Log: misc.c,v $
X * Revision 4.0 91/07/17 14:46:31 kolb
X * Initial version.
X#include "rayshade.h"
X#ifdef RUSAGE
X#include <sys/time.h>
X#include <sys/resource.h>
X#else
X#ifdef TIMES
X#include <sys/types.h>
X#include <sys/times.h>
X#include <sys/param.h>
X#endif
X#endif
X#include "options.h"
X#include "stats.h"
XFloat RSabstmp; /* Temporary value used by fabs macro. Ugly. */
Xstatic void RSmessage();
X * Open input file and call yyparse().
Xvoid
XRSReadInputFile()
X extern FILE *yyin; /* lex/yacc file pointer */
X extern char yyfilename[];
X#if defined(CPPSTDIN) && defined(POPEN)
X char cmd[BUFSIZ];
X if (Options.cppargs != (char *)NULL)
X sprintf(cmd, "%s %s ", CPPSTDIN, Options.cppargs);
X else
X /* fromstdin */
X sprintf(cmd, "%s %s ", CPPSTDIN, CPPMINUS);
X if (Options.inputname == (char *)NULL) {
X (void)strcpy(yyfilename, "stdin");
X } else {
X (void)strcpy(yyfilename, Options.inputname);
X (void)strcat(cmd, Options.inputname);
X yyin = popen(cmd, "r");
X if (yyin == (FILE *)NULL)
X RLerror(RL_PANIC, "popen of \"%s\" failed!\n", cmd);
X#else
X if (Options.inputname == (char *)NULL) {
X yyin = stdin;
X (void)strcpy(yyfilename, "stdin");
X } else {
X (void)strcpy(yyfilename, Options.inputname);
X yyin = fopen(Options.inputname, "r");
X if (yyin == (FILE *)NULL)
X RLerror(RL_PANIC,
X "Cannot open %s.\n",Options.inputname);
X#endif
X * Initialize symbol table.
X */
X SymtabInit();
X (void)yyparse();
Xvoid
XOpenStatsFile()
X if (Options.statsname == (char *)NULL || Stats.fstats != stderr)
X return; /* Not specified or already opened. */
X Stats.fstats = fopen(Options.statsname, "w");
X if (Stats.fstats == (FILE *)NULL) {
X RLerror(RL_PANIC,
X "Cannot open stats file %s.\n", Options.statsname);
Xvoid
XRLerror(level, pat, arg1, arg2, arg3)
Xint level;
Xchar *pat, *arg1, *arg2, *arg3;
X switch (level) {
X case RL_ADVISE:
X if (!Options.quiet)
X RSmessage("Warning", pat, arg1, arg2, arg3);
X break;
X case RL_WARN:
X RSmessage("Warning", pat, arg1, arg2, arg3);
X break;
X case RL_ABORT:
X RSmessage("Error", pat, arg1, arg2, arg3);
X exit(1);
X break;
X case RL_PANIC:
X RSmessage("Fatal error", pat, arg1, arg2, arg3);
X exit(2);
X break;
X default:
X RSmessage("Unknown error", pat, arg1, arg2, arg3);
X exit(3);
Xstatic void
XRSmessage(type, pat, arg1, arg2, arg3)
Xchar *type, *pat, *arg1, *arg2, *arg3;
X extern FILE *yyin;
X extern int yylineno;
X extern char yyfilename[];
X if (yyin) {
X /*
X * cleanup() hasn't nulled yyin, so line #
X * info is valid.
X */
X fprintf(stderr,"%s: %s: %s, line %d: ",
X Options.progname, type,
X yyfilename == (char *)NULL ? "stdin" :
X yyfilename, yylineno);
X } else {
X fprintf(stderr,"%s: %s: ", Options.progname, type);
X fprintf(stderr, pat, arg1, arg2, arg3);
X#ifdef RUSAGE
Xvoid
XRSGetCpuTime(usertime, systime)
XFloat *usertime, *systime;
X struct rusage usage;
X getrusage(RUSAGE_SELF, &usage);
X *usertime = (Float)usage.ru_utime.tv_sec +
X (Float)usage.ru_utime.tv_usec / 1000000.;
X *systime = (Float)usage.ru_stime.tv_sec +
X (Float)usage.ru_stime.tv_usec / 1000000.;
X#else
X#ifdef TIMES
Xvoid
XRSGetCpuTime(usertime, systime)
XFloat *usertime, *systime;
X extern CLOCKTYPE times();
X struct tms time;
X (void)times(&time);
X *usertime = (Float)time.tms_utime / (Float)HZ;
X *systime = (Float)time.tms_stime / (Float)HZ;
X#else /* !RUSAGE && !TIMES */
Xvoid
XRSGetCpuTime(usertime, systime)
XFloat *usertime, *systime;
X *usertime = *systime = 0.;
X#endif /* TIMES */
X#endif /* RUSAGE */
END_OF_FILE
if test 4080 -ne `wc -c <'libshade/misc.c'`; then
echo shar: \"'libshade/misc.c'\" unpacked with wrong size!
# end of 'libshade/misc.c'
if test -f 'libshade/stats.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'libshade/stats.c'\"
echo shar: Extracting \"'libshade/stats.c'\" \(4043 characters\)
sed "s/^X//" >'libshade/stats.c' <<'END_OF_FILE'
X * stats.c
X * Copyright (C) 1989, 1991, Craig E. Kolb
X * All rights reserved.
X * This software may be freely copied, modified, and redistributed
X * provided that this copyright notice is preserved on all copies.
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 * There is no warranty or other guarantee of fitness of this software
X * for any purpose. It is provided solely "as is".
X * $Id: stats.c,v 4.0 91/07/17 14:47:41 kolb Exp Locker: kolb $
X * $Log: stats.c,v $
X * Revision 4.0 91/07/17 14:47:41 kolb
X * Initial version.
X#include <ctype.h>
X#include "rayshade.h"
X#include "options.h"
X#include "stats.h"
XRSStats Stats; /* Statistical information */
XGeom *GeomRep = NULL; /* Linked list of object representatives */
Xstatic void PrintGeomStats();
Xvoid
XStatsPrint()
X extern void PrintMemoryStats();
X unsigned long TotalRays;
X#ifndef LINDA
X RSGetCpuTime(&Stats.Utime, &Stats.Stime);
X#endif
X ShadowStats(&Stats.ShadowRays, &Stats.ShadowHits,
X &Stats.CacheHits, &Stats.CacheMisses);
X IntersectStats(&Stats.BVTests);
X TotalRays = Stats.EyeRays + Stats.ShadowRays + Stats.ReflectRays
X + Stats.RefractRays;
X Stats.ShadowHits += Stats.CacheHits;
X Stats.HitRays += Stats.ShadowHits;
X#ifdef LINDA
X fprintf(Stats.fstats,"Workers:\t\t\t%d\n",Options.workers);
X#endif
X fprintf(Stats.fstats,"Eye rays:\t\t\t%lu\n", Stats.EyeRays);
X fprintf(Stats.fstats,"Shadow rays:\t\t\t%lu\n",Stats.ShadowRays);
X fprintf(Stats.fstats,"Reflected rays:\t\t\t%lu\n",Stats.ReflectRays);
X fprintf(Stats.fstats,"Refracted rays:\t\t\t%lu\n",Stats.RefractRays);
X fprintf(Stats.fstats,"Total rays:\t\t\t%lu\n", TotalRays);
X if (TotalRays != 0)
X fprintf(Stats.fstats,"Intersecting rays:\t\t%lu (%3.3f%%)\n",
X Stats.HitRays,
X 100. * (float)Stats.HitRays / (float)TotalRays);
X if (Stats.ShadowRays != 0) {
X if (Options.cache)
X fprintf(Stats.fstats,
X "Shadow cache hits:\t\t%lu (%lu misses)\n",
X Stats.CacheHits, Stats.CacheMisses);
X fprintf(Stats.fstats,"Total shadow hits:\t\t%lu (%3.3f%%)\n",
X Stats.ShadowHits, 100.*(float)Stats.ShadowHits /
X (float)Stats.ShadowRays);
X fprintf(Stats.fstats,"Supersampled pixels:\t\t%lu\n",
X Stats.SuperSampled);
X fprintf(Stats.fstats,"B.V. intersection tests:\t%lu\n",Stats.BVTests);
X PrintGeomStats();
X#ifdef LINDA
X fprintf(Stats.fstats,"Average CPU time/processor:\t");
X#else
X fprintf(Stats.fstats,"Total CPU time (sec):\t\t");
X#endif
X fprintf(Stats.fstats,"%2.2f (%2.2fu + %2.2fs)\n",
X Stats.Utime+Stats.Stime, Stats.Utime, Stats.Stime);
X if (TotalRays != 0.)
X fprintf(Stats.fstats,"Seconds / ray:\t\t\t%4.4f\n",
X (Stats.Utime + Stats.Stime) / (Float)TotalRays);
X if (Stats.HitRays != 0.)
X fprintf(Stats.fstats,"Seconds / intersecting ray:\t%4.4f\n",
X (Stats.Utime + Stats.Stime)/(Float)Stats.HitRays);
X PrintMemoryStats(Stats.fstats);
Xstatic void
XPrintGeomStats()
X Geom *otmp;
X unsigned long tests, hits, totaltests, totalhits;
X char *name;
X extern void GeomStats();
X totaltests = totalhits = 0;
X for (otmp = GeomRep; otmp; otmp = otmp->next) {
X GeomStats(otmp, &tests, &hits);
X if (tests <= 0)
X continue;
X name = GeomName(otmp);
X fprintf(Stats.fstats,
X "%c%s intersection tests:\t%lu (%lu hit, %f%%)\n",
X toupper((int)name[0]), &name[1], tests, hits,
X 100.*(float)hits/(float)tests);
X if (!IsAggregate(otmp)) {
X totaltests += tests;
X totalhits += hits;
X fprintf(Stats.fstats,"Total prim. intersection tests:\t%lu",
X totaltests);
X if (totaltests == 0)
X fprintf(Stats.fstats,"\n");
X else
X fprintf(Stats.fstats," (%lu hit, %f%%)\n", totalhits,
X 100.*(float)totalhits/(float)totaltests);
Xvoid
XStatsAddRep(obj)
XGeom *obj;
X Geom *otmp;
X for (otmp = GeomRep; otmp; otmp = otmp->next) {
X if (otmp->methods->stats == obj->methods->stats)
X return;
X * Stats method didn't match anything found so far. Add
X * a copy of obj to head of GeomRep list.
X */
X otmp = GeomCopy(obj);
X otmp->next = GeomRep;
X GeomRep = otmp;
END_OF_FILE
if test 4043 -ne `wc -c <'libshade/stats.c'`; then
echo shar: \"'libshade/stats.c'\" unpacked with wrong size!
# end of 'libshade/stats.c'
echo shar: End of archive 8 \(of 19\).
cp /dev/null ark8isdone
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
if test "${MISSING}" = "" ; then
echo You have unpacked all 19 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
echo You still need to unpack the following archives:
echo " " ${MISSING}
## End of shell archive.
exit 0
exit 0 # Just in case...