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

  1. Newsgroups: comp.sources.misc
  2. From: Rayshade Construction Co. <rayshade@weedeater.math.YALE.EDU>
  3. Subject:  v21i015:  rayshade - A raytracing package for UNIX, Part12/19
  4. Message-ID: <1991Jul21.033750.29232@sparky.IMD.Sterling.COM>
  5. X-Md4-Signature: 659b41552716715c348d36c3e751450a
  6. Date: Sun, 21 Jul 1991 03:37:50 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 15
  11. Archive-name: rayshade/part12
  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 12 (of 19)."
  21. # Contents:  Doc/Guide/lights.tex Doc/quickref.txt libray/libobj/geom.c
  22. #   libray/libobj/torus.c libshade/options.c
  23. # Wrapped by kolb@woody on Wed Jul 17 17:56:51 1991
  24. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  25. if test -f 'Doc/Guide/lights.tex' -a "${1}" != "-c" ; then 
  26.   echo shar: Will not clobber existing file \"'Doc/Guide/lights.tex'\"
  27. else
  28. echo shar: Extracting \"'Doc/Guide/lights.tex'\" \(8326 characters\)
  29. sed "s/^X//" >'Doc/Guide/lights.tex' <<'END_OF_FILE'
  30. X\chapter{Light Sources}
  31. X
  32. XThe lighting in a scene is determined by the number, type, and nature
  33. Xof the light sources defined in the input file.  Available light sources
  34. Xrange from simple directional sources to more realistic but computationally
  35. Xcostly quadrilateral area light sources.  Typically, you will want to use
  36. Xpoint or directional light sources while developing images.  When
  37. Xfinal renderings are made, these simple light sources may be replaced by
  38. Xthe more complex ones.
  39. X
  40. XNo matter what kind of light source you use, you will need to
  41. Xspecify its intensity.
  42. XIn this chapter, an {\em Intensity\/} is either a red-green-blue triple
  43. Xindicating the color of the light source, or a single value that is
  44. Xinterpreted as the intensity of a ``white'' light.
  45. XIn the current version of {\em rayshade}, the intensity of a light does
  46. Xnot decrease as
  47. Xone moves farther from it.
  48. X
  49. XIf you do not define a light source, \rayshade will create a directional
  50. Xlight source of intensity 1.0 defined by the vector (1., -1., 1.).
  51. XThis default light source is designed to work well when default
  52. Xviewing parameters and surface values are being used.
  53. X
  54. XYou may define any number of light sources, but keep in mind that
  55. Xit will require more time to render images that include many
  56. Xlight sources.  It should also be noted that the light sources themselves
  57. Xwill not appear in the image, even if they are placed in frame.
  58. X
  59. X\section{Light Source Types}
  60. X
  61. XThe amount of ambient light present in a scene is controlled by a
  62. Xpseudo light source of type {\em ambient}.
  63. X
  64. X\begin{defkey}{light}{{\em Intensity\/} ambient}
  65. X    Define the amount of ambient light present in the entire
  66. X    scene.
  67. X\end{defkey}
  68. X
  69. XThere is only one ambient light source; its default intensity is
  70. X{1, 1, 1}.  If more than one ambient light source is defined,
  71. Xonly the last instance is used.  A surface's ambient color
  72. Xis multiplied by the intensity of the ambient source to give the
  73. Xtotal ambient light reflected from the surface.
  74. X
  75. XDirectional sources are described by a direction alone, and are useful
  76. Xfor modeling light sources that are effectively infinitely far away
  77. Xfrom the objects they illuminate.   
  78. X
  79. X\begin{defkey}{light}{{\em Intensity\/} {\tt directional} \evec{direction}}
  80. X    Define a light source with the given intensity that is
  81. X    defined to be in the given direction from every point
  82. X    it illuminates.  The direction need not be normalized.
  83. X\end{defkey}
  84. X
  85. XPoint sources are defined as a single point in space.  They produce
  86. Xshadows with sharp edges and are a good replacement for extended
  87. Xand other computationally expensive light source.
  88. X
  89. X\begin{defkey}{light}{{\em Intensity\/} {\tt point} \evec{pos}}
  90. X    Place a point light source with the given intensity at the
  91. X    given position.
  92. X\end{defkey}
  93. X
  94. XSpotlights are useful for creating dramatic localized lighting effects.
  95. XThey are defined by their position, the direction in which they
  96. Xare pointing, and the width of the beam of light they produce.
  97. X
  98. X\begin{defkey}{light}{{\em Intensity\/} {\tt spot} \evec{pos} \evec{to}
  99. X    {$\alpha$} [ $\theta_{in}$ $\theta_{out}$ ]}
  100. X    Place a spotlight at \evec{pos}, oriented as to be pointing at
  101. X    \evec{to}.  The intensity of the light falls off as
  102. X    $(cosine \theta)^{\alpha}$, where $\theta$ is the angle between the
  103. X    spotlight's main axis and the vector from the spotlight to the
  104. X    point being illuminated.  $\theta_{in}$ and
  105. X    $\theta_{out}$ may be used to control the radius of the cone of light
  106. X    produced by the spotlight.
  107. X\end{defkey}
  108. X$\theta_{in}$ is the the angle at which
  109. Xthe light source begins to be attenuated.  At $\theta_{out}$,
  110. Xthe spotlight intensity is zero.
  111. XThis affords control
  112. Xover how ``fuzzy'' the edges of the spotlight are.  If neither angle
  113. Xis given, they both are effectively set to 180 degrees.
  114. X
  115. XExtended sources are meant to model spherical light sources.  Unlike
  116. Xpoint sources, extended sources actually possess a radius, and as such
  117. Xare capable or producing shadows with fuzzy edges ({\em penumbrae}).  If
  118. Xyou do not specifically desire penumbrae in your image, use a point
  119. Xsource instead.
  120. X
  121. X\begin{defkey}{light}{{\em Intensity\/} {\tt extended} {\em radius} \evec{pos} }
  122. X    Create an extended light source at the given position and with
  123. X    the given {\em radius}.
  124. X\end{defkey}
  125. XThe shadows cast by
  126. Xextended sources are modeled by taking samples of the source at
  127. Xdifferent locations on its surface.  When the source is partially
  128. Xhidden from a given point in space, that point is in partial shadow
  129. Xwith respect to the extended source, and the sampling process is
  130. Xusually able to determine this fact.
  131. X
  132. XQuadrilateral light sources are computationally more expensive than extended
  133. Xlight sources, but are more flexible and produce more realistic results.
  134. XThis is due to the fact that an area source is approximated by a
  135. Xnumber of point sources whose positions are jittered to reduce aliasing.
  136. XBecause each of these point sources has shading calculations performed
  137. Xindividually, area sources may be placed relatively close to the
  138. Xobjects it illuminates, and a reasonable image will result.
  139. X
  140. X\begin{defkey}{light}{{\em Intensity\/} {\tt area} \evec{p1} \evec{p2} {\em usamp}
  141. X    \evec{p3} {\em vsamp}}
  142. X    Create a quadrilateral area light source.
  143. X    The $u$ axis
  144. X    is defined by the vector from \evec{p1} to \evec{p2}.  Along
  145. X    this axis a total of {\em usamp} samples will be taken.
  146. X    The $v$ axis of the light source is defined by the vector
  147. X    from \evec{p1} to \evec{p3}.  Along this axis a total of
  148. X    {\em vsamp} samples will be taken.
  149. X\end{defkey}
  150. XThe values of {\em usamp} and {\em vsamp} are usually chosen to be
  151. Xproportional to the lengths of the $u$ and $v$ axes.  Choosing a
  152. Xrelatively high number of samples will result in a good approximation
  153. Xto a ``real'' quadrilateral source.  However, because complete
  154. Xlighting calculations are performed for each sample,
  155. Xthe computational cost is directly proportional to the product
  156. Xof {\em usamp} and {\em vsamp}.
  157. X
  158. X\section{Shadows}
  159. X
  160. XIn order to determine the color of a point on the surface
  161. Xof any object, it is necessary
  162. Xto determine if that point is in shadow with respect to each
  163. Xdefined light source.  If the point is totally in shadow with respect to
  164. Xa light source, then the light source makes no contribution to the
  165. Xpoint's final color.
  166. X
  167. XThis shadowing determination is made by tracing rays from the point
  168. Xof intersection to each light source.  These ``shadow feeler'' rays
  169. Xcan add substantially to the overall rendering time.  This is especially
  170. Xtrue if extended or area light sources are used.  If at any point you
  171. Xwish to disable shadow determination on a global scale, there is
  172. Xa command-line option ({\tt -n}) that allows you to do so.  It is also
  173. Xpossible
  174. Xto disable the casting of shadows onto given objects through the use
  175. Xof the {\tt noshadow} keyword in surface descriptions.  In addition,
  176. Xthe {\tt noshadow} keyword may be given following the definition
  177. Xof a light source, causing the light source to cast no shadows onto
  178. Xany surface.
  179. X
  180. XDetermining if a point is in shadow with respect to a light source
  181. Xis relatively simple if all the objects in a scene are opaque.  In
  182. Xthis case, one simply traces a ray from the point to the light source.
  183. XIf the ray hits an object before it reaches the light source, then
  184. Xthe point is in shadow.
  185. X
  186. XShadow determination
  187. Xbecomes more complicated if there are one or more objects with
  188. Xnon-zero transparency between the point and the light source.
  189. XTransparent objects may not completely block the light from a source,
  190. Xbut merely attenuate it. In such cases, it is necessary to compute the
  191. Xamount of attenuation at each intersection and to continue
  192. Xthe shadow ray until it either reaches the light source or until
  193. Xthe light is completely attenuated.
  194. X
  195. XBy default, \rayshade computes shadow attenuation by assuming
  196. Xthat the index of refraction of the transparent object is the
  197. Xsame as that of the medium through which the ray is traveling.
  198. XTo disable
  199. Xpartial shadowing due to transparent objects, the {\em shadowtransp}
  200. Xkeyword should be given somewhere in the input file.
  201. X
  202. X\begin{defkey}{shadowtransp}{}
  203. X    The intensity of light striking a point is {\em not} affected by
  204. X    intervening transparent objects.
  205. X\end{defkey}
  206. XIf you enclose an object behind a transparent surface, and you wish
  207. Xthe inner object to be illuminated, you must not use the {\tt shadowtransp}
  208. Xkeyword or the {\tt -o} option.
  209. END_OF_FILE
  210. if test 8326 -ne `wc -c <'Doc/Guide/lights.tex'`; then
  211.     echo shar: \"'Doc/Guide/lights.tex'\" unpacked with wrong size!
  212. fi
  213. # end of 'Doc/Guide/lights.tex'
  214. fi
  215. if test -f 'Doc/quickref.txt' -a "${1}" != "-c" ; then 
  216.   echo shar: Will not clobber existing file \"'Doc/quickref.txt'\"
  217. else
  218. echo shar: Extracting \"'Doc/quickref.txt'\" \(9588 characters\)
  219. sed "s/^X//" >'Doc/quickref.txt' <<'END_OF_FILE'
  220. X                      Rayshade Quick Reference
  221. X
  222. X-------------------------------------------------------------------------------
  223. XKey:
  224. X[thing]  Optional item              <Thing>  Production
  225. XThing    Number or String           (thing)  Default value(s)
  226. Xthing    Keyword
  227. X-------------------------------------------------------------------------------
  228. X
  229. XReals and integers may be written in exponential notation, with or without a
  230. Xdecimal point.  Reals are truncated to integers when need be.  Numbers may also
  231. Xbe written as expressions surrounded by a matched pair of parentheses.
  232. XSubexpressions may be parenthesized to control order of evaluation.  Variables
  233. Xmay be defined and used in parenthesized expressions.  Predefined variables
  234. Xinclude time (current time) and frame (current frame number, 0 - frames-1), pi,
  235. Xdtor (pi/180), rotd (180/pi).  Available operators are '+' (addition),
  236. X'-' (subtraction and negation), '*' (multiplication), '/' (division),
  237. X'%' (remainder), '^' (exponentiation).  Functions include sin, cos, tan, asin,
  238. Xacos, atan, sqrt, hypot.
  239. X
  240. XStrings are written as non-quoted strings that may include include the
  241. Xspecial characters '/' ("slash"), '-' ("dash"), '_' ("underscore), and '.'
  242. X("period"), in addition to upper and lowercase letters and non-leading digits.
  243. X
  244. X-------------------------------------------------------------------------------
  245. XCommand-line options (override options set in input file):
  246. X
  247. X-A frame       First frame to render 
  248. X-a             Toggle alpha channel   -C cutoff      Adaptive tree cutoff 
  249. X-c             Continued rendering    -D depth       Maximum ray tree depth.
  250. X-E eye_sep     Eye separation         -e             Exponential RLE output
  251. X-F freq        Report frequency       -f             Flip triangle normals
  252. X-G gamma       Gamma exponent         -g             Use gaussian filter
  253. X-h             Help                   -j             Toggle jittered sampling
  254. X-l             Render left eye view   -m             Produce sample map
  255. X-N frames      Total frames to render -n             No shadows
  256. X-O outfile     Output file name       -o             Toggle opaque shadows 
  257. X-P cpp-args    Arguments for cpp      -p             Preview-quality
  258. X-q             Run quietly            -R xres yres   Resolution
  259. X-r             Right eye view         -S samples     Use Samples^2 samples
  260. X-s             Toggle shadow caching  -T r g b       Contrast threshold
  261. X-V filename    Verbose file output    -v             Verbose output
  262. X-W lx ly hx hy Render subwindow
  263. X-------------------------------------------------------------------------------
  264. X
  265. XFile: /* Input file consists of...*/
  266. X        <Item> [<Item> ... ]
  267. X
  268. XItem:
  269. X        <Viewing>
  270. X        <Light>
  271. X        <Atmosphere>
  272. X        <RenderOption>
  273. X        <ObjItem>
  274. X        <Definition>
  275. X
  276. XObjItem: /* Items used in object definition blocks */
  277. X        <SurfDef>
  278. X        <ApplySurf>
  279. X        <Instance>
  280. X        <ObjDef>
  281. X
  282. XViewing:
  283. X        eyep Xpos Ypos Zpos     /* Eye position (0 -10 0) */
  284. X        lookp Xpos Ypos Zpos    /* Look position (0 0 0) */
  285. X        up Xup Yup Zup          /* "up" vector (0 0 1) */
  286. X        fov Hfov [Vfov]         /* Field of view in degrees (horiontal=45) */
  287. X        aperture Width          /* Aperture width (0) */
  288. X        focaldist Distance      /* focal distance (|eyep - lookp|) */
  289. X        shutter Speed           /* Shutter speed (0 --> no blur) */
  290. X        framelength Length      /* Length of a singelf frame (1) */
  291. X        screen Xsize Ysize      /* Screen size */
  292. X        window Xmin Ymin Xmax Ymax /* Window (0 0 xsize-1 ysize-1) */
  293. X        eyesep Separation       /* eye separation (0) */
  294. X
  295. XSurfDef: /* Give a name to a set of surface attributes. */
  296. X        surface Name <SurfSpec> [<SurfSpec> ...]
  297. X
  298. XSurface: /* Surface specification */
  299. X        <SurfSpec>                /* Use gven attributes */
  300. X        Surfname [<SurfSpec> ...] /* Use named surface w/ optional mods. */
  301. X        cursurf  [<SurfSpec> ...] /* Use cur. surface w/mods - see ApplySurf */
  302. X
  303. XSurfSpec: /* Surface attribute specification */
  304. X        ambient R G B           /* Ambient contribution */
  305. X        diffuse R G B           /* Diffuse color */
  306. X        specular R G B          /* Specular color */
  307. X        specpow Exponent        /* Phong exponent */
  308. X        body R G B              /* Body color */
  309. X        extinct Coef            /* Extinction coefficient */
  310. X        transp Ktr              /* Transparency */
  311. X        reflect Kr              /* Reflectivity */
  312. X        index N                 /* Index of refraction */
  313. X        translu Ktl R G B Stpow /* Translucency, transmit diffuse, spec exp */
  314. X        noshadow                /* No shadows cast on this surface */
  315. X
  316. XEffect: /* Atmospheric Effects */
  317. X        mist   R G B Rtrans Gtrans Btrans Zero Scale
  318. X        fog    R G B Rtrans Gtrans Btrans
  319. X
  320. XAtmosphere: /* Global atmosphere */
  321. X        atmosphere [Index] <Effect> [<Effect>...] /* Global index, effects */
  322. X
  323. XApplySurf:
  324. X        applysurf <Surface> /* apply surf to all following objs w/o surface */
  325. X
  326. XInstance: /* Instance of an object */
  327. X        <Object> [<Transforms>] [<Textures>] 
  328. X
  329. XObject:
  330. X        Primitive        /* Primitive object */
  331. X        Aggregate        /* Named aggregate */
  332. X
  333. XObjDef: /* define a named object */
  334. X        name Objname <Instance>
  335. X        
  336. XPrimitive: /* Primitive object */
  337. X        plane    [<Surface>] Xpos Ypos Zpos Xnorm Ynorm Znorm
  338. X        disc     [<Surface>] Radius Xpos Ypos Zpos Xnorm Ynorm Znorm
  339. X        sphere   [<Surface>] Radius Xpos Ypos Zpos
  340. X        triangle [<Surface>] Xv1 Yv1 Zv1
  341. X                             Xv2 Yv2 Zv2  Xv3 Yv3 Zv3/* flat-shaded triangle */
  342. X        triangle [<Surface>] Xv1 Yv1 Zv1 Xn1 Yn1 Zn1
  343. X                             Xv2 Yv2 Zv2 Xn2 Yn2 Zn2
  344. X                             Xv3 Yv3 Zv3 Xn3 Yn3 Zn3/* Phong-shaded triangle */
  345. X        polygon  [<Surface>] Xv1 Yv1 Zv1
  346. X                             Xv2 Yv2 Zv2  Xv3 Yv3 Zv3 [Xv3 Yv4 Zv4 ...]
  347. X        box      [<Surface>] Xlow Ylow Zlow
  348. X                             Xhi  Yhi  Zhi
  349. X        cylinder [<Surface>] Radius Xbase Ybase Zbase Xapex Yapex Zapex
  350. X        cone     [<Surface>] Rbase Xbase Ybase Zbase  Rapex Xapex Yapex Zapex
  351. X        torus    [<Surface>] Rswept Rtube Xpos Ypos Zpos Xnorm Ynorm Znorm
  352. X        blob     [<Surface>] Thresh Stren Rad Xpos Ypos Zpos
  353. X                             [Stren Rad X Y Z ...]
  354. X        heightfield [<Surface>] Filename
  355. X
  356. XAggregate:
  357. X        Grid
  358. X        List
  359. X        Csg
  360. X
  361. XGrid:
  362. X        grid X Y Z <ObjItem> [<ObjItem> ...]  end
  363. X
  364. XList:
  365. X        list <ObjItem> [<ObjItem> ...] end
  366. X
  367. XCsg:
  368. X        union      <Object> <Object> [<Object> ...] end
  369. X        intersect  <Object> <Object> [<Object> ...] end
  370. X        difference <Object> <Object> [<Object> ...] end
  371. X
  372. X        /* CSG will only work properly when applied to closed objects, e.g.:
  373. X         * sphere, box, torus, blob, closed Aggregate, other Csg object
  374. X         */
  375. X
  376. XTransforms: /* Transformations */
  377. X        translate  Xtrans Ytrans Ztrans
  378. X        scale      Xscale Yscale Zscale
  379. X        rotate     Xaxis Yaxis Zaxis Degrees
  380. X        transform  A   B   C
  381. X                   D   E   F
  382. X                   G   H   I
  383. X                  [Xt  Yt  Zt]
  384. X
  385. XTextures:
  386. X        texture <TextType> [Transforms] [<Texture> [Transforms] ...]
  387. X
  388. XTexture:
  389. X        checker    <Surface>
  390. X        blotch    Scale <Surface>
  391. X        bump      Bumpscale
  392. X        marble    [Colormapname]
  393. X        fbm       Offset Scale H Lambda Octaves Thresh [Colormapname]
  394. X        fbmbump   Offset Scale H Lambda Octaves
  395. X        wood
  396. X        gloss     Glossiness
  397. X        cloud     Offset Scale H Lambda Octaves Cthresh Lthresh Transcale
  398. X        sky       Scale H Lambda Octaves Cthresh Lthresh
  399. X        stripe    <Surface> Width Bumpscale
  400. X        image     Imagefile [<ImageTextOption> [<ImageTextOption> ...]]
  401. X
  402. XImageTextOption:
  403. X        component <SufComp>
  404. X        range     Lo Hi
  405. X        smooth
  406. X        textsurf  <Surface>
  407. X        tile      U V
  408. X        <Mapping>
  409. X
  410. XSurfComp:
  411. X        ambient
  412. X        diffuse
  413. X        reflect
  414. X        transp
  415. X        specular
  416. X        specpow
  417. X
  418. XMapping:
  419. X        map uv
  420. X        map cylindrical [Xorigin Yorigin Zorigin Xup Yup Zup Xu Yu Zu] 
  421. X        map linear      [Xorigin Yorigin Zorigin Xv  Yv  Zv  Xu Yu Zu]
  422. X        map spherical   [Xorigin Yorigin Zorigin Xup Yup Zup Xu Yu Zu]
  423. X
  424. XLight:
  425. X        light R G B <LightType> [noshadow]
  426. X        light Intensity <LightType> [noshadow]
  427. X
  428. XLightType:
  429. X        ambient
  430. X        point       Xpos Ypos Zpos
  431. X        directional Xdir Ydir Zdir
  432. X        extended    Xpos Ypos Zpos Radius
  433. X        spot        Xpos Ypos Zpos Xat Yat Zat Coef Thetain Thetaout
  434. X        area        Xorigin Yorigin Zorigin Xu Yu Zu Usamples Xv Yv Zv Vsamples
  435. X
  436. XRenderOption:
  437. X        samples      Nsamp [jitter | nojitter]
  438. X                                /* Use Nsamp^2 pixel samples (3^2 jittered) */
  439. X        background   R G B      /* Background color (0 0 0) */
  440. X        outfile      Filename   /* Output file name (written to stdout) */
  441. X        frames       Nframes    /* Number of frames to render (1) */
  442. X        starttime    Time       /* Time corresponding to start of frame 0 */
  443. X        contrast     R G B      /* Maximum contrast w/o supersampling */
  444. X        maxdepth     Depth      /* Maximum ray tree depth (5) */
  445. X        cutoff       Factor     /* Minium spawned ray contribution (.001) */
  446. X        report [verbose] [quiet] [Freq] [Statfile]
  447. X                                /* Reporting mode (false false 10 stderr) */
  448. X        shadowtransp            /* Toggle object opacity affects shadows */
  449. X
  450. XDefinition: /* Variable definition */
  451. X        define Name Expr        /* Assign value for Name */
  452. END_OF_FILE
  453. if test 9588 -ne `wc -c <'Doc/quickref.txt'`; then
  454.     echo shar: \"'Doc/quickref.txt'\" unpacked with wrong size!
  455. fi
  456. # end of 'Doc/quickref.txt'
  457. fi
  458. if test -f 'libray/libobj/geom.c' -a "${1}" != "-c" ; then 
  459.   echo shar: Will not clobber existing file \"'libray/libobj/geom.c'\"
  460. else
  461. echo shar: Extracting \"'libray/libobj/geom.c'\" \(9132 characters\)
  462. sed "s/^X//" >'libray/libobj/geom.c' <<'END_OF_FILE'
  463. X/*
  464. X * object.c
  465. X *
  466. X * Copyright (C) 1989, 1991, Craig E. Kolb
  467. X * All rights reserved.
  468. X *
  469. X * This software may be freely copied, modified, and redistributed
  470. X * provided that this copyright notice is preserved on all copies.
  471. X *
  472. X * You may not distribute this software, in whole or in part, as part of
  473. X * any commercial product without the express consent of the authors.
  474. X *
  475. X * There is no warranty or other guarantee of fitness of this software
  476. X * for any purpose.  It is provided solely "as is".
  477. X *
  478. X * $Id: geom.c,v 4.0 91/07/17 14:37:47 kolb Exp Locker: kolb $
  479. X *
  480. X * $Log:    geom.c,v $
  481. X * Revision 4.0  91/07/17  14:37:47  kolb
  482. X * Initial version.
  483. X * 
  484. X */
  485. X#include "geom.h"
  486. X#include "list.h"
  487. X#include "libcommon/sampling.h"
  488. X
  489. Xstatic void GeomBounds(), GeomBoundsAnimated();
  490. Xvoid GeomResolveAssoc();    /* probably static */
  491. X
  492. XGeom *
  493. XGeomCreate(objptr, methods)
  494. XGeomRef objptr;
  495. XMethods *methods;
  496. X{
  497. X    Geom *obj;
  498. X
  499. X    if (objptr == (GeomRef)NULL)
  500. X        return (Geom *)NULL;
  501. X        
  502. X    obj = (Geom *)share_calloc(1, sizeof(Geom));
  503. X    obj->obj = objptr;
  504. X    obj->methods = methods;
  505. X    obj->animtrans = FALSE;
  506. X    obj->trans = obj->transtail = (Trans *) NULL;
  507. X    obj->frame = -1;    /* impossible value */
  508. X    BoundsInit(obj->bounds);
  509. X#ifdef SHAREDMEM
  510. X    /*
  511. X     * If the counter is in shared memory, processes will
  512. X     * be modifying it left-and-right.  So, we cheat and
  513. X     * make counter a pointer to a non-shared location and
  514. X     * store the value there.
  515. X     */
  516. X    new->counter = (unsigned long *)Malloc(sizeof(unsigned long));
  517. X    *new->counter = 0;
  518. X#endif
  519. X    return obj;
  520. X}
  521. X
  522. X/*
  523. X * Return a copy of the given object.
  524. X * Note that surface, texturing, and transformation information
  525. X * is copied by reference.
  526. X */
  527. XGeom *
  528. XGeomCopy(obj)
  529. XGeom *obj;
  530. X{
  531. X    Geom *new;
  532. X
  533. X    new = GeomCreate(obj->obj, obj->methods);
  534. X    /* Share texturing, name, #prims, surface info */
  535. X    new->name = obj->name;
  536. X    new->texture = obj->texture;
  537. X    new->surf = obj->surf;
  538. X    new->prims = obj->prims;
  539. X    new->trans = obj->trans;
  540. X    new->animtrans = obj->animtrans;
  541. X    new->transtail = obj->transtail;
  542. X    /* copy bounds */
  543. X    BoundsCopy(obj->bounds, new->bounds);
  544. X    return new;
  545. X}
  546. X
  547. X/*
  548. X * Report bounding box and number of primitives in object.
  549. X */
  550. Xvoid
  551. XAggregatePrintInfo(obj, fp)
  552. XGeom *obj;
  553. XFILE *fp;
  554. X{
  555. X    if (fp) {
  556. X        if (obj->name && obj->name[0])
  557. X            fprintf(fp,"%s \"%s\":\n", GeomName(obj), obj->name);
  558. X        else
  559. X            fprintf(fp,"%s:\n", GeomName(obj));
  560. X        if (!UNBOUNDED(obj))
  561. X            BoundsPrint(obj->bounds, fp);
  562. X        fprintf(fp,"\t%lu primitive%c\n",obj->prims,
  563. X            obj->prims == 1 ? ' ' : 's');
  564. X    }
  565. X}
  566. X
  567. X/*
  568. X * Convert the given object from a linked list of objects to
  569. X * the desired aggregate type.
  570. X */
  571. Xint
  572. XAggregateConvert(obj, objlist)
  573. XGeom *obj, *objlist;
  574. X{
  575. X    if (!IsAggregate(obj)) {
  576. X        RLerror(RL_ABORT, "A %s isn't an aggregate.\n",
  577. X            GeomName(obj));
  578. X        return 0;
  579. X    }
  580. X
  581. X    return (*obj->methods->convert)(obj->obj, objlist);
  582. X}
  583. X
  584. X/*
  585. X * This should really be called
  586. X * GeomInitialize
  587. X * or something.
  588. X */
  589. Xvoid
  590. XGeomComputeBounds(obj)
  591. XGeom *obj;
  592. X{
  593. X    if (obj->frame == Sampling.framenum)
  594. X        return;
  595. X
  596. X    if (!obj->animtrans) {
  597. X        /*
  598. X         * If it isn't animated,
  599. X         * just compute bbox directly 
  600. X         */
  601. X        GeomBounds(obj, obj->bounds);
  602. X    } else {
  603. X        /*
  604. X         * Animated things are gonna get a bbox
  605. X         * which is large enough to enclose all
  606. X         * the places where the object goes.
  607. X         */
  608. X        GeomBoundsAnimated(obj);
  609. X    }
  610. X    /*
  611. X     * Enlarge by EPSILON in each direction just to
  612. X     * be on the safe side.
  613. X     */
  614. X    obj->bounds[LOW][X] -= EPSILON;
  615. X    obj->bounds[HIGH][X] += EPSILON;
  616. X    obj->bounds[LOW][Y] -= EPSILON;
  617. X    obj->bounds[HIGH][Y] += EPSILON;
  618. X    obj->bounds[LOW][Z] -= EPSILON;
  619. X    obj->bounds[HIGH][Z] += EPSILON;
  620. X    /*
  621. X     * Mark the fact that that the obj is initialized
  622. X     * for this frame.
  623. X     */
  624. X    obj->frame = Sampling.framenum;
  625. X    obj->counter = 0;
  626. X}
  627. X
  628. Xstatic void
  629. XGeomBoundsAnimated(obj)
  630. XGeom *obj;
  631. X{
  632. X    int i, m;
  633. X    Float newbounds[2][3];
  634. X    Float window, subwindow, jitter, subjitter;
  635. X
  636. X    /*
  637. X     * For each possible screen sample,
  638. X     * choose TIME_SUB_SAMPLES times and recompute the
  639. X     * bounds of obj at that time,
  640. X     * expanding the computed bounding box appropriately.
  641. X     */
  642. X    BoundsInit(obj->bounds);
  643. X    jitter = Sampling.shutter / Sampling.totsamples;
  644. X    subjitter = jitter / (Float)TIME_SUB_SAMPLES;
  645. X    window = Sampling.starttime;
  646. X    for (i = 0; i < Sampling.totsamples; i++, window += jitter) {
  647. X        subwindow = window;
  648. X        for (m = 0; m < TIME_SUB_SAMPLES; m++, subwindow += subjitter) {
  649. X            /*
  650. X             * Set the current time.
  651. X             */
  652. X            TimeSet(subwindow + subjitter*nrand());
  653. X            /*
  654. X             * Resolve the objects geometric associations
  655. X             */
  656. X            GeomResolveAssoc(obj);
  657. X            /*
  658. X             * Compute bounds and expand current bounds.
  659. X             */
  660. X            GeomBounds(obj, newbounds);
  661. X            BoundsEnlarge(obj->bounds, newbounds);
  662. X        }
  663. X    }
  664. X    /*
  665. X     * Also sample at time extremes, as for many
  666. X     * movements, extremes occur at beginning/end times.
  667. X     */
  668. X    TimeSet(Sampling.starttime);
  669. X    GeomResolveAssoc(obj);
  670. X    GeomBounds(obj, newbounds);
  671. X    BoundsEnlarge(obj->bounds, newbounds);
  672. X
  673. X    TimeSet(Sampling.starttime + Sampling.shutter);
  674. X    GeomResolveAssoc(obj);
  675. X    GeomBounds(obj, newbounds);
  676. X    BoundsEnlarge(obj->bounds, newbounds);
  677. X}
  678. X
  679. Xvoid
  680. XGeomResolveAssoc(obj)
  681. XGeom *obj;
  682. X{
  683. X    /*
  684. X     * PrimResolveAssoc(obj);
  685. X     */
  686. X    TransResolveAssoc(obj->trans);
  687. X}
  688. X
  689. X/*
  690. X * Set "bounds" of object to be the extent of the primitive.
  691. X */
  692. Xstatic void
  693. XGeomBounds(obj, bounds)
  694. XGeom *obj;
  695. XFloat bounds[2][3];
  696. X{
  697. X    Trans *trans;
  698. X
  699. X    if (!obj || !obj->methods->bounds)
  700. X        RLerror(RL_ABORT, "Can't compute bounds of \"%s\".\n",
  701. X            GeomName(obj));
  702. X    (*obj->methods->bounds) (obj->obj, bounds);
  703. X    if (obj->trans) {
  704. X        for (trans = obj->trans; trans; trans = trans->next)
  705. X            BoundsTransform(&trans->trans, bounds);
  706. X    }
  707. X}
  708. X
  709. Xchar *
  710. XGeomName(obj)
  711. XGeom *obj;
  712. X{
  713. X    if (obj->methods->name)
  714. X        return (*obj->methods->name)();
  715. X
  716. X    return "unknown";
  717. X}
  718. X
  719. Xvoid
  720. XGeomStats(obj, tests, hits)
  721. XGeom *obj;
  722. Xunsigned long *tests, *hits;
  723. X{
  724. X    if (obj && obj->methods->stats)
  725. X        (*obj->methods->stats)(tests, hits);
  726. X    else {
  727. X        *tests = *hits = 0;
  728. X    }
  729. X}
  730. X
  731. X/*
  732. X * Push an object onto the head of the given stack, returning
  733. X * the new head.
  734. X */
  735. XGeomList *
  736. XGeomStackPush(obj, list)
  737. XGeom *obj;
  738. XGeomList *list;
  739. X{
  740. X    GeomList *new;
  741. X    /*
  742. X     * Pretty simple.
  743. X     * Make new element point to old head and return new head.
  744. X     */
  745. X    new = (GeomList *)Malloc(sizeof(GeomList));
  746. X    new->obj = obj;
  747. X    new->next = list;
  748. X    return new;
  749. X}
  750. X
  751. X/*
  752. X * Pop the topmost object off of the given stack, returning the new head.
  753. X * The old head is freed, but the object it points to is not.
  754. X */
  755. XGeomList *
  756. XGeomStackPop(list)
  757. XGeomList *list;
  758. X{
  759. X    GeomList *ltmp;
  760. X
  761. X    ltmp = list->next;    /* Save new head. */
  762. X    free((voidstar)list);    /* Free old head. */
  763. X    return ltmp;        /* Return new head. */
  764. X}
  765. X
  766. XMethods *
  767. XMethodsCreate()
  768. X{
  769. X    return (Methods *)share_calloc(1, sizeof(Methods));
  770. X}
  771. X
  772. X/*
  773. X * Call appropriate routine to compute UV and, if non-null,
  774. X * dpdu and dpdv at given point on the given primitive.  The
  775. X * normal is used to facilitate computation of u, v, and the
  776. X * partial derivatives.
  777. X */
  778. Xvoid
  779. XPrimUV(prim, pos, norm, uv, dpdu, dpdv)
  780. XGeom *prim;
  781. XVector *pos, *norm, *dpdu, *dpdv;
  782. XVec2d *uv;
  783. X{
  784. X    /*
  785. X     * Call appropriate inverse mapping routine
  786. X     */
  787. X    if (prim->methods->uv == NULL) {
  788. X        uv->u = uv->v = 0.;
  789. X        if (dpdu) {
  790. X            dpdu->y = dpdu->z = 0.;
  791. X            dpdu->x = 1.;
  792. X        }
  793. X        if (dpdv) {
  794. X            dpdv->x = dpdv->z = 0.;
  795. X            dpdv->y = 1.;
  796. X        }    
  797. X    } else
  798. X        (*prim->methods->uv)(prim->obj,pos,norm,uv,dpdu,dpdv);
  799. X}
  800. X
  801. Xint
  802. XPrimNormal(prim, pos, norm, gnorm)
  803. XGeom *prim;
  804. XVector *pos, *norm, *gnorm;
  805. X{
  806. X    /*
  807. X     * Call appropriate normal routine
  808. X     */
  809. X    return (*prim->methods->normal) (prim->obj, pos, norm, gnorm);
  810. X}
  811. X
  812. Xint
  813. XPrimEnter(obj, ray, mind, hitd)
  814. XGeom *obj;
  815. XRay *ray;
  816. XFloat mind, hitd;
  817. X{
  818. X    /*
  819. X     * Call appropriate enter/leave routine
  820. X     */
  821. X    if (obj->methods->enter == NULL) {
  822. X        Vector pos, nrm, gnrm;
  823. X        /*
  824. X         * Sleazy method:  Use hit point, find normal 
  825. X         * and take dot prod with ray 
  826. X         */
  827. X        VecAddScaled(ray->pos, hitd, ray->dir, &pos);
  828. X        PrimNormal(obj, &pos, &nrm, &gnrm);
  829. X
  830. X        return dotp(&ray->dir, &gnrm) < 0.0;
  831. X    }
  832. X    else
  833. X        return (*obj->methods->enter) (obj->obj, ray, mind, hitd);
  834. X}
  835. X
  836. X/*
  837. X * Walk through a linked-list of objects.  If the object is unbounded,
  838. X * unlink it it from the list and add it to the 'unbounded' list.
  839. X * If the object is bounded, enlarge the given bounding box if
  840. X * necessary.  Return pointer to unbounded list.
  841. X */
  842. XGeom *
  843. XGeomComputeAggregateBounds(bounded, unbounded, bounds)
  844. XGeom **bounded, *unbounded;
  845. XFloat bounds[2][3];
  846. X{
  847. X    Geom *ltmp, *prev, *nextobj;
  848. X
  849. X    BoundsInit(bounds);
  850. X
  851. X    prev = (Geom *)0;
  852. X
  853. X    for (ltmp = *bounded; ltmp; ltmp = nextobj) {
  854. X        nextobj = ltmp->next;
  855. X        GeomComputeBounds(ltmp);
  856. X        if (UNBOUNDED(ltmp)) {
  857. X            /*
  858. X             * Geom is unbounded -- unlink it...
  859. X             */
  860. X            if (prev)
  861. X                prev->next = ltmp->next;
  862. X            else
  863. X                *bounded = ltmp->next;
  864. X            /*
  865. X             * And add it to unbounded object list.
  866. X             */
  867. X            ltmp->next = unbounded;
  868. X            unbounded = ltmp;
  869. X        } else {
  870. X            /*
  871. X             * Geom is bounded.
  872. X             */
  873. X            BoundsEnlarge(bounds, ltmp->bounds);
  874. X            prev = ltmp;
  875. X        }
  876. X    }
  877. X    return unbounded;
  878. X}
  879. X
  880. X/*
  881. X * Find 'highest' animated object on the hitlist.
  882. X */
  883. Xint
  884. XFirstAnimatedGeom(hitlist)
  885. XHitList *hitlist;
  886. X{
  887. X    int i;
  888. X
  889. X    for (i = hitlist->nodes -1; i; i--)
  890. X        /*
  891. X         * If object itself is animated, have
  892. X         * to check other flag, too...
  893. X         */
  894. X        if (hitlist->data[i].obj->animtrans)
  895. X            return i;
  896. X    return 0;
  897. X}
  898. END_OF_FILE
  899. if test 9132 -ne `wc -c <'libray/libobj/geom.c'`; then
  900.     echo shar: \"'libray/libobj/geom.c'\" unpacked with wrong size!
  901. fi
  902. # end of 'libray/libobj/geom.c'
  903. fi
  904. if test -f 'libray/libobj/torus.c' -a "${1}" != "-c" ; then 
  905.   echo shar: Will not clobber existing file \"'libray/libobj/torus.c'\"
  906. else
  907. echo shar: Extracting \"'libray/libobj/torus.c'\" \(8916 characters\)
  908. sed "s/^X//" >'libray/libobj/torus.c' <<'END_OF_FILE'
  909. X/*
  910. X * torus.c
  911. X *
  912. X * Copyright (C) 1990, 1991, Mark Podlipec, Craig E. Kolb
  913. X * All rights reserved.
  914. X *
  915. X * This software may be freely copied, modified, and redistributed
  916. X * provided that this copyright notice is preserved on all copies.
  917. X *
  918. X * You may not distribute this software, in whole or in part, as part of
  919. X * any commercial product without the express consent of the authors.
  920. X *
  921. X * There is no warranty or other guarantee of fitness of this software
  922. X * for any purpose.  It is provided solely "as is".
  923. X *
  924. X * $Id: torus.c,v 4.0 91/07/17 14:39:28 kolb Exp Locker: kolb $
  925. X *
  926. X * $Log:    torus.c,v $
  927. X * Revision 4.0  91/07/17  14:39:28  kolb
  928. X * Initial version.
  929. X * 
  930. X */
  931. X#include "geom.h"
  932. X#include "torus.h"
  933. X
  934. Xstatic Methods *iTorusMethods = NULL;
  935. Xstatic char torusName[] = "torus";
  936. Xunsigned long TorusTests, TorusHits;
  937. X
  938. X/*
  939. X * Create & return reference to a torus.
  940. X */
  941. XTorus *
  942. XTorusCreate(a, b, pos, norm)
  943. XFloat a, b;
  944. XVector *pos, *norm;
  945. X{
  946. X    Torus  *torus;
  947. X    Vector tmpnrm;
  948. X
  949. X    if ((a < EPSILON) || (b < EPSILON)) {
  950. X        RLerror(RL_WARN, "Degenerate torus.\n");
  951. X        return (Torus *)NULL;
  952. X    }
  953. X
  954. X    tmpnrm = *norm;
  955. X    if (VecNormalize(&tmpnrm) == 0.) {
  956. X        RLerror(RL_WARN, "Degenerate torus normal.\n");
  957. X        return (Torus *)NULL;
  958. X    }
  959. X
  960. X    torus = (Torus *)share_malloc(sizeof(Torus));
  961. X
  962. X    /*
  963. X     * torus->aa holds the square of the swept radius.
  964. X     * torus->bb holds the square of the tube radius.
  965. X     */
  966. X    torus->a = a;
  967. X    torus->b = b;
  968. X    torus->aa = a*a;
  969. X    torus->bb = b*b;
  970. X    CoordSysTransform(pos, &tmpnrm, 1., 1., &torus->trans);
  971. X
  972. X    return torus;
  973. X}
  974. X
  975. X/*
  976. X * Ray/torus intersection test.
  977. X */
  978. Xint
  979. XTorusIntersect(torus, inray, mindist, maxdist)
  980. XTorus *torus;
  981. XRay *inray;
  982. XFloat mindist, *maxdist;
  983. X{
  984. X    Vector pos,ray;
  985. X    double c[5],s[4], dist, nmin;
  986. X    Float distfactor;
  987. X    register int num,i;
  988. X
  989. X    TorusTests++;
  990. X
  991. X    /* Transform ray into toroid space */
  992. X    {
  993. X        Ray tmpray;
  994. X        tmpray = *inray;
  995. X        distfactor = RayTransform(&tmpray, &torus->trans.itrans);
  996. X        ray = tmpray.dir;
  997. X        pos = tmpray.pos;
  998. X        nmin = mindist * distfactor;
  999. X    }
  1000. X
  1001. X    /*
  1002. X * Original Equations for Toroid with position of (0,0,0) and axis (0,0,1)
  1003. X *
  1004. X * Equation for two circles of radius b centered at (-a,0,0) and (a,0,0) 
  1005. X *
  1006. X *      ((R-a)^2 + z*2 - b*b) * ((R+a)^2 + z*z - b*b) = 0 
  1007. X *
  1008. X *       a         is swept radius
  1009. X *       b         is tube  radius
  1010. X *
  1011. X * subsitute R*R = x*x + y*y  to rotate about z-axis
  1012. X *
  1013. X * and substitute the parametric ray equations:
  1014. X *
  1015. X *       x = x0 + t * x1;
  1016. X *       y = y0 + t * y1;
  1017. X *       z = z0 + t * z1;
  1018. X *
  1019. X * to get a Quartic in t.
  1020. X *
  1021. X *       c4*t^4 + c3*t^3 + c2*t^2 + c1*t + c0 = 0
  1022. X *
  1023. X * where the coefficients are:
  1024. X *
  1025. X *       c4 =   (x1s + y1s + z1s) * (x1s + y1s + z1s); 
  1026. X *       c3 =   4.0 * (tx + ty + tz) * (x1s + y1s + z1s);
  1027. X *       c2 =   2.0 * (x1s + y1s + z1s) * (x0s + y0s + z0s - as - bs)
  1028. X *            + 4.0 * (tx + ty + tz)    * (tx + ty + tz)
  1029. X *            + 4.0 * as * z1s;
  1030. X *       c1 =   4.0 * (tx + ty + tz) * (x0s + y0s + z0s - as - bs)
  1031. X *            + 8.0 * as * tz;
  1032. X *       c0 =   (x0s + y0s + z0s - as - bs) * (x0s + y0s + z0s - as - bs)
  1033. X *            + 4.0 * as * (z0s - bs);
  1034. X *
  1035. X *       as        is swept radius squared
  1036. X *       bs        is tube  radius squared
  1037. X *      (x0,y0,z0) is origin of ray to be tested
  1038. X *      (x1,y1,z1) is direction vector of ray to be tested
  1039. X *       tx        is x0 * x1
  1040. X *       ty        is y0 * y1
  1041. X *       tz        is z0 * z1
  1042. X *
  1043. X *   Since the direction vector (x1,y1,z1) is normalized:
  1044. X *              (x1s + y1s + z1s) = 1.0
  1045. X *
  1046. X *   Also let     g2s = (x1 * x0) + (y1 * y0) + (z1 * z0)
  1047. X *    and let     g0s = (x0 * x0) * (y0 * y0) + (z0 * z0) - as - bs 
  1048. X *    since these terms are used fairly often
  1049. X */
  1050. X    {
  1051. X        register Float g0s,g2s;
  1052. X        register Float as,bs;
  1053. X        register Float z0s,z1s,tz;
  1054. X
  1055. X        as  = torus->aa;
  1056. X        bs  = torus->bb;
  1057. X        z0s = pos.z * pos.z;
  1058. X        z1s = ray.z * ray.z;
  1059. X        tz  = pos.z * ray.z;
  1060. X        g0s = pos.x * pos.x  +  pos.y * pos.y  +  z0s  -  as  -  bs;
  1061. X        g2s = pos.x * ray.x  +  pos.y * ray.y  +  tz;
  1062. X
  1063. X        c[4] =   1.0;
  1064. X        c[3] =   4.0 * g2s;
  1065. X        c[2] =   2.0 * (g0s  +  2.0 * g2s * g2s  +  2.0 * as * z1s);
  1066. X        c[1] =   4.0 * (g2s*g0s  +  2.0*as*tz);
  1067. X        c[0] =   g0s * g0s  +  4.0 * as * (z0s - bs);
  1068. X    }
  1069. X
  1070. X    /* use GraphGem's Solve Quartic to find roots */
  1071. X    num = SolveQuartic(c,s);
  1072. X
  1073. X    /* no roots - return 0. */
  1074. X    if (num==0) return FALSE;
  1075. X
  1076. X    /* of roots return the smallest root > EPSILON */
  1077. X    dist = 0.0;
  1078. X    for(i=0;i<num;i++)
  1079. X    {
  1080. X        /* if root is in front of ray origin */
  1081. X        if (s[i] > nmin) {
  1082. X            /* first valid root */
  1083. X            if (dist == 0.0) dist = s[i];
  1084. X            /* else update only if it's closer to ray origin */
  1085. X            else if (s[i] < dist) dist = s[i];
  1086. X        }
  1087. X    }
  1088. X    dist /= distfactor;
  1089. X    if (dist > mindist && dist < *maxdist) {
  1090. X        *maxdist = dist;
  1091. X        TorusHits++;
  1092. X        return TRUE;
  1093. X    }
  1094. X    return FALSE;
  1095. X}
  1096. X
  1097. X/*
  1098. X * Compute the normal to a torus at a given location on its surface
  1099. X */
  1100. Xint
  1101. XTorusNormal(torus, rawpos, nrm, gnrm)
  1102. XTorus *torus;
  1103. XVector *rawpos, *nrm, *gnrm;
  1104. X{
  1105. X    Vector pos;
  1106. X    register Float dist,posx,posy,xm,ym;
  1107. X
  1108. X    /* Transform intersection point to torus space. */
  1109. X    pos = *rawpos;
  1110. X    PointTransform(&pos, &torus->trans.itrans);
  1111. X
  1112. X/* 
  1113. X *  The code for the toroid is simpified by always having the axis
  1114. X *  be the z-axis and then transforming information to and from
  1115. X *  toroid space.
  1116. X *
  1117. X *  Flatten toroid by ignoring z. Now imagine a knife cutting from
  1118. X *  center of toroid to the ray intersection point(x,y). The point
  1119. X *  on the tube axis(a circle about the origin with radius 'a') 
  1120. X *  where the knife cuts is (xm,ym,zm=0). Unflattening the toroid,
  1121. X *  the normal at the point [x,y,z] is (x-xm,y-ym,z). Of course, we
  1122. X *  must transform the normal back into world coordinates.
  1123. X *  Instead of messing with tan-1,sin and cos, we can find (xm,ym)
  1124. X *  by using the proportions:
  1125. X *
  1126. X *     xm     x           ym     y
  1127. X *    ---- = ----   and  ---- = ----
  1128. X *     a     dist         a     dist
  1129. X *
  1130. X *       a         is the swept radius
  1131. X *    [x,y,z]      is the point on the toroids surface
  1132. X *      dist       is the distance from the z-axis (x*x + y*y).
  1133. X *    [xm,ym,zm=0] is the point on the tube's axis 
  1134. X *
  1135. X */
  1136. X
  1137. X    /* find distance from axis */
  1138. X    posx = pos.x;
  1139. X    posy = pos.y;
  1140. X    dist = sqrt(posx * posx + posy * posy);
  1141. X
  1142. X    if (dist > EPSILON)
  1143. X    {
  1144. X        xm = torus->a * posx / dist;
  1145. X        ym = torus->a * posy / dist;
  1146. X    }
  1147. X    else /* ERROR - dist should not be < EPSILON (should never happen)*/
  1148. X    {
  1149. X        xm = 0.0;
  1150. X        ym = 0.0;
  1151. X    }
  1152. X
  1153. X    /* normal is vector from [xm,ym,zm] to [x,y,z] */
  1154. X    nrm->x = posx - xm;
  1155. X    nrm->y = posy - ym;
  1156. X    nrm->z = pos.z;   /* note by default zm is 0 */
  1157. X
  1158. X    /* Transform normal back to world space. */
  1159. X    NormalTransform(nrm, &torus->trans.itrans);
  1160. X    *gnrm = *nrm;
  1161. X    return FALSE;
  1162. X}
  1163. X
  1164. Xvoid
  1165. XTorusUV(torus, pos, norm, uv, dpdu, dpdv)
  1166. XTorus *torus;
  1167. XVector *pos, *norm, *dpdu, *dpdv;
  1168. XVec2d *uv;
  1169. X{
  1170. X    Vector npos;
  1171. X    Float costheta, sintheta, rad, cosphi;
  1172. X
  1173. X    npos = *pos;
  1174. X    PointTransform(&npos, &torus->trans.itrans);
  1175. X    /*
  1176. X     * u = theta / 2PI
  1177. X     */
  1178. X    rad = sqrt(npos.x*npos.x + npos.y*npos.y);
  1179. X    costheta = npos.x / rad;
  1180. X    sintheta = npos.y / rad;
  1181. X    if (costheta > 1.)    /* roundoff */
  1182. X        uv->u = 0.;
  1183. X    else if (costheta < -1.)
  1184. X        uv->u = 0.5;
  1185. X    else
  1186. X        uv->u = acos(costheta) / TWOPI;
  1187. X    if (sintheta < 0.)
  1188. X        uv->u = 1. - uv->u;
  1189. X    if (dpdu) {
  1190. X        dpdu->x = -npos.y;
  1191. X        dpdu->y = npos.x;
  1192. X        dpdu->z = 0.;
  1193. X        VecTransform(dpdu, &torus->trans.trans);
  1194. X        (void)VecNormalize(dpdu);
  1195. X    }
  1196. X    /*
  1197. X     * sinphi = npos.z / tor->b;
  1198. X     * cosphi = rad - tor->a;
  1199. X     * cosphi is negated in order to make texture 'seam'
  1200. X     * occur on the interior of the torus.
  1201. X     */
  1202. X    cosphi = -(rad - torus->a) / torus->b;
  1203. X    if (cosphi > 1.)
  1204. X        uv->v = 0.;
  1205. X    else if (cosphi < -1.)
  1206. X        uv->v = 0.5;
  1207. X    else
  1208. X        uv->v = acos(cosphi) / TWOPI;
  1209. X    if (npos.z > 0.)    /* if sinphi > 0... */
  1210. X        uv->v = 1. - uv->v;
  1211. X    /*
  1212. X     * dpdv = norm X dpdu
  1213. X     */
  1214. X    if (dpdv) {
  1215. X        VecCross(norm, dpdu, dpdv);
  1216. X        VecTransform(dpdv, &torus->trans.trans);
  1217. X        (void)VecNormalize(dpdv);
  1218. X    }
  1219. X}
  1220. X
  1221. X/*
  1222. X * Return the extent of a torus.
  1223. X */
  1224. Xvoid
  1225. XTorusBounds(torus, bounds)
  1226. XTorus *torus;
  1227. XFloat bounds[2][3];
  1228. X{
  1229. X    bounds[LOW][X]  = bounds[LOW][Y]  = -(torus->a+torus->b);
  1230. X    bounds[HIGH][X] = bounds[HIGH][Y] =  torus->a+torus->b;
  1231. X    bounds[LOW][Z]  = -torus->b;
  1232. X    bounds[HIGH][Z] =  torus->b;
  1233. X    /*
  1234. X         * Transform bounding box to world space.
  1235. X         */
  1236. X    BoundsTransform(&torus->trans.trans, bounds);
  1237. X}
  1238. X
  1239. Xchar *
  1240. XTorusName()
  1241. X{
  1242. X    return torusName;
  1243. X}
  1244. X
  1245. Xvoid
  1246. XTorusStats(tests, hits)
  1247. Xunsigned long *tests, *hits;
  1248. X{
  1249. X    *tests = TorusTests;
  1250. X    *hits = TorusHits;
  1251. X}
  1252. X
  1253. XMethods *
  1254. XTorusMethods()
  1255. X{
  1256. X    if (iTorusMethods == NULL) {
  1257. X        iTorusMethods = MethodsCreate();
  1258. X        iTorusMethods->create = (GeomCreateFunc *)TorusCreate;
  1259. X        iTorusMethods->methods  = TorusMethods;
  1260. X        iTorusMethods->name = TorusName;
  1261. X        iTorusMethods->intersect = TorusIntersect;
  1262. X        iTorusMethods->bounds = TorusBounds;
  1263. X        iTorusMethods->normal = TorusNormal;
  1264. X        iTorusMethods->uv = TorusUV;
  1265. X        iTorusMethods->stats = TorusStats;
  1266. X        iTorusMethods->checkbounds = TRUE;
  1267. X        iTorusMethods->closed = TRUE;
  1268. X    }
  1269. X    return iTorusMethods;
  1270. X}
  1271. X
  1272. Xvoid
  1273. XTorusMethodRegister(meth)
  1274. XUserMethodType meth;
  1275. X{
  1276. X    if (iTorusMethods)
  1277. X        iTorusMethods->user = meth;
  1278. X}
  1279. END_OF_FILE
  1280. if test 8916 -ne `wc -c <'libray/libobj/torus.c'`; then
  1281.     echo shar: \"'libray/libobj/torus.c'\" unpacked with wrong size!
  1282. fi
  1283. # end of 'libray/libobj/torus.c'
  1284. fi
  1285. if test -f 'libshade/options.c' -a "${1}" != "-c" ; then 
  1286.   echo shar: Will not clobber existing file \"'libshade/options.c'\"
  1287. else
  1288. echo shar: Extracting \"'libshade/options.c'\" \(8699 characters\)
  1289. sed "s/^X//" >'libshade/options.c' <<'END_OF_FILE'
  1290. X/*
  1291. X * options.c
  1292. X *
  1293. X * Copyright (C) 1989, 1991, Craig E. Kolb
  1294. X * All rights reserved.
  1295. X *
  1296. X * This software may be freely copied, modified, and redistributed
  1297. X * provided that this copyright notice is preserved on all copies.
  1298. X *
  1299. X * You may not distribute this software, in whole or in part, as part of
  1300. X * any commercial product without the express consent of the authors.
  1301. X *
  1302. X * There is no warranty or other guarantee of fitness of this software
  1303. X * for any purpose.  It is provided solely "as is".
  1304. X *
  1305. X * $Id: options.c,v 4.0 91/07/17 14:46:47 kolb Exp Locker: kolb $
  1306. X *
  1307. X * $Log:    options.c,v $
  1308. X * Revision 4.0  91/07/17  14:46:47  kolb
  1309. X * Initial version.
  1310. X * 
  1311. X */
  1312. X#include "rayshade.h"
  1313. X#include "options.h"
  1314. X#include "stats.h"
  1315. X#include "viewing.h"
  1316. X
  1317. XRSOptions    Options;
  1318. X
  1319. Xstatic void usage();
  1320. X
  1321. Xvoid
  1322. XRSOptionsSet(argc, argv)
  1323. Xint argc;
  1324. Xchar **argv;
  1325. X{
  1326. X    extern void OpenStatsFile();
  1327. X
  1328. X    Options.progname = strsave(argv[0]);
  1329. X    Options.inputname = (char *)NULL;
  1330. X
  1331. X    while (--argc) {
  1332. X        argv++;
  1333. X        if (argv[0][0] != '-') {
  1334. X            /*
  1335. X             * Must be the input file name.
  1336. X             * If already given, complain and then exit.
  1337. X             */
  1338. X            if (Options.inputname != (char *)NULL) {
  1339. X                usage();    
  1340. X                exit(1);
  1341. X            }
  1342. X            Options.inputname = strsave(argv[0]);
  1343. X            continue;
  1344. X        }
  1345. X        /* else */
  1346. X        switch(argv[0][1]) {
  1347. X            case 'A':
  1348. X                /*
  1349. X                 * First frame number
  1350. X                 */
  1351. X                Options.startframe = atoi(argv[1]);
  1352. X                argv++; argc--;
  1353. X                break;
  1354. X#ifdef URT
  1355. X            case 'a':
  1356. X                Options.alpha = !Options.alpha;
  1357. X                break;
  1358. X#endif
  1359. X            case 'C':
  1360. X                Options.cutoff.r = atof(argv[1]);
  1361. X                Options.cutoff.g = atof(argv[2]);
  1362. X                Options.cutoff.b = atof(argv[3]);
  1363. X                Options.cutoff_set = TRUE;
  1364. X                argv += 3; argc -= 3;
  1365. X                break;
  1366. X#ifdef URT
  1367. X            case 'c':
  1368. X                Options.appending = TRUE;
  1369. X                break;
  1370. X#endif
  1371. X            case 'D':
  1372. X                Options.maxdepth = atoi(argv[1]);
  1373. X                Options.maxdepth_set = TRUE;
  1374. X                argv++; argc--;
  1375. X                break;
  1376. X            case 'E':
  1377. X                Options.eyesep = atof(argv[1]);
  1378. X                Options.eyesep_set = TRUE;
  1379. X                argc--; argv++;
  1380. X                break;
  1381. X#ifdef URT
  1382. X            case 'e':
  1383. X                Options.exp_output = TRUE;
  1384. X                break;
  1385. X#endif
  1386. X            case 'F':
  1387. X                Options.report_freq = atoi(argv[1]);
  1388. X                if (Options.report_freq < 1)
  1389. X                    Options.report_freq = 1;
  1390. X                Options.freq_set = TRUE;
  1391. X                argv++; argc--;
  1392. X                break;
  1393. X            case 'f':
  1394. X                Options.flipnorm = !Options.flipnorm;
  1395. X                break;
  1396. X            case 'G':
  1397. X                Options.gamma = atof(argv[1]);
  1398. X                argv++; argc--;
  1399. X                break;
  1400. X            case 'g':
  1401. X                Options.gaussian = !Options.gaussian;
  1402. X                break;
  1403. X            case 'h':
  1404. X                usage();
  1405. X                exit(0);
  1406. X                break;
  1407. X            case 'j':
  1408. X                Options.jitter = !Options.jitter;
  1409. X                Options.jitter_set = TRUE;
  1410. X                break;
  1411. X            case 'l':
  1412. X                Options.stereo = LEFT;
  1413. X                break;
  1414. X#ifdef URT
  1415. X            case 'm':
  1416. X                Options.samplemap = !Options.samplemap;
  1417. X                break;
  1418. X#endif
  1419. X            case 'N':
  1420. X                Options.totalframes = atof(argv[1]);
  1421. X                Options.totalframes_set = TRUE;
  1422. X                argv++; argc--;
  1423. X                break;
  1424. X            case 'n':
  1425. X                Options.no_shadows = !Options.no_shadows;
  1426. X                break;
  1427. X            case 'O':
  1428. X                Options.imgname = strsave(argv[1]);
  1429. X                argv++;
  1430. X                argc--;
  1431. X                break;
  1432. X            case 'o':
  1433. X                Options.shadowtransp = !Options.shadowtransp;
  1434. X                break;
  1435. X            case 'P':
  1436. X                Options.cppargs = argv[1];
  1437. X                argv++; argc--;
  1438. X                break;
  1439. X            case 'p':
  1440. X                /*
  1441. X                 * Preview-quality rendering
  1442. X                 * no shadows
  1443. X                 * max depth of 0
  1444. X                 * 1 jittered sample/pixel
  1445. X                 */
  1446. X                Options.no_shadows = TRUE;
  1447. X                Options.maxdepth = 0;
  1448. X                Options.maxdepth_set = TRUE;
  1449. X                Options.jitter = TRUE;
  1450. X                Options.jitter_set = TRUE;
  1451. X                Options.samples = 1;
  1452. X                Options.samples_set = TRUE;
  1453. X                break;
  1454. X            case 'q':
  1455. X                Options.quiet = TRUE;
  1456. X                break;
  1457. X            case 'R':
  1458. X                Screen.xres = atoi(argv[1]);
  1459. X                Screen.yres = atoi(argv[2]);
  1460. X                Options.resolution_set = TRUE;
  1461. X                argv += 2;
  1462. X                argc -= 2;
  1463. X                break;
  1464. X            case 'r':
  1465. X                Options.stereo = RIGHT;
  1466. X                break;
  1467. X            case 'S':
  1468. X                Options.samples = atoi(argv[1]);
  1469. X                if (Options.samples < 1)
  1470. X                    Options.samples = 1;
  1471. X                Options.samples_set = TRUE;
  1472. X                argv++; argc--;
  1473. X                break;
  1474. X            case 's':
  1475. X                Options.cache = !Options.cache;
  1476. X                break;
  1477. X            case 'T':
  1478. X                Options.contrast.r = atof(argv[1]);
  1479. X                Options.contrast.g = atof(argv[2]);
  1480. X                Options.contrast.b = atof(argv[3]);
  1481. X                Options.contrast_set = TRUE;
  1482. X                argv += 3;
  1483. X                argc -= 3;
  1484. X                break;
  1485. X            case 'v':
  1486. X                Options.verbose = TRUE;
  1487. X                break;
  1488. X            case 'V':
  1489. X                Options.verbose = TRUE;
  1490. X                if (argv[1][0] == '-') {
  1491. X                    /* User probably blew it, and
  1492. X                     * it's difficult to remove a file
  1493. X                     * that begins with '-'...
  1494. X                     */
  1495. X                    usage();
  1496. X                    exit(2);
  1497. X                }
  1498. X                Options.statsname = strsave(argv[1]);
  1499. X                OpenStatsFile();
  1500. X                argv++; argc--;
  1501. X                break;
  1502. X#ifdef URT
  1503. X            case 'W':
  1504. X                Options.xmin = atof(argv[1]);
  1505. X                Options.xmax = atof(argv[2]);
  1506. X                Options.ymin = atof(argv[3]);
  1507. X                Options.ymax = atof(argv[4]);
  1508. X                Options.window_set = TRUE;
  1509. X                argv += 4; argc -= 4;
  1510. X                break;
  1511. X#endif
  1512. X#ifdef LINDA
  1513. X            case 'X':
  1514. X                Options.workers = atoi(argv[1]);
  1515. X                if (Options.workers<0 || Options.workers>17) {
  1516. X                    RLerror(RL_PANIC, "%d workers?\n",
  1517. X                            Options.workers);
  1518. X                }
  1519. X                argv++; argc--;
  1520. X                break;
  1521. X            case 'w':
  1522. X                Options.verbose_worker =
  1523. X                    !Options.verbose_worker;
  1524. X                break;
  1525. X#endif
  1526. X            default:
  1527. X                RLerror(RL_PANIC,"Bad argument: %s\n",argv[0]);
  1528. X        }
  1529. X    }
  1530. X}
  1531. X
  1532. Xvoid
  1533. XRSOptionsList()
  1534. X{
  1535. X    if (Options.totalframes > 1) {
  1536. X        fprintf(Stats.fstats,"Rendering frames %d through %d.\n",
  1537. X            Options.startframe, Options.endframe);
  1538. X    } else {
  1539. X        fprintf(Stats.fstats,"Rendering frame %d.\n", Options.startframe);
  1540. X    }
  1541. X
  1542. X    fprintf(Stats.fstats,"Screen resolution: %d x %d\n",
  1543. X        Screen.xres,Screen.yres);
  1544. X    fprintf(Stats.fstats,"Image window: (%d - %d), (%d - %d).\n",
  1545. X            Screen.minx, Screen.maxx, Screen.miny, Screen.maxy);
  1546. X
  1547. X    if (Options.jitter)
  1548. X        fprintf(Stats.fstats,"Using jittered sampling, ");
  1549. X    fprintf(Stats.fstats,"Max sampling rate %d %s/pixel.\n",
  1550. X        Options.samples*Options.samples,
  1551. X        Options.samples == 1 ? "sample" : "samples");
  1552. X
  1553. X    fprintf(Stats.fstats,
  1554. X        "Maximum contrast: %g red, %g green, %g blue.\n",
  1555. X        Options.contrast.r, Options.contrast.g,
  1556. X        Options.contrast.b);
  1557. X    fprintf(Stats.fstats,"Maximum ray depth: %d.  Cutoff thresh: %g %g %g.\n",
  1558. X            Options.maxdepth,
  1559. X            Options.cutoff.r, Options.cutoff.g, Options.cutoff.b);
  1560. X    if (Options.stereo == LEFT)
  1561. X        fprintf(Stats.fstats,"Rendering image for left eye.\n");
  1562. X    else if (Options.stereo == RIGHT)
  1563. X        fprintf(Stats.fstats,"Rendering image for right eye.\n");
  1564. X    if (Options.no_shadows) {
  1565. X        fprintf(Stats.fstats,"No shadows are rendered.\n");
  1566. X    } else if (Options.shadowtransp) {
  1567. X        fprintf(Stats.fstats,
  1568. X            "Object opacity affects depth of shadowing.\n");
  1569. X    }
  1570. X    if (!Options.cache)
  1571. X        fprintf(Stats.fstats,"Shadow caching is disabled.\n");
  1572. X    if (Options.totalframes != 1)
  1573. X        fprintf(Stats.fstats,"Rendering %d frames.\n",
  1574. X            Options.totalframes);
  1575. X}
  1576. X
  1577. Xstatic void
  1578. Xusage()
  1579. X{
  1580. X    fprintf(stderr,"usage: %s [options] [filename]\n", Options.progname);
  1581. X    fprintf(stderr,"Where options include:\n");
  1582. X    fprintf(stderr,"\t-A frame\t(Begin with given frame #.)\n");
  1583. X#ifdef URT
  1584. X    fprintf(stderr,"\t-a \t\t(Toggle writing of alpha channel.)\n");
  1585. X#endif
  1586. X    fprintf(stderr,"\t-C thresh\t(Set adaptive ray tree cutoff value.)\n");
  1587. X#ifdef URT
  1588. X    fprintf(stderr,"\t-c \t\t(Continue interrupted rendering.)\n");
  1589. X#endif
  1590. X    fprintf(stderr,"\t-D depth\t(Set maximum ray tree depth.)\n");
  1591. X    fprintf(stderr,"\t-E eye_sep\t(Set eye separation in stereo pairs.)\n");
  1592. X#ifdef URT
  1593. X    fprintf(stderr,"\t-e \t\t(Write exponential RLE file.)\n");
  1594. X#endif
  1595. X    fprintf(stderr,"\t-F freq\t\t(Set frequency of status report.)\n");
  1596. X    fprintf(stderr,"\t-G gamma\t(Use given gamma correction exponent.)\n");
  1597. X    fprintf(stderr,"\t-h \t\t(Print this message.)\n");
  1598. X    fprintf(stderr,"\t-l \t\t(Render image for left eye view.)\n");
  1599. X    fprintf(stderr,"\t-N number\t(Render given number of frames.)\n");
  1600. X    fprintf(stderr,"\t-n \t\t(Do not render shadows.)\n");
  1601. X    fprintf(stderr,"\t-O outfile \t(Set output file name.)\n");
  1602. X    fprintf(stderr,"\t-o \t\t(Toggle opacity effect on shadowing.)\n");
  1603. X    fprintf(stderr,"\t-P cpp-args\t(Options to pass to C pre-processor.\n");
  1604. X    fprintf(stderr,"\t-p \t\t(Preview-quality rendering.)\n");
  1605. X    fprintf(stderr,"\t-q \t\t(Run quietly.)\n");
  1606. X    fprintf(stderr,"\t-R xres yres\t(Render at given resolution.)\n");
  1607. X    fprintf(stderr,"\t-r \t\t(Render image for right eye view.)\n");
  1608. X    fprintf(stderr,"\t-S samples\t(Max density of samples^2 samples.)\n");
  1609. X    fprintf(stderr,"\t-s \t\t(Don't cache shadowing information.)\n");
  1610. X    fprintf(stderr,"\t-T r g b\t(Set contrast threshold (0. - 1.).)\n");
  1611. X    fprintf(stderr,"\t-V filename \t(Write verbose output to filename.)\n");
  1612. X    fprintf(stderr,"\t-v \t\t(Verbose output.)\n");
  1613. X#ifdef URT
  1614. X    fprintf(stderr,"\t-W x y x y \t(Render subwindow.)\n");
  1615. X#endif
  1616. X#ifdef LINDA
  1617. X    fprintf(stderr,"\t-X workers\t(Number of workers.)\n");
  1618. X    fprintf(stderr,"\t-w \t\t(Verbose worker output.)\n");
  1619. X#endif
  1620. X}
  1621. END_OF_FILE
  1622. if test 8699 -ne `wc -c <'libshade/options.c'`; then
  1623.     echo shar: \"'libshade/options.c'\" unpacked with wrong size!
  1624. fi
  1625. # end of 'libshade/options.c'
  1626. fi
  1627. echo shar: End of archive 12 \(of 19\).
  1628. cp /dev/null ark12isdone
  1629. MISSING=""
  1630. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
  1631.     if test ! -f ark${I}isdone ; then
  1632.     MISSING="${MISSING} ${I}"
  1633.     fi
  1634. done
  1635. if test "${MISSING}" = "" ; then
  1636.     echo You have unpacked all 19 archives.
  1637.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1638. else
  1639.     echo You still need to unpack the following archives:
  1640.     echo "        " ${MISSING}
  1641. fi
  1642. ##  End of shell archive.
  1643. exit 0
  1644.  
  1645. exit 0 # Just in case...
  1646.