home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume21 / rayshade / part13 < prev    next >
Encoding:
Text File  |  1991-07-21  |  45.7 KB  |  1,619 lines

  1. Newsgroups: comp.sources.misc
  2. From: Rayshade Construction Co. <rayshade@weedeater.math.YALE.EDU>
  3. Subject:  v21i016:  rayshade - A raytracing package for UNIX, Part13/19
  4. Message-ID: <1991Jul21.033819.29294@sparky.IMD.Sterling.COM>
  5. X-Md4-Signature: 53f3ff77cd6fa10e38fc8bd025d16e01
  6. Date: Sun, 21 Jul 1991 03:38:19 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: Rayshade Construction Co. <rayshade@weedeater.math.YALE.EDU>
  10. Posting-number: Volume 21, Issue 16
  11. Archive-name: rayshade/part13
  12. Environment: UNIX, !16BIT
  13.  
  14. #! /bin/sh
  15. # This is a shell archive.  Remove anything before this line, then unpack
  16. # it by saving it into a file and typing "sh file".  To overwrite existing
  17. # files, type "sh file -c".  You can also feed this as standard input via
  18. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  19. # will see the following message at the end:
  20. #        "End of archive 13 (of 19)."
  21. # Contents:  Doc/Guide/surfaces.tex libray/libcommon/transform.c
  22. #   libray/libobj/csg.c libshade/shade.c
  23. # Wrapped by kolb@woody on Wed Jul 17 17:56:52 1991
  24. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  25. if test -f 'Doc/Guide/surfaces.tex' -a "${1}" != "-c" ; then 
  26.   echo shar: Will not clobber existing file \"'Doc/Guide/surfaces.tex'\"
  27. else
  28. echo shar: Extracting \"'Doc/Guide/surfaces.tex'\" \(10193 characters\)
  29. sed "s/^X//" >'Doc/Guide/surfaces.tex' <<'END_OF_FILE'
  30. X\chapter{Surfaces and Atmospheric Effects}
  31. X
  32. XSurfaces are used to control the interaction between light sources and
  33. Xobjects.  A surface specification consists of information
  34. Xabout how the light interacts with both the exterior and
  35. Xinterior of an object .
  36. XFor non-closed objects, such as polygons,
  37. Xthe ``interior'' of an object is the ``other side'' of the object's surface
  38. Xrelative to the origin of a ray.
  39. X
  40. XRayshade usually ensures that a primitive's surface normal is pointing
  41. Xtowards the origin of the incident ray when performing shading
  42. Xcalculations.  Exceptions to this rule are transparent primitives, for
  43. Xwhich rayshade uses the direction of the surface normal to determine if
  44. Xthe incident ray is entering or exiting the object.
  45. XAll non-transparent primitives will, in effect, be double-sided.
  46. X
  47. X\section{Surface Description}
  48. X
  49. XA surface definition consists of a number of component keywords, each
  50. Xof which is usually followed by either a single number or a red-green-blue
  51. Xcolor triple.   Each of the values in the color triple are normalized,
  52. Xwith zero indicating zero intensity, and one indicating full intensity.
  53. X
  54. XIf any surface component is left unspecified, its value defaults to zero,
  55. Xwith the exception of the index of refraction, which is assigned the
  56. Xdefault index of refraction (normally 1.0).
  57. X
  58. XSurface descriptions are used in rayshade to compute the color of a ray
  59. Xthat strikes the surface at a point \evec{P}. The normal to the surface
  60. Xat \evec{P}, \evec{N}, is also computed.
  61. X
  62. X\begin{defkey}{ambient}{\evec{color}}
  63. X    Use the given {\em color} to approximate those surface-surface 
  64. X    interactions (e.g., diffuse interreflection) not modeled by the
  65. X    ray tracing process.
  66. X\end{defkey}
  67. XA surface's ambient color is always applied to a ray.  The color
  68. Xapplied is computed by multiplying the ambient color by the intensity
  69. Xof the ambient light source.
  70. X
  71. XIf \evec{P} is in shadow with respect to a given light source,
  72. Xthat light source makes no contribution to the shading of \evec{P}.
  73. X
  74. X\begin{defkey}{diffuse}{\evec{color}}
  75. X    Specifies the diffuse color.
  76. X\end{defkey}
  77. XThe diffuse contribution from each non-shadowed light source at \evec{P}
  78. Xis equal to the diffuse color of the surface scaled by the cosine of
  79. Xthe angle between \evec{N}
  80. Xand the vector from \evec{P} to the light source.
  81. X
  82. X\begin{defkey}{specular}{\evec{color}}
  83. X    Specifies the base color of specular reflections.
  84. X\end{defkey}
  85. X
  86. X\begin{defkey}{specpow}{{\em exponent}}
  87. X    Specifies the specular highlight) exponent.
  88. X\end{defkey}
  89. XThe intensity of specular highlights from light sources are
  90. Xscaled by the specular color of the surface.
  91. X
  92. X\begin{defkey}{reflect}{{\em reflectivity}}
  93. X    Specifies the specular reflectivity of the surface.  If non-zero,
  94. X    reflected rays will be spawned.
  95. X\end{defkey}
  96. XThe intensity of specularly reflected rays will be proportional to
  97. Xthe specular color of the surface scaled by the reflectivity.
  98. X
  99. X\begin{defkey}{transp}{{\em transparency}}
  100. X    Specifies the specular transmissivity of the surface.  If
  101. X    non-zero,
  102. X    transmitted (refracted) rays will be spawned.
  103. X\end{defkey}
  104. X
  105. X\begin{defkey}{body}{\evec{color}}
  106. X    Specifies the body color of the object.  The body color
  107. X    affects the color of rays that are transmitted through the
  108. X    object.
  109. X\end{defkey}
  110. X
  111. X\begin{defkey}{extinct}{{\em coefficient}}
  112. X    Specifies the extinction coefficient of the interior
  113. X    of the object.
  114. X\end{defkey}
  115. XThe extinction coefficient is raised to a power equal to the distance
  116. Xthe transmitted ray travels through the object.
  117. XThe overall intensity of specularly transmitted rays will be proportional to
  118. Xthis factor multiplied by the surface's body color
  119. Xmultiplied by the transparency of the object.
  120. X
  121. X\begin{defkey}{index}{{\em N}}
  122. X    Specifies the index of refraction.  The default value is equal
  123. X    to the index of refraction of the atmosphere surrounding the eye.
  124. X\end{defkey}
  125. X
  126. X\begin{defkey}{translucency}{{\em translu} \evec{color} {\em stexp}}
  127. X    Specifies the translucency, diffusely transmitted color,
  128. X    and Phong exponent for transmitted specular highlights.
  129. X\end{defkey}
  130. XIf a light source illuminates a translucent surface from the side opposite
  131. Xthat from which a ray approaches, illumination computations are performed,
  132. Xusing the given color as the surface's diffuse color, and the given
  133. Xexponent as the Phong highlight exponent.  The resulting color is then
  134. Xscaled by the surface's translucency.
  135. X
  136. X\section{Atmospheric Effects}
  137. X
  138. XAny number of atmospheric effects may also be associated with a surface.
  139. XThese effects will be applied to those rays that are transmitted through
  140. Xthe surface.  Applying atmospheric effects to opaque objects is a waste
  141. Xof input file.
  142. X
  143. X\begin{defkey}{fog}{\evec{color} \evec{thinness}}
  144. XAdd exponential fog with the specified {\em thinness} and {\em color}.
  145. X\end{defkey}
  146. XFog is simulated by blending the color of the fog with the color of
  147. Xeach ray.  The amount of fog color blended into a ray color is an exponential
  148. Xfunction of the distance from the ray origin to the point of intersection
  149. Xdivided by the specified {\em thinness} for each color channel.
  150. XIf the distance is equal to {\em thinness},
  151. Xa ray's new color will be half of the fog color plus half its
  152. Xoriginal color.
  153. X
  154. X\begin{defkey}{mist}{\evec{color} \evec{thinness} {\em zero scale}}
  155. XAdd global low-altitude mist of the specified color.  The color of
  156. Xa ray is modulated by a fog with density that varies linearly with
  157. Xthe difference in $z$ coordinate (altitude) between the ray origin and
  158. Xthe point of intersection.  The thinness values specify the transmissivity
  159. Xof the fog for each color channel.
  160. XThe base altitude of the
  161. Xmist is given by {\em zero}, and the apparent height of the mist can
  162. Xbe modulated using {\em scale}, which scales the difference in
  163. Xaltitude used to compute the fog.
  164. X\end{defkey}
  165. X
  166. X\section {The Default Medium}
  167. X
  168. XThe default medium is the medium which surrounds and encompasses
  169. Xall of the objects in the scene; it is the ``air'' through which eye
  170. Xrays usually travel before hitting an object.  The properties of
  171. Xthe default medium may be modified through the use of the {\tt atmosphere}
  172. Xkeyword.
  173. X
  174. X\begin{defkey}{atmosphere}{[{\em N\/}] [{\em atmospheric effects}]}
  175. XIf given, {\em N} specifies the index of refraction of the default
  176. Xmedium.  The default is 1.0.  Any atmospheric effects listed are applied
  177. Xto rays that are exterior to every object in the scene (e.g., rays
  178. Xemanating from the camera).
  179. X\end{defkey}
  180. X
  181. X\begin{verbatim}
  182. X    /*
  183. X     * Red sphere on a grey plane, with fog.
  184. X     */
  185. X    eyep 0. -10. 2.
  186. X    atmosphere fog  .8 .8 .8 14. 14. 14.
  187. X    plane 0 0 0  0 0 1
  188. X    sphere diffuse 0.8 0 0   1.5  0 0 1.5
  189. X\end{verbatim}
  190. X
  191. X\section {Surface Specification}
  192. X
  193. X{\em Rayshade} provides a number of ways to define surfaces and to
  194. Xbind these surfaces to objects.  The most straight-forward method
  195. Xof surface specification is to simply list the surface properties to
  196. Xbe used.
  197. XAlternatively, one may associate a name with a given surface.
  198. XThis name may subsequently be used to refer to that surface.
  199. X
  200. X\begin{defkey}{surface}{{\em name\/} $<${\em Surface Definition}$>$}
  201. X    Associate the given collection of surface attributes with the
  202. X    given name.
  203. X\end{defkey}
  204. X
  205. XThe binding of a collection of surface properties to a given object
  206. Xis accomplished in a bottom-up manner; the surface that ``closest''
  207. Xin the modeling tree to the primitive being rendered is the one that
  208. Xis used to give the primitive its appearance.
  209. X
  210. XAn object that has no surface bound to it is assigned a default surface
  211. Xthat give an object the appearance of white plastic.
  212. X
  213. XThe first
  214. Xand most direct way to bind a surface to a primitive
  215. Xis by specifying the surface to be bound to
  216. Xthe primitive when it is instantiated.
  217. XThis is accomplished
  218. Xby inserting a list of surface attributes or a surface name after
  219. Xthe primitive's type keyword and before the actual primitive data.
  220. X
  221. X\begin{verbatim}
  222. X    /*
  223. X     * A red 'mud' colored sphere reseting on a
  224. X     * white sphere. To the right is a sphere with
  225. X     * default surface attributes.
  226. X     */
  227. X    surface mud ambient .03 0. 0.  diffuse .7 .3 0.
  228. X    sphere  ambient .05 .05 .05 diffuse .7 .7 .7   1. 0 0 0
  229. X    sphere mud  1. 0 0 2
  230. X    sphere 1. 1.5 0 0
  231. X\end{verbatim}
  232. X
  233. XHere, we define a red surface named ``mud''.  We then instantiate
  234. Xa sphere, which has a diffuse white surface bound to it.  The
  235. Xnext line instantiates a sphere with the defined ``mud'' surface bound
  236. Xto it.  The last line instantiates a sphere with no surface bound to it;
  237. Xit is assigned the default surface by {\em rayshade}.
  238. X
  239. XThe {\tt applysurf} keyword may be used to set the default surface
  240. Xcharacteristics for the aggregate object currently being defined.
  241. X
  242. X\begin{defkey}{applysurf}{$<${\em Surface Specification}$>$}
  243. XThe specified surface is applied to all following
  244. Xinstantiated objects that do not have surfaces associated with them.
  245. XThe scope of this keyword is limited to the aggregate currently
  246. Xbeing defined.
  247. X\end{defkey}
  248. X
  249. X\begin{verbatim}
  250. X    /*
  251. X     * Mirrored ball and cylinder sitting on 'default' plane.
  252. X     */
  253. X    surface mirror .01 .01 .01  diffuse .05 .05 .05
  254. X            specular .8 .8 .8 speccoef 20  reflect 0.95
  255. X    plane 0 0 0  0 0 1
  256. X    applysurf mirror
  257. X    sphere 1 0 0 0
  258. X    cylinder 1  3 0 0  3 0 3
  259. X\end{verbatim}
  260. X
  261. XFor convenience, the name {\tt cursurf} may be used to refer to the
  262. Xcurrent default surface.
  263. X
  264. XThe utility of bottom-up binding of surfaces lies in the fact that
  265. Xone may be as adamant or as noncommittal about
  266. Xsurface binding as one sees fit when defining objects.  For example,
  267. Xone could define a king chess piece consisting of triangles that have no
  268. Xsurface bound to them, save for the cross on top, which has
  269. Xa gold-colored surface associated with it.  One may then instantiate
  270. Xthe king twice, once applying a black surface, and once applying
  271. Xa white surface.  The result:  a black king and a white king, each
  272. Xadorned with a golden cross.
  273. X
  274. X\begin{verbatim}
  275. X    surface white ...
  276. X    surface black ...
  277. X    surface gold  ...
  278. X    ...
  279. X    define cross
  280. X            box x y z  x y z
  281. X            ...
  282. X    defend
  283. X    define king
  284. X            triangle x y z  x y z  x y z
  285. X            ...
  286. X            object gold cross
  287. X    defend
  288. X
  289. X    object white king translate 1. 0 0
  290. X    object black king
  291. X\end{verbatim}
  292. END_OF_FILE
  293. if test 10193 -ne `wc -c <'Doc/Guide/surfaces.tex'`; then
  294.     echo shar: \"'Doc/Guide/surfaces.tex'\" unpacked with wrong size!
  295. fi
  296. # end of 'Doc/Guide/surfaces.tex'
  297. fi
  298. if test -f 'libray/libcommon/transform.c' -a "${1}" != "-c" ; then 
  299.   echo shar: Will not clobber existing file \"'libray/libcommon/transform.c'\"
  300. else
  301. echo shar: Extracting \"'libray/libcommon/transform.c'\" \(10691 characters\)
  302. sed "s/^X//" >'libray/libcommon/transform.c' <<'END_OF_FILE'
  303. X/*
  304. X * transform.c
  305. X *
  306. X * Copyright (C) 1989, 1991, Craig E. Kolb
  307. X * All rights reserved.
  308. X *
  309. X * This software may be freely copied, modified, and redistributed
  310. X * provided that this copyright notice is preserved on all copies.
  311. X *
  312. X * You may not distribute this software, in whole or in part, as part of
  313. X * any commercial product without the express consent of the authors.
  314. X *
  315. X * There is no warranty or other guarantee of fitness of this software
  316. X * for any purpose.  It is provided solely "as is".
  317. X *
  318. X * $Id: transform.c,v 4.0 91/07/17 14:32:25 kolb Exp Locker: kolb $
  319. X *
  320. X * $Log:    transform.c,v $
  321. X * Revision 4.0  91/07/17  14:32:25  kolb
  322. X * Initial version.
  323. X * 
  324. X */
  325. X#include "common.h"
  326. X
  327. X/*
  328. X * Matrices are indexed row-first; that is:
  329. X * matrix[ROW][COLUMN]
  330. X */
  331. X/*
  332. X * Allocate new structure that holds both object-to-world and
  333. X * world-to-object space transformation structures.  It probably
  334. X * should hold pointers to these structures.
  335. X */
  336. XTrans *
  337. XTransCreate(tr, meth)
  338. XTransRef tr;
  339. XTransMethods *meth;
  340. X{
  341. X    Trans *res;
  342. X
  343. X    res = (Trans *)share_malloc(sizeof(Trans));
  344. X    res->tr = tr;
  345. X    res->methods = meth;
  346. X    res->animated = FALSE;
  347. X    res->assoc = (ExprAssoc *)NULL;
  348. X    res->prev = res->next = (Trans *)NULL;
  349. X    MatrixInit(&res->trans);
  350. X    MatrixInit(&res->itrans);
  351. X    return res;
  352. X}
  353. X
  354. Xvoid
  355. XTransFree(trans)
  356. XTrans *trans;
  357. X{
  358. X    if (trans->tr)
  359. X        free((voidstar)trans->tr);
  360. X    free((voidstar)trans);
  361. X}
  362. X
  363. Xvoid
  364. XTransAssoc(trans, ptr, expr)
  365. XTrans *trans;
  366. XFloat *ptr;
  367. XExpr *expr;
  368. X{
  369. X    ExprAssoc *assoc;
  370. X
  371. X    if (expr->timevary) {
  372. X        /*
  373. X         * Gotta store the sucker.
  374. X         */
  375. X        trans->assoc = AssocCreate(ptr, expr, trans->assoc);
  376. X        trans->animated = TRUE;
  377. X    } else {
  378. X        *ptr = expr->value;
  379. X    }
  380. X    fflush(stderr);
  381. X}
  382. X
  383. X/*
  384. X * Allocate new transformation 'matrix'.
  385. X */
  386. XRSMatrix *
  387. XMatrixCreate()
  388. X{
  389. X    RSMatrix *res;
  390. X
  391. X    res = (RSMatrix *)share_malloc(sizeof(RSMatrix));
  392. X    MatrixInit(res);
  393. X    return res;
  394. X}
  395. X
  396. X/*
  397. X * Multiply m1 and m2, copy result into "res".
  398. X */
  399. Xvoid
  400. XMatrixMult(t1, t2, res)
  401. XRSMatrix *t1, *t2, *res;
  402. X{
  403. X    register int i;
  404. X    RSMatrix tmp;
  405. X
  406. X    for (i = 0; i < 3; i++) {
  407. X        tmp.matrix[i][0] = t1->matrix[i][0] * t2->matrix[0][0] +
  408. X                     t1->matrix[i][1] * t2->matrix[1][0] +
  409. X                     t1->matrix[i][2] * t2->matrix[2][0];
  410. X        tmp.matrix[i][1] = t1->matrix[i][0] * t2->matrix[0][1] +
  411. X                     t1->matrix[i][1] * t2->matrix[1][1] +
  412. X                     t1->matrix[i][2] * t2->matrix[2][1];
  413. X        tmp.matrix[i][2] = t1->matrix[i][0] * t2->matrix[0][2] +
  414. X                     t1->matrix[i][1] * t2->matrix[1][2] +
  415. X                     t1->matrix[i][2] * t2->matrix[2][2];
  416. X    }
  417. X
  418. X    tmp.translate.x = t1->translate.x * t2->matrix[0][0] +
  419. X              t1->translate.y * t2->matrix[1][0] +
  420. X              t1->translate.z * t2->matrix[2][0] + t2->translate.x;
  421. X    tmp.translate.y = t1->translate.x * t2->matrix[0][1] +
  422. X              t1->translate.y * t2->matrix[1][1] +
  423. X              t1->translate.z * t2->matrix[2][1] + t2->translate.y;
  424. X    tmp.translate.z = t1->translate.x * t2->matrix[0][2] +
  425. X              t1->translate.y * t2->matrix[1][2] +
  426. X              t1->translate.z * t2->matrix[2][2] + t2->translate.z;
  427. X    MatrixCopy(&tmp, res);
  428. X}
  429. X
  430. X/*
  431. X * Return transformation information to map the "coordinate system"
  432. X * with the given origin, "up" vector, radius, and up axis lengths to
  433. X * one in which the "up" vector is the Z axis and the x/y/up axes
  434. X * have unit length.  This is useful for transforming a general
  435. X * form of a primitive into a canonical, Z-axis aligned, unit size
  436. X * primitive, facilitating intersection testing.
  437. X */
  438. Xvoid
  439. XCoordSysTransform(origin, up, r, len, trans)
  440. XVector *origin, *up;
  441. XFloat r, len;
  442. XTrans *trans;
  443. X{
  444. X    RSMatrix tmp;
  445. X    Vector atmp;
  446. X
  447. X    ScaleMatrix(r, r, len, &trans->trans);
  448. X    if (fabs(up->z) == 1.) {
  449. X        atmp.x = 1.;
  450. X        atmp.y = atmp.z = 0.;
  451. X    } else {
  452. X        atmp.x = up->y;
  453. X        atmp.y = -up->x;
  454. X        atmp.z= 0.;
  455. X    }
  456. X    /*
  457. X     * Might want to make sure that |up->z| is < 1.
  458. X     */
  459. X    RotationMatrix(atmp.x, atmp.y, atmp.z, -acos(up->z), &tmp);
  460. X    MatrixMult(&trans->trans, &tmp, &trans->trans);
  461. X    TranslationMatrix(origin->x, origin->y, origin->z, &tmp);
  462. X    MatrixMult(&trans->trans, &tmp, &trans->trans);
  463. X    MatrixInvert(&trans->trans, &trans->itrans);
  464. X}
  465. X
  466. Xvoid
  467. XTransCopy(from, into)
  468. XTrans *into, *from;
  469. X{
  470. X    MatrixCopy(&from->trans, &into->trans);
  471. X    MatrixCopy(&from->itrans, &into->itrans);
  472. X}
  473. X
  474. Xvoid
  475. XTransInvert(from, into)
  476. XTrans *into, *from;
  477. X{
  478. X    RSMatrix ttmp;
  479. X    /*
  480. X     * In case into == from...
  481. X     */
  482. X    if (from == into) {
  483. X        ttmp = from->trans;
  484. X        into->trans = from->itrans;
  485. X        into->itrans = ttmp;
  486. X    } else {
  487. X        into->trans = from->itrans;
  488. X        into->itrans = from->trans;
  489. X    }
  490. X}
  491. X
  492. X/*
  493. X * Copy a given transformation structure.
  494. X */
  495. Xvoid
  496. XMatrixCopy(from, into)
  497. XRSMatrix *into, *from;
  498. X{
  499. X    into->matrix[0][0] = from->matrix[0][0];
  500. X    into->matrix[0][1] = from->matrix[0][1];
  501. X    into->matrix[0][2] = from->matrix[0][2];
  502. X    into->matrix[1][0] = from->matrix[1][0];
  503. X    into->matrix[1][1] = from->matrix[1][1];
  504. X    into->matrix[1][2] = from->matrix[1][2];
  505. X    into->matrix[2][0] = from->matrix[2][0];
  506. X    into->matrix[2][1] = from->matrix[2][1];
  507. X    into->matrix[2][2] = from->matrix[2][2];
  508. X    into->translate = from->translate;
  509. X}
  510. X
  511. Xvoid
  512. XTransInit(trans)
  513. XTrans *trans;
  514. X{
  515. X    MatrixInit(&trans->trans);
  516. X    MatrixInit(&trans->itrans);
  517. X}
  518. X
  519. Xvoid
  520. XTransCompose(t1, t2, res)
  521. XTrans *t1, *t2, *res;
  522. X{
  523. X    MatrixMult(&t1->trans, &t2->trans, &res->trans);
  524. X    MatrixMult(&t2->itrans, &t1->itrans, &res->itrans);
  525. X}
  526. X
  527. X/*
  528. X * Initialize transformation structure.
  529. X */
  530. Xvoid
  531. XMatrixInit(trans)
  532. XRSMatrix *trans;
  533. X{
  534. X    trans->matrix[0][0] = trans->matrix[1][1] = trans->matrix[2][2] = 1.;
  535. X    trans->matrix[0][1] = trans->matrix[0][2] = trans->matrix[1][0] =
  536. X    trans->matrix[1][2] = trans->matrix[2][0] = trans->matrix[2][1] = 0.;
  537. X    trans->translate.x = trans->translate.y = trans->translate.z = 0.;
  538. X}
  539. X
  540. X/*
  541. X * Calculate inverse of the given transformation structure.
  542. X */
  543. Xvoid
  544. XMatrixInvert(trans, inverse)
  545. XRSMatrix *inverse, *trans;
  546. X{
  547. X    RSMatrix ttmp;
  548. X    int i;
  549. X    Float d;
  550. X    extern int yylineno;
  551. X
  552. X    ttmp.matrix[0][0] = trans->matrix[1][1]*trans->matrix[2][2] -
  553. X                trans->matrix[1][2]*trans->matrix[2][1];
  554. X    ttmp.matrix[1][0] = trans->matrix[1][0]*trans->matrix[2][2] -
  555. X                trans->matrix[1][2]*trans->matrix[2][0];
  556. X    ttmp.matrix[2][0] = trans->matrix[1][0]*trans->matrix[2][1] -
  557. X                trans->matrix[1][1]*trans->matrix[2][0];
  558. X
  559. X    ttmp.matrix[0][1] = trans->matrix[0][1]*trans->matrix[2][2] -
  560. X                trans->matrix[0][2]*trans->matrix[2][1];
  561. X    ttmp.matrix[1][1] = trans->matrix[0][0]*trans->matrix[2][2] -
  562. X                trans->matrix[0][2]*trans->matrix[2][0];
  563. X    ttmp.matrix[2][1] = trans->matrix[0][0]*trans->matrix[2][1] -
  564. X                trans->matrix[0][1]*trans->matrix[2][0];
  565. X
  566. X    ttmp.matrix[0][2] = trans->matrix[0][1]*trans->matrix[1][2] -
  567. X                trans->matrix[0][2]*trans->matrix[1][1];
  568. X    ttmp.matrix[1][2] = trans->matrix[0][0]*trans->matrix[1][2] -
  569. X                trans->matrix[0][2]*trans->matrix[1][0];
  570. X    ttmp.matrix[2][2] = trans->matrix[0][0]*trans->matrix[1][1] -
  571. X                trans->matrix[0][1]*trans->matrix[1][0];
  572. X
  573. X    d = trans->matrix[0][0]*ttmp.matrix[0][0] -
  574. X        trans->matrix[0][1]*ttmp.matrix[1][0] +
  575. X        trans->matrix[0][2]*ttmp.matrix[2][0];
  576. X
  577. X    if (fabs(d) < EPSILON*EPSILON)
  578. X        RLerror(RL_PANIC, "Singular matrix.\n",yylineno);
  579. X
  580. X    ttmp.matrix[0][0] /= d;
  581. X    ttmp.matrix[0][2] /= d;
  582. X    ttmp.matrix[1][1] /= d;
  583. X    ttmp.matrix[2][0] /= d;
  584. X    ttmp.matrix[2][2] /= d;
  585. X
  586. X    d = -d;
  587. X
  588. X    ttmp.matrix[0][1] /= d;
  589. X    ttmp.matrix[1][0] /= d;
  590. X    ttmp.matrix[1][2] /= d;
  591. X    ttmp.matrix[2][1] /= d;
  592. X
  593. X    ttmp.translate.x = -(ttmp.matrix[0][0]*trans->translate.x +
  594. X                 ttmp.matrix[1][0]*trans->translate.y +
  595. X                 ttmp.matrix[2][0]*trans->translate.z);
  596. X    ttmp.translate.y = -(ttmp.matrix[0][1]*trans->translate.x +
  597. X                 ttmp.matrix[1][1]*trans->translate.y +
  598. X                 ttmp.matrix[2][1]*trans->translate.z);
  599. X    ttmp.translate.z = -(ttmp.matrix[0][2]*trans->translate.x +
  600. X                 ttmp.matrix[1][2]*trans->translate.y +
  601. X                 ttmp.matrix[2][2]*trans->translate.z);
  602. X
  603. X    MatrixCopy(&ttmp, inverse);
  604. X}
  605. X
  606. X/*
  607. X * Apply a transformation to a point (translation affects the point).
  608. X */
  609. Xvoid
  610. XPointTransform(vec, trans)
  611. XVector *vec;
  612. XRSMatrix *trans;
  613. X{
  614. X    Vector tmp;
  615. X
  616. X    tmp.x = vec->x * trans->matrix[0][0] + vec->y * trans->matrix[1][0] +
  617. X            vec->z * trans->matrix[2][0] + trans->translate.x;
  618. X    tmp.y = vec->x * trans->matrix[0][1] + vec->y * trans->matrix[1][1] +
  619. X            vec->z * trans->matrix[2][1] + trans->translate.y;
  620. X    tmp.z = vec->x * trans->matrix[0][2] + vec->y * trans->matrix[1][2] +
  621. X            vec->z * trans->matrix[2][2] + trans->translate.z;
  622. X    *vec = tmp;
  623. X}
  624. X
  625. X/*
  626. X * 'c1x' is the X (0th) component of the first column, and so on.
  627. X */
  628. Xvoid
  629. XArbitraryMatrix(c1x, c2x, c3x, c1y, c2y, c3y, c1z, c2z, c3z, tx, ty, tz, trans)
  630. XFloat c1x, c1y, c1z, c2x, c2y, c2z, c3x, c3y, c3z, tx, ty, tz;
  631. XRSMatrix *trans;
  632. X{
  633. X    trans->matrix[0][0] = c1x;
  634. X    trans->matrix[1][0] = c1y;
  635. X    trans->matrix[2][0] = c1z;
  636. X
  637. X    trans->matrix[0][1] = c2x;
  638. X    trans->matrix[1][1] = c2y;
  639. X    trans->matrix[2][1] = c2z;
  640. X
  641. X    trans->matrix[0][2] = c3x;
  642. X    trans->matrix[1][2] = c3y;
  643. X    trans->matrix[2][2] = c3z;
  644. X
  645. X    trans->translate.x = tx;
  646. X    trans->translate.y = ty;
  647. X    trans->translate.z = tz;
  648. X}
  649. X
  650. X/*
  651. X * Apply transformation to a vector (translations have no effect).
  652. X */
  653. Xvoid
  654. XVecTransform(vec, trans)
  655. XVector *vec;
  656. XRSMatrix *trans;
  657. X{
  658. X    Vector tmp;
  659. X
  660. X    tmp.x = vec->x*trans->matrix[0][0] +
  661. X        vec->y*trans->matrix[1][0] + vec->z*trans->matrix[2][0];
  662. X    tmp.y = vec->x*trans->matrix[0][1] +
  663. X        vec->y*trans->matrix[1][1] + vec->z*trans->matrix[2][1];
  664. X    tmp.z = vec->x*trans->matrix[0][2] +
  665. X        vec->y*trans->matrix[1][2] + vec->z*trans->matrix[2][2];
  666. X
  667. X    *vec = tmp;
  668. X}
  669. X
  670. X/*
  671. X * Transform normal -- multiply by the transpose of the given
  672. X * matrix (which is the inverse of the 'desired' transformation).
  673. X */
  674. Xvoid
  675. XNormalTransform(norm, it)
  676. XVector *norm;
  677. XRSMatrix *it;
  678. X{
  679. X    Vector onorm;
  680. X
  681. X    onorm = *norm;
  682. X
  683. X    norm->x = onorm.x*it->matrix[0][0] + onorm.y*it->matrix[0][1] +
  684. X                onorm.z*it->matrix[0][2];
  685. X    norm->y = onorm.x*it->matrix[1][0] + onorm.y*it->matrix[1][1] +
  686. X                onorm.z*it->matrix[1][2];
  687. X    norm->z = onorm.x*it->matrix[2][0] + onorm.y*it->matrix[2][1] +
  688. X                onorm.z*it->matrix[2][2];
  689. X    (void)VecNormalize(norm);
  690. X}
  691. X
  692. X/*
  693. X * Transform "ray" by transforming the origin point and direction vector.
  694. X */
  695. XFloat
  696. XRayTransform(ray, trans)
  697. XRay *ray;
  698. XRSMatrix *trans;
  699. X{
  700. X    PointTransform(&ray->pos, trans);
  701. X    VecTransform(&ray->dir, trans);
  702. X    return VecNormalize(&ray->dir);
  703. X}
  704. X
  705. Xvoid
  706. XTransPropagate(trans)
  707. XTrans *trans;
  708. X{
  709. X    (*trans->methods->propagate)(trans->tr, &trans->trans, &trans->itrans);
  710. X}
  711. X
  712. Xvoid
  713. XTransResolveAssoc(trans)
  714. XTrans *trans;
  715. X{
  716. X    Trans *curtrans;
  717. X    ExprAssoc *curassoc;
  718. X
  719. X    for (curtrans = trans; curtrans; curtrans = curtrans->next) {
  720. X        for (curassoc = curtrans->assoc; curassoc; curassoc = curassoc->next) {
  721. X            *curassoc->lhs = ExprEval(curassoc->expr);
  722. X        }
  723. X        if (curtrans->assoc)
  724. X            TransPropagate(curtrans);
  725. X    }
  726. X}
  727. X
  728. Xvoid
  729. XTransComposeList(list, result)
  730. XTrans *list, *result;
  731. X{
  732. X    TransCopy(list, result);
  733. X    for (list = list->next; list; list = list->next)
  734. X        TransCompose(list, result, result);
  735. X}
  736. END_OF_FILE
  737. if test 10691 -ne `wc -c <'libray/libcommon/transform.c'`; then
  738.     echo shar: \"'libray/libcommon/transform.c'\" unpacked with wrong size!
  739. fi
  740. # end of 'libray/libcommon/transform.c'
  741. fi
  742. if test -f 'libray/libobj/csg.c' -a "${1}" != "-c" ; then 
  743.   echo shar: Will not clobber existing file \"'libray/libobj/csg.c'\"
  744. else
  745. echo shar: Extracting \"'libray/libobj/csg.c'\" \(10585 characters\)
  746. sed "s/^X//" >'libray/libobj/csg.c' <<'END_OF_FILE'
  747. X/*
  748. X * csg.c
  749. X *
  750. X * Copyright (C) 1991, Rod G. Bogart, Craig E. Kolb
  751. X * All rights reserved.
  752. X *
  753. X * This software may be freely copied, modified, and redistributed
  754. X * provided that this copyright notice is preserved on all copies.
  755. X *
  756. X * You may not distribute this software, in whole or in part, as part of
  757. X * any commercial product without the express consent of the authors.
  758. X *
  759. X * There is no warranty or other guarantee of fitness of this software
  760. X * for any purpose.  It is provided solely "as is".
  761. X *
  762. X * $Id: csg.c,v 4.0 91/07/17 14:37:00 kolb Exp Locker: kolb $
  763. X *
  764. X * $Log:    csg.c,v $
  765. X * Revision 4.0  91/07/17  14:37:00  kolb
  766. X * Initial version.
  767. X * 
  768. X */
  769. X#include "geom.h"
  770. X#include "csg.h"
  771. X
  772. X#define csg_set_enter(l, f) ((l)->data[0].enter = (f) + 1)
  773. X
  774. Xstatic Methods *iCsgMethods = NULL;
  775. Xstatic char csgName[] = "csg";
  776. X
  777. Xstatic int    CsgUnionInt(), CsgDifferenceInt(),
  778. X        CsgIntersectInt();
  779. Xstatic void    CsgHitlistCopy(), CsgSetBounds();
  780. X
  781. XCsg *
  782. XCsgCreate(op)
  783. Xint op;
  784. X{
  785. X    Csg *csg;
  786. X
  787. X    csg = (Csg *)share_malloc(sizeof(Csg));
  788. X    csg->operator = op;
  789. X    csg->obj1 = csg->obj2 = (Geom *)NULL;
  790. X
  791. X
  792. X    switch(op) {
  793. X        case CSG_UNION:
  794. X            csg->intmeth = CsgUnionInt;
  795. X            break;
  796. X        case CSG_INTERSECT:
  797. X            csg->intmeth = CsgIntersectInt;
  798. X            break;
  799. X        case CSG_DIFFERENCE:
  800. X            csg->intmeth = CsgDifferenceInt;
  801. X            break;
  802. X        default:
  803. X            RLerror(RL_ABORT, "Unknown csg op type %d?\n",op);
  804. X    }
  805. X    return csg;
  806. X}
  807. X
  808. XMethods *
  809. XCsgMethods()
  810. X{
  811. X    if (iCsgMethods== (Methods *)NULL) {
  812. X        iCsgMethods = MethodsCreate();
  813. X        iCsgMethods->create = (GeomCreateFunc *)CsgCreate;
  814. X        iCsgMethods->convert = CsgConvert;
  815. X        iCsgMethods->methods = CsgMethods;
  816. X        iCsgMethods->name = CsgName;
  817. X        iCsgMethods->intersect = CsgIntersect;
  818. X        iCsgMethods->bounds = CsgBounds;
  819. X        iCsgMethods->checkbounds = FALSE;
  820. X        iCsgMethods->closed = TRUE;
  821. X    }
  822. X    return iCsgMethods;
  823. X}
  824. X
  825. Xchar *
  826. XCsgName()
  827. X{
  828. X    return csgName;
  829. X}
  830. X
  831. Xcsg_intersect_objs(csg, ray, hit1, hit2, mindist, dist1, dist2)
  832. XCsg *csg;
  833. XRay *ray;
  834. XHitList *hit1, *hit2;
  835. XFloat mindist, *dist1, *dist2;
  836. X{
  837. X    int operator;
  838. X
  839. X    hit1->nodes = 0;
  840. X    hit2->nodes = 0;
  841. X    *dist1 = FAR_AWAY;
  842. X    *dist2 = FAR_AWAY;
  843. X    operator = csg->operator;
  844. X
  845. X    if (!intersect(csg->obj1, ray, hit1, mindist, dist1) &&
  846. X        ((operator == CSG_INTERSECT) || (operator == CSG_DIFFERENCE))) {
  847. X        /*
  848. X         * Intersection and Difference cases: if you miss the first
  849. X         * object, you missed the whole thing.
  850. X         */
  851. X        return FALSE;
  852. X    }
  853. X
  854. X    if (!intersect(csg->obj2, ray, hit2, mindist, dist2) &&
  855. X        ((operator == CSG_INTERSECT) ||
  856. X         (hit1->nodes == 0) && (operator == CSG_UNION))) {
  857. X        /*
  858. X         * Intersect case:  if you miss either object, you miss whole
  859. X         * Union case: if you miss both object, you miss whole
  860. X         */
  861. X        return FALSE;
  862. X    }
  863. X
  864. X    return TRUE;
  865. X}
  866. X
  867. Xint
  868. Xcsg_enter_obj(hitp)
  869. XHitList *hitp;
  870. X{
  871. X    if (hitp->data[0].enter)
  872. X        return hitp->data[0].enter - 1;
  873. X
  874. X    return PrimEnter(hitp->data[0].obj, &hitp->data[0].ray,
  875. X            hitp->data[0].mindist, hitp->data[0].dist);
  876. X}
  877. X
  878. Xstatic int
  879. XCsgUnionInt(ray, hit1p, hit2p, dist1, dist2, hitclose, distclose)
  880. XRay *ray;
  881. XHitList *hit1p, *hit2p, **hitclose;
  882. XFloat dist1, dist2, *distclose;
  883. X{
  884. X    Float distnext;
  885. X    HitList hitnext, *hittmp;
  886. X
  887. X    while (TRUE) {
  888. X        if (hit2p->nodes == 0 ||
  889. X            csg_enter_obj(hit2p)) {
  890. X            /* return hit1 */
  891. X            *hitclose = hit1p;
  892. X            *distclose = dist1;
  893. X            csg_set_enter(hit1p, csg_enter_obj(hit1p));
  894. X            return TRUE;
  895. X        } else {
  896. X            distnext = FAR_AWAY;
  897. X            hitnext.nodes = 0;
  898. X            if (!intersect(hit1p->data[hit1p->nodes-1].obj,
  899. X                ray, &hitnext, dist2+EPSILON, &distnext)) {
  900. X                /*
  901. X                 * None of obj1 beyond, return hit2 (leaving)
  902. X                 */
  903. X                *hitclose = hit2p;
  904. X                *distclose = dist2;
  905. X                csg_set_enter(hit2p, FALSE);
  906. X                return TRUE;
  907. X            } else {
  908. X                /*
  909. X                 * Since hit1 is supposed to be the close one,
  910. X                 * swap them and copy hitnext into hit2.
  911. X                      */
  912. X                hittmp = hit1p;
  913. X                hit1p = hit2p;
  914. X                hit2p = hittmp;
  915. X                dist1 = dist2;
  916. X                CsgHitlistCopy(&hitnext, hit2p);
  917. X                dist2 = distnext;
  918. X                /* and continue */
  919. X            }
  920. X        }
  921. X    }
  922. X}
  923. X
  924. Xstatic int
  925. XCsgIntersectInt(ray, hit1p, hit2p, dist1, dist2, hitclose, distclose)
  926. XRay *ray;
  927. XHitList *hit1p, *hit2p, **hitclose;
  928. XFloat dist1, dist2, *distclose;
  929. X{
  930. X    HitList *hittmp, hitnext;
  931. X    Float distnext;
  932. X
  933. X    while (TRUE) {
  934. X        if (!csg_enter_obj(hit2p)) {
  935. X            /* Ray is leaving obj2 */
  936. X            /* Return hit1 info */
  937. X            *hitclose = hit1p;
  938. X            *distclose = dist1;
  939. X            csg_set_enter(hit1p, csg_enter_obj(hit1p));
  940. X            return TRUE;
  941. X        } else {
  942. X            distnext = FAR_AWAY;
  943. X            hitnext.nodes = 0;
  944. X            if (!intersect(hit1p->data[hit1p->nodes-1].obj,
  945. X                ray, &hitnext, dist2+EPSILON, &distnext)) {
  946. X                /*
  947. X                 * None of obj1 beyond, so return miss
  948. X                 */
  949. X                return FALSE;
  950. X            } else {
  951. X                /*
  952. X                 * Since hit1 is supposed to be the
  953. X                 * close one, swap them and copy
  954. X                 * hitnext into hit2.
  955. X                 */
  956. X                hittmp = hit1p;
  957. X                hit1p = hit2p;
  958. X                hit2p = hittmp;
  959. X                dist1 = dist2;
  960. X                CsgHitlistCopy(&hitnext, hit2p);
  961. X                dist2 = distnext;
  962. X                /* and continue */
  963. X            }
  964. X        }
  965. X    }
  966. X}
  967. X
  968. Xstatic int
  969. XCsgDifferenceInt(ray, hit1p, hit2p, dist1, dist2, hitclose, distclose)
  970. XRay *ray;
  971. XHitList *hit1p, *hit2p, **hitclose;
  972. XFloat dist1, dist2, *distclose;
  973. X{
  974. X    Float distnext;
  975. X    HitList hitnext;
  976. X
  977. X    while (TRUE) {
  978. X        if (dist1 < dist2) {
  979. X            if (hit2p->nodes == 0 ||
  980. X                csg_enter_obj(hit2p)) {
  981. X                /* return hit1 */
  982. X                *hitclose = hit1p;
  983. X                *distclose = dist1;
  984. X                csg_set_enter(hit1p, csg_enter_obj(hit1p));
  985. X                return TRUE;
  986. X            } else {
  987. X                distnext = FAR_AWAY;
  988. X                hitnext.nodes = 0;
  989. X                if (!intersect(hit1p->data[hit1p->nodes-1].obj,
  990. X                    ray, &hitnext, dist2+EPSILON, &distnext)) {
  991. X                    /*
  992. X                     * None of obj1 beyond, so
  993. X                     * return miss
  994. X                     */
  995. X                    return FALSE;
  996. X                } else {
  997. X                    dist1 = distnext;
  998. X                    CsgHitlistCopy(&hitnext, hit1p);
  999. X                    /* and continue */
  1000. X                }
  1001. X            }
  1002. X        } else { /* dist1 <= dist2 */
  1003. X            if (hit1p->nodes == 0) {
  1004. X                /* return a miss */
  1005. X                return FALSE;
  1006. X            }
  1007. X            if (!csg_enter_obj(hit1p)) {
  1008. X                /*
  1009. X                 * return hit2, but invert hit2
  1010. X                 * Enter/Leave flag
  1011. X                 */
  1012. X                *hitclose = hit2p;
  1013. X                *distclose = dist2;
  1014. X                csg_set_enter(hit2p, !csg_enter_obj(hit2p));
  1015. X                return TRUE;
  1016. X            } else {
  1017. X                distnext = FAR_AWAY;
  1018. X                hitnext.nodes = 0;
  1019. X                if (!intersect(hit2p->data[hit2p->nodes-1].obj,
  1020. X                    ray, &hitnext, dist1+EPSILON, &distnext)) {
  1021. X                    /*
  1022. X                     * None of obj2 beyond, so
  1023. X                     * return hit1
  1024. X                     */
  1025. X                    *hitclose = hit1p;
  1026. X                    *distclose = dist1;
  1027. X                    /* we know we're entering obj1 */
  1028. X                    csg_set_enter(hit1p, TRUE);
  1029. X                    return TRUE;
  1030. X                } else {
  1031. X                    dist2 = distnext;
  1032. X                    CsgHitlistCopy(&hitnext, hit2p);
  1033. X                    /* and continue */
  1034. X                }
  1035. X            }
  1036. X        }
  1037. X    }
  1038. X}
  1039. X
  1040. Xint
  1041. XCsgIntersect(csg, ray, hitlist, mindist, maxdist)
  1042. XCsg *csg;
  1043. XRay *ray;
  1044. XHitList *hitlist;
  1045. XFloat mindist, *maxdist;
  1046. X{
  1047. X    Float dist1, dist2, disttmp, distclose;
  1048. X    HitList hit1, hit2, *hit1p, *hit2p, *hitclose;
  1049. X
  1050. X    hit1p = &hit1;
  1051. X    hit2p = &hit2;
  1052. X    if (!csg_intersect_objs(csg, ray, hit1p, hit2p, mindist,
  1053. X        &dist1, &dist2)) {
  1054. X        /* missed the csg object */
  1055. X        return FALSE;
  1056. X    }
  1057. X
  1058. X    if ((dist1 > dist2) &&
  1059. X        (csg->operator == CSG_UNION || csg->operator == CSG_INTERSECT)) {
  1060. X        /* swap so 1 is closest (except in difference case) */
  1061. X        disttmp = dist2;  
  1062. X        dist2 = dist1;  
  1063. X        dist1 = disttmp;
  1064. X        hit1p = &hit2;  
  1065. X        hit2p = &hit1;
  1066. X    }
  1067. X
  1068. X    /*
  1069. X     * Call appropriate intersection method.  If FALSE is return,
  1070. X     * no hit of any kind was found.
  1071. X     */
  1072. X    if (!(*csg->intmeth)(ray, hit1p, hit2p, dist1, dist2,
  1073. X        &hitclose, &distclose))
  1074. X        return FALSE;
  1075. X
  1076. X    /*
  1077. X     * At this time, the closest hit is in hitclose and
  1078. X     * distclose.
  1079. X     */
  1080. X    if (distclose < mindist || distclose > *maxdist)
  1081. X        return FALSE;
  1082. X
  1083. X    CsgHitlistCopy(hitclose, hitlist);
  1084. X    *maxdist = distclose;
  1085. X    return TRUE;
  1086. X}
  1087. X
  1088. Xstatic void
  1089. XCsgHitlistCopy(from, to)
  1090. XHitList *from, *to;
  1091. X{
  1092. X    int i;
  1093. X
  1094. X    to->nodes = from->nodes;
  1095. X    for (i = 0; i < from->nodes; i++)
  1096. X        to->data[i] = from->data[i];
  1097. X}
  1098. X
  1099. Xstatic void
  1100. XCsgSetBounds(csg, bounds)
  1101. XCsg *csg;
  1102. XFloat bounds[2][3];
  1103. X{
  1104. X    GeomComputeBounds(csg->obj1);
  1105. X    GeomComputeBounds(csg->obj2);
  1106. X
  1107. X    switch (csg->operator) {
  1108. X    case CSG_UNION:
  1109. X        bounds[LOW][X] = min(csg->obj1->bounds[LOW][X], csg->obj2->bounds[LOW][X]);
  1110. X        bounds[HIGH][X] = max(csg->obj1->bounds[HIGH][X], csg->obj2->bounds[HIGH][X]);
  1111. X        bounds[LOW][Y] = min(csg->obj1->bounds[LOW][Y], csg->obj2->bounds[LOW][Y]);
  1112. X        bounds[HIGH][Y] = max(csg->obj1->bounds[HIGH][Y], csg->obj2->bounds[HIGH][Y]);
  1113. X        bounds[LOW][Z] = min(csg->obj1->bounds[LOW][Z], csg->obj2->bounds[LOW][Z]);
  1114. X        bounds[HIGH][Z] = max(csg->obj1->bounds[HIGH][Z], csg->obj2->bounds[HIGH][Z]);
  1115. X        break;
  1116. X    case CSG_INTERSECT:
  1117. X        bounds[LOW][X] = max(csg->obj1->bounds[LOW][X], csg->obj2->bounds[LOW][X]);
  1118. X        bounds[HIGH][X] = min(csg->obj1->bounds[HIGH][X], csg->obj2->bounds[HIGH][X]);
  1119. X        bounds[LOW][Y] = max(csg->obj1->bounds[LOW][Y], csg->obj2->bounds[LOW][Y]);
  1120. X        bounds[HIGH][Y] = min(csg->obj1->bounds[HIGH][Y], csg->obj2->bounds[HIGH][Y]);
  1121. X        bounds[LOW][Z] = max(csg->obj1->bounds[LOW][Z], csg->obj2->bounds[LOW][Z]);
  1122. X        bounds[HIGH][Z] = min(csg->obj1->bounds[HIGH][Z], csg->obj2->bounds[HIGH][Z]);
  1123. X        break;
  1124. X    case CSG_DIFFERENCE:
  1125. X        bounds[LOW][X] = csg->obj1->bounds[LOW][X];
  1126. X        bounds[HIGH][X] = csg->obj1->bounds[HIGH][X];
  1127. X        bounds[LOW][Y] = csg->obj1->bounds[LOW][Y];
  1128. X        bounds[HIGH][Y] = csg->obj1->bounds[HIGH][Y];
  1129. X        bounds[LOW][Z] = csg->obj1->bounds[LOW][Z];
  1130. X        bounds[HIGH][Z] = csg->obj1->bounds[HIGH][Z];
  1131. X        break;
  1132. X    default:
  1133. X        RLerror(RL_ABORT, "Unknown csg operator type %d?\n",
  1134. X            csg->operator);
  1135. X    }
  1136. X}
  1137. X
  1138. X/*
  1139. X * Return index of hitlist node closest to the leaf and not below any
  1140. X * CSG object.
  1141. X */
  1142. Xint
  1143. XFirstCSGGeom(hitlist)
  1144. XHitList *hitlist;
  1145. X{
  1146. X    int i;
  1147. X
  1148. X    /*
  1149. X     * UUUUGLY -- detect if obj is a CsgGeom by comparing
  1150. X     * methods with iCsgMethods.
  1151. X     */
  1152. X    for (i = hitlist->nodes -1; i; i--)
  1153. X        if (hitlist->data[i].obj->methods == iCsgMethods)
  1154. X            return i;
  1155. X    return 0;
  1156. X}
  1157. X
  1158. Xvoid
  1159. XCsgBounds(csg, bounds)
  1160. XCsg *csg;
  1161. XFloat bounds[2][3];
  1162. X{
  1163. X    CsgSetBounds(csg, csg->bounds);
  1164. X    BoundsCopy(csg->bounds, bounds);
  1165. X}
  1166. X
  1167. Xint
  1168. XCsgConvert(csg, list)
  1169. XCsg *csg;
  1170. XGeom *list;
  1171. X{
  1172. X    static int OpenAdvised = FALSE;
  1173. X    /*
  1174. X     * Currently, this only handles two objects.
  1175. X     * Will be fixed in the future.
  1176. X     * No really we promise.
  1177. X     */
  1178. X    if (!list || !list->next) {
  1179. X        RLerror(RL_WARN, "CSG needs at least two objects.\n");
  1180. X        return 0;
  1181. X    }
  1182. X    if (list->next->next) {
  1183. X        RLerror(RL_WARN, "Currently, CSG only handles two objects.\n");
  1184. X        return 0;
  1185. X    }
  1186. X    /*
  1187. X     * Things are put into lists backwards....
  1188. X     */
  1189. X    csg->obj2 = list;
  1190. X    csg->obj1 = list->next;
  1191. X    if ((!csg->obj1->methods->closed || !csg->obj2->methods->closed) &&
  1192. X        !OpenAdvised) {
  1193. X        RLerror(RL_ADVISE,
  1194. X            "Performing CSG with non-closed object(s).\n");
  1195. X        OpenAdvised = TRUE;
  1196. X    }
  1197. X    return csg->obj1->prims + csg->obj2->prims;
  1198. X}
  1199. X
  1200. Xvoid
  1201. XCsgMethodRegister(meth)
  1202. XUserMethodType meth;
  1203. X{
  1204. X    if (iCsgMethods)
  1205. X        iCsgMethods->user = meth;
  1206. X}
  1207. END_OF_FILE
  1208. if test 10585 -ne `wc -c <'libray/libobj/csg.c'`; then
  1209.     echo shar: \"'libray/libobj/csg.c'\" unpacked with wrong size!
  1210. fi
  1211. # end of 'libray/libobj/csg.c'
  1212. fi
  1213. if test -f 'libshade/shade.c' -a "${1}" != "-c" ; then 
  1214.   echo shar: Will not clobber existing file \"'libshade/shade.c'\"
  1215. else
  1216. echo shar: Extracting \"'libshade/shade.c'\" \(10451 characters\)
  1217. sed "s/^X//" >'libshade/shade.c' <<'END_OF_FILE'
  1218. X/*
  1219. X * shade.c
  1220. X *
  1221. X * Copyright (C) 1989, 1991, Craig E. Kolb
  1222. X * All rights reserved.
  1223. X *
  1224. X * This software may be freely copied, modified, and redistributed
  1225. X * provided that this copyright notice is preserved on all copies.
  1226. X *
  1227. X * You may not distribute this software, in whole or in part, as part of
  1228. X * any commercial product without the express consent of the authors.
  1229. X *
  1230. X * There is no warranty or other guarantee of fitness of this software
  1231. X * for any purpose.  It is provided solely "as is".
  1232. X *
  1233. X * $Id: shade.c,v 4.0 91/07/17 14:47:36 kolb Exp Locker: kolb $
  1234. X *
  1235. X * $Log:    shade.c,v $
  1236. X * Revision 4.0  91/07/17  14:47:36  kolb
  1237. X * Initial version.
  1238. X * 
  1239. X */
  1240. X#include "rayshade.h"
  1241. X#include "libtext/texture.h"
  1242. X#include "libsurf/surface.h"
  1243. X#include "liblight/light.h"
  1244. X#include "libsurf/atmosphere.h"
  1245. X#include "options.h"
  1246. X#include "stats.h"
  1247. X
  1248. XMedium    TopMedium;
  1249. XAtmosphere *AtmosEffects;
  1250. X
  1251. Xstatic void shade(), LightRay(), Lighting(), ReflectRay();
  1252. Xstatic int TransmitRay();
  1253. X
  1254. X/*
  1255. X * Calculate color of ray.
  1256. X */
  1257. Xvoid
  1258. XShadeRay(hitlist, ray, dist, back, color, contrib)
  1259. XHitList *hitlist;        /* Information about point of intersection. */
  1260. XRay *ray;            /* Direction and origin of ray. */
  1261. XFloat dist;            /* Distance from origin of intersection. */
  1262. XColor    *back,            /* "Background" color */
  1263. X    *color,            /* Color to assign current ray. */
  1264. X    *contrib;        /* Contribution of this ray to final color */
  1265. X{
  1266. X    Vector norm, gnorm, pos; /* surface normal, point of intersection */
  1267. X    Surface surf, *stmp;    /* surface properties */
  1268. X    int enter, smooth;    /* entering ?, gnorm != snorm ?*/
  1269. X
  1270. X    if (hitlist->nodes == 0) {
  1271. X        /*
  1272. X         * No valid intersection.  Set distance for atmospheric
  1273. X         * effects and set color of ray to background.
  1274. X         */
  1275. X        *color = *back;
  1276. X        VecAddScaled(ray->pos, FAR_AWAY, ray->dir, &pos);
  1277. X        if (!ray->media && AtmosEffects)
  1278. X            Atmospherics(AtmosEffects, ray, FAR_AWAY, &pos, color);
  1279. X        return;
  1280. X    }
  1281. X
  1282. X    /*
  1283. X     * Compute normal, surface properties, etc.
  1284. X     */
  1285. X    stmp = GetShadingSurf(hitlist);
  1286. X    surf = *stmp;
  1287. X    enter = ComputeSurfProps(hitlist, ray, &pos, &norm, &gnorm, &surf,
  1288. X            &smooth);
  1289. X    Stats.HitRays++;
  1290. X
  1291. X    /*
  1292. X     * Calculate ray color.
  1293. X     */
  1294. X    shade(&pos, ray, &norm, &gnorm, smooth, enter, &surf, back, color,
  1295. X            contrib);
  1296. X    if (!ray->media && AtmosEffects)
  1297. X        Atmospherics(AtmosEffects, ray, dist, &pos, color);
  1298. X}
  1299. X
  1300. X/*
  1301. X * Perform lighting calculations based on surface normal & other properties,
  1302. X * incident ray direction and position, and light source properties.
  1303. X * Spawn any necessary reflected and transmitted rays.
  1304. X */
  1305. Xstatic void
  1306. Xshade(pos, ray, nrm, gnrm, smooth, enter, surf, back, color, contrib)
  1307. XVector *pos, *nrm, *gnrm;    /* hit pos, shade normal, geo normal */
  1308. Xint smooth;            /* true if shading norm and geo norm differ */
  1309. Xint enter;            /* TRUE if entering surface */
  1310. XRay *ray;            /* indicent ray */
  1311. XSurface *surf;            /* properties of hit surface */
  1312. XColor *back, *color;        /* background color, computed color */
  1313. XColor *contrib;            /* contribution to final pixel value */
  1314. X{
  1315. X    Float    k;        /* -ray . normal */
  1316. X    Color    newcontrib;
  1317. X    Vector    refl;        /* reflected direction */
  1318. X    Color    reflectivity,    /* effective surface reflectivity */
  1319. X        intens;        /* reflected/transmitted intensity */
  1320. X    Light *lp;        /* current light source */
  1321. X    extern Light *Lights;    /* list of defined sources */
  1322. X
  1323. X    /*
  1324. X     * Ambient color is always included.
  1325. X     */
  1326. X    ColorMultiply(surf->amb, Options.ambient, color);
  1327. X
  1328. X    /*
  1329. X     * Calculate direction of reflected ray.
  1330. X     */
  1331. X    k = -dotp(&ray->dir, nrm);
  1332. X    VecAddScaled(ray->dir, 2.*k, *nrm, &refl);
  1333. X
  1334. X    /*
  1335. X     * Calculate intensity contributed by each light source.
  1336. X     */
  1337. X    for (lp = Lights; lp; lp = lp->next)
  1338. X        LightRay(lp, pos, nrm, gnrm, smooth, &refl, surf,
  1339. X                ray->depth, ray->sample, ray->time, color);
  1340. X
  1341. X    if (ray->depth >= Options.maxdepth)
  1342. X        /*
  1343. X         * Don't spawn any transmitted/reflected rays.
  1344. X         */
  1345. X        return;
  1346. X    /*
  1347. X     * Specular transmission (refraction).
  1348. X     */
  1349. X    ColorScale(surf->reflect, surf->spec, &reflectivity);
  1350. X
  1351. X    if (surf->transp > EPSILON) {
  1352. X        ColorScale(surf->transp, surf->body, &intens);
  1353. X        ColorMultiply(intens, *contrib, &newcontrib);
  1354. X        if (newcontrib.r > Options.cutoff.r ||
  1355. X            newcontrib.g > Options.cutoff.g ||
  1356. X            newcontrib.b > Options.cutoff.b)
  1357. X            /*
  1358. X             * Transmit ray.  If TIR occurs, add transmitted
  1359. X             * component to reflected component.  Kinda strange, but...
  1360. X             */
  1361. X            if (TransmitRay(ray, pos, nrm, k, surf->index,
  1362. X                surf->statten, enter, back, &newcontrib, &intens, color))
  1363. X                ColorAdd(reflectivity, intens, &reflectivity);
  1364. X    }
  1365. X
  1366. X    if (reflectivity.r > EPSILON ||
  1367. X        reflectivity.g > EPSILON ||
  1368. X        reflectivity.b > EPSILON) {
  1369. X        ColorMultiply(reflectivity, *contrib, &newcontrib);
  1370. X        if (newcontrib.r > Options.cutoff.r ||
  1371. X            newcontrib.g > Options.cutoff.g ||
  1372. X            newcontrib.b > Options.cutoff.b)
  1373. X            ReflectRay(ray, pos, &refl, back, &reflectivity,
  1374. X                &newcontrib, color);
  1375. X    }
  1376. X}
  1377. X
  1378. X/*
  1379. X * Lighting calculations
  1380. X */
  1381. Xstatic void
  1382. XLightRay(lp, pos, norm, gnorm, smooth, reflect, surf, depth, samp, time, color)
  1383. XLight *lp;            /* Light source */
  1384. XVector *pos, *norm, *gnorm;    /* hit pos, shade norm, geo norm */
  1385. Xint smooth;            /* true if shade and geo norm differ */
  1386. XVector *reflect;        /* reflection direction */
  1387. XSurface *surf;            /* surface characteristics */
  1388. Xint depth, samp;        /* ray depth, sample # */
  1389. XFloat time;
  1390. XColor *color;            /* resulting color */
  1391. X{
  1392. X    Color lcolor;
  1393. X    Ray newray;
  1394. X    Float costheta, cosalpha, dist;
  1395. X
  1396. X    newray.pos = *pos;
  1397. X    newray.depth = depth;
  1398. X    newray.sample = samp;
  1399. X    newray.time = time; 
  1400. X    newray.media = (Medium *)NULL;    
  1401. X
  1402. X    LightDirection(lp, pos, &newray.dir, &dist);
  1403. X
  1404. X    costheta = dotp(&newray.dir, norm);
  1405. X
  1406. X    if (smooth) {
  1407. X        cosalpha = dotp(&newray.dir, gnorm); 
  1408. X        /*
  1409. X         * If shading normal indicates self-shadowing
  1410. X         * and geom normal indicates no self-shadowing,
  1411. X         * trust the geom normal.
  1412. X         */
  1413. X        if (costheta <= 0. && cosalpha > 0.)
  1414. X            costheta = cosalpha;
  1415. X        /*
  1416. X         * If geom normal indicates self-shadowing and
  1417. X         * geom normal doesn't, then have to do something
  1418. X         * clever ala Snyder & Barr.
  1419. X         */
  1420. X    }
  1421. X
  1422. X    if (costheta <= 0.) {
  1423. X        /*
  1424. X         * Light source is on opposite side of surface,
  1425. X         * hence light must be transmitted through...
  1426. X         */
  1427. X        if (surf->translucency < EPSILON)
  1428. X            return;
  1429. X        if (!LightIntens(lp, &newray, dist,
  1430. X            (int)surf->noshadow, &lcolor))
  1431. X            return;
  1432. X        cosalpha = -dotp(reflect, &newray.dir);
  1433. X        Lighting(-costheta, cosalpha, &lcolor, &surf->translu,
  1434. X                &surf->body, surf->stexp, color);
  1435. X        ColorScale(surf->translucency, *color, color);
  1436. X    } else {
  1437. X        if (!LightIntens(lp, &newray, dist,
  1438. X            (int)surf->noshadow, &lcolor))
  1439. X            return;  /* prim is in shadow w.r.t light source */
  1440. X
  1441. X        cosalpha = dotp(reflect, &newray.dir);
  1442. X        Lighting(costheta, cosalpha, &lcolor, &surf->diff,
  1443. X                &surf->spec, surf->srexp, color);
  1444. X    }
  1445. X}
  1446. X
  1447. X/*
  1448. X * Compute shading function (diffuse reflection and specular highlight)
  1449. X *
  1450. X * This function *adds* the computed color to "color".
  1451. X */
  1452. Xstatic void
  1453. XLighting(costheta, cosalpha, lcolor, diff, spec, coef, color)
  1454. XFloat costheta, cosalpha, coef;
  1455. XColor *diff, *spec, *color, *lcolor;
  1456. X{
  1457. X    Float intens;
  1458. X
  1459. X    /*
  1460. X     * Diffuse reflection.
  1461. X     * Falls off as the cosine of the angle between
  1462. X     * the normal and the ray to the light (costheta).
  1463. X     */
  1464. X    color->r += diff->r * costheta * lcolor->r;
  1465. X    color->g += diff->g * costheta * lcolor->g;
  1466. X    color->b += diff->b * costheta * lcolor->b;
  1467. X    /*
  1468. X     * Specularly reflected highlights.
  1469. X     * Fall off as the cosine of the angle
  1470. X     * between the reflected ray and the ray to the light source.
  1471. X     */
  1472. X    if (coef < EPSILON || cosalpha <= 0.)
  1473. X        return;
  1474. X    /*
  1475. X     * Specular highlight = cosine of the angle raised to the
  1476. X     * appropriate power.
  1477. X     */
  1478. X    intens = pow(cosalpha, coef);
  1479. X    color->r += spec->r * intens * lcolor->r;
  1480. X    color->g += spec->g * intens * lcolor->g;
  1481. X    color->b += spec->b * intens * lcolor->b;
  1482. X}
  1483. X
  1484. X/*
  1485. X * Spawn a transmitted ray.  Returns TRUE if total internal reflection
  1486. X * occurs, FALSE otherwise.
  1487. X */
  1488. Xstatic int
  1489. XTransmitRay(ray, pos, norm, k, index, statten, enter, back, contrib, intens, color)
  1490. XRay *ray;
  1491. XVector *pos, *norm;
  1492. XFloat k, index, statten;
  1493. Xint enter;
  1494. XColor *back, *contrib, *intens, *color;
  1495. X{
  1496. X    int total_int_refl = FALSE;
  1497. X    Ray NewRay;
  1498. X    Float dist;
  1499. X    Color newcol;
  1500. X    HitList hittmp;        /* Geom intersection record */
  1501. X
  1502. X    NewRay.pos = *pos;        /* Origin == hit point */
  1503. X    NewRay.media = ray->media;    /* Media == old media */
  1504. X    NewRay.sample = ray->sample;
  1505. X    NewRay.time = ray->time;
  1506. X    NewRay.depth = ray->depth + 1;
  1507. X
  1508. X    if (enter) {
  1509. X        /*
  1510. X         * Entering surface.
  1511. X         */
  1512. X        if (Refract(&NewRay.dir,
  1513. X            NewRay.media ? NewRay.media->index :
  1514. X            TopMedium.index, index, &ray->dir, norm, k)) {
  1515. X            total_int_refl = TRUE;
  1516. X        } else {
  1517. X            /*
  1518. X             * Push information for new medium.
  1519. X             */
  1520. X            NewRay.media = MediumPush(index, statten, NewRay.media);
  1521. X        }
  1522. X    } else {
  1523. X        /*
  1524. X         * Exiting surface
  1525. X         * Pop medium from stack.
  1526. X         */
  1527. X        if (NewRay.media != (Medium *)0)
  1528. X            NewRay.media = NewRay.media->next;
  1529. X        if (Refract(&NewRay.dir, index,
  1530. X            NewRay.media ? NewRay.media->index :
  1531. X            TopMedium.index, &ray->dir, norm, k)) {
  1532. X            total_int_refl = TRUE;
  1533. X        }
  1534. X    }
  1535. X
  1536. X    /*
  1537. X     * At this point, NewRay.media is the medium into which
  1538. X     * the new ray is entering.
  1539. X     */
  1540. X
  1541. X    if (!total_int_refl) {
  1542. X        Stats.RefractRays++;
  1543. X        hittmp.nodes = 0;
  1544. X        dist = FAR_AWAY;
  1545. X        TraceRay(&NewRay, &hittmp, EPSILON, &dist);
  1546. X        ShadeRay(&hittmp, &NewRay, dist, back, &newcol, contrib);
  1547. X        ColorMultiply(newcol, *intens, &newcol);
  1548. X        /*
  1549. X         * Attenuate transmitted color.  Note that
  1550. X         * if the transmitted ray hit nothing, we still
  1551. X         * perform this computation, as it's possible
  1552. X         * that 'air' has a non-unit statten.
  1553. X         */
  1554. X        statten = NewRay.media ? NewRay.media->statten :
  1555. X            TopMedium.statten;
  1556. X        if (statten != 1.0) {
  1557. X            statten = pow(statten, dist);
  1558. X            ColorScale(statten, newcol, &newcol);
  1559. X        }
  1560. X        ColorAdd(*color, newcol, color);
  1561. X        /* Free pushed medium */
  1562. X        if (enter)
  1563. X            free((voidstar)NewRay.media);
  1564. X    }
  1565. X
  1566. X    return total_int_refl;
  1567. X}
  1568. X
  1569. Xstatic void
  1570. XReflectRay(ray, pos, dir, back, intens, contrib, color)
  1571. XRay *ray;
  1572. XVector *pos, *dir;
  1573. XColor *back, *intens, *contrib, *color;
  1574. X{
  1575. X    Ray NewRay;
  1576. X    HitList hittmp;        /* Geom intersection record */
  1577. X    Color newcol;
  1578. X    Float dist;
  1579. X
  1580. X    NewRay.pos = *pos;        /* Origin == hit point */
  1581. X    NewRay.dir = *dir;        /* Direction == reflection */
  1582. X    NewRay.media = ray->media;    /* Medium == old medium */
  1583. X    NewRay.sample = ray->sample;
  1584. X    NewRay.time = ray->time;
  1585. X    NewRay.depth = ray->depth + 1;
  1586. X    Stats.ReflectRays++;
  1587. X    hittmp.nodes = 0;
  1588. X    dist = FAR_AWAY;
  1589. X    (void)TraceRay(&NewRay, &hittmp, EPSILON, &dist);
  1590. X    ShadeRay(&hittmp, &NewRay, dist, back, &newcol, contrib);
  1591. X    ColorMultiply(newcol, *intens, &newcol);
  1592. X    ColorAdd(*color, newcol, color);
  1593. X}
  1594. END_OF_FILE
  1595. if test 10451 -ne `wc -c <'libshade/shade.c'`; then
  1596.     echo shar: \"'libshade/shade.c'\" unpacked with wrong size!
  1597. fi
  1598. # end of 'libshade/shade.c'
  1599. fi
  1600. echo shar: End of archive 13 \(of 19\).
  1601. cp /dev/null ark13isdone
  1602. MISSING=""
  1603. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
  1604.     if test ! -f ark${I}isdone ; then
  1605.     MISSING="${MISSING} ${I}"
  1606.     fi
  1607. done
  1608. if test "${MISSING}" = "" ; then
  1609.     echo You have unpacked all 19 archives.
  1610.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1611. else
  1612.     echo You still need to unpack the following archives:
  1613.     echo "        " ${MISSING}
  1614. fi
  1615. ##  End of shell archive.
  1616. exit 0
  1617.  
  1618. exit 0 # Just in case...
  1619.