home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume21 / rayshade / part08 (.txt) < prev    next >
LaTeX Document  |  1991-07-21  |  53KB  |  1,568 lines

  1. Newsgroups: comp.sources.misc
  2. From: Rayshade Construction Co. <rayshade@weedeater.math.YALE.EDU>
  3. Subject:  v21i011:  rayshade - A raytracing package for UNIX, Part08/19
  4. Message-ID: <1991Jul21.033530.28980@sparky.IMD.Sterling.COM>
  5. X-Md4-Signature: 1ec025725cfa48faa06a8a934d79ef56
  6. Date: Sun, 21 Jul 1991 03:35:30 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8. Submitted-by: Rayshade Construction Co. <rayshade@weedeater.math.YALE.EDU>
  9. Posting-number: Volume 21, Issue 11
  10. Archive-name: rayshade/part08
  11. Environment: UNIX, !16BIT
  12. #! /bin/sh
  13. # This is a shell archive.  Remove anything before this line, then unpack
  14. # it by saving it into a file and typing "sh file".  To overwrite existing
  15. # files, type "sh file -c".  You can also feed this as standard input via
  16. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  17. # will see the following message at the end:
  18. #        "End of archive 8 (of 19)."
  19. # Contents:  Doc/Guide/animate.tex etc/rsconvert/lex.l
  20. #   libray/libobj/cylinder.c libray/libobj/disc.c
  21. #   libray/libobj/roots.c libray/libobj/sphere.c
  22. #   libray/libsurf/surfshade.c libray/libtext/texture.c
  23. #   libshade/misc.c libshade/stats.c
  24. # Wrapped by kolb@woody on Wed Jul 17 17:56:47 1991
  25. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  26. if test -f 'Doc/Guide/animate.tex' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'Doc/Guide/animate.tex'\"
  28. echo shar: Extracting \"'Doc/Guide/animate.tex'\" \(4147 characters\)
  29. sed "s/^X//" >'Doc/Guide/animate.tex' <<'END_OF_FILE'
  30. X\chapter{Animation}
  31. X\Rayshade provides basic animation animation support by
  32. Xallowing time-varying
  33. Xtransformations to be associated with primitives and aggregate objects.
  34. XCommands are provided for controlling the amount of time between each
  35. Xframe, the speed of the camera shutter, and the total number of frames
  36. Xto be rendered.
  37. XBy default, rayshade renders a single frame, with the shutter open for
  38. Xan instant (0 units of time, in fact).  The shutter speed in no way
  39. Xchanges the light-gathering properties of the camera, i.e. frames
  40. Xrendered using
  41. Xa longer exposure will not appear brighter than those with a shorter
  42. Xexposure.  The only change will be in the potential amount of movement
  43. Xthat the
  44. Xframe ``sees'' during the time that the shutter is open.
  45. XEach ray cast by \rayshade samples a particular moment in time.
  46. XThe time value assigned to a ray
  47. Xranges from the starting time of the current frame to the starting
  48. Xtime plus the amount of time the shutter is open.  When
  49. Xa ray encounters an object or texture that possesses an animated
  50. Xtransformation, the transformed
  51. Xentity is moved into whatever position is appropriate
  52. Xfor the ray's current time value before intersection, shading, or texturing
  53. Xcomputations are performed.
  54. XThe starting time of the current frame is computed using the
  55. Xlength of each frame
  56. Xthe current frame number, and the starting time of the first frame.
  57. X\begin{defkey}{shutter}{{\em t}}
  58. X    Specifies that the shutter is open for t units of
  59. X    time for each exposure.
  60. X\end{defkey}
  61. XA larger value of {\em t} will lead to more motion blur in the final
  62. Ximage.   Note that {\em t} may be greater than the actual length
  63. Xof a frame.  By default, {\em t} is zero, which prevents all motion blur.
  64. X\begin{defkey}{framelength}{{\em frameinc}}
  65. X    Specifies the time increment between frames.
  66. X\end{defkey}
  67. XThe default time between frames is 1 unit.
  68. X\begin{defkey}{starttime}{{\em time}}
  69. X    Specifies the starting time of the first frame.
  70. X\end{defkey}
  71. XBy default, {\em time} is zero.
  72. XVariables may be defined thorugh the use of the {\tt define} keyword:
  73. X\begin{defkey}{define}{{\em name value}}
  74. X    Associate {\em name} with the given {\em value}.  Value may
  75. X    be a constant or a parenthesized expression.
  76. X\end{defkey}
  77. XThe variable {\em name} may thereafter be used in expressions in the
  78. Xinput file.
  79. XAn animated transformation is one for which animated expressions have
  80. Xbeen used to define one or more of its parameters (e.g. the angle through
  81. Xwhich a rotation occurs).  An animated expression is one that makes
  82. Xuse of a time-varying (``animated'') variable or function.
  83. XThere are two supported animated variables.
  84. XThe first, {\tt time}, is equal to the current time.
  85. XWhen a ray encounters an animated
  86. Xtransformation defined using an expression containing {\tt time}, the ray
  87. Xsubstitutes its time value into the expression before evaluation.
  88. XUsing the {\tt time} variable in an animated expression is the most
  89. Xbasic way to create blur-causing motion.
  90. XThe second animated variable, {\tt frame}, is equal to the current
  91. Xframe number.  Unlike the {\tt time} variable, {\tt frame} takes on
  92. Xa single value for the duration of each frame.  Thus, transforms
  93. Xanimated through the use of the {\tt frame} variable will not exhibit
  94. Xmotion blurring.
  95. XAlso supported is the {\tt linear} function.  This function uses
  96. X{\tt time} implicitly to interplate between two values.
  97. X\begin{defkey}{linear}{{\tt (} {\em Stime, Sval, Etime, Eval} {\tt )}}
  98. X    Linearly interpolate between {\em Sval} at time
  99. X    {\em Stime} and {\em Eval} at time {\em Etime}.
  100. X    If the current time is less than {\em Stime}, the function
  101. X    returns {\em Sval}.  If the current time is greater than
  102. X    {\em Etime}, {\em Eval} is returned.
  103. X\end{defkey}
  104. XThe following example shows the use of the {\tt time} variable to
  105. Xanimate a sphere by translating it downwards over five frames.
  106. XNote thet the {\tt shutter} keyword is used to set the shutter duration
  107. Xin order to induce motion blurring.
  108. X\begin{verbatim}
  109. X    frames 5
  110. X    shutter 1
  111. X    sphere 1 0 0 2 translate 0 0 (-time)
  112. X\end{verbatim}
  113. XFurther examples of animation may be found in the Examples directory
  114. Xof the \rayshade distribution.
  115. END_OF_FILE
  116. if test 4147 -ne `wc -c <'Doc/Guide/animate.tex'`; then
  117.     echo shar: \"'Doc/Guide/animate.tex'\" unpacked with wrong size!
  118. # end of 'Doc/Guide/animate.tex'
  119. if test -f 'etc/rsconvert/lex.l' -a "${1}" != "-c" ; then 
  120.   echo shar: Will not clobber existing file \"'etc/rsconvert/lex.l'\"
  121. echo shar: Extracting \"'etc/rsconvert/lex.l'\" \(4148 characters\)
  122. sed "s/^X//" >'etc/rsconvert/lex.l' <<'END_OF_FILE'
  123. X/* lex.l                                   */
  124. X/* Copyright (C) 1989, 1991, Craig E. Kolb                   */
  125. X/* All rights reserved.                               */
  126. X/*                                       */
  127. X/* This software may be freely copied, modified, and redistributed,       */
  128. X/* provided that this copyright notice is preserved on all copies.       */
  129. X/*                                       */
  130. X/* You may not distribute this software, in whole or in part, as part of   */
  131. X/* any commercial product without the express consent of the authors.       */
  132. X/*                                        */
  133. X/* There is no warranty or other guarantee of fitness of this software       */
  134. X/* for any purpose.  It is provided solely "as is".               */
  135. X/* $Id: lex.l,v 4.0 91/07/17 14:29:16 kolb Exp Locker: kolb $ */
  136. X#include "config.h"
  137. X#include <stdio.h>
  138. X#ifdef I_STRING
  139. X#include <string.h>
  140. X#else
  141. X#include <strings.h>
  142. X#endif
  143. X#include "libcommon/common.h"
  144. X#include "y.tab.h"
  145. Xalpha    [a-zA-Z]
  146. Xspecial    [\.\_-]
  147. Xdigit    [0-9]
  148. Xexp    [Ee][-+]?{digit}+
  149. Xstring    ({alpha}|"/")({alpha}|{digit}|{special}|"/")*
  150. X%p 3000
  151. X[\t\n]            {WriteVerbatim(yytext);};
  152. X" "            {};
  153. X^#            {handlehash();}
  154. X"/*"            {skipcomments();}
  155. Xadaptive        {return(tADAPTIVE);}
  156. Xaperture        {return(tAPERTURE);}
  157. Xbackground        {return(tBACKGROUND);}
  158. Xblotch            {return(tBLOTCH);}
  159. Xbox            {return(tBOX);}
  160. Xbump            {return(tBUMP);}
  161. Xchecker            {return(tCHECKER);}
  162. Xcone            {return(tCONE);}
  163. Xcontrast        {return(tCONTRAST);}
  164. Xcutoff            {return(tCUTOFF);}
  165. Xcylinder        {return(tCYL);}
  166. Xdefend            {return(tENDDEF);}
  167. Xdefine            {return(tSTARTDEF);}
  168. Xdirectional        {return(tDIRECTIONAL);}
  169. Xendfile            {return(tENDFILE);}
  170. Xextended        {return(tEXTENDED);}
  171. Xeyep            {return(tEYEP);}
  172. Xfbm            {return(tFBM);}
  173. Xfbmbump            {return(tFBMBUMP);}
  174. Xfocaldist        {return(tFOCALDIST);}
  175. Xfog            {return(tFOG);}
  176. Xfov            {return(tFOV);}
  177. Xgloss            {return(tGLOSS);}
  178. Xgrid            {return(tGRID);}
  179. Xheightfield        {return(tHEIGHTFIELD);}
  180. Xjittered        {return(tJITTERED);}
  181. Xlight            {return(tLIGHT);}
  182. Xlist            {return(tLIST);}
  183. Xlookp            {return(tLOOKP);}
  184. Xmarble            {return(tMARBLE);}
  185. Xmaxdepth        {return(tMAXDEPTH);}
  186. Xmist            {return(tMIST);}
  187. Xobject            {return(tOBJECT);}
  188. Xoutfile            {return(tOUTFILE);}
  189. Xplane            {return(tPLANE);}
  190. Xpoint            {return(tPOINT);}
  191. Xpoly            {return(tPOLY);}
  192. Xresolution        {return(tRESOLUTION);}
  193. Xrotate            {return(tROTATE);}
  194. Xsamples            {return(tSAMPLES);}
  195. Xscale            {return(tSCALE);}
  196. Xscreen            {return(tSCREEN);}
  197. Xsphere            {return(tSPHERE);}
  198. Xsuperq            {return(tSUPERQ);}
  199. Xsurface            {return(tSURFACE);}
  200. Xtexture            {return(tTEXTURE);}
  201. Xtransform        {return(tTRANSFORM);}
  202. Xtranslate        {return(tTRANSLATE);}
  203. Xtriangle        {return(tTRIANGLE);}
  204. Xup            {return(tUP);}
  205. Xwood            {return(tWOOD);}
  206. X{string}        {yylval.c = strsave(yytext);
  207. X                return(tSTRING);}
  208. X[+-]?{digit}+        {yylval.i = atoi(yytext);
  209. X                return(tINT);}
  210. X[+-]?{digit}+"."{digit}*({exp})? |
  211. X[+-]?{digit}*"."{digit}+({exp})? |
  212. X[+-]?{digit}+{exp}        {yylval.d = atof(yytext); return(tFLOAT);}
  213. X.            {return yytext[0];}
  214. Xyywrap() {return(1);}
  215. X * Skip over comments.
  216. Xskipcomments()
  217. X    char c;
  218. X    WriteVerbatim("/*");
  219. X    while (1) {
  220. X        while ((c = input()) != '*')
  221. X            WriteChar(c);
  222. X        WriteChar(c);
  223. X        if ((c = input()) == '/') {
  224. X            WriteChar(c);
  225. X            return;
  226. X        unput(c);
  227. X * Deal with ccp-produced lines of the form:
  228. X * # n "filename"
  229. X * and
  230. X * # n
  231. X * Where filename is the name of the file being processed, and n is
  232. X * the current line number in that file.
  233. Xhandlehash()
  234. X    char buf[BUFSIZ];
  235. X    int i;
  236. X    extern int yylineno;
  237. X    extern char yyfilename[];
  238. X     * Read the entire line into buf.
  239. X     */
  240. X    for (i = 0; (buf[i] = input()) != '\n'; i++)
  241. X            ;
  242. X    unput(buf[i]);        /* To make sure consecutive # lines work. */
  243. X    buf[i] = (char)NULL;    /* Replace newline with NULL. */
  244. X     * Check to see if it's #include or
  245. X     * #define.
  246. X     * If so just spit out the line.
  247. X     */
  248. X    if (strncmp("include", buf, 7) == 0 || strncmp("define", buf, 6) == 0) {
  249. X        WriteVerbatim("#");
  250. X        WriteVerbatim(buf);
  251. X        return;
  252. X     * Complain if the line was not of the form #n "filename"
  253. X     */
  254. X    if ((i = sscanf(buf, "%d \"%[^\"]s\"", &yylineno, yyfilename)) == 0) {
  255. X        yyerror("Unknown '#' control.");
  256. X        exit(1);
  257. X    if (i == 1) {
  258. X#ifdef SYSV
  259. X        if (strchr(buf, '"') != (char *)0) {
  260. X#else
  261. X        if (index(buf, '"') != (char *)0) {
  262. X#endif
  263. X            /*
  264. X             * Filename was "", which means stdin.
  265. X             */
  266. X            strcpy(yyfilename, "stdin");
  267. END_OF_FILE
  268. if test 4148 -ne `wc -c <'etc/rsconvert/lex.l'`; then
  269.     echo shar: \"'etc/rsconvert/lex.l'\" unpacked with wrong size!
  270. # end of 'etc/rsconvert/lex.l'
  271. if test -f 'libray/libobj/cylinder.c' -a "${1}" != "-c" ; then 
  272.   echo shar: Will not clobber existing file \"'libray/libobj/cylinder.c'\"
  273. echo shar: Extracting \"'libray/libobj/cylinder.c'\" \(4773 characters\)
  274. sed "s/^X//" >'libray/libobj/cylinder.c' <<'END_OF_FILE'
  275. X * cylinder.c
  276. X * Copyright (C) 1989, 1991, Craig E. Kolb
  277. X * All rights reserved.
  278. X * This software may be freely copied, modified, and redistributed
  279. X * provided that this copyright notice is preserved on all copies.
  280. X * You may not distribute this software, in whole or in part, as part of
  281. X * any commercial product without the express consent of the authors.
  282. X * There is no warranty or other guarantee of fitness of this software
  283. X * for any purpose.  It is provided solely "as is".
  284. X * $Id: cylinder.c,v 4.0 91/07/17 14:37:12 kolb Exp Locker: kolb $
  285. X * $Log:    cylinder.c,v $
  286. X * Revision 4.0  91/07/17  14:37:12  kolb
  287. X * Initial version.
  288. X#include "geom.h"
  289. X#include "cylinder.h"
  290. Xstatic Methods *iCylinderMethods = NULL;
  291. Xstatic char cylName[] = "cylinder";
  292. Xunsigned long CylTests, CylHits;
  293. XCylinder *
  294. XCylinderCreate(r, bot, top)
  295. XFloat r;
  296. XVector *bot, *top;
  297. X    Cylinder *cyl;
  298. X    Float len;
  299. X    Vector axis;
  300. X    if (r <= 0.) {
  301. X        RLerror(RL_WARN, "Invalid cylinder radius.\n");
  302. X        return (Cylinder*)NULL;
  303. X    VecSub(*top, *bot, &axis);
  304. X    len = VecNormalize(&axis);
  305. X    if (len < EPSILON) {
  306. X        RLerror(RL_WARN, "Degenerate cylinder.\n");
  307. X        return (Cylinder *)NULL;
  308. X    cyl = (Cylinder *)share_malloc(sizeof(Cylinder));
  309. X    CoordSysTransform(bot, &axis, r, len, &cyl->trans);
  310. X    return cyl;
  311. XMethods *
  312. XCylinderMethods()
  313. X    if (iCylinderMethods == (Methods *)NULL) {
  314. X        iCylinderMethods = MethodsCreate();
  315. X        iCylinderMethods->name = CylinderName;
  316. X        iCylinderMethods->create = (GeomCreateFunc *)CylinderCreate;
  317. X        iCylinderMethods->methods = CylinderMethods;
  318. X        iCylinderMethods->intersect = CylinderIntersect;
  319. X        iCylinderMethods->normal = CylinderNormal;
  320. X        iCylinderMethods->uv = CylinderUV;
  321. X        iCylinderMethods->bounds = CylinderBounds;
  322. X        iCylinderMethods->stats = CylinderStats;
  323. X        iCylinderMethods->checkbounds = TRUE;
  324. X        iCylinderMethods->closed = FALSE;
  325. X    return iCylinderMethods;
  326. X * Ray-cylinder intersection test.
  327. XCylinderIntersect(cyl, ray, mindist, maxdist)
  328. XCylinder *cyl;
  329. XRay *ray;
  330. XFloat mindist, *maxdist;
  331. X    Float t1, t2, a, b, c, zpos1, zpos2, disc;
  332. X    Float distfact;
  333. X    Ray newray;
  334. X    Vector nray, npos;
  335. X    Float nmin;
  336. X    CylTests++;
  337. X     * Transform ray into canonical cylinder space.
  338. X     */
  339. X    newray = *ray;
  340. X    distfact = RayTransform(&newray, &cyl->trans.itrans);
  341. X    nray = newray.dir;
  342. X    npos = newray.pos;
  343. X    nmin = mindist * distfact;
  344. X    a = nray.x * nray.x + nray.y * nray.y;
  345. X    if (a < EPSILON*EPSILON)
  346. X        /* |nray.z| == 1. */
  347. X        return FALSE;
  348. X    b = nray.x * npos.x + nray.y * npos.y;
  349. X    c = npos.x*npos.x + npos.y*npos.y - 1;
  350. X    disc = b*b - a*c;
  351. X    if(disc < 0.)
  352. X        return FALSE;
  353. X    disc = sqrt(disc);
  354. X    t1 = (-b + disc) / a;
  355. X    t2 = (-b - disc) / a;
  356. X    if (t1 < nmin && t2 < nmin)
  357. X        return FALSE;
  358. X    zpos1 = npos.z + t1 * nray.z;
  359. X    zpos2 = npos.z + t2 * nray.z;
  360. X    if (t1 < nmin || zpos1 < 0. || zpos1 > 1.) {
  361. X        if (t2 < nmin || zpos2 < 0. || zpos2 > 1.)
  362. X            return FALSE;
  363. X        else
  364. X            t1 = t2 / distfact;
  365. X    } else {
  366. X        if (t2 < nmin || zpos2 < 0. || zpos2 > 1.)
  367. X            t1 /= distfact;
  368. X        else {
  369. X            t1 = min(t1, t2) / distfact;
  370. X    if (t1 < *maxdist) {
  371. X        *maxdist = t1;
  372. X        CylHits++;
  373. X        return TRUE;
  374. X    return FALSE;
  375. XCylinderNormal(cyl, pos, nrm, gnrm)
  376. XCylinder *cyl;
  377. XVector *pos, *nrm, *gnrm;
  378. X     * Transform position into cylinder space.
  379. X     */
  380. X    *nrm = *pos;
  381. X    PointTransform(nrm, &cyl->trans.itrans);
  382. X     * The normal is equal to the point of intersection in cylinder
  383. X     * space, but with Z = 0.;
  384. X     */
  385. X    nrm->z = 0.;
  386. X     * Tranform normal back to world space.
  387. X     */
  388. X    NormalTransform(nrm, &cyl->trans.itrans);
  389. X    *gnrm = *nrm;
  390. X    return FALSE;
  391. Xvoid
  392. XCylinderUV(cyl, pos, norm, uv, dpdu, dpdv)
  393. XCylinder *cyl;
  394. XVector *pos, *norm, *dpdu, *dpdv;
  395. XVec2d *uv;
  396. X    Vector npos;
  397. X    npos = *pos;
  398. X    PointTransform(&npos, &cyl->trans.itrans);
  399. X    uv->v = npos.z;
  400. X     * Due to roundoff error, |npos.x| may be > 1.
  401. X     */
  402. X    if (npos.x > 1.)
  403. X        uv->u = 0.;
  404. X    else if (npos.x < -1.)
  405. X        uv->u = 0.5;
  406. X    else
  407. X        uv->u = acos(npos.x) / TWOPI;
  408. X    if (npos.y < 0.)
  409. X        uv->u = 1. - uv->u;
  410. X    if (dpdu) {
  411. X        dpdv->x = dpdv->y = 0.;
  412. X        dpdv->z = 1.;
  413. X        dpdu->x = -npos.y;
  414. X        dpdu->y = npos.x;
  415. X        dpdu->z = 0.;
  416. X        VecTransform(dpdu, &cyl->trans.trans);
  417. X        VecTransform(dpdv, &cyl->trans.trans);
  418. X        (void)VecNormalize(dpdu);
  419. X        (void)VecNormalize(dpdv);
  420. Xvoid
  421. XCylinderBounds(cyl, bounds)
  422. XCylinder *cyl;
  423. XFloat bounds[2][3];
  424. X    bounds[LOW][X] = bounds[LOW][Y] = -1;
  425. X    bounds[HIGH][X] = bounds[HIGH][Y] = 1;
  426. X    bounds[LOW][Z] = 0.;
  427. X    bounds[HIGH][Z] = 1;
  428. X     * Transform bounding box to world space.
  429. X     */
  430. X    BoundsTransform(&cyl->trans.trans, bounds);
  431. Xchar *
  432. XCylinderName()
  433. X    return cylName;
  434. Xvoid
  435. XCylinderStats(tests, hits)
  436. Xunsigned long *tests, *hits;
  437. X    *tests = CylTests;
  438. X    *hits = CylHits;
  439. Xvoid
  440. XCylinderMethodRegister(meth)
  441. XUserMethodType meth;
  442. X    if (iCylinderMethods)
  443. X        iCylinderMethods->user = meth;
  444. END_OF_FILE
  445. if test 4773 -ne `wc -c <'libray/libobj/cylinder.c'`; then
  446.     echo shar: \"'libray/libobj/cylinder.c'\" unpacked with wrong size!
  447. # end of 'libray/libobj/cylinder.c'
  448. if test -f 'libray/libobj/disc.c' -a "${1}" != "-c" ; then 
  449.   echo shar: Will not clobber existing file \"'libray/libobj/disc.c'\"
  450. echo shar: Extracting \"'libray/libobj/disc.c'\" \(4405 characters\)
  451. sed "s/^X//" >'libray/libobj/disc.c' <<'END_OF_FILE'
  452. X * disc.c
  453. X * Copyright (C) 1989, 1991, Craig E. Kolb
  454. X * All rights reserved.
  455. X * This software may be freely copied, modified, and redistributed
  456. X * provided that this copyright notice is preserved on all copies.
  457. X * You may not distribute this software, in whole or in part, as part of
  458. X * any commercial product without the express consent of the authors.
  459. X * There is no warranty or other guarantee of fitness of this software
  460. X * for any purpose.  It is provided solely "as is".
  461. X * $Id: disc.c,v 4.0 91/07/17 14:37:23 kolb Exp Locker: kolb $
  462. X * $Log:    disc.c,v $
  463. X * Revision 4.0  91/07/17  14:37:23  kolb
  464. X * Initial version.
  465. X#include "geom.h"
  466. X#include "disc.h"
  467. Xstatic Methods *iDiscMethods = NULL;
  468. Xstatic char discName[] = "disc";
  469. Xunsigned long DiscTests, DiscHits;
  470. XDisc *
  471. XDiscCreate(r, pos, norm)
  472. XFloat r;
  473. XVector *pos, *norm;
  474. X    Disc *disc;        /* Pointer to new disc. */
  475. X    if (r < EPSILON) {
  476. X        RLerror(RL_WARN, "Degenerate disc.\n");
  477. X            /*
  478. X             * Don't create this primitive.
  479. X             */
  480. X            return (Disc *)NULL;
  481. X    if (VecNormalize(norm) == 0.) {
  482. X        RLerror(RL_WARN, "Degenerate disc normal.\n");
  483. X        return (Disc *)NULL;
  484. X     * Allocate new Disc.
  485. X     */
  486. X    disc = (Disc *)share_malloc(sizeof(Disc));
  487. X     * Initialize new disc.
  488. X     * We store the square of the radius to save us a sqrt().
  489. X     */
  490. X    disc->radius = r*r;
  491. X    disc->pos = *pos;
  492. X    disc->norm = *norm;
  493. X     * Compute plane constant.
  494. X     */
  495. X    disc->d = dotp(pos, norm);
  496. X     * Allocate new primitive
  497. X     */
  498. X    return disc;
  499. XMethods *
  500. XDiscMethods()
  501. X    if (iDiscMethods == (Methods *)NULL) {
  502. X        iDiscMethods = MethodsCreate();
  503. X        iDiscMethods->name = DiscName;
  504. X        iDiscMethods->create = (GeomCreateFunc *)DiscCreate;
  505. X        iDiscMethods->methods = DiscMethods;
  506. X        iDiscMethods->intersect = DiscIntersect;
  507. X        iDiscMethods->normal = DiscNormal;
  508. X        iDiscMethods->uv = DiscUV;
  509. X        iDiscMethods->bounds = DiscBounds;
  510. X        iDiscMethods->stats = DiscStats;
  511. X        iDiscMethods->checkbounds = FALSE;
  512. X        iDiscMethods->closed = FALSE;
  513. X    return iDiscMethods;
  514. XDiscIntersect(disc, ray, mindist, maxdist)
  515. XDisc *disc;
  516. XRay *ray;
  517. XFloat mindist, *maxdist;
  518. X    Vector hit;
  519. X    Float denom, dist;
  520. X    DiscTests++;
  521. X    denom = dotp(&disc->norm, &ray->dir);
  522. X    if (fabs(denom) < EPSILON)
  523. X        /* Edge-on intersection */
  524. X         return FALSE;
  525. X    dist = (disc->d - dotp(&disc->norm, &ray->pos)) / denom;
  526. X    if (dist < mindist || dist > *maxdist)
  527. X        /* Too close or too far */
  528. X        return FALSE;
  529. X     *  Find difference between point of intersection and center of disc.
  530. X     */
  531. X    VecAddScaled(ray->pos, dist, ray->dir, &hit);
  532. X    VecSub(hit, disc->pos, &hit);
  533. X     * If hit point is <= disc->radius from center, we've hit the disc.
  534. X     */
  535. X    if (dotp(&hit, &hit) <= disc->radius) {
  536. X        *maxdist = dist;
  537. X        DiscHits++;
  538. X        return TRUE;
  539. X    return FALSE;
  540. XDiscNormal(disc, pos, nrm, gnrm)
  541. XDisc *disc;
  542. XVector *pos, *nrm, *gnrm;
  543. X    *gnrm = *nrm = disc->norm;
  544. X    return FALSE;
  545. Xvoid
  546. XDiscUV(disc, pos, norm, uv, dpdu, dpdv)
  547. XDisc *disc;
  548. XVector *pos, *norm, *dpdu, *dpdv;
  549. XVec2d *uv;
  550. X    Float dist, val;
  551. X    dist =    (pos->x - disc->pos.x) * (pos->x - disc->pos.x) +
  552. X        (pos->y - disc->pos.y) * (pos->y - disc->pos.y) +
  553. X        (pos->z - disc->pos.z) * (pos->z - disc->pos.z);
  554. X    if (dist < EPSILON) {
  555. X        uv->u = uv->v = 0.;
  556. X        return;
  557. X    dist = sqrt(dist);
  558. X    uv->v = dist / sqrt(disc->radius); /* should store r and r*r */
  559. X    val = pos->x / dist;
  560. X    if (fabs(val) > 1.)
  561. X        uv->u = 0.5;
  562. X    else {
  563. X        uv->u = acos(val) / TWOPI; 
  564. X        if (pos->y < 0.)
  565. X            uv->u = 1. - uv->u;
  566. X    if (dpdu) {
  567. X        VecSub(*pos, disc->pos, dpdv);
  568. X        /* dpdu = dpdv X norm */
  569. X        VecCross(dpdv, norm, dpdu);
  570. Xvoid
  571. XDiscBounds(disc, bounds)
  572. XDisc *disc;
  573. XFloat bounds[2][3];
  574. X    Float extent, rad;
  575. X    rad = sqrt(disc->radius);
  576. X     * Project disc along each of X, Y and Z axes.
  577. X     */
  578. X    extent = rad * sqrt(1. - disc->norm.x * disc->norm.x);
  579. X    bounds[LOW][X] = disc->pos.x - extent;
  580. X    bounds[HIGH][X] = disc->pos.x + extent;
  581. X    extent = rad * sqrt(1. - disc->norm.y * disc->norm.y);
  582. X    bounds[LOW][Y] = disc->pos.y - extent;
  583. X    bounds[HIGH][Y] = disc->pos.y + extent;
  584. X    extent = rad * sqrt(1. - disc->norm.z * disc->norm.z);
  585. X    bounds[LOW][Z] = disc->pos.z - extent;
  586. X    bounds[HIGH][Z] = disc->pos.z + extent;
  587. Xchar *
  588. XDiscName()
  589. X    return discName;
  590. Xvoid
  591. XDiscStats(tests, hits)
  592. Xunsigned long *tests, *hits;
  593. X    *tests = DiscTests;
  594. X    *hits = DiscHits;
  595. Xvoid
  596. XDiscMethodRegister(meth)
  597. XUserMethodType meth;
  598. X    if (iDiscMethods)
  599. X        iDiscMethods->user = meth;
  600. END_OF_FILE
  601. if test 4405 -ne `wc -c <'libray/libobj/disc.c'`; then
  602.     echo shar: \"'libray/libobj/disc.c'\" unpacked with wrong size!
  603. # end of 'libray/libobj/disc.c'
  604. if test -f 'libray/libobj/roots.c' -a "${1}" != "-c" ; then 
  605.   echo shar: Will not clobber existing file \"'libray/libobj/roots.c'\"
  606. echo shar: Extracting \"'libray/libobj/roots.c'\" \(4798 characters\)
  607. sed "s/^X//" >'libray/libobj/roots.c' <<'END_OF_FILE'
  608. X *  Roots3And4.c
  609. X *  Utility functions to find cubic and quartic roots,
  610. X *  coefficients are passed like this:
  611. X *      c[0] + c[1]*x + c[2]*x^2 + c[3]*x^3 + c[4]*x^4 = 0
  612. X *  The functions return the number of non-complex roots and
  613. X *  put the values into the s array.
  614. X *  Author:         Jochen Schwarze (schwarze@isa.de)
  615. X *  Jan 26, 1990    Version for Graphics Gems
  616. X *  Oct 11, 1990    Fixed sign problem for negative q's in SolveQuartic
  617. X *                  (reported by Mark Podlipec),
  618. X *                  Old-style function definitions,
  619. X *                  IsZero() as a macro
  620. X *  Nov 23, 1990    Some systems do not declare acos() and cbrt() in
  621. X *                  <math.h>, though the functions exist in the library.
  622. X *                  If large coefficients are used, EQN_EPS should be
  623. X *                  reduced considerably (e.g. to 1E-30), results will be
  624. X *                  correct but multiple roots might be reported more
  625. X *                  than once.
  626. X#include "libcommon/common.h"
  627. Xextern double   sqrt(), cbrt(), cos(), acos();
  628. X/* epsilon surrounding for near zero values */
  629. X * In case M_PI isn't defined in math.h
  630. X#ifndef M_PI
  631. X#define M_PI PI
  632. X#endif
  633. X#define     EQN_EPS     1e-9
  634. X#define        IsZero(x)    ((x) > -EQN_EPS && (x) < EQN_EPS)
  635. X#ifndef CBRT
  636. X#define     cbrt(x)     ((x) > 0.0 ? pow((double)(x), 1.0/3.0) : \
  637. X              ((x) < 0.0 ? -pow((double)-(x), 1.0/3.0) : 0.0))
  638. X#endif
  639. Xint SolveQuadric(c, s)
  640. X    double c[ 3 ];
  641. X    double s[ 2 ];
  642. X    double p, q, D;
  643. X    /* normal form: x^2 + px + q = 0 */
  644. X    p = c[ 1 ] / (2 * c[ 2 ]);
  645. X    q = c[ 0 ] / c[ 2 ];
  646. X    D = p * p - q;
  647. X    if (IsZero(D))
  648. X    {
  649. X    s[ 0 ] = - p;
  650. X    return 1;
  651. X    }
  652. X    else if (D > 0)
  653. X    {
  654. X    double sqrt_D = sqrt(D);
  655. X    s[ 0 ] =   sqrt_D - p;
  656. X    s[ 1 ] = - sqrt_D - p;
  657. X    return 2;
  658. X    }
  659. X    else /* if (D < 0) */
  660. X        return 0;
  661. Xint SolveCubic(c, s)
  662. X    double c[ 4 ];
  663. X    double s[ 3 ];
  664. X    int     i, num;
  665. X    double  sub;
  666. X    double  A, B, C;
  667. X    double  sq_A, p, q;
  668. X    double  cb_p, D;
  669. X    /* normal form: x^3 + Ax^2 + Bx + C = 0 */
  670. X    A = c[ 2 ] / c[ 3 ];
  671. X    B = c[ 1 ] / c[ 3 ];
  672. X    C = c[ 0 ] / c[ 3 ];
  673. X    /*  substitute x = y - A/3 to eliminate quadric term:
  674. X    x^3 +px + q = 0 */
  675. X    sq_A = A * A;
  676. X    p = 1.0/3 * (- 1.0/3 * sq_A + B);
  677. X    q = 1.0/2 * (2.0/27 * A * sq_A - 1.0/3 * A * B + C);
  678. X    /* use Cardano's formula */
  679. X    cb_p = p * p * p;
  680. X    D = q * q + cb_p;
  681. X    if (IsZero(D))
  682. X    {
  683. X    if (IsZero(q)) /* one triple solution */
  684. X        s[ 0 ] = 0;
  685. X        num = 1;
  686. X    else /* one single and one double solution */
  687. X        double u = cbrt(-q);
  688. X        s[ 0 ] = 2 * u;
  689. X        s[ 1 ] = - u;
  690. X        num = 2;
  691. X    }
  692. X    else if (D < 0) /* Casus irreducibilis: three real solutions */
  693. X    {
  694. X    double phi = 1.0/3 * acos(-q / sqrt(-cb_p));
  695. X    double t = 2 * sqrt(-p);
  696. X    s[ 0 ] =   t * cos(phi);
  697. X    s[ 1 ] = - t * cos(phi + M_PI / 3);
  698. X    s[ 2 ] = - t * cos(phi - M_PI / 3);
  699. X    num = 3;
  700. X    }
  701. X    else /* one real solution */
  702. X    {
  703. X    double sqrt_D = sqrt(D);
  704. X    double u = cbrt(sqrt_D - q);
  705. X    double v = - cbrt(sqrt_D + q);
  706. X    s[ 0 ] = u + v;
  707. X    num = 1;
  708. X    }
  709. X    /* resubstitute */
  710. X    sub = 1.0/3 * A;
  711. X    for (i = 0; i < num; ++i)
  712. X    s[ i ] -= sub;
  713. X    return num;
  714. Xint SolveQuartic(c, s)
  715. X    double c[ 5 ]; 
  716. X    double s[ 4 ];
  717. X    double  coeffs[ 4 ];
  718. X    double  z, u, v, sub;
  719. X    double  A, B, C, D;
  720. X    double  sq_A, p, q, r;
  721. X    int     i, num;
  722. X    /* normal form: x^4 + Ax^3 + Bx^2 + Cx + D = 0 */
  723. X    A = c[ 3 ] / c[ 4 ];
  724. X    B = c[ 2 ] / c[ 4 ];
  725. X    C = c[ 1 ] / c[ 4 ];
  726. X    D = c[ 0 ] / c[ 4 ];
  727. X    /*  substitute x = y - A/4 to eliminate cubic term:
  728. X    x^4 + px^2 + qx + r = 0 */
  729. X    sq_A = A * A;
  730. X    p = - 3.0/8 * sq_A + B;
  731. X    q = 1.0/8 * sq_A * A - 1.0/2 * A * B + C;
  732. X    r = - 3.0/256*sq_A*sq_A + 1.0/16*sq_A*B - 1.0/4*A*C + D;
  733. X    if (IsZero(r))
  734. X    {
  735. X    /* no absolute term: y(y^3 + py + q) = 0 */
  736. X    coeffs[ 0 ] = q;
  737. X    coeffs[ 1 ] = p;
  738. X    coeffs[ 2 ] = 0;
  739. X    coeffs[ 3 ] = 1;
  740. X    num = SolveCubic(coeffs, s);
  741. X    s[ num++ ] = 0;
  742. X    }
  743. X    else
  744. X    {
  745. X    /* solve the resolvent cubic ... */
  746. X    coeffs[ 0 ] = 1.0/2 * r * p - 1.0/8 * q * q;
  747. X    coeffs[ 1 ] = - r;
  748. X    coeffs[ 2 ] = - 1.0/2 * p;
  749. X    coeffs[ 3 ] = 1;
  750. X    (void) SolveCubic(coeffs, s);
  751. X    /* ... and take the one real solution ... */
  752. X    z = s[ 0 ];
  753. X    /* ... to build two quadric equations */
  754. X    u = z * z - r;
  755. X    v = 2 * z - p;
  756. X    if (IsZero(u))
  757. X        u = 0;
  758. X    else if (u > 0)
  759. X        u = sqrt(u);
  760. X    else
  761. X        return 0;
  762. X    if (IsZero(v))
  763. X        v = 0;
  764. X    else if (v > 0)
  765. X        v = sqrt(v);
  766. X    else
  767. X        return 0;
  768. X    coeffs[ 0 ] = z - u;
  769. X    coeffs[ 1 ] = q < 0 ? -v : v;
  770. X    coeffs[ 2 ] = 1;
  771. X    num = SolveQuadric(coeffs, s);
  772. X    coeffs[ 0 ]= z + u;
  773. X    coeffs[ 1 ] = q < 0 ? v : -v;
  774. X    coeffs[ 2 ] = 1;
  775. X    num += SolveQuadric(coeffs, s + num);
  776. X    }
  777. X    /* resubstitute */
  778. X    sub = 1.0/4 * A;
  779. X    for (i = 0; i < num; ++i)
  780. X    s[ i ] -= sub;
  781. X    return num;
  782. END_OF_FILE
  783. if test 4798 -ne `wc -c <'libray/libobj/roots.c'`; then
  784.     echo shar: \"'libray/libobj/roots.c'\" unpacked with wrong size!
  785. # end of 'libray/libobj/roots.c'
  786. if test -f 'libray/libobj/sphere.c' -a "${1}" != "-c" ; then 
  787.   echo shar: Will not clobber existing file \"'libray/libobj/sphere.c'\"
  788. echo shar: Extracting \"'libray/libobj/sphere.c'\" \(4775 characters\)
  789. sed "s/^X//" >'libray/libobj/sphere.c' <<'END_OF_FILE'
  790. X * sphere.c
  791. X * Copyright (C) 1989, 1991, Craig E. Kolb
  792. X * All rights reserved.
  793. X * This software may be freely copied, modified, and redistributed
  794. X * provided that this copyright notice is preserved on all copies.
  795. X * You may not distribute this software, in whole or in part, as part of
  796. X * any commercial product without the express consent of the authors.
  797. X * There is no warranty or other guarantee of fitness of this software
  798. X * for any purpose.  It is provided solely "as is".
  799. X * $Id: sphere.c,v 4.0 91/07/17 14:39:17 kolb Exp Locker: kolb $
  800. X * $Log:    sphere.c,v $
  801. X * Revision 4.0  91/07/17  14:39:17  kolb
  802. X * Initial version.
  803. X#include "geom.h"
  804. X#include "sphere.h"
  805. Xstatic Methods *iSphereMethods = NULL;
  806. Xstatic char sphereName[] = "sphere";
  807. Xunsigned long SphTests, SphHits;
  808. X * Create & return reference to a sphere.
  809. XSphere *
  810. XSphereCreate(r, pos)
  811. XFloat r;
  812. XVector *pos;
  813. X    Sphere *sphere;
  814. X    if (r < EPSILON) {
  815. X        RLerror(RL_WARN, "Degenerate sphere.\n");
  816. X        return (Sphere *)NULL;
  817. X    sphere = (Sphere *)share_malloc(sizeof(Sphere));
  818. X     * sphere->rsq holds the square of the radius.
  819. X     */
  820. X    sphere->r = r;
  821. X    sphere->rsq = r*r;
  822. X    sphere->x = pos->x;
  823. X    sphere->y = pos->y;
  824. X    sphere->z = pos->z;
  825. X    return sphere;
  826. XMethods *
  827. XSphereMethods()
  828. X    if (iSphereMethods == (Methods *)NULL) {
  829. X        iSphereMethods = MethodsCreate();
  830. X        iSphereMethods->create = (GeomCreateFunc *)SphereCreate;
  831. X        iSphereMethods->methods = SphereMethods;
  832. X        iSphereMethods->name = SphereName;
  833. X        iSphereMethods->intersect = SphereIntersect;
  834. X        iSphereMethods->normal = SphereNormal;
  835. X        iSphereMethods->uv = SphereUV;
  836. X        iSphereMethods->enter = SphereEnter;
  837. X        iSphereMethods->bounds = SphereBounds;
  838. X        iSphereMethods->stats = SphereStats;
  839. X        iSphereMethods->checkbounds = TRUE;
  840. X        iSphereMethods->closed = TRUE;
  841. X    return iSphereMethods;
  842. X * Ray/sphere intersection test.
  843. XSphereIntersect(sph, ray, mindist, maxdist)
  844. XSphere *sph;
  845. XRay *ray;
  846. XFloat mindist, *maxdist;
  847. X    Float xadj, yadj, zadj;
  848. X    Float b, t, s;
  849. X    SphTests++;
  850. X     * Translate ray origin to object space and negate everything.
  851. X     * (Thus, we translate the sphere into ray space, which saves
  852. X     * us a couple of negations below.)
  853. X     */
  854. X    xadj = sph->x - ray->pos.x;
  855. X    yadj = sph->y - ray->pos.y;
  856. X    zadj = sph->z - ray->pos.z;
  857. X     * Solve quadratic equation.
  858. X     */
  859. X    b = xadj * ray->dir.x + yadj * ray->dir.y + zadj * ray->dir.z;
  860. X    t = b * b - xadj * xadj - yadj * yadj - zadj * zadj + sph->rsq;
  861. X    if (t < 0.)
  862. X        return FALSE;
  863. X    t = (Float)sqrt((double)t);
  864. X    s = b - t;
  865. X    if (s > mindist) {
  866. X        if (s < *maxdist) {
  867. X            *maxdist = s;
  868. X            SphHits++;
  869. X            return TRUE;
  870. X        return FALSE;
  871. X    s = b + t;
  872. X    if (s > mindist && s < *maxdist) {
  873. X        *maxdist = s;
  874. X        SphHits++;
  875. X        return TRUE;
  876. X    return FALSE;
  877. X * Compute normal to sphere at pos
  878. XSphereNormal(sphere, pos, nrm, gnrm)
  879. XSphere *sphere;
  880. XVector *pos, *nrm, *gnrm;
  881. X    nrm->x = (pos->x - sphere->x) / sphere->r;
  882. X    nrm->y = (pos->y - sphere->y) / sphere->r;
  883. X    nrm->z = (pos->z - sphere->z) / sphere->r;
  884. X    *gnrm = *nrm;
  885. X    return FALSE;
  886. X * Determine if ray enters (TRUE) or leaves (FALSE) sphere at pos
  887. XSphereEnter(sphere, ray, mind, hitd)
  888. XSphere *sphere;
  889. XRay *ray;
  890. XFloat mind, hitd;
  891. X    Vector pos;
  892. X    VecAddScaled(ray->pos, mind, ray->dir, &pos);
  893. X    pos.x -= sphere->x;
  894. X    pos.y -= sphere->y;
  895. X    pos.z -= sphere->z;
  896. X    return dotp(&pos, &pos) > sphere->rsq;
  897. X/*ARGSUSED*/
  898. Xvoid
  899. XSphereUV(sphere, pos, norm, uv, dpdu, dpdv)
  900. XSphere *sphere;
  901. XVector *pos, *norm, *dpdu, *dpdv;
  902. XVec2d *uv;
  903. X    Float phi, theta;
  904. X    Vector realnorm;
  905. X    realnorm.x = pos->x - sphere->x;
  906. X    realnorm.y = pos->y - sphere->y;
  907. X    realnorm.z = pos->z - sphere->z;
  908. X    VecNormalize( &realnorm );
  909. X    if (realnorm.z > 1.)    /* roundoff */
  910. X        phi = PI;
  911. X    else if (realnorm.z < -1.)
  912. X        phi = 0;
  913. X    else
  914. X        phi = acos(-realnorm.z);
  915. X    uv->v = phi / PI;
  916. X    if (fabs(uv->v) < EPSILON || equal(uv->v, 1.))
  917. X        uv->u = 0.;
  918. X    else {
  919. X        theta = realnorm.x / sin(phi);
  920. X        if (theta > 1.)
  921. X            theta = 0.;
  922. X        else if (theta < -1.)
  923. X            theta = 0.5;
  924. X        else
  925. X            theta = acos(theta) / TWOPI;
  926. X        if (realnorm.y > 0)
  927. X            uv->u = theta;
  928. X        else
  929. X            uv->u = 1 - theta;
  930. X    if (dpdu != (Vector *)0) {
  931. X        dpdu->x = -realnorm.y;
  932. X        dpdu->y = realnorm.x;
  933. X        dpdu->z = 0.;
  934. X        (void)VecNormalize(dpdu);
  935. X        (void)VecNormCross(&realnorm, dpdu, dpdv);
  936. Xvoid
  937. XSphereBounds(s, bounds)
  938. XSphere *s;
  939. XFloat bounds[2][3];
  940. X    bounds[LOW][X] = s->x - s->r;
  941. X    bounds[HIGH][X] = s->x + s->r;
  942. X    bounds[LOW][Y] = s->y - s->r;
  943. X    bounds[HIGH][Y] = s->y + s->r;
  944. X    bounds[LOW][Z] = s->z - s->r;
  945. X    bounds[HIGH][Z] = s->z + s->r;
  946. Xchar *
  947. XSphereName()
  948. X    return sphereName;
  949. Xvoid
  950. XSphereStats(tests, hits)
  951. Xunsigned long *tests, *hits;
  952. X    *tests = SphTests;
  953. X    *hits = SphHits;
  954. Xvoid
  955. XSphereMethodRegister(meth)
  956. XUserMethodType meth;
  957. X    if (iSphereMethods)
  958. X        iSphereMethods->user = meth;
  959. END_OF_FILE
  960. if test 4775 -ne `wc -c <'libray/libobj/sphere.c'`; then
  961.     echo shar: \"'libray/libobj/sphere.c'\" unpacked with wrong size!
  962. # end of 'libray/libobj/sphere.c'
  963. if test -f 'libray/libsurf/surfshade.c' -a "${1}" != "-c" ; then 
  964.   echo shar: Will not clobber existing file \"'libray/libsurf/surfshade.c'\"
  965. echo shar: Extracting \"'libray/libsurf/surfshade.c'\" \(4829 characters\)
  966. sed "s/^X//" >'libray/libsurf/surfshade.c' <<'END_OF_FILE'
  967. X * surfshade.c
  968. X * Copyright (C) 1989, 1991, Craig E. Kolb
  969. X * All rights reserved.
  970. X * This software may be freely copied, modified, and redistributed
  971. X * provided that this copyright notice is preserved on all copies.
  972. X * You may not distribute this software, in whole or in part, as part of
  973. X * any commercial product without the express consent of the authors.
  974. X * There is no warranty or other guarantee of fitness of this software
  975. X * for any purpose.  It is provided solely "as is".
  976. X * $Id: surfshade.c,v 4.0 91/07/17 14:41:15 kolb Exp Locker: kolb $
  977. X * $Log:    surfshade.c,v $
  978. X * Revision 4.0  91/07/17  14:41:15  kolb
  979. X * Initial version.
  980. X#include "libobj/geom.h"
  981. X#include "surface.h"
  982. X * Compute surface properties from given hitlist
  983. X * Returns TRUE if ray is entering object, FALSE otherwise.
  984. XComputeSurfProps(hitlist, ray, pos, norm, gnorm, surf, smooth)
  985. XHitList *hitlist;    /* Hit information (path through DAG) */
  986. XRay *ray;        /* Ray in world space */
  987. XVector *pos;        /* Intersection point */
  988. XVector *norm, *gnorm;    /* shading normal, geometric normal (return values) */
  989. XSurface *surf;        /* Copy of surface to use, texture-modified */
  990. Xint *smooth;
  991. X    HitNode *hp;
  992. X    int i;
  993. X    Ray rtmp;
  994. X    Geom *prim, *obj;
  995. X    Float k, kp;
  996. X    int texturing, transforming, entering;
  997. X    Trans prim2model, world2model;
  998. X    hp = hitlist->data;
  999. X    prim = hp->obj;
  1000. X     * Compute point of intersection in "primitive space".
  1001. X     */
  1002. X    VecAddScaled(hp->ray.pos, hp->dist, hp->ray.dir, pos);
  1003. X     * Find normal to primitive at point of intersection.
  1004. X     */
  1005. X    *smooth = PrimNormal(prim, pos, norm, gnorm);
  1006. X    texturing = transforming = FALSE;
  1007. X     * Walk down hit list, constructing world<-->primitive transformation
  1008. X     * and determining if we need to perform texture mapping.
  1009. X     * The last node is the World node, which cannot be textured or
  1010. X     * transformed, so we skip it.
  1011. X     */
  1012. X    for (i = 0, hp = hitlist->data; i < hitlist->nodes -1; hp++, i++) {
  1013. X        obj = hp->obj;
  1014. X        if (hp->dotrans) {
  1015. X            /*
  1016. X             * Here we're actually computing prim2world.
  1017. X             * When finished, we invert it.
  1018. X             */
  1019. X            if (transforming) {
  1020. X                TransCompose(&hp->trans, &world2model,
  1021. X                    &world2model);
  1022. X            } else {
  1023. X                TransCopy(&hp->trans, &world2model);
  1024. X            }
  1025. X            transforming = TRUE;
  1026. X        if (obj->texture)
  1027. X            texturing = TRUE;
  1028. X     * Determine if we're entering or exiting the surface,
  1029. X     * flipping surface normals if necessary.
  1030. X     */
  1031. X    k = dotp(&hitlist->data[0].ray.dir, norm);
  1032. X    if (*smooth) {
  1033. X        /*
  1034. X         * If gnorm and shading norm differ and
  1035. X         * their dot products with the ray have
  1036. X         * different signs, use the geometric normal
  1037. X         * instead, ala Snyder & Barr's paper.
  1038. X         */
  1039. X        kp = dotp(&hitlist->data[0].ray.dir, gnorm);
  1040. X        if (k <= 0. && kp > 0. || k >= 0. && kp < 0.)
  1041. X            k = kp;
  1042. X    if (k > 0.) {
  1043. X        /* flip normals */
  1044. X        VecScale(-1., *gnorm, gnorm);
  1045. X        VecScale(-1., *norm, norm);
  1046. X        /*
  1047. X         * Normal indicates that we're exiting.
  1048. X         * Only set entering to TRUE if csg has indicated
  1049. X         * that the ray is, indeed, entering.
  1050. X         */
  1051. X        entering = (hitlist->data[0].enter == ENTERING);
  1052. X    } else {
  1053. X        /*
  1054. X         * Normal indicates that we're entering.
  1055. X         * Set entering flag as such unless csg has
  1056. X         * told us that we're exiting.
  1057. X         */
  1058. X        entering = !(hitlist->data[0].enter == EXITING);
  1059. X     * If there are no transformations, then world2model is identity.
  1060. X     */
  1061. X    if (!transforming)
  1062. X        TransInit(&world2model);
  1063. X     * If we're not performing texturing, we simply need to compute
  1064. X     * the normal and point of intersection to world space.
  1065. X     */
  1066. X    if (!texturing) {
  1067. X        /*
  1068. X          * At this point 'world2model' is really 'prim2world'.
  1069. X         */
  1070. X        if (transforming) {
  1071. X            NormalTransform(norm, &world2model.itrans);
  1072. X            NormalTransform(gnorm, &world2model.itrans);
  1073. X            VecAddScaled(ray->pos,
  1074. X                     hitlist->data[hitlist->nodes -1].dist,
  1075. X                     ray->dir, pos);
  1076. X        return entering;
  1077. X     * world2model currently transforms from primitive to world space.
  1078. X     * Invert it to get transformation from world to primitive space.
  1079. X     */
  1080. X    TransInvert(&world2model, &world2model);
  1081. X    TransInit(&prim2model);
  1082. X    rtmp = hitlist->data[0].ray;
  1083. X     * Walk down hitlist.
  1084. X     */
  1085. X    for (hp = hitlist->data, i = 0; i < hitlist->nodes -1; i++, hp++) {
  1086. X        obj = hp->obj;
  1087. X        if (hp->dotrans) {
  1088. X            NormalTransform(norm, &hp->trans.itrans);
  1089. X            if (texturing) {
  1090. X                /*
  1091. X                 * Compose prim<-->model and world<-->model
  1092. X                 * with current transformation.
  1093. X                 */
  1094. X                TransCompose(&hp->trans, &prim2model,
  1095. X                    &prim2model);
  1096. X                TransCompose(&hp->trans, &world2model,
  1097. X                    &world2model);
  1098. X                /*
  1099. X                 * Transform point and ray to model space.
  1100. X                 */
  1101. X                PointTransform(pos, &hp->trans.trans);
  1102. X                (void)RayTransform(&rtmp, &hp->trans.trans);
  1103. X            }
  1104. X        /*
  1105. X         * Apply textures
  1106. X         */
  1107. X        if (obj->texture)
  1108. X            TextApply(obj->texture, prim, &rtmp, pos, norm,
  1109. X                gnorm, surf, &prim2model, &world2model);
  1110. X    return entering;
  1111. END_OF_FILE
  1112. if test 4829 -ne `wc -c <'libray/libsurf/surfshade.c'`; then
  1113.     echo shar: \"'libray/libsurf/surfshade.c'\" unpacked with wrong size!
  1114. # end of 'libray/libsurf/surfshade.c'
  1115. if test -f 'libray/libtext/texture.c' -a "${1}" != "-c" ; then 
  1116.   echo shar: Will not clobber existing file \"'libray/libtext/texture.c'\"
  1117. echo shar: Extracting \"'libray/libtext/texture.c'\" \(4973 characters\)
  1118. sed "s/^X//" >'libray/libtext/texture.c' <<'END_OF_FILE'
  1119. X * texture.c
  1120. X * Copyright (C) 1989, 1991, Craig E. Kolb
  1121. X * All rights reserved.
  1122. X * This software may be freely copied, modified, and redistributed
  1123. X * provided that this copyright notice is preserved on all copies.
  1124. X * You may not distribute this software, in whole or in part, as part of
  1125. X * any commercial product without the express consent of the authors.
  1126. X * There is no warranty or other guarantee of fitness of this software
  1127. X * for any purpose.  It is provided solely "as is".
  1128. X * $Id: texture.c,v 4.0 91/07/17 14:44:11 kolb Exp Locker: kolb $
  1129. X * $Log:    texture.c,v $
  1130. X * Revision 4.0  91/07/17  14:44:11  kolb
  1131. X * Initial version.
  1132. X#include "texture.h"
  1133. X * Transformation structures used to map from texture space to
  1134. X * model/primitive/world space.
  1135. XTrans prim2model, model2text, prim2text, world2text;
  1136. X#define ApplyMapping(m,o,p,n,c,u,v)    (*m->method)(m, o, p, n, c, u, v)
  1137. XTexture *
  1138. XTextCreate(data, meth)
  1139. XTextRef data;
  1140. Xvoid (*meth)();
  1141. X    Texture *res;
  1142. X    res = (Texture *)share_calloc(1, sizeof(Texture));
  1143. X    res->data = data;
  1144. X    res->method = meth;
  1145. X    res->trans = (Trans *)NULL; 
  1146. X    res->next = (Texture *)NULL;
  1147. X    res->animtrans = FALSE;
  1148. X    return res;
  1149. X * Apply appropriate textures to a surface.
  1150. Xvoid
  1151. XTextApply(tlist, prim, ray, pos, norm, gnorm, surf, p2model, world2model)
  1152. XTexture *tlist;                /* Textures */
  1153. XGeom *prim;
  1154. XRay *ray;
  1155. XVector *pos, *norm, *gnorm;        /* pos, shading norm, geo. norm */
  1156. XSurface *surf;
  1157. XTrans *p2model, *world2model;
  1158. X    Vector ptmp;
  1159. X    Texture *ttmp;
  1160. X    prim2model = *p2model;
  1161. X     * Walk down texture list, applying each in turn.
  1162. X     */
  1163. X    for (ttmp = tlist; ttmp; ttmp = ttmp->next) {
  1164. X        /*
  1165. X         * Make copies of pos & ray to pass to the texturing function.
  1166. X         */
  1167. X        ptmp = *pos;
  1168. X        if (ttmp->trans) {
  1169. X            /*
  1170. X             * 'take' the inverse of ttmp->trans, since
  1171. X             * transforming a texture means applying the
  1172. X             * inverse of the transformation
  1173. X             * to the point of intersection, etc.
  1174. X             */
  1175. X            if (ttmp->animtrans) {
  1176. X                /*
  1177. X                 * Resolve animated associations.
  1178. X                 * We currently do not store a time
  1179. X                 * for the texture, so we can't know if
  1180. X                 * we're already resolved for the current
  1181. X                 * ray->time.
  1182. X                 */
  1183. X                TransResolveAssoc(ttmp->trans);
  1184. X                TransComposeList(ttmp->trans, &model2text);
  1185. X                TransInvert(&model2text, &model2text);
  1186. X            } else
  1187. X                TransInvert(ttmp->trans, &model2text);
  1188. X            /*
  1189. X             * We compose ttmp->trans, which maps from model to
  1190. X             * texture space, with prim2model and world2model
  1191. X             * to get prim2text and world2text.
  1192. X             */
  1193. X            TransCompose(&model2text, &prim2model, &prim2text);
  1194. X            TransCompose(&model2text, world2model, &world2text);
  1195. X            /*
  1196. X             * Transform intersection point to texture space.
  1197. X             * Ray and normal are passed in model space.
  1198. X             */
  1199. X            ModelPointToText(&ptmp);
  1200. X        } else {
  1201. X            /*
  1202. X              * By default, texture and model space are identical.
  1203. X              */
  1204. X            TransInit(&model2text);
  1205. X            TransCopy(&prim2model, &prim2text);
  1206. X            TransCopy(world2model, &world2text);
  1207. X        /*
  1208. X         * Call texture function.
  1209. X         */
  1210. X        (*ttmp->method) (ttmp->data,prim,ray,&ptmp,norm,gnorm,surf);
  1211. X * Compute UV at 'pos' on given primitive.
  1212. XTextToUV(mapping, prim, pos, norm, u, v, dpdu, dpdv)
  1213. XMapping *mapping;
  1214. XGeom *prim;
  1215. XVector *pos, *norm, *dpdu, *dpdv;
  1216. XFloat *u, *v;
  1217. X    Vec2d uv;
  1218. X    Vector ptmp;
  1219. X    RSMatrix t;
  1220. X    ptmp = *pos;
  1221. X    if (mapping->flags & PRIMSPACE) {
  1222. X        /*
  1223. X          * Convert point and normal to primitive space.
  1224. X          */
  1225. X        TextPointToPrim(&ptmp);
  1226. X    } else {
  1227. X        /*
  1228. X         * Convert point and normal to object space.
  1229. X         */
  1230. X        TextPointToModel(&ptmp);
  1231. X    ApplyMapping(mapping, prim, &ptmp, norm, &uv, dpdu, dpdv);
  1232. X     * Transform UV by model2text.  We set X = u and Y = v,
  1233. X     * while Z = 0.
  1234. X     * Although the UV coordinates may be in prim space,
  1235. X     * we treat them as if they are model-space coords.
  1236. X     * This is due to the fact that we want the texture
  1237. X     * to be applied in model space.
  1238. X     */
  1239. X    ptmp.x = uv.u;
  1240. X    ptmp.y = uv.v;
  1241. X    ptmp.z = 0.;
  1242. X    PointTransform(&ptmp, &model2text.trans);
  1243. X    *u = ptmp.x;
  1244. X    *v = ptmp.y;
  1245. X    if (dpdu == (Vector *)NULL || dpdv == (Vector *)NULL)
  1246. X        return;
  1247. X     * Here's the ugly part.
  1248. X     * Build initial UVN-->XYZ matrix...
  1249. X     */
  1250. X    ArbitraryMatrix(dpdu->x, dpdu->y, dpdu->z,
  1251. X             dpdv->x, dpdv->y, dpdv->z,
  1252. X             norm->x, norm->y, norm->z, 0., 0., 0., &t);
  1253. X     * ...transform to model space...
  1254. X     */
  1255. X    MatrixMult(&t, &prim2model.trans, &t);
  1256. X     * ... apply model2text in UVN space.
  1257. X     */
  1258. X    MatrixMult(&model2text.itrans, &t, &t);
  1259. X    dpdu->x = t.matrix[0][0];
  1260. X    dpdu->y = t.matrix[0][1];
  1261. X    dpdu->z = t.matrix[0][2];
  1262. X    dpdv->x = t.matrix[1][0];
  1263. X    dpdv->y = t.matrix[1][1];
  1264. X    dpdv->z = t.matrix[1][2];
  1265. X    (void)VecNormalize(dpdu);
  1266. X    (void)VecNormalize(dpdv);
  1267. X * Append 'text' to the given linked list of textures.
  1268. X * Note that 'text' may be a list, too.
  1269. XTexture *
  1270. XTextAppend(text, list)
  1271. XTexture *text, *list;
  1272. X    Texture *tp;
  1273. X    if (list) {
  1274. X        /*
  1275. X         * Walk to the end of the list
  1276. X         */
  1277. X        for (tp = list;tp->next ;tp = tp->next)
  1278. X                ;
  1279. X        tp->next = text;
  1280. X        return list;
  1281. X    /* else */
  1282. X    return text;
  1283. END_OF_FILE
  1284. if test 4973 -ne `wc -c <'libray/libtext/texture.c'`; then
  1285.     echo shar: \"'libray/libtext/texture.c'\" unpacked with wrong size!
  1286. # end of 'libray/libtext/texture.c'
  1287. if test -f 'libshade/misc.c' -a "${1}" != "-c" ; then 
  1288.   echo shar: Will not clobber existing file \"'libshade/misc.c'\"
  1289. echo shar: Extracting \"'libshade/misc.c'\" \(4080 characters\)
  1290. sed "s/^X//" >'libshade/misc.c' <<'END_OF_FILE'
  1291. X * misc.c
  1292. X * Copyright (C) 1989, 1991, Craig E. Kolb
  1293. X * All rights reserved.
  1294. X * This software may be freely copied, modified, and redistributed
  1295. X * provided that this copyright notice is preserved on all copies.
  1296. X * You may not distribute this software, in whole or in part, as part of
  1297. X * any commercial product without the express consent of the authors.
  1298. X * There is no warranty or other guarantee of fitness of this software
  1299. X * for any purpose.  It is provided solely "as is".
  1300. X * $Id: misc.c,v 4.0 91/07/17 14:46:31 kolb Exp Locker: kolb $
  1301. X * $Log:    misc.c,v $
  1302. X * Revision 4.0  91/07/17  14:46:31  kolb
  1303. X * Initial version.
  1304. X#include "rayshade.h"
  1305. X#ifdef RUSAGE
  1306. X#include <sys/time.h>
  1307. X#include <sys/resource.h>
  1308. X#else
  1309. X#ifdef TIMES
  1310. X#include <sys/types.h>
  1311. X#include <sys/times.h>
  1312. X#include <sys/param.h>
  1313. X#endif
  1314. X#endif
  1315. X#include "options.h"
  1316. X#include "stats.h"
  1317. XFloat RSabstmp;    /* Temporary value used by fabs macro.  Ugly. */
  1318. Xstatic void RSmessage();
  1319. X * Open input file and call yyparse().
  1320. Xvoid
  1321. XRSReadInputFile()
  1322. X    extern FILE *yyin;    /* lex/yacc file pointer */
  1323. X    extern char yyfilename[];
  1324. X#if defined(CPPSTDIN) && defined(POPEN)
  1325. X    char cmd[BUFSIZ];
  1326. X    if (Options.cppargs != (char *)NULL)
  1327. X        sprintf(cmd, "%s %s ", CPPSTDIN, Options.cppargs);
  1328. X    else
  1329. X        /* fromstdin */
  1330. X        sprintf(cmd, "%s %s ", CPPSTDIN, CPPMINUS);
  1331. X    if (Options.inputname == (char *)NULL) {
  1332. X        (void)strcpy(yyfilename, "stdin");
  1333. X    } else {
  1334. X        (void)strcpy(yyfilename, Options.inputname);
  1335. X        (void)strcat(cmd, Options.inputname);
  1336. X    yyin = popen(cmd, "r");
  1337. X    if (yyin == (FILE *)NULL)
  1338. X        RLerror(RL_PANIC, "popen of \"%s\" failed!\n", cmd);
  1339. X#else
  1340. X    if (Options.inputname == (char *)NULL) {
  1341. X        yyin = stdin;
  1342. X        (void)strcpy(yyfilename, "stdin");
  1343. X    } else {
  1344. X        (void)strcpy(yyfilename, Options.inputname);
  1345. X        yyin = fopen(Options.inputname, "r");
  1346. X        if (yyin == (FILE *)NULL)
  1347. X            RLerror(RL_PANIC,
  1348. X                "Cannot open %s.\n",Options.inputname);
  1349. X#endif
  1350. X     * Initialize symbol table.
  1351. X     */
  1352. X    SymtabInit();
  1353. X    (void)yyparse();
  1354. Xvoid
  1355. XOpenStatsFile()
  1356. X    if (Options.statsname == (char *)NULL || Stats.fstats != stderr)
  1357. X        return;        /* Not specified or already opened. */
  1358. X    Stats.fstats = fopen(Options.statsname, "w");
  1359. X    if (Stats.fstats == (FILE *)NULL) {
  1360. X        RLerror(RL_PANIC,
  1361. X            "Cannot open stats file %s.\n", Options.statsname);
  1362. Xvoid
  1363. XRLerror(level, pat, arg1, arg2, arg3)
  1364. Xint level;
  1365. Xchar *pat, *arg1, *arg2, *arg3;
  1366. X    switch (level) {
  1367. X        case RL_ADVISE:
  1368. X            if (!Options.quiet)
  1369. X                RSmessage("Warning", pat, arg1, arg2, arg3);
  1370. X            break;
  1371. X        case RL_WARN:
  1372. X            RSmessage("Warning", pat, arg1, arg2, arg3);
  1373. X            break;
  1374. X        case RL_ABORT:
  1375. X            RSmessage("Error", pat, arg1, arg2, arg3);
  1376. X            exit(1);
  1377. X            break;
  1378. X        case RL_PANIC:
  1379. X            RSmessage("Fatal error", pat, arg1, arg2, arg3);
  1380. X            exit(2);
  1381. X            break;
  1382. X        default:
  1383. X            RSmessage("Unknown error", pat, arg1, arg2, arg3);
  1384. X            exit(3);
  1385. Xstatic void
  1386. XRSmessage(type, pat, arg1, arg2, arg3)
  1387. Xchar *type, *pat, *arg1, *arg2, *arg3;
  1388. X    extern FILE *yyin;
  1389. X    extern int yylineno;
  1390. X    extern char yyfilename[];
  1391. X    if (yyin) {
  1392. X        /*
  1393. X         * cleanup() hasn't nulled yyin, so line #
  1394. X         * info is valid.
  1395. X         */
  1396. X        fprintf(stderr,"%s: %s: %s, line %d: ",
  1397. X            Options.progname, type,
  1398. X            yyfilename == (char *)NULL ? "stdin" :
  1399. X                yyfilename, yylineno);
  1400. X    } else {
  1401. X        fprintf(stderr,"%s: %s: ", Options.progname, type);
  1402. X    fprintf(stderr, pat, arg1, arg2, arg3);
  1403. X#ifdef RUSAGE
  1404. Xvoid
  1405. XRSGetCpuTime(usertime, systime)
  1406. XFloat *usertime, *systime;
  1407. X    struct rusage usage;
  1408. X    getrusage(RUSAGE_SELF, &usage);
  1409. X    *usertime = (Float)usage.ru_utime.tv_sec +
  1410. X            (Float)usage.ru_utime.tv_usec / 1000000.;
  1411. X    *systime = (Float)usage.ru_stime.tv_sec +
  1412. X            (Float)usage.ru_stime.tv_usec / 1000000.;
  1413. X#else
  1414. X#ifdef TIMES
  1415. Xvoid
  1416. XRSGetCpuTime(usertime, systime)
  1417. XFloat *usertime, *systime;
  1418. X    extern CLOCKTYPE times();
  1419. X    struct tms time;
  1420. X    (void)times(&time);
  1421. X    *usertime = (Float)time.tms_utime / (Float)HZ;
  1422. X    *systime = (Float)time.tms_stime / (Float)HZ;
  1423. X#else /* !RUSAGE && !TIMES */
  1424. Xvoid
  1425. XRSGetCpuTime(usertime, systime)
  1426. XFloat *usertime, *systime;
  1427. X    *usertime = *systime = 0.;
  1428. X#endif /* TIMES */
  1429. X#endif /* RUSAGE */
  1430. END_OF_FILE
  1431. if test 4080 -ne `wc -c <'libshade/misc.c'`; then
  1432.     echo shar: \"'libshade/misc.c'\" unpacked with wrong size!
  1433. # end of 'libshade/misc.c'
  1434. if test -f 'libshade/stats.c' -a "${1}" != "-c" ; then 
  1435.   echo shar: Will not clobber existing file \"'libshade/stats.c'\"
  1436. echo shar: Extracting \"'libshade/stats.c'\" \(4043 characters\)
  1437. sed "s/^X//" >'libshade/stats.c' <<'END_OF_FILE'
  1438. X * stats.c
  1439. X * Copyright (C) 1989, 1991, Craig E. Kolb
  1440. X * All rights reserved.
  1441. X * This software may be freely copied, modified, and redistributed
  1442. X * provided that this copyright notice is preserved on all copies.
  1443. X * You may not distribute this software, in whole or in part, as part of
  1444. X * any commercial product without the express consent of the authors.
  1445. X * There is no warranty or other guarantee of fitness of this software
  1446. X * for any purpose.  It is provided solely "as is".
  1447. X * $Id: stats.c,v 4.0 91/07/17 14:47:41 kolb Exp Locker: kolb $
  1448. X * $Log:    stats.c,v $
  1449. X * Revision 4.0  91/07/17  14:47:41  kolb
  1450. X * Initial version.
  1451. X#include <ctype.h>
  1452. X#include "rayshade.h"
  1453. X#include "options.h"
  1454. X#include "stats.h"
  1455. XRSStats Stats;            /* Statistical information */
  1456. XGeom *GeomRep = NULL;    /* Linked list of object representatives */
  1457. Xstatic void PrintGeomStats();
  1458. Xvoid
  1459. XStatsPrint()
  1460. X    extern void PrintMemoryStats();
  1461. X    unsigned long TotalRays;
  1462. X#ifndef LINDA
  1463. X    RSGetCpuTime(&Stats.Utime, &Stats.Stime);
  1464. X#endif
  1465. X    ShadowStats(&Stats.ShadowRays, &Stats.ShadowHits,
  1466. X            &Stats.CacheHits, &Stats.CacheMisses);
  1467. X    IntersectStats(&Stats.BVTests);
  1468. X    TotalRays = Stats.EyeRays + Stats.ShadowRays + Stats.ReflectRays
  1469. X             + Stats.RefractRays;
  1470. X    Stats.ShadowHits += Stats.CacheHits;
  1471. X    Stats.HitRays += Stats.ShadowHits;
  1472. X#ifdef LINDA
  1473. X    fprintf(Stats.fstats,"Workers:\t\t\t%d\n",Options.workers);
  1474. X#endif
  1475. X    fprintf(Stats.fstats,"Eye rays:\t\t\t%lu\n", Stats.EyeRays);
  1476. X    fprintf(Stats.fstats,"Shadow rays:\t\t\t%lu\n",Stats.ShadowRays);
  1477. X    fprintf(Stats.fstats,"Reflected rays:\t\t\t%lu\n",Stats.ReflectRays);
  1478. X    fprintf(Stats.fstats,"Refracted rays:\t\t\t%lu\n",Stats.RefractRays);
  1479. X    fprintf(Stats.fstats,"Total rays:\t\t\t%lu\n", TotalRays);
  1480. X    if (TotalRays != 0)
  1481. X        fprintf(Stats.fstats,"Intersecting rays:\t\t%lu (%3.3f%%)\n",
  1482. X            Stats.HitRays,
  1483. X            100. * (float)Stats.HitRays / (float)TotalRays);
  1484. X    if (Stats.ShadowRays != 0) {
  1485. X        if (Options.cache)
  1486. X            fprintf(Stats.fstats,
  1487. X                "Shadow cache hits:\t\t%lu (%lu misses)\n",
  1488. X                Stats.CacheHits, Stats.CacheMisses);
  1489. X        fprintf(Stats.fstats,"Total shadow hits:\t\t%lu (%3.3f%%)\n",
  1490. X            Stats.ShadowHits, 100.*(float)Stats.ShadowHits /
  1491. X            (float)Stats.ShadowRays);
  1492. X    fprintf(Stats.fstats,"Supersampled pixels:\t\t%lu\n",
  1493. X        Stats.SuperSampled);
  1494. X    fprintf(Stats.fstats,"B.V. intersection tests:\t%lu\n",Stats.BVTests);
  1495. X    PrintGeomStats();
  1496. X#ifdef LINDA
  1497. X    fprintf(Stats.fstats,"Average CPU time/processor:\t");
  1498. X#else
  1499. X    fprintf(Stats.fstats,"Total CPU time (sec):\t\t");
  1500. X#endif
  1501. X    fprintf(Stats.fstats,"%2.2f (%2.2fu + %2.2fs)\n",
  1502. X        Stats.Utime+Stats.Stime, Stats.Utime, Stats.Stime);
  1503. X    if (TotalRays != 0.)
  1504. X        fprintf(Stats.fstats,"Seconds / ray:\t\t\t%4.4f\n",
  1505. X            (Stats.Utime + Stats.Stime) / (Float)TotalRays);
  1506. X    if (Stats.HitRays != 0.)
  1507. X        fprintf(Stats.fstats,"Seconds / intersecting ray:\t%4.4f\n",
  1508. X            (Stats.Utime + Stats.Stime)/(Float)Stats.HitRays);
  1509. X    PrintMemoryStats(Stats.fstats);
  1510. Xstatic void
  1511. XPrintGeomStats()
  1512. X    Geom *otmp;
  1513. X    unsigned long tests, hits, totaltests, totalhits;
  1514. X    char *name;
  1515. X    extern void GeomStats();
  1516. X    totaltests = totalhits = 0;
  1517. X    for (otmp = GeomRep; otmp; otmp = otmp->next) {
  1518. X        GeomStats(otmp, &tests, &hits);
  1519. X        if (tests <= 0)
  1520. X            continue;
  1521. X        name = GeomName(otmp);
  1522. X        fprintf(Stats.fstats,
  1523. X            "%c%s intersection tests:\t%lu (%lu hit, %f%%)\n",
  1524. X                toupper((int)name[0]), &name[1], tests, hits,
  1525. X                100.*(float)hits/(float)tests);
  1526. X        if (!IsAggregate(otmp)) {
  1527. X            totaltests += tests;
  1528. X            totalhits += hits;
  1529. X    fprintf(Stats.fstats,"Total prim. intersection tests:\t%lu",
  1530. X        totaltests);
  1531. X    if (totaltests == 0)
  1532. X        fprintf(Stats.fstats,"\n");
  1533. X    else
  1534. X        fprintf(Stats.fstats," (%lu hit, %f%%)\n", totalhits,
  1535. X            100.*(float)totalhits/(float)totaltests);
  1536. Xvoid
  1537. XStatsAddRep(obj)
  1538. XGeom *obj;
  1539. X    Geom *otmp;
  1540. X    for (otmp = GeomRep; otmp; otmp = otmp->next) {
  1541. X        if (otmp->methods->stats == obj->methods->stats)
  1542. X            return;
  1543. X     * Stats method didn't match anything found so far.  Add
  1544. X     * a copy of obj to head of GeomRep list.
  1545. X     */
  1546. X    otmp = GeomCopy(obj);
  1547. X    otmp->next = GeomRep;
  1548. X    GeomRep = otmp;
  1549. END_OF_FILE
  1550. if test 4043 -ne `wc -c <'libshade/stats.c'`; then
  1551.     echo shar: \"'libshade/stats.c'\" unpacked with wrong size!
  1552. # end of 'libshade/stats.c'
  1553. echo shar: End of archive 8 \(of 19\).
  1554. cp /dev/null ark8isdone
  1555. MISSING=""
  1556. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
  1557.     if test ! -f ark${I}isdone ; then
  1558.     MISSING="${MISSING} ${I}"
  1559.     fi
  1560. if test "${MISSING}" = "" ; then
  1561.     echo You have unpacked all 19 archives.
  1562.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1563.     echo You still need to unpack the following archives:
  1564.     echo "        " ${MISSING}
  1565. ##  End of shell archive.
  1566. exit 0
  1567. exit 0 # Just in case...
  1568.