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