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

  1. Newsgroups: comp.sources.misc
  2. From: Rayshade Construction Co. <rayshade@weedeater.math.YALE.EDU>
  3. Subject:  v21i017:  rayshade - A raytracing package for UNIX, Part14/19
  4. Message-ID: <1991Jul21.033851.29357@sparky.IMD.Sterling.COM>
  5. X-Md4-Signature: ebcce76c5e73059627767f18b563b69c
  6. Date: Sun, 21 Jul 1991 03:38:51 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 17
  10. Archive-name: rayshade/part14
  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 14 (of 19)."
  19. # Contents:  Doc/Guide/texture.tex libray/libobj/grid.c
  20. #   libray/libobj/triangle.c rayshade/raytrace.c
  21. # Wrapped by kolb@woody on Wed Jul 17 17:56:53 1991
  22. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  23. if test -f 'Doc/Guide/texture.tex' -a "${1}" != "-c" ; then 
  24.   echo shar: Will not clobber existing file \"'Doc/Guide/texture.tex'\"
  25. echo shar: Extracting \"'Doc/Guide/texture.tex'\" \(13009 characters\)
  26. sed "s/^X//" >'Doc/Guide/texture.tex' <<'END_OF_FILE'
  27. X\chapter {Texturing}
  28. XTextures are used to modify the appearance of an object through the
  29. Xuse of procedural functions.  A texture may modify any surface characteristic,
  30. Xsuch as diffuse color, reflectivity, or transparency, or it may 
  31. Xmodify the surface normal (``bump mapping'') in order to give the
  32. Xappearance of a rough surface.
  33. XAny number of textures may be associated with an object.  If more than
  34. Xone texture is specified, they are applied in the order given.  This allows
  35. Xone to compose texturing functions and create, for example
  36. Xa tiled marble ground plane using the {\em checker} and {\em marble}
  37. Xtextures.
  38. XTextures are associated with objects by following the object specification
  39. Xby a number of lines of the form:
  40. X\begin{center}
  41. X{\tt texture} {\em name} $<${\em Texturing Arguments}$>$ [{\em Transformations}]
  42. X\end{center}
  43. XTransformations may be applied to the texture in order to, for example,
  44. Xshrink or grow feature size, change the orientation of features, and
  45. Xchange the position of features.
  46. XSeveral of the texturing functions take the name of a colormap as an
  47. Xargument.  A colormap is 256-line ASCII file, with each line containing
  48. Xthree space-separated values ranging from 0 to 255.  Each line gives
  49. Xthe red, green, and blue values for a single entry in the colormap.
  50. X\section {Texturing Functions}
  51. X\begin{defkey}{blotch}{{\em BlendFactor surface}}
  52. XProduces a mildly interesting blotchy-looking surface.
  53. X{\em BlendFactor} is used to control the interpolation between
  54. Xthe default surface characteristics and the characteristics of
  55. Xthe given surface.  A value of 0 results in a roughly 50-50 mix
  56. Xof the two surfaces.  Higher values result in a great portion of
  57. Xthe default surface characteristics.
  58. X\end{defkey}
  59. X\begin{defkey}{bump}{{\em scale}}
  60. XApply a random bump map.  The point of intersection is passed to
  61. X{\em DNoise()}.
  62. XThe returned normalized vector is weighted by {\em scale}
  63. Xand the result is added to the normal vector at the point of intersection.
  64. X\end{defkey}
  65. X\begin{defkey}{checker}{$<${\em Surface}$>$}
  66. XApplies a 3D checkerboard texture.  Every point that falls within an
  67. X``even'' unit cube will be assigned the characteristics of the named surface
  68. Xapplied to it, while points that fall within ``odd'' cubes will have
  69. Xits usual surface characteristics.  Be wary of strange effects due
  70. Xto roundoff error that occur when a planar checkered surface lies
  71. Xin a plane of constant integral value (e.g., $z=0$) in texture space.
  72. XIn such cases,
  73. Xsimply translate the texture to ensure that the planar surface is not
  74. Xcoincident with an integral plane in texture space
  75. X(e.g., {\tt translate 0 0 0.1}).
  76. X\end{defkey}
  77. X\begin{defkey}{cloud}{{\em scale H $\lambda$ octaves cthresh lthresh tscale}}
  78. X    This texture is a variant on Geoff Gardner's ellipsoid-texturing
  79. X    algorithm.  It should be applied to unit spheres centered
  80. X    at the origin.  These spheres may, of course, be transformed
  81. X    at will to form the appropriately-shaped cloud or tree.
  82. X    A sample of normalized {\em fBm} (see the {\em fbm} texture) is
  83. X    generated
  84. X    at the point of intersection.  This sample is used to
  85. X    modulate the surface transparency.  The final transparency
  86. X    if a function of the sample value, the
  87. X    the proximity of the point of intersection to the edge of
  88. X    the sphere (as seen from the ray origin), and three parameters
  89. X    to control the overall ``density.''  The proximity of the point
  90. X    to the sphere edge is determined by evaluating a {\em limb} function,
  91. X    which varies from 0 on the limb to 1 at the center of the sphere.
  92. Xtransp = 1. - \frac{fBm - cthresh - (lthresh - cthresh)(1 - limb)}{tscale}
  93. X\end{defkey}
  94. X\begin{defkey}{fbm}{{\em offset scale H $\lambda$ octaves thresh}
  95. X[{\em colormap}]}
  96. XGenerate a sample of discretized fractional Brownian motion (fBm) and
  97. Xuses it to scale the diffuse and ambient component of an object's surface.
  98. X{\em Scale} is used to scale the value
  99. Xreturned by the fBm function.  {\em Offset} allows one to control the minimum
  100. Xvalue of the fBm function.  {\em H} is the {\em Holder exponent}
  101. Xused in the fBm function (a value of 0.5 works well).  $\lambda$ is
  102. Xused to control {\em lacunarity}, and specifies the the frequency
  103. Xdifference between successive samples of the fBm basis function (a
  104. Xvalue of 2.0 will suffice).  {\em Octaves} specifies the number of
  105. Xoctaves (samples) to take of the fBm basis function (in this case, Noise()).
  106. XBetween five and seven octaves usually works well.  {\em Thresh} is used
  107. Xto specify a lower bound onthe output of the fBm function.  Any
  108. Xvalue lower than {\em thresh} is set to zero.
  109. XIf a {\em colormap} is named, a 256-entry colormap is read from the named
  110. Xfile, and the sample of fBm is scaled by 255 and is used as an index into
  111. Xthe colormap.  The resulting colormap entry
  112. Xis used to scale the ambient and diffuse components of the
  113. Xobject's surface.
  114. X\end{defkey}
  115. X\begin{defkey}{fbmbump}{{\em offset scale H $\lambda$ octaves}}
  116. XSimilar to the {\em fbm} texture.  Rather than modifying the color of
  117. Xa surface, this texture acts as a bump map.
  118. X\end{defkey}
  119. X\begin{defkey}{gloss}{{\em glossiness}}
  120. XGives reflective surfaces a glossy appearance. This texture perturbs
  121. Xthe object's surface normal such that the normal ``samples'' a cone of
  122. Xunit height with radius $1. - glossiness$.  A value of 1 results
  123. Xin perfect mirror-like reflections, while a value of 0 results
  124. Xin extremely fuzzy reflections.  For best results, jittered sampling
  125. Xshould be used to render scenes that make use of this texture.
  126. X\end{defkey}
  127. X\begin{defkey}{marble}{[{\em colormap}]}
  128. XGives a surface a marble-like appearance.  The texture is implemented as
  129. Xroughly parallel alternating veins of marble, each of which is
  130. Xseparated by 1/7 of a unit and runs perpendicular to the Z axis.
  131. XIf a colormap is named, the surface's ambient and diffuse colors
  132. Xwill be scaled using the RGB values in the colormap.  If no colormap is
  133. Xgiven, the diffuse and ambient components are simply scaled by the
  134. Xvalue of the marble function.  One may transform the texture to
  135. Xcontrol the density and orientation of the marble veins.
  136. X\end{defkey}
  137. X\begin{defkey}{sky}{{\em scale H $\lambda$ octaves cthresh ltresh}}
  138. X    Similar to the {\em fbm} texture.  Rather than modifying the
  139. X    color of a surface, this texture modulates its transparency.
  140. X    {\em cthresh} is the value of the {\em fBm} function above
  141. X    which the surface is totally opaque.  Below {\em lthresh},
  142. X    the surface is totally transparent.
  143. X\end{defkey}
  144. X\begin{defkey}{stripe}{$<${\em Surface}$>$ {\em size bump} $<$Mapping$>$}
  145. X    Apply a ``raised'' stripe pattern to the surface.
  146. X    The surface properties used to color the stripe are those
  147. X    of the given surface.  The width of the stripe, as compared
  148. X    to the unit interval, is given by {\em size}.  The magnitude
  149. X    of {\em bump} controls the extent to which the bump appears
  150. X    to be displaced from the rest of the surface.  If negative,
  151. X    the stripe will appear to
  152. X    sink into the surface; if negative, it will appear to stand
  153. X    out of the surface.
  154. X\end{defkey}
  155. XMapping functions are described below.
  156. X\begin{defkey}{wood}{}
  157. XGives a surface a wood-like appearance.  The feature size of this texture
  158. Xis approximately $0.01$ of a unit, making it often necessary to
  159. Xscale the texture in order to achieve the desired appearance.
  160. X\end{defkey}
  161. X\section {Image Texturing}
  162. X{\em Rayshade} also supports an {\tt image} texture.  This texture
  163. Xallows you to use images to modify the characteristics of a surface.  You
  164. Xcan use three-channel images to modify the any or all of
  165. Xthe ambient, diffuse, and specular colors of a surface.
  166. XIf you are using the Utah Raster Toolkit,
  167. Xyou can also use single-channel images to modify surface reflectance,
  168. Xtransparency, and the specular exponent.  You can also use a single-channel
  169. Ximage to apply a bump map to a surface.
  170. XIn all but the bump-mapping case,
  171. Xa component is modified by multiplying the given value by the value
  172. Xcomputed by the texturing function.  When using the Utah Raster Toolkit,
  173. Xsurface characteristics are modified in proportion to the value of
  174. Xthe {\em alpha} channel in the image.  If there is no {\em alpha} channel,
  175. Xor you are not using the Utah Raster Toolkit, {\em alpha} is assumed to be
  176. Xeverywhere
  177. Xequal to $1$.
  178. X\begin{defkey}{component}{$<${\em Component}$>$}
  179. X    The named component will be modified.
  180. X\end{defkey}
  181. XPossible surface components are:
  182. X{\tt ambient} (modify ambient color),
  183. X{\tt diffuse} (modify diffuse color),
  184. X{\tt specular} (modify specular color),
  185. X{\tt specpow}, (modify specular exponent),
  186. X{\tt reflect},    (modify reflectivity),
  187. X{\tt transp} (modify transparency),
  188. X{\tt bump}, (modify surface normal).
  189. XThe {\tt specpow}, {\tt reflect}, {\tt transp}, and {\tt bump}
  190. Xcomponents require the use of a single-channel image.
  191. X\begin{defkey}{range}{{\em high low}}
  192. X    Specify the range of values to which the values in the
  193. X    image should be mapped.  An value of $1$ will
  194. X    be mapped {\em high}, $0$ to {\em low}.  Intermediate
  195. X    values will be linearly interpolated.
  196. X\end{defkey}
  197. X\begin{defkey}{smooth}{}
  198. X    When given, pixel averaging will be performed in order
  199. X    to smooth the sampled image.  If not specified, no averaging
  200. X    will occur.
  201. X\end{defkey}
  202. X\begin{defkey}{textsurf}{$<${\em Surface Specification}$>$}
  203. X    For use when modifying surface colors, this keyword specifies
  204. X    that the given surface should be used as the base
  205. X    to be modified when the {\em alpha} value in the image
  206. X    is non-zero.  When {\em alpha} is zero, the object's
  207. X    unmodified default surface characteristics are retained.
  208. X\end{defkey}
  209. XThe usual behavior is for the object's default surface properties to
  210. Xbe used.
  211. X\begin{defkey}{tile}{{\em un vn}}
  212. X    Specify how the image should be tiled (repeated) along the
  213. X    $u$ and $v$ axes.
  214. X    If positive, the value of {\em un} gives the number of
  215. X    times the image should be repeated along the $u$ axis, starting
  216. X    from the origin of the texture, and positive {\em vn} gives the
  217. X    number of times it
  218. X    should be repeated along the $v$ axis.  If either value is zero,
  219. X    the image is repeated infinitely along the appropriate axis.
  220. X\end{defkey}
  221. XTiling is usually only a concern when linear mapping is being used,
  222. Xthough it may also be used if image textures are being scaled.  By default
  223. X{\em un} and {\em vn} are both zero.
  224. XA mapping function may also be associated with an image texture.
  225. X\section {Mapping Functions}
  226. XMapping functions are used to apply two-dimensional textures to
  227. Xsurfaces.  Each mapping functions defines a different method of transforming
  228. Xa three dimensional point of intersection to a two dimensional $u-v$ pair
  229. Xtermed texturing coordinates.
  230. XTypically, the arguments to a mapping method define a center of
  231. Xa projection and two non-parallel axes that define a local coordinate system.
  232. XThe default mapping method is termed $u-v$ mapping or {\em inverse mapping}.
  233. XNormally, there is a different inverse mapping method for each primitive type
  234. X(see chapter 5).
  235. XWhen inverse mapping is used, the point of intersection is passed to
  236. Xthe $uv$ method for the primitive that was hit.
  237. X\begin{defkey}{map}{{\tt uv}}
  238. X    Use the $uv$ (inverse mapping) method associated with the
  239. X    object that was intersected in order to map from 3D to determine
  240. X    texturing coordinates.
  241. X\end{defkey}
  242. XThe inverse mapping method for each primitive is described in Chapter 5.
  243. X\begin{defkey}{map}{{\tt linear} [\evec{origin} \evec{vaxis} \evec{uaxis}]}
  244. X    Use a linear mapping method. The 2D texture is transformed
  245. X    so that its $u$ axis is given by \evec{uaxis} and its $v$
  246. X    axis by $vaxis$.  The texture is projected along the vector
  247. X    defined by the cross product of the $u$ and $v$ axes, with
  248. X    the (0,0) in texture space mapped to \evec{origin}.
  249. X\end{defkey}
  250. X\begin{defkey}{map}{{\tt cylindrical} [\evec{origin} \evec{vaxis} \evec{uaxis}]}
  251. X    Use a cylindrical mapping method.  The point of intersection
  252. X    is projected onto an imaginary cylinder, and the location
  253. X    of the projected point is used to determine the texture coordinates.
  254. X    If given, \evec{origin} and
  255. X    \evec{vaxis} define the cylinder's axis, and \evec{uaxis} defines
  256. X    where $u=0$ is located.
  257. X\end{defkey}
  258. XSee the description of the inverse mapping method for the 
  259. Xcylinder in Chapter 5.  By default, the point of intersection is
  260. Xprojected onto a cylinder that runs through the origin along the $z$
  261. Xaxis, with \evec{uaxis} equal to the $x$ axis.
  262. X\begin{defkey}{map}{{\tt spherical} [\evec{origin} \evec{vaxis} \evec{uaxis}]}
  263. X    Use a spherical mapping method.  The intersection point is
  264. X    projected onto an imaginary sphere, and the location of the
  265. X    projected point     is used to determine the texturing coordinates
  266. X    in a manner identical to that used in the inverse mapping method
  267. X    for the sphere primitive.
  268. X    If given, the center of
  269. X    the projection is \evec{origin}, \evec{vaxis} defines
  270. X    the sphere axis, and the point where the
  271. X    non-parallel \evec{uaxis} intersects the sphere
  272. X    defines where $u=0$ is located.
  273. X\end{defkey}
  274. XBy default, a spherical mapping projects points towards the origin,
  275. Xwith \evec{vaxis} defined to be the $z$ axis and
  276. X\evec{uaxis} defined to be the $x$ axis.
  277. END_OF_FILE
  278. if test 13009 -ne `wc -c <'Doc/Guide/texture.tex'`; then
  279.     echo shar: \"'Doc/Guide/texture.tex'\" unpacked with wrong size!
  280. # end of 'Doc/Guide/texture.tex'
  281. if test -f 'libray/libobj/grid.c' -a "${1}" != "-c" ; then 
  282.   echo shar: Will not clobber existing file \"'libray/libobj/grid.c'\"
  283. echo shar: Extracting \"'libray/libobj/grid.c'\" \(11666 characters\)
  284. sed "s/^X//" >'libray/libobj/grid.c' <<'END_OF_FILE'
  285. X * grid.c
  286. X * Copyright (C) 1989, 1991, Craig E. Kolb
  287. X * All rights reserved.
  288. X * This software may be freely copied, modified, and redistributed
  289. X * provided that this copyright notice is preserved on all copies.
  290. X * You may not distribute this software, in whole or in part, as part of
  291. X * any commercial product without the express consent of the authors.
  292. X * There is no warranty or other guarantee of fitness of this software
  293. X * for any purpose.  It is provided solely "as is".
  294. X * $Id: grid.c,v 4.0 91/07/17 14:38:02 kolb Exp Locker: kolb $
  295. X * $Log:    grid.c,v $
  296. X * Revision 4.0  91/07/17  14:38:02  kolb
  297. X * Initial version.
  298. X#include "geom.h"
  299. X#include "grid.h"
  300. Xstatic Methods *iGridMethods = NULL;
  301. Xstatic char gridName[] = "grid";
  302. Xstatic unsigned long raynumber = 1;        /* Current "ray number". */
  303. X                        /* (should be "grid number") */
  304. Xstatic void engrid(), GridFreeVoxels();
  305. Xstatic int pos2grid(), CheckVoxel();
  306. XGrid *
  307. XGridCreate(x, y, z)
  308. Xint x, y, z;
  309. X    Grid *grid;
  310. X    if (x < 1 || y < 1 || z < 1) {
  311. X        RLerror(RL_WARN, "Invalid grid specification.\n");
  312. X        return (Grid *)NULL;
  313. X    grid = (Grid *)share_calloc(1, sizeof(Grid));
  314. X    grid->xsize = x;
  315. X    grid->ysize = y;
  316. X    grid->zsize = z;
  317. X    return grid;    
  318. Xchar *
  319. XGridName()
  320. X    return gridName;
  321. X * Intersect ray with grid, returning distance from "pos" to
  322. X * nearest intersection with an object in the grid.  Returns 0.
  323. X * if no intersection.
  324. XGridIntersect(grid, ray, hitlist, mindist, maxdist)
  325. XGrid *grid;
  326. XRay *ray;
  327. XHitList *hitlist;
  328. XFloat mindist, *maxdist;
  329. X    GeomList *list;
  330. X    Geom *obj;
  331. X    int hit;
  332. X    Float offset, tMaxX, tMaxY, tMaxZ;
  333. X    Float tDeltaX, tDeltaY, tDeltaZ, *raybounds[2][3];
  334. X    int stepX, stepY, stepZ, outX, outY, outZ, x, y, z;
  335. X    Vector curpos, nXp, nYp, nZp, np, pDeltaX, pDeltaY, pDeltaZ;
  336. X    unsigned long counter;
  337. X    hit = FALSE;
  338. X     * Check unbounded objects.
  339. X     */
  340. X    for (obj = grid->unbounded ; obj; obj = obj->next) {
  341. X        if (intersect(obj, ray, hitlist, mindist, maxdist))
  342. X            hit = TRUE;
  343. X     * If outside of the bounding box, check to see if we
  344. X     * hit it.
  345. X     */
  346. X    VecAddScaled(ray->pos, mindist, ray->dir, &curpos);
  347. X    if (OutOfBounds(&curpos, grid->bounds)) {
  348. X        offset = *maxdist;
  349. X        if (!BoundsIntersect(ray, grid->bounds, mindist, &offset))
  350. X            /*
  351. X             * Ray never hit grid space.
  352. X             */
  353. X            return hit;
  354. X        /*
  355. X         * else
  356. X         *    The ray enters voxel space before it hits
  357. X         *     an unbounded object.
  358. X         */
  359. X        VecAddScaled(ray->pos, offset, ray->dir, &curpos);
  360. X    } else
  361. X        offset = mindist;
  362. X    counter = raynumber++;
  363. X     * tMaxX is the absolute distance from the ray origin we must move
  364. X     *        to get to the next voxel in the X
  365. X     *        direction.  It is incrementally updated
  366. X     *         by DDA as we move from voxel-to-voxel.
  367. X     * tDeltaX is the relative amount along the ray we move to
  368. X     *        get to the next voxel in the X direction. Thus,
  369. X     *        when we decide to move in the X direction,
  370. X     *         we increment tMaxX by tDeltaX.
  371. X     */
  372. X    x = x2voxel(grid, curpos.x);
  373. X    if (x == grid->xsize)
  374. X        x--;
  375. X    if (ray->dir.x < 0.) {
  376. X        tMaxX = offset + (voxel2x(grid, x) - curpos.x) / ray->dir.x;
  377. X        tDeltaX = grid->voxsize[X] / - ray->dir.x;
  378. X        stepX = outX = -1;
  379. X        raybounds[LOW][X] = &np.x;
  380. X        raybounds[HIGH][X] = &curpos.x;
  381. X    } else if (ray->dir.x > 0.) {
  382. X        tMaxX = offset + (voxel2x(grid, x+1) - curpos.x) / ray->dir.x;
  383. X        tDeltaX = grid->voxsize[X] / ray->dir.x;
  384. X        stepX = 1;
  385. X        outX = grid->xsize;
  386. X        raybounds[LOW][X] = &curpos.x;
  387. X        raybounds[HIGH][X] = &np.x;
  388. X    } else {
  389. X        tMaxX = FAR_AWAY;
  390. X        raybounds[LOW][X] = &curpos.x;
  391. X        raybounds[HIGH][X] = &np.x;
  392. X        tDeltaX = 0.;
  393. X    y = y2voxel(grid, curpos.y);
  394. X    if (y == grid->ysize)
  395. X        y--;
  396. X    if (ray->dir.y < 0.) {
  397. X        tMaxY = offset + (voxel2y(grid, y) - curpos.y) / ray->dir.y;
  398. X        tDeltaY = grid->voxsize[Y] / - ray->dir.y;
  399. X        stepY = outY = -1;
  400. X        raybounds[LOW][Y] = &np.y;
  401. X        raybounds[HIGH][Y] = &curpos.y;
  402. X    } else if (ray->dir.y > 0.) {
  403. X        tMaxY = offset + (voxel2y(grid, y+1) - curpos.y) / ray->dir.y;
  404. X        tDeltaY = grid->voxsize[Y] / ray->dir.y;
  405. X        stepY = 1;
  406. X        outY = grid->ysize;
  407. X        raybounds[LOW][Y] = &curpos.y;
  408. X        raybounds[HIGH][Y] = &np.y;
  409. X    } else {
  410. X        tMaxY = FAR_AWAY;
  411. X        raybounds[LOW][Y] = &curpos.y;
  412. X        raybounds[HIGH][Y] = &np.y;
  413. X        tDeltaY = 0.;
  414. X    z = z2voxel(grid, curpos.z);
  415. X    if (z == grid->zsize)
  416. X        z--;
  417. X    if (ray->dir.z < 0.) {
  418. X        tMaxZ = offset + (voxel2z(grid, z) - curpos.z) / ray->dir.z;
  419. X        tDeltaZ = grid->voxsize[Z] / - ray->dir.z;
  420. X        stepZ = outZ = -1;
  421. X        raybounds[LOW][Z] = &np.z;
  422. X        raybounds[HIGH][Z] = &curpos.z;
  423. X    } else if (ray->dir.z > 0.) {
  424. X        tMaxZ = offset + (voxel2z(grid, z+1) - curpos.z) / ray->dir.z;
  425. X        tDeltaZ = grid->voxsize[Z] / ray->dir.z;
  426. X        stepZ = 1;
  427. X        outZ = grid->zsize;
  428. X        raybounds[LOW][Z] = &curpos.z;
  429. X        raybounds[HIGH][Z] = &np.z;
  430. X    } else {
  431. X        tMaxZ = FAR_AWAY;
  432. X        raybounds[LOW][Z] = &curpos.z;
  433. X        raybounds[HIGH][Z] = &np.z;
  434. X        tDeltaZ = 0.;
  435. X    VecScale(tDeltaX, ray->dir, &pDeltaX);
  436. X    VecScale(tDeltaY, ray->dir, &pDeltaY);
  437. X    VecScale(tDeltaZ, ray->dir, &pDeltaZ);
  438. X    VecAddScaled(ray->pos, tMaxX, ray->dir, &nXp);
  439. X    VecAddScaled(ray->pos, tMaxY, ray->dir, &nYp);
  440. X    VecAddScaled(ray->pos, tMaxZ, ray->dir, &nZp);
  441. X    while (TRUE) {
  442. X        list = grid->cells[x][y][z];
  443. X        if (tMaxX < tMaxY && tMaxX < tMaxZ) {
  444. X            if (list) {
  445. X                np = nXp;
  446. X                    if (CheckVoxel(list,ray,raybounds,
  447. X                        hitlist,counter,offset,maxdist))
  448. X                    hit = TRUE;
  449. X            }
  450. X            x += stepX;
  451. X            if (*maxdist < tMaxX || x == outX)
  452. X                break;
  453. X            tMaxX += tDeltaX;
  454. X            curpos = nXp;
  455. X            nXp.x += pDeltaX.x;
  456. X            nXp.y += pDeltaX.y;
  457. X            nXp.z += pDeltaX.z;
  458. X        } else if (tMaxZ < tMaxY) {
  459. X            if (list) {
  460. X                np = nZp;
  461. X                    if (CheckVoxel(list,ray, raybounds,
  462. X                        hitlist,counter,offset,maxdist))
  463. X                    hit = TRUE;
  464. X            }
  465. X            z += stepZ;
  466. X            if (*maxdist < tMaxZ || z == outZ)
  467. X                break;
  468. X            tMaxZ += tDeltaZ;
  469. X            curpos = nZp;
  470. X            nZp.x += pDeltaZ.x;
  471. X            nZp.y += pDeltaZ.y;
  472. X            nZp.z += pDeltaZ.z;
  473. X        } else {
  474. X            if (list) {
  475. X                np = nYp;
  476. X                    if (CheckVoxel(list,ray,raybounds,
  477. X                        hitlist,counter,offset,maxdist))
  478. X                    hit = TRUE;
  479. X            }
  480. X            y += stepY;
  481. X            if (*maxdist < tMaxY || y == outY)
  482. X                break;
  483. X            tMaxY += tDeltaY;
  484. X            curpos = nYp;
  485. X            nYp.x += pDeltaY.x;
  486. X            nYp.y += pDeltaY.y;
  487. X            nYp.z += pDeltaY.z;
  488. X    return hit;
  489. X * Intersect ray with objects in grid cell.  Note that there are a many ways
  490. X * to speed up this routine, all of which uglify the code to a large extent.
  491. Xstatic int
  492. XCheckVoxel(list,ray,raybounds,hitlist,counter,mindist,maxdist)
  493. XGeomList *list;
  494. XRay *ray;
  495. XFloat *raybounds[2][3];
  496. XHitList *hitlist;
  497. Xunsigned long counter;
  498. XFloat mindist, *maxdist;
  499. X    Geom *obj;
  500. X    int hit;
  501. X    Float lx, hx, ly, hy, lz, hz;
  502. X    lx = *raybounds[LOW][X];
  503. X    hx = *raybounds[HIGH][X];
  504. X    ly = *raybounds[LOW][Y];
  505. X    hy = *raybounds[HIGH][Y];
  506. X    lz = *raybounds[LOW][Z];
  507. X    hz = *raybounds[HIGH][Z];
  508. X    hit = FALSE;
  509. X    do {
  510. X        obj = list->obj;
  511. X        /*
  512. X         * If object's counter is greater than or equal to the
  513. X         * number associated with the current grid,
  514. X         * don't bother checking again.  In addition, if the
  515. X         * bounding box of the ray's extent in the voxel does
  516. X         * not intersect the bounding box of the object, don't bother.
  517. X         */
  518. X#ifdef SHAREDMEM
  519. X        if (*obj->counter < counter &&
  520. X#else
  521. X        if (obj->counter < counter &&
  522. X#endif
  523. X            obj->bounds[LOW][X] <= hx  &&
  524. X            obj->bounds[HIGH][X] >= lx &&
  525. X            obj->bounds[LOW][Y] <= hy  &&
  526. X            obj->bounds[HIGH][Y] >= ly &&
  527. X            obj->bounds[LOW][Z] <= hz  &&
  528. X            obj->bounds[HIGH][Z] >= lz) {
  529. X#ifdef SHAREDMEM
  530. X            *obj->counter = counter;
  531. X#else
  532. X            obj->counter = counter;
  533. X#endif
  534. X            if (intersect(obj, ray, hitlist, mindist, maxdist))
  535. X                hit = TRUE;
  536. X    } while ((list = list->next) != (GeomList *)0);
  537. X    return hit;
  538. XGridConvert(grid, objlist)
  539. XGrid *grid;
  540. XGeom *objlist;
  541. X    int num;
  542. X     * Keep linked list of all bounded objects in grid; it may come
  543. X     * in handy.
  544. X     */
  545. X    grid->objects = objlist;
  546. X    for (num = 0; objlist; objlist = objlist->next)
  547. X        num += objlist->prims;
  548. X    return num;
  549. Xvoid
  550. XGridBounds(grid, bounds)
  551. XGrid *grid;
  552. XFloat bounds[2][3];
  553. X    Geom *obj, *ltmp;
  554. X    int x, y, i;
  555. X    BoundsInit(bounds);
  556. X     * For each object on the list,
  557. X     * compute its bounds...
  558. X     */
  559. X     * Find bounding box of bounded objects and get list of
  560. X     * unbounded objects.
  561. X     */
  562. X    grid->unbounded = GeomComputeAggregateBounds(&grid->objects,
  563. X                grid->unbounded, grid->bounds);
  564. X    BoundsCopy(grid->bounds, bounds);
  565. X    grid->voxsize[X] = (grid->bounds[HIGH][X]-grid->bounds[LOW][X])/
  566. X                grid->xsize;
  567. X    grid->voxsize[Y] = (grid->bounds[HIGH][Y]-grid->bounds[LOW][Y])/
  568. X                grid->ysize;
  569. X    grid->voxsize[Z] = (grid->bounds[HIGH][Z]-grid->bounds[LOW][Z])/
  570. X                grid->zsize;
  571. X    if (grid->cells == (GeomList ****)NULL) {
  572. X        /*
  573. X          * Allocate voxels.
  574. X          */
  575. X        grid->cells = (GeomList ****)share_malloc(grid->xsize *
  576. X                    sizeof(GeomList ***));
  577. X        for (x = 0; x < grid->xsize; x++) {
  578. X            grid->cells[x] = (GeomList ***)share_malloc(grid->ysize *
  579. X                sizeof(GeomList **));
  580. X            for (y = 0; y < grid->ysize; y++)
  581. X                grid->cells[x][y] = (GeomList **)share_calloc(
  582. X                    (unsigned)grid->zsize,sizeof(GeomList *));
  583. X    } else {
  584. X        /*
  585. X         * New frame...
  586. X         * Free up the objlists in each voxel.
  587. X         */
  588. X        GridFreeVoxels(grid);
  589. X     * objlist now holds a linked list of bounded objects.
  590. X     */
  591. X    for (ltmp = grid->objects; ltmp != (Geom *)0; ltmp = ltmp->next)
  592. X        engrid(ltmp, grid);
  593. Xstatic void
  594. XGridFreeVoxels(grid)
  595. XGrid *grid;
  596. X    int x, y, z;
  597. X    GeomList *cell, *next;
  598. X    for (x = 0; x < grid->xsize; x++) {
  599. X        for (y = 0; y < grid->ysize; y++) {
  600. X            for (z = 0; z < grid->zsize; z++) {
  601. X                for (cell = grid->cells[x][y][z]; cell; cell = next) {
  602. X                    next = cell->next;
  603. X                    free((voidstar)cell);
  604. X                }
  605. X                grid->cells[x][y][z] = (GeomList *)NULL;
  606. X            }
  607. XMethods *
  608. XGridMethods()
  609. X    if (iGridMethods == (Methods *)NULL) {
  610. X        iGridMethods = MethodsCreate();
  611. X        iGridMethods->methods = GridMethods;
  612. X        iGridMethods->create = (GeomCreateFunc *)GridCreate;
  613. X        iGridMethods->intersect = GridIntersect;
  614. X        iGridMethods->name = GridName;
  615. X        iGridMethods->convert = GridConvert;
  616. X        iGridMethods->bounds = GridBounds;
  617. X        iGridMethods->checkbounds = FALSE;
  618. X        iGridMethods->closed = TRUE;
  619. X    return iGridMethods;
  620. X * Place an object in a grid.
  621. Xstatic void
  622. Xengrid(obj, grid)
  623. XGeom *obj;
  624. XGrid *grid;
  625. X    int x, y, z, low[3], high[3];
  626. X    GeomList *ltmp;
  627. X     * This routine should *never* be passed an unbounded object, but...
  628. X     */
  629. X    if (!pos2grid(grid, obj->bounds[LOW], low) ||
  630. X        !pos2grid(grid, obj->bounds[HIGH], high) ||
  631. X        obj->bounds[LOW][X] > obj->bounds[HIGH][X]) {
  632. X        /*
  633. X         * Geom is partially on wholly outside of
  634. X         * grid -- this should never happen, but just
  635. X         * in case...
  636. X         */
  637. X        RLerror(RL_ABORT, "Engrid got an unbounded object?!\n");
  638. X        return;
  639. X        }
  640. X     * For each voxel that intersects the object's bounding
  641. X     * box, add pointer to this object to voxel's linked list.
  642. X      */
  643. X    for (x = low[X]; x <= high[X]; x++) {
  644. X        for (y = low[Y]; y <= high[Y]; y++) {
  645. X            for (z = low[Z]; z <= high[Z]; z++) {
  646. X                ltmp = (GeomList *)share_malloc(sizeof(GeomList));
  647. X                ltmp->obj = obj;
  648. X                ltmp->next = grid->cells[x][y][z];
  649. X                grid->cells[x][y][z] = ltmp;
  650. X            }
  651. X * Convert 3D point to index into grid's voxels.
  652. Xstatic int
  653. Xpos2grid(grid, pos, index)
  654. XGrid *grid;
  655. XFloat pos[3];
  656. Xint index[3];
  657. X    index[X] = (int)(x2voxel(grid, pos[0]));
  658. X    index[Y] = (int)(y2voxel(grid, pos[1]));
  659. X    index[Z] = (int)(z2voxel(grid, pos[2]));
  660. X    if (index[X] == grid->xsize)
  661. X        index[X]--;
  662. X    if (index[Y] == grid->ysize)
  663. X        index[Y]--;
  664. X    if (index[Z] == grid->zsize)
  665. X        index[Z]--;
  666. X    if (index[X] < 0 || index[X] >= grid->xsize ||
  667. X        index[Y] < 0 || index[Y] >= grid->ysize ||
  668. X        index[Z] < 0 || index[Z] >= grid->zsize)
  669. X        return FALSE;
  670. X    return TRUE;
  671. Xvoid
  672. XGridMethodRegister(meth)
  673. XUserMethodType meth;
  674. X    if (iGridMethods)
  675. X        iGridMethods->user = meth;
  676. END_OF_FILE
  677. if test 11666 -ne `wc -c <'libray/libobj/grid.c'`; then
  678.     echo shar: \"'libray/libobj/grid.c'\" unpacked with wrong size!
  679. # end of 'libray/libobj/grid.c'
  680. if test -f 'libray/libobj/triangle.c' -a "${1}" != "-c" ; then 
  681.   echo shar: Will not clobber existing file \"'libray/libobj/triangle.c'\"
  682. echo shar: Extracting \"'libray/libobj/triangle.c'\" \(11924 characters\)
  683. sed "s/^X//" >'libray/libobj/triangle.c' <<'END_OF_FILE'
  684. X * triangle.c
  685. X * Copyright (C) 1989, 1991, Craig E. Kolb
  686. X * All rights reserved.
  687. X * This software may be freely copied, modified, and redistributed
  688. X * provided that this copyright notice is preserved on all copies.
  689. X * You may not distribute this software, in whole or in part, as part of
  690. X * any commercial product without the express consent of the authors.
  691. X * There is no warranty or other guarantee of fitness of this software
  692. X * for any purpose.  It is provided solely "as is".
  693. X * $Id: triangle.c,v 4.0 91/07/17 14:39:38 kolb Exp Locker: kolb $
  694. X * $Log:    triangle.c,v $
  695. X * Revision 4.0  91/07/17  14:39:38  kolb
  696. X * Initial version.
  697. X#include "geom.h"
  698. X#include "triangle.h"
  699. Xstatic Methods *iTriangleMethods = NULL;
  700. Xstatic char triName[] = "triangle";
  701. Xunsigned long TriTests, TriHits;
  702. Xstatic void TriangleSetdPdUV();
  703. X * Create and return reference to a triangle.
  704. XTriangle *
  705. XTriangleCreate(type, p1, p2, p3, n1, n2, n3, u1, u2, u3, flipflag)
  706. Xint    type;
  707. XVector    *p1, *p2, *p3, *n1, *n2, *n3;
  708. XVec2d    *u1, *u2, *u3;
  709. Xint flipflag;
  710. X    Triangle *triangle;
  711. X    Vector ptmp, anorm;
  712. X    Float d;
  713. X     * Allocate new triangle and primitive to point to it.
  714. X     */
  715. X    triangle = (Triangle *)share_malloc(sizeof(Triangle));
  716. X    triangle->type = type;    /* so inttri can tell the difference */
  717. X    VecSub(*p2, *p1, &triangle->e[0]);
  718. X    VecSub(*p3, *p2, &triangle->e[1]);
  719. X    VecSub(*p1, *p3, &triangle->e[2]);
  720. X    /* Find plane normal. */
  721. X    VecCross(&triangle->e[0], &triangle->e[1], &ptmp);
  722. X    triangle->nrm = ptmp;
  723. X    if (VecNormalize(&triangle->nrm) == 0.) {
  724. X        RLerror(RL_ADVISE, "Degenerate triangle.\n");
  725. X        return (Triangle *)NULL;
  726. X    if (flipflag)
  727. X        VecScale(-1, triangle->nrm, &triangle->nrm);
  728. X    triangle->d = dotp(&triangle->nrm, p1);
  729. X    triangle->p[0] = *p1;
  730. X    triangle->p[1] = *p2;
  731. X    triangle->p[2] = *p3;
  732. X    if (type == PHONGTRI) {
  733. X        if (VecNormalize(n1) == 0. || VecNormalize(n2) == 0. ||
  734. X            VecNormalize(n3) == 0.) {
  735. X            RLerror(RL_WARN, "Degenerate vertex normal.\n");
  736. X            return (Triangle *)NULL;
  737. X        triangle->vnorm = (Vector *)Malloc(3 * sizeof(Vector));
  738. X        triangle->vnorm[0] = *n1;
  739. X        triangle->vnorm[1] = *n2;
  740. X        triangle->vnorm[2] = *n3;
  741. X        if (flipflag) {
  742. X            /* Flip the vertex normals */
  743. X            VecScale(-1, triangle->vnorm[0],
  744. X                &triangle->vnorm[0]);
  745. X            VecScale(-1, triangle->vnorm[1],
  746. X                &triangle->vnorm[1]);
  747. X            VecScale(-1, triangle->vnorm[2],
  748. X                &triangle->vnorm[2]);
  749. X        } else if (dotp(&triangle->vnorm[0], &triangle->nrm) < 0.) {
  750. X            /*
  751. X             * Reverse direction of surface normal on Phong
  752. X             * triangle if the surface normal points "away"
  753. X             * from the first vertex normal.
  754. X             * Note that this means that we trust the vertex
  755. X             * normals rather than trust that the user gave the
  756. X             * vertices in the correct order.
  757. X             */
  758. X            RLerror(RL_ADVISE, "Inconsistant triangle normals.\n");
  759. X            VecScale(-1., triangle->nrm, &triangle->nrm);
  760. X            VecScale(-1., ptmp, &ptmp);
  761. X            triangle->d = -triangle->d;
  762. X            VecScale(-1., triangle->e[0], &triangle->e[0]);
  763. X            VecScale(-1., triangle->e[1], &triangle->e[1]);
  764. X            VecScale(-1., triangle->e[2], &triangle->e[2]);
  765. X     * If UV coordinates are given for the vertices, allocate and
  766. X     * store them.
  767. X     */
  768. X    if (u1 && u2 && u3) {
  769. X        triangle->uv = (Vec2d *)Malloc(3 * sizeof(Vec2d));
  770. X        triangle->uv[0] = *u1;
  771. X        triangle->uv[1] = *u2;
  772. X        triangle->uv[2] = *u3;
  773. X        /* Calculate dpdu and dpdv vectors */
  774. X        triangle->dpdu = (Vector *)Malloc(sizeof(Vector));
  775. X        triangle->dpdv = (Vector *)Malloc(sizeof(Vector));
  776. X        TriangleSetdPdUV(triangle->p, triangle->uv,
  777. X                 triangle->dpdu, triangle->dpdv);
  778. X    } else {
  779. X        triangle->uv = (Vec2d *)NULL;
  780. X     * Find "dominant" part of normal vector.
  781. X     */
  782. X    anorm.x = fabs(ptmp.x);
  783. X    anorm.y = fabs(ptmp.y);
  784. X    anorm.z = fabs(ptmp.z);
  785. X     * Scale edges by dominant part of normal.  This makes intersection
  786. X     * testing a bit faster.
  787. X     */ 
  788. X    if (anorm.x > anorm.y && anorm.x > anorm.z) {
  789. X        triangle->index = XNORMAL;
  790. X        d = 1. / ptmp.x;
  791. X    } else if (anorm.y > anorm.z) {
  792. X        triangle->index = YNORMAL;
  793. X        d = 1. / ptmp.y;
  794. X    } else {
  795. X        triangle->index = ZNORMAL;
  796. X        d = 1. /ptmp.z;
  797. X    VecScale(d, triangle->e[0], &triangle->e[0]);
  798. X    VecScale(d, triangle->e[1], &triangle->e[1]);
  799. X    VecScale(d, triangle->e[2], &triangle->e[2]);
  800. X    return triangle;
  801. XMethods *
  802. XTriangleMethods()
  803. X    if (iTriangleMethods == (Methods *)NULL) {
  804. X        iTriangleMethods = MethodsCreate();
  805. X        iTriangleMethods->create = (GeomCreateFunc *)TriangleCreate;
  806. X        iTriangleMethods->methods = TriangleMethods;
  807. X        iTriangleMethods->name = TriangleName;
  808. X        iTriangleMethods->intersect = TriangleIntersect;
  809. X        iTriangleMethods->normal = TriangleNormal;
  810. X        iTriangleMethods->uv = TriangleUV;
  811. X        iTriangleMethods->bounds = TriangleBounds;
  812. X        iTriangleMethods->stats = TriangleStats;
  813. X        iTriangleMethods->checkbounds = TRUE;
  814. X        iTriangleMethods->closed = FALSE;
  815. X    return iTriangleMethods;
  816. X * Intersect ray with triangle.  This is an optimized version of the
  817. X * intersection routine from Snyder and Barr's '87 SIGGRAPH paper.
  818. XTriangleIntersect(tri, ray, mindist, maxdist)
  819. XTriangle *tri;
  820. XRay *ray;
  821. XFloat mindist, *maxdist;
  822. X    Float qi1, qi2, s, k, b0, b1, b2;
  823. X    Vector pos, dir;
  824. X    TriTests++;
  825. X    pos = ray->pos;
  826. X    dir = ray->dir;
  827. X     * Plane intersection.
  828. X     */
  829. X    k = dotp(&tri->nrm, &dir);
  830. X    if (fabs(k) < EPSILON)
  831. X        return FALSE;
  832. X    s = (tri->d - dotp(&tri->nrm, &pos)) / k;
  833. X    if (s < mindist || s > *maxdist)
  834. X        return FALSE;
  835. X    if (tri->index == XNORMAL) {
  836. X        qi1 = pos.y + s * dir.y;
  837. X        qi2 = pos.z + s * dir.z;
  838. X        b0 = tri->e[1].y * (qi2 - tri->p[1].z) -
  839. X                tri->e[1].z * (qi1 - tri->p[1].y);
  840. X        if (b0 < 0. || b0 > 1.)
  841. X            return FALSE;
  842. X        b1 = tri->e[2].y * (qi2 - tri->p[2].z) -
  843. X                tri->e[2].z * (qi1 - tri->p[2].y);
  844. X        if (b1 < 0. || b1 > 1.)
  845. X            return FALSE;
  846. X        b2 = tri->e[0].y * (qi2 - tri->p[0].z) -
  847. X                tri->e[0].z * (qi1 - tri->p[0].y);
  848. X        if (b2 < 0. || b2 > 1.)
  849. X            return FALSE;
  850. X    } else if (tri->index == YNORMAL) {
  851. X        qi1 = pos.x + s * dir.x;
  852. X        qi2 = pos.z + s * dir.z;
  853. X        b0 = tri->e[1].z * (qi1 - tri->p[1].x) -
  854. X            tri->e[1].x * (qi2 - tri->p[1].z);
  855. X        if (b0 < 0. || b0 > 1.)
  856. X            return FALSE;
  857. X        b1 = tri->e[2].z * (qi1 - tri->p[2].x) -
  858. X            tri->e[2].x * (qi2 - tri->p[2].z);
  859. X        if (b1 < 0. || b1 > 1.)
  860. X            return FALSE;
  861. X        b2 = tri->e[0].z * (qi1 - tri->p[0].x) -
  862. X            tri->e[0].x * (qi2 - tri->p[0].z);
  863. X        if (b2 < 0. || b2 > 1.)
  864. X            return FALSE;
  865. X    } else {
  866. X        qi1 = pos.x + s * dir.x;
  867. X        qi2 = pos.y + s * dir.y;
  868. X        b0 = tri->e[1].x * (qi2 - tri->p[1].y) -
  869. X            tri->e[1].y * (qi1 - tri->p[1].x);
  870. X        if (b0 < 0. || b0 > 1.)
  871. X            return FALSE;
  872. X        b1 = tri->e[2].x * (qi2 - tri->p[2].y) -
  873. X                tri->e[2].y * (qi1 - tri->p[2].x);
  874. X        if (b1 < 0. || b1 > 1.)
  875. X            return FALSE;
  876. X        b2 = tri->e[0].x * (qi2 - tri->p[0].y) -
  877. X                tri->e[0].y * (qi1 - tri->p[0].x);
  878. X        if (b2 < 0. || b2 > 1.)
  879. X            return FALSE;
  880. X    tri->b[0] = b0;
  881. X    tri->b[1] = b1;
  882. X    tri->b[2] = b2;
  883. X    TriHits++;
  884. X    *maxdist = s;
  885. X    return TRUE;
  886. XTriangleNormal(tri, pos, nrm, gnrm)
  887. XTriangle *tri;
  888. XVector *pos, *nrm, *gnrm;
  889. X    *gnrm = tri->nrm;
  890. X    if (tri->type == FLATTRI) {
  891. X        *nrm = tri->nrm;
  892. X        return FALSE;
  893. X     * Interpolate normals of Phong-shaded triangles.
  894. X     */
  895. X    nrm->x = tri->b[0]*tri->vnorm[0].x+tri->b[1]*tri->vnorm[1].x+
  896. X        tri->b[2]*tri->vnorm[2].x;
  897. X    nrm->y = tri->b[0]*tri->vnorm[0].y+tri->b[1]*tri->vnorm[1].y+
  898. X        tri->b[2]*tri->vnorm[2].y;
  899. X    nrm->z = tri->b[0]*tri->vnorm[0].z+tri->b[1]*tri->vnorm[1].z+
  900. X        tri->b[2]*tri->vnorm[2].z;
  901. X    (void)VecNormalize(nrm);
  902. X    return TRUE;
  903. X/*ARGSUSED*/
  904. Xvoid
  905. XTriangleUV(tri, pos, norm, uv, dpdu, dpdv)
  906. XTriangle *tri;
  907. XVector *pos, *norm, *dpdu, *dpdv;
  908. XVec2d *uv;
  909. X    Float d;
  910. X     * Normalize barycentric coordinates.
  911. X     */
  912. X    d = tri->b[0]+tri->b[1]+tri->b[2];
  913. X    tri->b[0] /= d;
  914. X    tri->b[1] /= d; 
  915. X    tri->b[2] /= d;
  916. X    if (dpdu) {
  917. X        if (tri->uv == (Vec2d *)NULL) {
  918. X            *dpdu = tri->e[0];
  919. X            (void)VecNormalize(dpdu);
  920. X            VecSub(tri->p[0], *pos, dpdv);
  921. X            (void)VecNormalize(dpdv);
  922. X        } else {
  923. X            *dpdu = *tri->dpdu;
  924. X            *dpdv = *tri->dpdv;
  925. X    if (tri->uv == (Vec2d *)NULL) {
  926. X        uv->v = tri->b[2];
  927. X        if (equal(uv->v, 1.))
  928. X            uv->u = 0.;
  929. X        else
  930. X            uv->u = tri->b[1] / (tri->b[0] + tri->b[1]);
  931. X    } else {
  932. X        /*
  933. X         * Compute UV by taking weighted sum of UV coordinates.
  934. X         */
  935. X        uv->u = tri->b[0]*tri->uv[0].u + tri->b[1]*tri->uv[1].u +
  936. X            tri->b[2]*tri->uv[2].u;
  937. X        uv->v = tri->b[0]*tri->uv[0].v + tri->b[1]*tri->uv[1].v +
  938. X            tri->b[2]*tri->uv[2].v;
  939. Xvoid
  940. XTriangleBounds(tri, bounds)
  941. XTriangle *tri;
  942. XFloat bounds[2][3];
  943. X    bounds[LOW][X] = bounds[HIGH][X] = tri->p[0].x;
  944. X    bounds[LOW][Y] = bounds[HIGH][Y] = tri->p[0].y;
  945. X    bounds[LOW][Z] = bounds[HIGH][Z] = tri->p[0].z;
  946. X    if (tri->p[1].x < bounds[LOW][X]) bounds[LOW][X] = tri->p[1].x;
  947. X    if (tri->p[1].x > bounds[HIGH][X]) bounds[HIGH][X] = tri->p[1].x;
  948. X    if (tri->p[2].x < bounds[LOW][X]) bounds[LOW][X] = tri->p[2].x;
  949. X    if (tri->p[2].x > bounds[HIGH][X]) bounds[HIGH][X] = tri->p[2].x;
  950. X    if (tri->p[1].y < bounds[LOW][Y]) bounds[LOW][Y] = tri->p[1].y;
  951. X    if (tri->p[1].y > bounds[HIGH][Y]) bounds[HIGH][Y] = tri->p[1].y;
  952. X    if (tri->p[2].y < bounds[LOW][Y]) bounds[LOW][Y] = tri->p[2].y;
  953. X    if (tri->p[2].y > bounds[HIGH][Y]) bounds[HIGH][Y] = tri->p[2].y;
  954. X    if (tri->p[1].z < bounds[LOW][Z]) bounds[LOW][Z] = tri->p[1].z;
  955. X    if (tri->p[1].z > bounds[HIGH][Z]) bounds[HIGH][Z] = tri->p[1].z;
  956. X    if (tri->p[2].z < bounds[LOW][Z]) bounds[LOW][Z] = tri->p[2].z;
  957. X    if (tri->p[2].z > bounds[HIGH][Z]) bounds[HIGH][Z] = tri->p[2].z;
  958. Xchar *
  959. XTriangleName()
  960. X    return triName;
  961. Xvoid
  962. XTriangleStats(tests, hits)
  963. Xunsigned long *tests, *hits;
  964. X    *tests = TriTests;
  965. X    *hits = TriHits;
  966. X * Given three vertices of a triangle and the uv coordinates associated
  967. X * with each, compute directions of u and v axes.
  968. Xstatic void
  969. XTriangleSetdPdUV(p, t, dpdu, dpdv)
  970. XVector p[3];            /* Triangle vertices */
  971. XVec2d t[3];            /* uv coordinates for each vertex */
  972. XVector *dpdu, *dpdv;        /* u and v axes (return values) */
  973. X    Float scale;
  974. X    int hi, mid, lo;
  975. X    Vector base;
  976. X    /* sort u coordinates */
  977. X    if (t[2].u > t[1].u) {
  978. X        if (t[1].u > t[0].u) {
  979. X            hi = 2; mid = 1; lo = 0;
  980. X        } else if (t[2].u > t[0].u) {
  981. X            hi = 2; mid = 0; lo = 1;
  982. X        } else {
  983. X            hi = 0; mid = 2; lo = 1;
  984. X    } else {
  985. X        if (t[2].u > t[0].u) {
  986. X            hi = 1; mid = 2; lo = 0;
  987. X        } else if (t[1].u > t[0].u) {
  988. X            hi = 1; mid = 0; lo = 2;
  989. X        } else {
  990. X            hi = 0; mid = 1; lo = 2;
  991. X    if (t[hi].u - t[lo].u == 0.) {
  992. X        /* degenerate axis */
  993. X        dpdv->x = dpdv->y = dpdv->z = 0.;
  994. X    } else {
  995. X        /*
  996. X         * Given u coordinates of vertices forming the
  997. X         * 'long' edge, find where 'middle'
  998. X         * vertex falls on that edge given its u coordinate.
  999. X         */
  1000. X        scale = (t[mid].u - t[lo].u) / (t[hi].u - t[lo].u);
  1001. X        VecComb(1.0 - scale, p[lo], scale, p[hi], &base);
  1002. X        /*
  1003. X         * v axis extends from computed basepoint to
  1004. X         * middle vertex -- but in which direction?
  1005. X         */
  1006. X        if (t[mid].v < ((1.0 - scale)*t[lo].v + scale*t[hi].v))
  1007. X            VecSub(base, p[mid], dpdv);
  1008. X        else
  1009. X            VecSub(p[mid], base, dpdv);
  1010. X        (void)VecNormalize(dpdv);
  1011. X    /* sort v coordinates */
  1012. X    if (t[2].v > t[1].v) {
  1013. X        if (t[1].v > t[0].v) {
  1014. X            hi = 2; mid = 1; lo = 0;
  1015. X        } else if (t[2].v > t[0].v) {
  1016. X            hi = 2; mid = 0; lo = 1;
  1017. X        } else {
  1018. X            hi = 0; mid = 2; lo = 1;
  1019. X    } else {
  1020. X        if (t[2].v > t[0].v) {
  1021. X            hi = 1; mid = 2; lo = 0;
  1022. X        } else if (t[1].v > t[0].v) {
  1023. X            hi = 1; mid = 0; lo = 2;
  1024. X        } else {
  1025. X            hi = 0; mid = 1; lo = 2;
  1026. X    if (t[hi].v - t[lo].v == 0.) {
  1027. X        /* degenerate axis */
  1028. X        dpdu->x = dpdu->y = dpdu->z = 0.;
  1029. X    } else {
  1030. X        /*
  1031. X         * Given v coordinates of vertices forming the
  1032. X         * 'long' edge, find where 'middle'
  1033. X         * vertex falls on that edge given its v coordinate.
  1034. X         */
  1035. X        scale = (t[mid].v - t[lo].v) / (t[hi].v - t[lo].v);
  1036. X        VecComb(1.0 - scale, p[lo], scale, p[hi], &base);
  1037. X        /*
  1038. X         * u axis extends from computed basepoint to
  1039. X         * middle vertex -- but in which direction?
  1040. X         */
  1041. X        if (t[mid].u < ((1.0 - scale)*t[lo].u + scale*t[hi].u))
  1042. X            VecSub(base, p[mid], dpdu);
  1043. X        else
  1044. X            VecSub(p[mid], base, dpdu);
  1045. X        (void)VecNormalize(dpdu);
  1046. Xvoid
  1047. XTriangleMethodRegister(meth)
  1048. XUserMethodType meth;
  1049. X    if (iTriangleMethods)
  1050. X        iTriangleMethods->user = meth;
  1051. END_OF_FILE
  1052. if test 11924 -ne `wc -c <'libray/libobj/triangle.c'`; then
  1053.     echo shar: \"'libray/libobj/triangle.c'\" unpacked with wrong size!
  1054. # end of 'libray/libobj/triangle.c'
  1055. if test -f 'rayshade/raytrace.c' -a "${1}" != "-c" ; then 
  1056.   echo shar: Will not clobber existing file \"'rayshade/raytrace.c'\"
  1057. echo shar: Extracting \"'rayshade/raytrace.c'\" \(11786 characters\)
  1058. sed "s/^X//" >'rayshade/raytrace.c' <<'END_OF_FILE'
  1059. X * raytrace.c
  1060. X * Copyright (C) 1989, 1991, Craig E. Kolb
  1061. X * All rights reserved.
  1062. X * This software may be freely copied, modified, and redistributed
  1063. X * provided that this copyright notice is preserved on all copies.
  1064. X * You may not distribute this software, in whole or in part, as part of
  1065. X * any commercial product without the express consent of the authors.
  1066. X * There is no warranty or other guarantee of fitness of this software
  1067. X * for any purpose.  It is provided solely "as is".
  1068. X * $Id: raytrace.c,v 4.0 91/07/17 14:50:49 kolb Exp Locker: kolb $
  1069. X * $Log:    raytrace.c,v $
  1070. X * Revision 4.0  91/07/17  14:50:49  kolb
  1071. X * Initial version.
  1072. X#include "rayshade.h"
  1073. X#include "libsurf/atmosphere.h"
  1074. X#include "libsurf/surface.h"
  1075. X#include "libcommon/sampling.h"
  1076. X#include "options.h"
  1077. X#include "stats.h"
  1078. X#include "raytrace.h"
  1079. X#include "viewing.h"
  1080. X#define UNSAMPLED    -1
  1081. X#define SUPERSAMPLED    -2
  1082. Xtypedef struct {
  1083. X    Pixel    *pix;    /* Pixel values */
  1084. X    int    *samp;    /* Sample number */
  1085. X} Scanline;
  1086. Xstatic int        *SampleNumbers;
  1087. Xstatic void    RaytraceInit();
  1088. Xstatic Ray    TopRay;                /* Top-level ray. */
  1089. XFloat        SampleTime();
  1090. XPixel        WhitePix = {1., 1., 1., 1.},
  1091. X        BlackPix = {0., 0., 0., 0.};
  1092. X * "Dither matrices" used to encode the 'number' of a ray that samples a
  1093. X * particular portion of a pixel.  Hand-coding is ugly, but...
  1094. Xstatic int OneSample[1] =     {0};
  1095. Xstatic int TwoSamples[4] =    {0, 2,
  1096. X                 3, 1};
  1097. Xstatic int ThreeSamples[9] =    {0, 2, 7,
  1098. X                 6, 5, 1,
  1099. X                 3, 8, 4};
  1100. Xstatic int FourSamples[16] =    { 0,  8,  2, 10,
  1101. X                 12,  4, 14,  6,
  1102. X                  3, 11,  1,  9,
  1103. X                 15,  7, 13,  5};
  1104. Xstatic int FiveSamples[25] =    { 0,  8, 23, 17,  2,
  1105. X                 19, 12,  4, 20, 15,
  1106. X                  3, 21, 16,  9,  6,
  1107. X                 14, 10, 24,  1, 13,
  1108. X                 22,  7, 18, 11,  5};
  1109. Xstatic int SixSamples[36] =    { 6, 32,  3, 34, 35,  1,
  1110. X                  7, 11, 27, 28,  8, 30,
  1111. X                 24, 14, 16, 15, 23, 19,
  1112. X                 13, 20, 22, 21, 17, 18,
  1113. X                 25, 29, 10,  9, 26, 12,
  1114. X                 36,  5, 33,  4,  2, 31};
  1115. Xstatic int SevenSamples[49] =    {22, 47, 16, 41, 10, 35,  4,
  1116. X                  5, 23, 48, 17, 42, 11, 29,
  1117. X                 30,  6, 24, 49, 18, 36, 12,
  1118. X                 13, 31,  7, 25, 43, 19, 37,
  1119. X                 38, 14, 32,  1, 26, 44, 20,
  1120. X                 21, 39,  8, 33,  2, 27, 45,
  1121. X                 46, 15, 40,  9, 34,  3, 28};
  1122. Xstatic int EightSamples[64] =    { 8, 58, 59,  5,  4, 62, 63,  1,
  1123. X                 49, 15, 14, 52, 53, 11, 10, 56,
  1124. X                 41, 23, 22, 44, 45, 19, 18, 48,
  1125. X                 32, 34, 35, 29, 28, 38, 39, 25,
  1126. X                 40, 26, 27, 37, 36, 30, 31, 33,
  1127. X                 17, 47, 46, 20, 21, 43, 42, 24,
  1128. X                  9, 55, 54, 12, 13, 51, 50, 16,
  1129. X                 64,  2,  3, 61, 60,  6,  7, 57};
  1130. Xvoid    AdaptiveRefineScanline(), FullySamplePixel(), FullySampleScanline(),
  1131. X    SingleSampleScanline();
  1132. Xstatic int    ExcessiveContrast();
  1133. Xstatic Scanline scan0, scan1, scan2;
  1134. Xvoid
  1135. Xraytrace(argc, argv)
  1136. Xint argc;
  1137. Xchar **argv;
  1138. X    int y, *tmpsamp;
  1139. X    Pixel *tmppix;
  1140. X    Float usertime, systime, lasttime;
  1141. X     * If this is the first frame,
  1142. X     * allocate scanlines, etc.
  1143. X     */
  1144. X    if (Options.framenum == Options.startframe)
  1145. X        RaytraceInit();
  1146. X     * The top-level ray TopRay always has as its origin the
  1147. X     * eye position and as its medium NULL, indicating that it
  1148. X     * is passing through a medium with index of refraction
  1149. X     * equal to DefIndex.
  1150. X     */
  1151. X    TopRay.pos = Camera.pos;
  1152. X    TopRay.media = (Medium *)0;
  1153. X    TopRay.depth = 0;
  1154. X     * Always fully sample the bottom and top rows and the left
  1155. X     * and right column of pixels.  This minimizes artifacts that
  1156. X     * may arise when piecing together images.
  1157. X     */
  1158. X    FullySampleScanline(0, &scan0);
  1159. X    SingleSampleScanline(1, &scan1);
  1160. X    FullySamplePixel(0, 1, &scan1.pix[0], &scan1.samp[0]);
  1161. X    FullySamplePixel(Screen.xsize -1, 1, &scan1.pix[Screen.xsize -1],
  1162. X        &scan1.samp[Screen.xsize -1]);
  1163. X    lasttime = 0;
  1164. X    for (y = 1; y < Screen.ysize; y++) {
  1165. X        SingleSampleScanline(y+1, &scan2);
  1166. X        FullySamplePixel(0, y+1, &scan2.pix[0], &scan2.samp[0]);
  1167. X        FullySamplePixel(Screen.xsize -1, y+1,
  1168. X            &scan2.pix[Screen.xsize -1],
  1169. X            &scan2.samp[Screen.xsize -1]);
  1170. X        if (Sampling.sidesamples > 1)
  1171. X            AdaptiveRefineScanline(y,&scan0,&scan1,&scan2);
  1172. X        PictureWriteLine(scan0.pix);
  1173. X        tmppix = scan0.pix;
  1174. X        tmpsamp = scan0.samp;
  1175. X        scan0.pix = scan1.pix;
  1176. X        scan0.samp = scan1.samp;
  1177. X        scan1.pix = scan2.pix;
  1178. X        scan1.samp = scan2.samp;
  1179. X        scan2.pix = tmppix;
  1180. X        scan2.samp = tmpsamp;
  1181. X        if ((y-1) % Options.report_freq == 0) {
  1182. X            fprintf(Stats.fstats,"Finished line %d (%lu rays",y-1,
  1183. X                            Stats.EyeRays);
  1184. X            if (Options.verbose) {
  1185. X                /*
  1186. X                 * Report total CPU and split times.
  1187. X                 */
  1188. X                RSGetCpuTime(&usertime, &systime);
  1189. X                fprintf(Stats.fstats,", %2.2f sec,",
  1190. X                        usertime+systime);
  1191. X                fprintf(Stats.fstats," %2.2f split",
  1192. X                        usertime+systime-lasttime);
  1193. X                lasttime = usertime+systime;
  1194. X            }
  1195. X            fprintf(Stats.fstats,")\n");
  1196. X            (void)fflush(Stats.fstats);
  1197. X     * Supersample last scanline.
  1198. X     */
  1199. X    for (y = 1; y < Screen.xsize -1; y++) {
  1200. X        if (scan0.samp[y] != SUPERSAMPLED)
  1201. X            FullySamplePixel(y, Screen.ysize -1,
  1202. X                &scan0.pix[y],
  1203. X                &scan0.samp[y]);
  1204. X    PictureWriteLine(scan0.pix);
  1205. Xvoid
  1206. XSingleSampleScanline(line, data)
  1207. Xint line;
  1208. XScanline *data;
  1209. X    Float upos, vpos, yp;
  1210. X    int x, usamp, vsamp;
  1211. X    Pixel tmp;
  1212. X    yp = line + Screen.miny - 0.5*Sampling.filterwidth;
  1213. X    for (x = 0; x < Screen.xsize; x++) {
  1214. X        /*
  1215. X         * Pick a sample number...
  1216. X         */
  1217. X        data->samp[x] = nrand() * Sampling.totsamples;
  1218. X        /*
  1219. X         * Take sample corresponding to sample #.
  1220. X         */
  1221. X        usamp = data->samp[x] % Sampling.sidesamples;
  1222. X        vsamp = data->samp[x] / Sampling.sidesamples;
  1223. X        vpos = yp + vsamp * Sampling.filterdelta;
  1224. X        upos = x + Screen.minx - 0.5*Sampling.filterwidth +
  1225. X                usamp*Sampling.filterdelta;
  1226. X        if (Options.jitter) {
  1227. X            vpos += nrand()*Sampling.filterdelta;
  1228. X            upos += nrand()*Sampling.filterdelta;
  1229. X        TopRay.time = SampleTime(SampleNumbers[data->samp[x]]);
  1230. X        SampleScreen(upos, vpos, &TopRay,
  1231. X            &data->pix[x], SampleNumbers[data->samp[x]]);
  1232. X        if (Options.samplemap)
  1233. X            data->pix[x].alpha = 0;
  1234. Xvoid
  1235. XFullySampleScanline(line, data)
  1236. Xint line;
  1237. XScanline *data;
  1238. X    int x;
  1239. X    for (x = 0; x < Screen.xsize; x++) {
  1240. X        data->samp[x] = UNSAMPLED;
  1241. X        FullySamplePixel(x, line, &data->pix[x], &data->samp[x]);
  1242. Xvoid
  1243. XFullySamplePixel(xp, yp, pix, prevsamp)
  1244. Xint xp, yp;
  1245. XPixel *pix;
  1246. Xint *prevsamp;
  1247. X    Float upos, vpos, u, v;
  1248. X    int x, y, sampnum;
  1249. X    Pixel ctmp;
  1250. X    if (*prevsamp == SUPERSAMPLED)
  1251. X        return;    /* already done */
  1252. X    Stats.SuperSampled++;
  1253. X    if (*prevsamp == UNSAMPLED) {
  1254. X        /*
  1255. X         * No previous sample; initialize to black.
  1256. X         */
  1257. X        pix->r = pix->g = pix->b = pix->alpha = 0.;
  1258. X    } else {
  1259. X        if (Sampling.sidesamples == 1) {
  1260. X            *prevsamp = SUPERSAMPLED;
  1261. X            return;
  1262. X        x = *prevsamp % Sampling.sidesamples;
  1263. X        y = *prevsamp / Sampling.sidesamples;
  1264. X        pix->r *= Sampling.filter[x][y];
  1265. X        pix->g *= Sampling.filter[x][y];
  1266. X        pix->b *= Sampling.filter[x][y];
  1267. X        pix->alpha *= Sampling.filter[x][y];
  1268. X    sampnum = 0;
  1269. X    xp += Screen.minx;
  1270. X    vpos = Screen.miny + yp - 0.5*Sampling.filterwidth;
  1271. X    for (y = 0; y < Sampling.sidesamples; y++,
  1272. X         vpos += Sampling.filterdelta) {
  1273. X        upos = xp - 0.5*Sampling.filterwidth;
  1274. X        for (x = 0; x < Sampling.sidesamples; x++,
  1275. X             upos += Sampling.filterdelta) {
  1276. X            if (sampnum != *prevsamp) {
  1277. X                if (Options.jitter) {
  1278. X                    u = upos + nrand()*Sampling.filterdelta;
  1279. X                    v = vpos + nrand()*Sampling.filterdelta;
  1280. X                } else {
  1281. X                    u = upos;
  1282. X                    v = vpos;
  1283. X                }
  1284. X                TopRay.time = SampleTime(SampleNumbers[sampnum]);
  1285. X                SampleScreen(u, v, &TopRay, &ctmp,
  1286. X                    SampleNumbers[sampnum]);
  1287. X                pix->r += ctmp.r*Sampling.filter[x][y];
  1288. X                pix->g += ctmp.g*Sampling.filter[x][y];
  1289. X                pix->b += ctmp.b*Sampling.filter[x][y];
  1290. X                pix->alpha += ctmp.alpha*Sampling.filter[x][y];
  1291. X            }
  1292. X            if (++sampnum == Sampling.totsamples)
  1293. X                sampnum = 0;
  1294. X    if (Options.samplemap)
  1295. X        pix->alpha = 255;
  1296. X    *prevsamp = SUPERSAMPLED;
  1297. Xvoid
  1298. XAdaptiveRefineScanline(y, scan0, scan1, scan2)
  1299. Xint y;
  1300. XScanline *scan0, *scan1, *scan2;
  1301. X    int x, done;
  1302. X     * Walk down scan1, looking at 4-neighbors for excessive contrast.
  1303. X     * If found, supersample *all* neighbors not already supersampled.
  1304. X     * The process is repeated until either there are no
  1305. X     * high-contrast regions or all such regions are already supersampled.
  1306. X     */
  1307. X    do {
  1308. X        done = TRUE;
  1309. X        for (x = 1; x < Screen.xsize -1; x++) {
  1310. X            /*
  1311. X              * Find min and max RGB for area we care about
  1312. X             */
  1313. X            if (ExcessiveContrast(x, scan0->pix, scan1->pix,
  1314. X                scan2->pix)) {
  1315. X                if (scan1->samp[x-1] != SUPERSAMPLED) {
  1316. X                    done = FALSE;
  1317. X                    FullySamplePixel(x-1, y,
  1318. X                        &scan1->pix[x-1],
  1319. X                        &scan1->samp[x-1]);
  1320. X                }
  1321. X                if (scan0->samp[x] != SUPERSAMPLED) {
  1322. X                    done = FALSE;
  1323. X                    FullySamplePixel(x, y-1,
  1324. X                        &scan0->pix[x],
  1325. X                        &scan0->samp[x]);
  1326. X                }
  1327. X                if (scan1->samp[x+1] != SUPERSAMPLED) {
  1328. X                    done = FALSE;
  1329. X                    FullySamplePixel(x+1, y,
  1330. X                        &scan1->pix[x+1],
  1331. X                        &scan1->samp[x+1]);
  1332. X                }
  1333. X                if (scan2->samp[x] != SUPERSAMPLED) {
  1334. X                    done = FALSE;
  1335. X                    FullySamplePixel(x, y+1,
  1336. X                        &scan2->pix[x],
  1337. X                        &scan2->samp[x]);
  1338. X                }
  1339. X                if (scan1->samp[x] != SUPERSAMPLED) {
  1340. X                    done = FALSE;
  1341. X                    FullySamplePixel(x, y,
  1342. X                        &scan1->pix[x],
  1343. X                        &scan1->samp[x]);
  1344. X                }
  1345. X            }
  1346. X    } while (!done);
  1347. Xstatic int
  1348. XExcessiveContrast(x, pix0, pix1, pix2)
  1349. Xint x;
  1350. XPixel *pix0, *pix1, *pix2;
  1351. X    Float mini, maxi, sum, diff;
  1352. X    maxi = max(pix0[x].r, pix1[x-1].r);
  1353. X    if (pix1[x].r > maxi) maxi = pix1[x].r;
  1354. X    if (pix1[x+1].r > maxi) maxi = pix1[x+1].r;
  1355. X    if (pix2[x].r > maxi) maxi = pix2[x].r;
  1356. X    mini = min(pix0[x].r, pix1[x-1].r);
  1357. X    if (pix1[x].r < mini) mini = pix1[x].r;
  1358. X    if (pix1[x+1].r < mini) mini = pix1[x+1].r;
  1359. X    if (pix2[x].r < mini) mini = pix2[x].r;
  1360. X    diff = maxi - mini;
  1361. X    sum = maxi + mini;
  1362. X    if (sum > EPSILON && diff/sum > Options.contrast.r)
  1363. X        return TRUE;
  1364. X    maxi = max(pix0[x].g, pix1[x-1].g);
  1365. X    if (pix1[x].g > maxi) maxi = pix1[x].g;
  1366. X    if (pix1[x+1].g > maxi) maxi = pix1[x+1].g;
  1367. X    if (pix2[x].g > maxi) maxi = pix2[x].g;
  1368. X    mini = min(pix0[x].g, pix1[x-1].g);
  1369. X    if (pix1[x].g < mini) mini = pix1[x].g;
  1370. X    if (pix1[x+1].g < mini) mini = pix1[x+1].g;
  1371. X    if (pix2[x].g < mini) mini = pix2[x].g;
  1372. X    diff = maxi - mini;
  1373. X    sum = maxi + mini;
  1374. X    if (sum > EPSILON && diff/sum > Options.contrast.g)
  1375. X        return TRUE;
  1376. X    maxi = max(pix0[x].b, pix1[x-1].b);
  1377. X    if (pix1[x].b > maxi) maxi = pix1[x].b;
  1378. X    if (pix1[x+1].b > maxi) maxi = pix1[x+1].b;
  1379. X    if (pix2[x].b > maxi) maxi = pix2[x].b;
  1380. X    mini = min(pix0[x].b, pix1[x-1].b);
  1381. X    if (pix1[x].b < mini) mini = pix1[x].b;
  1382. X    if (pix1[x+1].b < mini) mini = pix1[x+1].b;
  1383. X    if (pix2[x].b < mini) mini = pix2[x].b;
  1384. X    diff = maxi - mini;
  1385. X    sum = maxi + mini;
  1386. X    if (sum > EPSILON && diff/sum > Options.contrast.b)
  1387. X        return TRUE;
  1388. X    return FALSE;
  1389. XFloat
  1390. XSampleTime(sampnum)
  1391. Xint sampnum;
  1392. X    Float window, jitter = 0.0, res;
  1393. X    if (Options.shutterspeed <= 0.)
  1394. X        return Options.framestart;
  1395. X    if (Options.jitter)
  1396. X        jitter = nrand();
  1397. X    window = Options.shutterspeed / Sampling.totsamples;
  1398. X    res = Options.framestart + window * (sampnum + jitter);
  1399. X    TimeSet(res);
  1400. X    return res;
  1401. Xstatic void
  1402. XRaytraceInit()
  1403. X    switch (Sampling.sidesamples) {
  1404. X        case 1:
  1405. X            SampleNumbers = OneSample;
  1406. X            break;
  1407. X        case 2:
  1408. X            SampleNumbers = TwoSamples;
  1409. X            break;
  1410. X        case 3:
  1411. X            SampleNumbers = ThreeSamples;
  1412. X            break;
  1413. X        case 4:
  1414. X            SampleNumbers = FourSamples;
  1415. X            break;
  1416. X        case 5:
  1417. X            SampleNumbers = FiveSamples;
  1418. X            break;
  1419. X        case 6:
  1420. X            SampleNumbers = SixSamples;
  1421. X            break;
  1422. X        case 7:
  1423. X            SampleNumbers = SevenSamples;
  1424. X            break;
  1425. X        case 8:
  1426. X            SampleNumbers = EightSamples;
  1427. X            break;
  1428. X        default:
  1429. X            RLerror(RL_PANIC,
  1430. X                "Sorry, %d rays/pixel not supported.\n",
  1431. X                    Sampling.totsamples);
  1432. X      * Allocate pixel arrays and arrays to store sampling info.
  1433. X      */
  1434. X    scan0.pix = (Pixel *)Malloc(Screen.xsize * sizeof(Pixel));
  1435. X    scan1.pix = (Pixel *)Malloc(Screen.xsize * sizeof(Pixel));
  1436. X    scan2.pix = (Pixel *)Malloc(Screen.xsize * sizeof(Pixel));
  1437. X    scan0.samp = (int *)Malloc(Screen.xsize * sizeof(int));
  1438. X    scan1.samp = (int *)Malloc(Screen.xsize * sizeof(int));
  1439. X    scan2.samp = (int *)Malloc(Screen.xsize * sizeof(int));
  1440. END_OF_FILE
  1441. if test 11786 -ne `wc -c <'rayshade/raytrace.c'`; then
  1442.     echo shar: \"'rayshade/raytrace.c'\" unpacked with wrong size!
  1443. # end of 'rayshade/raytrace.c'
  1444. echo shar: End of archive 14 \(of 19\).
  1445. cp /dev/null ark14isdone
  1446. MISSING=""
  1447. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
  1448.     if test ! -f ark${I}isdone ; then
  1449.     MISSING="${MISSING} ${I}"
  1450.     fi
  1451. if test "${MISSING}" = "" ; then
  1452.     echo You have unpacked all 19 archives.
  1453.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1454.     echo You still need to unpack the following archives:
  1455.     echo "        " ${MISSING}
  1456. ##  End of shell archive.
  1457. exit 0
  1458. exit 0 # Just in case...
  1459.