#! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'Doc/Guide/animate.tex' <<'END_OF_FILE' X\chapter{Animation} X 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. X 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. X 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. X 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 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 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 X\begin{defkey}{starttime}{{\em time}} X Specifies the starting time of the first frame. X\end{defkey} XBy default, {\em time} is zero. X XVariables may be defined thorugh the use of the {\tt define} keyword: X 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. X 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. X 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. X 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. X XAlso supported is the {\tt linear} function. This function uses X{\tt time} implicitly to interplate between two values. X 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} X 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 X\begin{verbatim} X frames 5 X shutter 1 X sphere 1 0 0 2 translate 0 0 (-time) X\end{verbatim} X XFurther examples of animation may be found in the Examples directory Xof the {\rayshade} distribution. END_OF_FILE if test 4160 -ne `wc -c <'Doc/Guide/animate.tex'`; then echo shar: \"'Doc/Guide/animate.tex'\" unpacked with wrong size! fi # end of 'Doc/Guide/animate.tex' fi if test -f 'etc/rsconvert/lex.l' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'etc/rsconvert/lex.l'\" else echo shar: Extracting \"'etc/rsconvert/lex.l'\" \(4010 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.1.1 91/11/26 21:12:29 cek Exp Locker: cek $ */ X%{ X#include "config.h" X#include X#ifdef I_STRING X#include X#else X#include X#endif X#include "libcommon/common.h" X#include "y.tab.h" X%} Xalpha [a-zA-Z] Xspecial [\.\_-] Xdigit [0-9] Xexp [Ee][-+]?{digit}+ Xstring ({alpha}|"/")({alpha}|{digit}|{special}|"/")* X%p 3000 X%% X[\t] {WriteVerbatim(yytext);}; X"\n" {}; X" " {}; X^# {return 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 X[+-]?{digit}+"."{digit}*({exp})? | X[+-]?{digit}*"."{digit}+({exp})? | X[+-]?{digit}+{exp} {yylval.d = atof(yytext); return(tFLOAT);} X X. {return yytext[0];} X X%% Xyywrap() {return(1);} X/* X * Skip over comments. X */ Xskipcomments() X{ X char c; X X WriteVerbatim("/*"); X while (1) { X while ((c = input()) != '*') X WriteChar(c); X WriteChar(c); X if ((c = input()) == '/') { X WriteChar(c); X WriteNewline(); X return; X } X unput(c); X } X} X/* 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. X */ Xhandlehash() X{ X char buf[BUFSIZ]; X int i, linenumber; X extern int yylineno; X extern char yyfilename[]; X X /* 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 X yylval.c = strsave(buf); X X /* X * Set file/line if the line was of the form #n "filename" X */ X if ((i = sscanf(buf, "%d \"%[^\"]s\"", &linenumber, buf)) != 0) { X yylineno = linenumber; 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"); X } else X strcpy(yyfilename, buf); X } X return tHASHTHING; X} END_OF_FILE if test 4010 -ne `wc -c <'etc/rsconvert/lex.l'`; then echo shar: \"'etc/rsconvert/lex.l'\" unpacked with wrong size! fi # end of 'etc/rsconvert/lex.l' fi if test -f 'libray/libobj/cylinder.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'libray/libobj/cylinder.c'\" else echo shar: Extracting \"'libray/libobj/cylinder.c'\" \(4773 characters\) sed "s/^X//" >'libray/libobj/cylinder.c' <<'END_OF_FILE' X/* X * cylinder.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: cylinder.c,v 4.0 91/07/17 14:37:12 kolb Exp Locker: kolb $ X * X * $Log: cylinder.c,v $ X * Revision 4.0 91/07/17 14:37:12 kolb X * Initial version. X * X */ X#include "geom.h" X#include "cylinder.h" X Xstatic Methods *iCylinderMethods = NULL; Xstatic char cylName[] = "cylinder"; X Xunsigned long CylTests, CylHits; X XCylinder * XCylinderCreate(r, bot, top) XFloat r; XVector *bot, *top; X{ X Cylinder *cyl; X Float len; X Vector axis; X X if (r <= 0.) { X RLerror(RL_WARN, "Invalid cylinder radius.\n"); X return (Cylinder*)NULL; X } X X VecSub(*top, *bot, &axis); X X len = VecNormalize(&axis); X X if (len < EPSILON) { X RLerror(RL_WARN, "Degenerate cylinder.\n"); X return (Cylinder *)NULL; X } X X cyl = (Cylinder *)share_malloc(sizeof(Cylinder)); X CoordSysTransform(bot, &axis, r, len, &cyl->trans); X return cyl; X} X XMethods * XCylinderMethods() X{ 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 } X return iCylinderMethods; X} X X/* X * Ray-cylinder intersection test. X */ Xint XCylinderIntersect(cyl, ray, mindist, maxdist) XCylinder *cyl; XRay *ray; XFloat mindist, *maxdist; X{ X Float t1, t2, a, b, c, zpos1, zpos2, disc; X Float distfact; X Ray newray; X Vector nray, npos; X Float nmin; X X CylTests++; X X /* 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 X a = nray.x * nray.x + nray.y * nray.y; X if (a < EPSILON*EPSILON) X /* |nray.z| == 1. */ X return FALSE; X 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 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 X } else { X if (t2 < nmin || zpos2 < 0. || zpos2 > 1.) X t1 /= distfact; X else { X t1 = min(t1, t2) / distfact; X } X } X X if (t1 < *maxdist) { X *maxdist = t1; X CylHits++; X return TRUE; X } X return FALSE; X} X Xint XCylinderNormal(cyl, pos, nrm, gnrm) XCylinder *cyl; XVector *pos, *nrm, *gnrm; X{ X /* X * Transform position into cylinder space. X */ X *nrm = *pos; X PointTransform(nrm, &cyl->trans.itrans); X /* X * The normal is equal to the point of intersection in cylinder X * space, but with Z = 0.; X */ X nrm->z = 0.; X X /* X * Tranform normal back to world space. X */ X NormalTransform(nrm, &cyl->trans.itrans); X *gnrm = *nrm; X return FALSE; X} X Xvoid XCylinderUV(cyl, pos, norm, uv, dpdu, dpdv) XCylinder *cyl; XVector *pos, *norm, *dpdu, *dpdv; XVec2d *uv; X{ X Vector npos; X X npos = *pos; X PointTransform(&npos, &cyl->trans.itrans); X X uv->v = npos.z; X /* 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 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); X } X} X Xvoid XCylinderBounds(cyl, bounds) XCylinder *cyl; XFloat bounds[2][3]; X{ X bounds[LOW][X] = bounds[LOW][Y] = -1; X bounds[HIGH][X] = bounds[HIGH][Y] = 1; X bounds[LOW][Z] = 0.; X bounds[HIGH][Z] = 1; X /* X * Transform bounding box to world space. X */ X BoundsTransform(&cyl->trans.trans, bounds); X} X Xchar * XCylinderName() X{ X return cylName; X} X Xvoid XCylinderStats(tests, hits) Xunsigned long *tests, *hits; X{ X *tests = CylTests; X *hits = CylHits; X} X Xvoid XCylinderMethodRegister(meth) XUserMethodType meth; X{ X if (iCylinderMethods) X iCylinderMethods->user = meth; X} END_OF_FILE if test 4773 -ne `wc -c <'libray/libobj/cylinder.c'`; then echo shar: \"'libray/libobj/cylinder.c'\" unpacked with wrong size! fi # end of 'libray/libobj/cylinder.c' fi if test -f 'libray/libobj/disc.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'libray/libobj/disc.c'\" else echo shar: Extracting \"'libray/libobj/disc.c'\" \(4405 characters\) sed "s/^X//" >'libray/libobj/disc.c' <<'END_OF_FILE' X/* X * disc.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: disc.c,v 4.0 91/07/17 14:37:23 kolb Exp Locker: kolb $ X * X * $Log: disc.c,v $ X * Revision 4.0 91/07/17 14:37:23 kolb X * Initial version. X * X */ X#include "geom.h" X#include "disc.h" X Xstatic Methods *iDiscMethods = NULL; Xstatic char discName[] = "disc"; X Xunsigned long DiscTests, DiscHits; X XDisc * XDiscCreate(r, pos, norm) XFloat r; XVector *pos, *norm; X{ X Disc *disc; /* Pointer to new disc. */ X X if (r < EPSILON) { X RLerror(RL_WARN, "Degenerate disc.\n"); X /* X * Don't create this primitive. X */ X return (Disc *)NULL; X } X X if (VecNormalize(norm) == 0.) { X RLerror(RL_WARN, "Degenerate disc normal.\n"); X return (Disc *)NULL; X } X /* X * Allocate new Disc. X */ X disc = (Disc *)share_malloc(sizeof(Disc)); X /* 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 /* X * Compute plane constant. X */ X disc->d = dotp(pos, norm); X /* X * Allocate new primitive X */ X return disc; X} X XMethods * XDiscMethods() X{ 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 } X return iDiscMethods; X} X Xint XDiscIntersect(disc, ray, mindist, maxdist) XDisc *disc; XRay *ray; XFloat mindist, *maxdist; X{ X Vector hit; X Float denom, dist; X X DiscTests++; X X denom = dotp(&disc->norm, &ray->dir); X if (fabs(denom) < EPSILON) X /* Edge-on intersection */ X return FALSE; X 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 /* 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 /* 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 } X return FALSE; X} X Xint XDiscNormal(disc, pos, nrm, gnrm) XDisc *disc; XVector *pos, *nrm, *gnrm; X{ X *gnrm = *nrm = disc->norm; X return FALSE; X} X Xvoid XDiscUV(disc, pos, norm, uv, dpdu, dpdv) XDisc *disc; XVector *pos, *norm, *dpdu, *dpdv; XVec2d *uv; X{ X Float dist, val; X 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 X if (dist < EPSILON) { X uv->u = uv->v = 0.; X return; X } X X dist = sqrt(dist); X uv->v = dist / sqrt(disc->radius); /* should store r and r*r */ X X val = pos->x / dist; X 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 } X X if (dpdu) { X VecSub(*pos, disc->pos, dpdv); X /* dpdu = dpdv X norm */ X VecCross(dpdv, norm, dpdu); X } X} X Xvoid XDiscBounds(disc, bounds) XDisc *disc; XFloat bounds[2][3]; X{ X Float extent, rad; X X rad = sqrt(disc->radius); X /* 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; X} X Xchar * XDiscName() X{ X return discName; X} X Xvoid XDiscStats(tests, hits) Xunsigned long *tests, *hits; X{ X *tests = DiscTests; X *hits = DiscHits; X} X Xvoid XDiscMethodRegister(meth) XUserMethodType meth; X{ X if (iDiscMethods) X iDiscMethods->user = meth; X} END_OF_FILE if test 4405 -ne `wc -c <'libray/libobj/disc.c'`; then echo shar: \"'libray/libobj/disc.c'\" unpacked with wrong size! fi # end of 'libray/libobj/disc.c' fi if test -f 'libray/libobj/geom.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'libray/libobj/geom.h'\" else echo shar: Extracting \"'libray/libobj/geom.h'\" \(4069 characters\) sed "s/^X//" >'libray/libobj/geom.h' <<'END_OF_FILE' X/* X * geom.h 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: geom.h,v 4.0.1.1 92/02/07 13:10:58 cek Exp Locker: cek $ X * X * $Log: geom.h,v $ X * Revision 4.0.1.1 92/02/07 13:10:58 cek X * patch6: Decreased MAXMODELDEPTH to keep from beating on the stack. X * X * Revision 4.0 91/07/17 14:37:52 kolb X * Initial version. X * X */ X#ifndef OBJECT_H X#define OBJECT_H X X#include "libcommon/common.h" X#include "libcommon/transform.h" X#include "bounds.h" X X/* X * Constants for enter flag in HitNode. X */ X#define EXITING 1 X#define ENTERING 2 X X#define MAXMODELDEPTH 32 /* Maximum height of DAG. */ X Xtypedef char * GeomRef; Xtypedef GeomRef GeomCreateFunc(); X X/* X * If the object has a normal method, it's a primitive X * otherwise it's an aggregate (or an instance) X */ X#define IsAggregate(o) ((o)->methods->normal == NULL) X X/* X * Geom methods. X * (p) means applies only to primitive objects X * (a) means applies only to aggregate objects X */ Xtypedef struct Methods { X char *(*name)(); /* Geom name */ X GeomRef (*create)(); /* Create and return ref */ X int (*intersect)(), /* Ray/obj intersection */ X (*normal)(), /* Geom normal (p) */ X (*enter)(), /* Ray enter or exit? (p) */ X (*convert)(); /* Convert from list (a) */ X void (*uv)(), /* 2D mapping (p) */ X (*stats)(), /* Statistics */ X (*bounds)(), /* Bounding volume */ X (*user)(); /* User-defined method */ X struct Methods *(*methods)(); /* object methods func. */ X char checkbounds, /* check bbox before int.? */ X closed; /* properly closed? */ X} Methods; X Xtypedef void (*UserMethodType)(); X X/* X * Geom definition X */ Xtypedef struct Geom { X char *name; /* Geom name, if any. */ X GeomRef obj; /* Pointer to object info. */ X Methods *methods; X unsigned long prims; /* sum of # primitive objects */ X Float bounds[2][3]; /* Bounding box */ X Float timenow; /* Geom's idea of what time it is */ X short int animtrans; /* transformation is animated */ X short int frame; /* frame for which obj is inited */ X struct Surface *surf; /* surface, if any */ X struct Trans *trans; /* Transformation information */ X struct Trans *transtail; /* Double linked list end */ X struct Texture *texture; /* Texture mapping info. */ X#ifdef SHAREDMEM X unsigned long *counter; /* Geoms are shared, counters aren't */ X#else X unsigned long counter; /* "mailbox" for grid intersection */ X#endif X struct Geom *next; /* Next object. */ X} Geom; X X/* X * Linked list of pointers to objects. X */ Xtypedef struct GeomList { X Geom *obj; X struct GeomList *next; X} GeomList; X X/* X * Array of hit information. Stores a path through an object DAG, X * as well as the ray in 'model' (object) space and the distance from X * the ray origin to the point of intersection. X */ Xtypedef struct HitNode { X Geom *obj; /* Geom hit */ X Ray ray; /* Ray */ X Float mindist; /* Amount of ray to ignore */ X Float dist; /* Distance from ray origin to hit */ X short enter, /* Enter (TRUE) or Leave (FALSE) obj */ X dotrans; /* transformations non-identity? */ X Trans trans; /* parent-->obj and inverse trans */ X} HitNode; X X/* X * Structure holding a list of HitNodes. A maximum of MAXMODELDEPTH X * nodes can be referenced. X */ Xtypedef struct HitList { X int nodes; X HitNode data[MAXMODELDEPTH]; X} HitList; X Xextern char *GeomName(); X Xextern Geom *GeomCreate(), *GeomCopy(), *GeomCopyNamed(), X *GeomComputeAggregateBounds(); X X Xextern GeomList *GeomStackPush(), *GeomStackPop(); X Xextern void PrimUV(), AggregatePrintInfo(), X IntersectStats(); X Xextern int AggregateConvert(), PrimNormal(), X TraceRay(); /* application-provided */ X Xextern Methods *MethodsCreate(); X X#endif /* OBJECT_H */ END_OF_FILE if test 4069 -ne `wc -c <'libray/libobj/geom.h'`; then echo shar: \"'libray/libobj/geom.h'\" unpacked with wrong size! fi # end of 'libray/libobj/geom.h' fi if test -f 'libray/libobj/intersect.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'libray/libobj/intersect.c'\" else echo shar: Extracting \"'libray/libobj/intersect.c'\" \(3980 characters\) sed "s/^X//" >'libray/libobj/intersect.c' <<'END_OF_FILE' X/* X * intersect.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: intersect.c,v 4.0 91/07/17 14:38:37 kolb Exp Locker: kolb $ X * X * $Log: intersect.c,v $ X * Revision 4.0 91/07/17 14:38:37 kolb X * Initial version. X * X */ X#include "geom.h" X Xstatic void AddToHitList(); X/* X * Number of bounding volume tests. X * External modules have read access via IntersectStats(). X */ Xstatic unsigned long BVTests; X X/* X * Intersect object & ray. Return distance from "pos" along "ray" to X * intersection point. Return value <= 0 indicates no intersection. X */ Xint Xintersect(obj, ray, hitlist, mindist, maxdist) XGeom *obj; /* Geom to be tested. */ XRay *ray; /* Ray origin, direction. */ XHitList *hitlist; /* Intersection path */ XFloat mindist, *maxdist; X{ X Ray newray; X Vector vtmp; X Trans *curtrans; X Float distfact, nmindist, nmaxdist; X X /* X * Check ray/bounding volume intersection, if required. X */ X if (obj->methods->checkbounds) { X VecAddScaled(ray->pos, mindist, ray->dir, &vtmp); X if (OutOfBounds(&vtmp, obj->bounds)) { X nmaxdist = *maxdist; X BVTests++; X if (!BoundsIntersect(ray, obj->bounds, mindist, X &nmaxdist)) X return FALSE; X } X } X X newray = *ray; X nmindist = mindist; X nmaxdist = *maxdist; X X /* X * Transform the ray if necessary. X */ X if (obj->trans != (Trans *)0) { X /* X * If object's idea of the current time is wrong, X * update the transformations. X */ X if (obj->animtrans && !equal(obj->timenow, ray->time)) { X TransResolveAssoc(obj->trans); X } X X /* X * Transforming the ray can change the distance between X * the ray origin and the point of intersection. X * We save the amount the ray is "stretched" and later X * divide the computed distance by this amount. X */ X distfact = 1.; X for (curtrans = obj->transtail; curtrans; X curtrans = curtrans->prev) X distfact *= RayTransform(&newray, &curtrans->itrans); X nmindist *= distfact; X nmaxdist *= distfact; X } X /* X * Geom has been updated to current time. X */ X obj->timenow = ray->time; X X /* X * Call correct intersection routine. X */ X if (IsAggregate(obj)) { X /* X * Aggregate X */ X if (!(*obj->methods->intersect) X (obj->obj, &newray, hitlist, nmindist, &nmaxdist)) X return FALSE; X } else { X /* X * Primitive X */ X if (!(*obj->methods->intersect) X (obj->obj, &newray, nmindist, &nmaxdist)) X return FALSE; X hitlist->nodes = 0; X } X X /* X * Had a hit -- add ray, distance and object to tail of hitlist. X */ X AddToHitList(hitlist, &newray, nmindist, nmaxdist, obj); X X /* X * Set dist to distance to intersection point from the origin X * of the untransformed ray. X */ X if (obj->trans != (Trans *)0) X *maxdist = nmaxdist / distfact; X else X *maxdist = nmaxdist; X X return TRUE; X} X Xstatic void XAddToHitList(hitlist, ray, mind, dist, obj) XHitList *hitlist; XRay *ray; XFloat mind, dist; XGeom *obj; X{ X HitNode *np; X Trans *list; X X np = &hitlist->data[hitlist->nodes++]; X X np->ray = *ray; X np->obj = obj; X np->mindist = mind; X np->dist = dist; X np->enter = 0; X X if (obj->trans) { X /* X * Compute total transformation, forward and inverse, X * for this object, and store in hitlist for use later. X */ X TransCopy(obj->trans, &np->trans); X for (list = obj->trans->next; list; list = list->next) X TransCompose(&np->trans, list, &np->trans); X np->dotrans = TRUE; X } else X np->dotrans = FALSE; X} X X/* X * Return intersection statistics. X * Currently, this is limited to the # of bounding volume test performed. X */ Xvoid XIntersectStats(bvtests) Xunsigned long *bvtests; X{ X *bvtests = BVTests; X} END_OF_FILE if test 3980 -ne `wc -c <'libray/libobj/intersect.c'`; then echo shar: \"'libray/libobj/intersect.c'\" unpacked with wrong size! fi # end of 'libray/libobj/intersect.c' fi if test -f 'libray/libobj/roots.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'libray/libobj/roots.c'\" else echo shar: Extracting \"'libray/libobj/roots.c'\" \(4798 characters\) sed "s/^X//" >'libray/libobj/roots.c' <<'END_OF_FILE' X/* X * Roots3And4.c X * X * Utility functions to find cubic and quartic roots, X * coefficients are passed like this: X * X * c[0] + c[1]*x + c[2]*x^2 + c[3]*x^3 + c[4]*x^4 = 0 X * X * The functions return the number of non-complex roots and X * put the values into the s array. X * X * Author: Jochen Schwarze (schwarze@isa.de) X * 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 * , 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 */ X X#include "libcommon/common.h" X Xextern double sqrt(), cbrt(), cos(), acos(); X X/* epsilon surrounding for near zero values */ X X/* X * In case M_PI isn't defined in math.h X */ X#ifndef M_PI X#define M_PI PI X#endif X X#define EQN_EPS 1e-9 X#define IsZero(x) ((x) > -EQN_EPS && (x) < EQN_EPS) X 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 X X Xint SolveQuadric(c, s) X double c[ 3 ]; X double s[ 2 ]; X{ X double p, q, D; X X /* normal form: x^2 + px + q = 0 */ X X p = c[ 1 ] / (2 * c[ 2 ]); X q = c[ 0 ] / c[ 2 ]; X X D = p * p - q; X 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 X s[ 0 ] = sqrt_D - p; X s[ 1 ] = - sqrt_D - p; X return 2; X } X else /* if (D < 0) */ X return 0; X} X X Xint SolveCubic(c, s) X double c[ 4 ]; X double s[ 3 ]; X{ X int i, num; X double sub; X double A, B, C; X double sq_A, p, q; X double cb_p, D; X X /* normal form: x^3 + Ax^2 + Bx + C = 0 */ X X A = c[ 2 ] / c[ 3 ]; X B = c[ 1 ] / c[ 3 ]; X C = c[ 0 ] / c[ 3 ]; X X /* substitute x = y - A/3 to eliminate quadric term: X x^3 +px + q = 0 */ X 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 X /* use Cardano's formula */ X X cb_p = p * p * p; X D = q * q + cb_p; X X if (IsZero(D)) X { X if (IsZero(q)) /* one triple solution */ X { X s[ 0 ] = 0; X num = 1; X } X else /* one single and one double solution */ X { X double u = cbrt(-q); X s[ 0 ] = 2 * u; X s[ 1 ] = - u; X num = 2; X } 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 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 X s[ 0 ] = u + v; X num = 1; X } X X /* resubstitute */ X X sub = 1.0/3 * A; X X for (i = 0; i < num; ++i) X s[ i ] -= sub; X X return num; X} X X Xint SolveQuartic(c, s) X double c[ 5 ]; X double s[ 4 ]; X{ 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 X /* normal form: x^4 + Ax^3 + Bx^2 + Cx + D = 0 */ X 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 X /* substitute x = y - A/4 to eliminate cubic term: X x^4 + px^2 + qx + r = 0 */ X 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 X if (IsZero(r)) X { X /* no absolute term: y(y^3 + py + q) = 0 */ X X coeffs[ 0 ] = q; X coeffs[ 1 ] = p; X coeffs[ 2 ] = 0; X coeffs[ 3 ] = 1; X X num = SolveCubic(coeffs, s); X X s[ num++ ] = 0; X } X else X { X /* solve the resolvent cubic ... */ X 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 X (void) SolveCubic(coeffs, s); X X /* ... and take the one real solution ... */ X X z = s[ 0 ]; X X /* ... to build two quadric equations */ X X u = z * z - r; X v = 2 * z - p; X X if (IsZero(u)) X u = 0; X else if (u > 0) X u = sqrt(u); X else X return 0; X X if (IsZero(v)) X v = 0; X else if (v > 0) X v = sqrt(v); X else X return 0; X X coeffs[ 0 ] = z - u; X coeffs[ 1 ] = q < 0 ? -v : v; X coeffs[ 2 ] = 1; X X num = SolveQuadric(coeffs, s); X X coeffs[ 0 ]= z + u; X coeffs[ 1 ] = q < 0 ? v : -v; X coeffs[ 2 ] = 1; X X num += SolveQuadric(coeffs, s + num); X } X X /* resubstitute */ X X sub = 1.0/4 * A; X X for (i = 0; i < num; ++i) X s[ i ] -= sub; X X return num; X} X END_OF_FILE if test 4798 -ne `wc -c <'libray/libobj/roots.c'`; then echo shar: \"'libray/libobj/roots.c'\" unpacked with wrong size! fi # end of 'libray/libobj/roots.c' fi if test -f 'libray/libobj/sphere.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'libray/libobj/sphere.c'\" else echo shar: Extracting \"'libray/libobj/sphere.c'\" \(4775 characters\) sed "s/^X//" >'libray/libobj/sphere.c' <<'END_OF_FILE' X/* X * sphere.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: sphere.c,v 4.0 91/07/17 14:39:17 kolb Exp Locker: kolb $ X * X * $Log: sphere.c,v $ X * Revision 4.0 91/07/17 14:39:17 kolb X * Initial version. X * X */ X#include "geom.h" X#include "sphere.h" X Xstatic Methods *iSphereMethods = NULL; Xstatic char sphereName[] = "sphere"; X Xunsigned long SphTests, SphHits; X X/* X * Create & return reference to a sphere. X */ XSphere * XSphereCreate(r, pos) XFloat r; XVector *pos; X{ X Sphere *sphere; X X if (r < EPSILON) { X RLerror(RL_WARN, "Degenerate sphere.\n"); X return (Sphere *)NULL; X } X X sphere = (Sphere *)share_malloc(sizeof(Sphere)); X /* 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 X return sphere; X} X XMethods * XSphereMethods() X{ 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 } X return iSphereMethods; X} X X/* X * Ray/sphere intersection test. X */ Xint XSphereIntersect(sph, ray, mindist, maxdist) XSphere *sph; XRay *ray; XFloat mindist, *maxdist; X{ X Float xadj, yadj, zadj; X Float b, t, s; X X SphTests++; X /* 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 X /* 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 } X return FALSE; X } X s = b + t; X if (s > mindist && s < *maxdist) { X *maxdist = s; X SphHits++; X return TRUE; X } X return FALSE; X} X X/* X * Compute normal to sphere at pos X */ Xint XSphereNormal(sphere, pos, nrm, gnrm) XSphere *sphere; XVector *pos, *nrm, *gnrm; X{ 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} X X/* X * Determine if ray enters (TRUE) or leaves (FALSE) sphere at pos X */ Xint XSphereEnter(sphere, ray, mind, hitd) XSphere *sphere; XRay *ray; XFloat mind, hitd; X{ X Vector pos; X X VecAddScaled(ray->pos, mind, ray->dir, &pos); X pos.x -= sphere->x; X pos.y -= sphere->y; X pos.z -= sphere->z; X X return dotp(&pos, &pos) > sphere->rsq; X} X X/*ARGSUSED*/ Xvoid XSphereUV(sphere, pos, norm, uv, dpdu, dpdv) XSphere *sphere; XVector *pos, *norm, *dpdu, *dpdv; XVec2d *uv; X{ X Float phi, theta; X Vector realnorm; X 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 X uv->v = phi / PI; X 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 X if (realnorm.y > 0) X uv->u = theta; X else X uv->u = 1 - theta; X } 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); X } X} X Xvoid XSphereBounds(s, bounds) XSphere *s; XFloat bounds[2][3]; X{ 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; X} X Xchar * XSphereName() X{ X return sphereName; X} X Xvoid XSphereStats(tests, hits) Xunsigned long *tests, *hits; X{ X *tests = SphTests; X *hits = SphHits; X} X Xvoid XSphereMethodRegister(meth) XUserMethodType meth; X{ X if (iSphereMethods) X iSphereMethods->user = meth; X} END_OF_FILE if test 4775 -ne `wc -c <'libray/libobj/sphere.c'`; then echo shar: \"'libray/libobj/sphere.c'\" unpacked with wrong size! fi # end of 'libray/libobj/sphere.c' fi if test -f 'libshade/misc.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'libshade/misc.c'\" else echo shar: Extracting \"'libshade/misc.c'\" \(4260 characters\) sed "s/^X//" >'libshade/misc.c' <<'END_OF_FILE' X/* X * misc.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: misc.c,v 4.0.1.1 92/01/14 18:29:05 cek Exp Locker: cek $ X * X * $Log: misc.c,v $ X * Revision 4.0.1.1 92/01/14 18:29:05 cek X * patch3: Added support for switching cpp on/off. X * X * Revision 4.0 91/07/17 14:46:31 kolb X * Initial version. X * X */ X#include "rayshade.h" X#ifdef RUSAGE X#include X#include X#else X#ifdef TIMES X#include X#include X#include X#endif X#endif X#include "options.h" X#include "stats.h" X XFloat RSabstmp; /* Temporary value used by fabs macro. Ugly. */ Xstatic void RSmessage(); X X/* X * Open input file and call yyparse(). X */ Xvoid XRSReadInputFile() X{ X extern FILE *yyin; /* lex/yacc file pointer */ X extern char yyfilename[]; X X#if defined(CPPSTDIN) && defined(POPEN) X char cmd[BUFSIZ]; X 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 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 } X X if (Options.cpp) { X yyin = popen(cmd, "r"); X if (yyin == (FILE *)NULL) X RLerror(RL_PANIC, "popen of \"%s\" failed!\n", cmd); X } else { X#endif 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 } X#if defined(CPPSTDIN) && defined(POPEN) X } X#endif X /* X * Initialize symbol table. X */ X SymtabInit(); X (void)yyparse(); X} X Xvoid XOpenStatsFile() X{ X if (Options.statsname == (char *)NULL || Stats.fstats != stderr) X return; /* Not specified or already opened. */ X 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); X } X} X Xvoid XRLerror(level, pat, arg1, arg2, arg3) Xint level; Xchar *pat, *arg1, *arg2, *arg3; X{ 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); X } X} X Xstatic void XRSmessage(type, pat, arg1, arg2, arg3) Xchar *type, *pat, *arg1, *arg2, *arg3; X{ X extern FILE *yyin; X extern int yylineno; X extern char yyfilename[]; X 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 } X fprintf(stderr, pat, arg1, arg2, arg3); X} X X#ifdef RUSAGE Xvoid XRSGetCpuTime(usertime, systime) XFloat *usertime, *systime; X{ X struct rusage usage; X X getrusage(RUSAGE_SELF, &usage); X 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} X X#else X#ifdef TIMES X Xvoid XRSGetCpuTime(usertime, systime) XFloat *usertime, *systime; X{ X extern CLOCKTYPE times(); X struct tms time; X X (void)times(&time); X *usertime = (Float)time.tms_utime / (Float)HZ; X *systime = (Float)time.tms_stime / (Float)HZ; X} X X#else /* !RUSAGE && !TIMES */ X Xvoid XRSGetCpuTime(usertime, systime) XFloat *usertime, *systime; X{ X *usertime = *systime = 0.; X} X X#endif /* TIMES */ X#endif /* RUSAGE */ END_OF_FILE if test 4260 -ne `wc -c <'libshade/misc.c'`; then echo shar: \"'libshade/misc.c'\" unpacked with wrong size! fi # end of 'libshade/misc.c' fi if test -f 'libshade/stats.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'libshade/stats.c'\" else echo shar: Extracting \"'libshade/stats.c'\" \(4043 characters\) sed "s/^X//" >'libshade/stats.c' <<'END_OF_FILE' X/* X * stats.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: stats.c,v 4.0 91/07/17 14:47:41 kolb Exp Locker: kolb $ X * X * $Log: stats.c,v $ X * Revision 4.0 91/07/17 14:47:41 kolb X * Initial version. X * X */ X#include X#include "rayshade.h" X#include "options.h" X#include "stats.h" X XRSStats Stats; /* Statistical information */ XGeom *GeomRep = NULL; /* Linked list of object representatives */ X Xstatic void PrintGeomStats(); X Xvoid XStatsPrint() X{ X extern void PrintMemoryStats(); X unsigned long TotalRays; X 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 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 } 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); X} X Xstatic void XPrintGeomStats() X{ X Geom *otmp; X unsigned long tests, hits, totaltests, totalhits; X char *name; X extern void GeomStats(); X X totaltests = totalhits = 0; X 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 } X } 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); X} X Xvoid XStatsAddRep(obj) XGeom *obj; X{ X Geom *otmp; X X for (otmp = GeomRep; otmp; otmp = otmp->next) { X if (otmp->methods->stats == obj->methods->stats) X return; X } X X /* 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; X} END_OF_FILE if test 4043 -ne `wc -c <'libshade/stats.c'`; then echo shar: \"'libshade/stats.c'\" unpacked with wrong size! fi # end of 'libshade/stats.c' fi 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 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