home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 3 / Amiga Tools 3.iso / grafik / raytracing / rayshade-4.0.6.3 / libray / libobj / disc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-09  |  4.5 KB  |  221 lines

  1. /*
  2.  * disc.c
  3.  *
  4.  * Copyright (C) 1989, 1991, Craig E. Kolb
  5.  * All rights reserved.
  6.  *
  7.  * This software may be freely copied, modified, and redistributed
  8.  * provided that this copyright notice is preserved on all copies.
  9.  *
  10.  * You may not distribute this software, in whole or in part, as part of
  11.  * any commercial product without the express consent of the authors.
  12.  *
  13.  * There is no warranty or other guarantee of fitness of this software
  14.  * for any purpose.  It is provided solely "as is".
  15.  *
  16.  * disc.c,v 4.1 1994/08/09 07:58:32 explorer Exp
  17.  *
  18.  * disc.c,v
  19.  * Revision 4.1  1994/08/09  07:58:32  explorer
  20.  * Bump version to 4.1
  21.  *
  22.  * Revision 1.1.1.1  1994/08/08  04:52:08  explorer
  23.  * Initial import.  This is a prerelease of 4.0.6enh3, or 4.1 possibly.
  24.  *
  25.  * Revision 4.0  91/07/17  14:37:23  kolb
  26.  * Initial version.
  27.  * 
  28.  */
  29. #include "geom.h"
  30. #include "disc.h"
  31.  
  32. static Methods *iDiscMethods = NULL;
  33. static char discName[] = "disc";
  34.  
  35. unsigned long DiscTests, DiscHits;
  36.  
  37. Disc *
  38. DiscCreate(r, pos, norm)
  39. Float r;
  40. Vector *pos, *norm;
  41. {
  42.     Disc *disc;        /* Pointer to new disc. */
  43.  
  44.     if (r < EPSILON) {
  45.         RLerror(RL_WARN, "Degenerate disc.\n");
  46.             /*
  47.              * Don't create this primitive.
  48.              */
  49.             return (Disc *)NULL;
  50.     }
  51.  
  52.     if (VecNormalize(norm) == 0.) {
  53.         RLerror(RL_WARN, "Degenerate disc normal.\n");
  54.         return (Disc *)NULL;
  55.     }
  56.     /*
  57.      * Allocate new Disc.
  58.      */
  59.     disc = (Disc *)share_malloc(sizeof(Disc));
  60.     /*
  61.      * Initialize new disc.
  62.      * We store the square of the radius to save us a sqrt().
  63.      */
  64.     disc->radius = r*r;
  65.     disc->pos = *pos;
  66.     disc->norm = *norm;
  67.     /*
  68.      * Compute plane constant.
  69.      */
  70.     disc->d = dotp(pos, norm);
  71.     /*
  72.      * Allocate new primitive
  73.      */
  74.     return disc;
  75. }
  76.  
  77. Methods *
  78. DiscMethods()
  79. {
  80.     if (iDiscMethods == (Methods *)NULL) {
  81.         iDiscMethods = MethodsCreate();
  82.         iDiscMethods->name = DiscName;
  83.         iDiscMethods->create = (GeomCreateFunc *)DiscCreate;
  84.         iDiscMethods->methods = DiscMethods;
  85.         iDiscMethods->intersect = DiscIntersect;
  86.         iDiscMethods->normal = DiscNormal;
  87.         iDiscMethods->uv = DiscUV;
  88.         iDiscMethods->bounds = DiscBounds;
  89.         iDiscMethods->stats = DiscStats;
  90.         iDiscMethods->checkbounds = FALSE;
  91.         iDiscMethods->closed = FALSE;
  92.     }
  93.     return iDiscMethods;
  94. }
  95.  
  96. int
  97. DiscIntersect(disc, ray, mindist, maxdist)
  98. Disc *disc;
  99. Ray *ray;
  100. Float mindist, *maxdist;
  101. {
  102.     Vector hit;
  103.     Float denom, dist;
  104.  
  105.     DiscTests++;
  106.  
  107.     denom = dotp(&disc->norm, &ray->dir);
  108.     if (fabs(denom) < EPSILON)
  109.         /* Edge-on intersection */
  110.          return FALSE;
  111.  
  112.     dist = (disc->d - dotp(&disc->norm, &ray->pos)) / denom;
  113.     if (dist < mindist || dist > *maxdist)
  114.         /* Too close or too far */
  115.         return FALSE;
  116.     /*
  117.      *  Find difference between point of intersection and center of disc.
  118.      */
  119.     VecAddScaled(ray->pos, dist, ray->dir, &hit);
  120.     VecSub(hit, disc->pos, &hit);
  121.     /*
  122.      * If hit point is <= disc->radius from center, we've hit the disc.
  123.      */
  124.     if (dotp(&hit, &hit) <= disc->radius) {
  125.         *maxdist = dist;
  126.         DiscHits++;
  127.         return TRUE;
  128.     }
  129.     return FALSE;
  130. }
  131.  
  132. int
  133. DiscNormal(disc, pos, nrm, gnrm)
  134. Disc *disc;
  135. Vector *pos, *nrm, *gnrm;
  136. {
  137.     *gnrm = *nrm = disc->norm;
  138.     return FALSE;
  139. }
  140.  
  141. void
  142. DiscUV(disc, pos, norm, uv, dpdu, dpdv)
  143. Disc *disc;
  144. Vector *pos, *norm, *dpdu, *dpdv;
  145. Vec2d *uv;
  146. {
  147.     Float dist, val;
  148.  
  149.     dist =    (pos->x - disc->pos.x) * (pos->x - disc->pos.x) +
  150.         (pos->y - disc->pos.y) * (pos->y - disc->pos.y) +
  151.         (pos->z - disc->pos.z) * (pos->z - disc->pos.z);
  152.  
  153.     if (dist < EPSILON) {
  154.         uv->u = uv->v = 0.;
  155.         return;
  156.     }
  157.  
  158.     dist = sqrt(dist);
  159.     uv->v = dist / sqrt(disc->radius); /* should store r and r*r */
  160.  
  161.     val = pos->x / dist;
  162.  
  163.     if (fabs(val) > 1.)
  164.         uv->u = 0.5;
  165.     else {
  166.         uv->u = acos(val) / TWOPI; 
  167.         if (pos->y < 0.)
  168.             uv->u = 1. - uv->u;
  169.     }
  170.  
  171.     if (dpdu) {
  172.         VecSub(*pos, disc->pos, dpdv);
  173.         /* dpdu = dpdv X norm */
  174.         VecCross(dpdv, norm, dpdu);
  175.     }
  176. }
  177.  
  178. void
  179. DiscBounds(disc, bounds)
  180. Disc *disc;
  181. Float bounds[2][3];
  182. {
  183.     Float extent, rad;
  184.  
  185.     rad = sqrt(disc->radius);
  186.     /*
  187.      * Project disc along each of X, Y and Z axes.
  188.      */
  189.     extent = rad * sqrt(1. - disc->norm.x * disc->norm.x);
  190.     bounds[LOW][X] = disc->pos.x - extent;
  191.     bounds[HIGH][X] = disc->pos.x + extent;
  192.     extent = rad * sqrt(1. - disc->norm.y * disc->norm.y);
  193.     bounds[LOW][Y] = disc->pos.y - extent;
  194.     bounds[HIGH][Y] = disc->pos.y + extent;
  195.     extent = rad * sqrt(1. - disc->norm.z * disc->norm.z);
  196.     bounds[LOW][Z] = disc->pos.z - extent;
  197.     bounds[HIGH][Z] = disc->pos.z + extent;
  198. }
  199.  
  200. char *
  201. DiscName()
  202. {
  203.     return discName;
  204. }
  205.  
  206. void
  207. DiscStats(tests, hits)
  208. unsigned long *tests, *hits;
  209. {
  210.     *tests = DiscTests;
  211.     *hits = DiscHits;
  212. }
  213.  
  214. void
  215. DiscMethodRegister(meth)
  216. UserMethodType meth;
  217. {
  218.     if (iDiscMethods)
  219.         iDiscMethods->user = meth;
  220. }
  221.