home *** CD-ROM | disk | FTP | other *** search
/ RISC DISC 3 / RISC_DISC_3.iso / resources / etexts / gems / gemsv / ch5_2 / quad_gg.c next >
C/C++ Source or Header  |  1994-11-22  |  5KB  |  141 lines

  1. /* ------------------------------------------------------------------------- *\
  2.    QUAD_GG.C :
  3.  
  4.    by Christophe Schlick and Gilles Subrenat (15 May 1994)
  5.  
  6.    "Ray Intersection of Tessellated Surfaces : Quadrangles versus Triangles"
  7.    in Graphics Gems V (edited by A. Paeth), Academic Press
  8. \* ------------------------------------------------------------------------- */
  9.  
  10. #include "quad_gg.h"
  11.  
  12.  
  13. /*********************
  14.  * macro definitions *
  15.  *********************/
  16. #define EPSILON             ((REAL) 0.0001)
  17.  
  18. #define DETERMINANT(A,B)    ((REAL) ((A).x * (B).y - (A).y * (B).x))
  19.  
  20. #define V3_LIN(R,A,k,B)     ((R).x = (A).x + k * (B).x, \
  21.                              (R).y = (A).y + k * (B).y, \
  22.                              (R).z = (A).z + k * (B).z)
  23.  
  24. #define LARGEST_COMPONENT(A)  (ABS((A).x) > ABS((A).y) ? \
  25.                               (ABS((A).x) > ABS((A).z) ? 'x' : 'z') : \
  26.                               (ABS((A).y) > ABS((A).z) ? 'y' : 'z'))
  27.  
  28. /*
  29. ** Compute uv-coordinates of the point
  30. ** Return TRUE if the point is in the quadrangle
  31. */
  32. static boolean point_in_quad (QUAD *Quad, HIT *Hit)
  33. {
  34.     char       LargestComponent;             /* of the normal vector         */
  35.     Point2     A, B, C, D;                   /* Projected vertices           */
  36.     Point2     M;                            /* Projected intersection point */
  37.     Vector2    AB, BC, CD, AD, AM, AE;       /* AE = DC - AB = DA - CB       */
  38.     REAL       u, v;                         /* Parametric coordinates       */
  39.     REAL       a, b, c, SqrtDelta;           /* for the quadratic equation   */
  40.     boolean    IsInside = FALSE;             /* if u and v are inside        */
  41.     Vector2    Vector;                       /* temporary 2D-vector          */
  42.  
  43.     /*
  44.     ** Projection on the plane that is most parallel to the facet
  45.     */
  46.     LargestComponent = LARGEST_COMPONENT(Quad->Normal);
  47.  
  48.     if (LargestComponent == 'x') {
  49.         A.x = Quad->A.y; B.x = Quad->B.y; C.x = Quad->C.y; D.x = Quad->D.y;
  50.         M.x = Hit->Point.y;
  51.     }
  52.     else {
  53.         A.x = Quad->A.x; B.x = Quad->B.x; C.x = Quad->C.x; D.x = Quad->D.x;
  54.         M.x = Hit->Point.x;
  55.     }
  56.  
  57.     if (LargestComponent == 'z') {
  58.         A.y = Quad->A.y; B.y = Quad->B.y; C.y = Quad->C.y; D.y = Quad->D.y;
  59.         M.y = Hit->Point.y;
  60.     }
  61.     else {
  62.         A.y = Quad->A.z; B.y = Quad->B.z; C.y = Quad->C.z; D.y = Quad->D.z;
  63.         M.y = Hit->Point.z;
  64.     }
  65.  
  66.     V2Sub (&B, &A, &AB); V2Sub (&C, &B, &BC);
  67.     V2Sub (&D, &C, &CD); V2Sub (&D, &A, &AD);
  68.     V2Add (&CD, &AB, &AE); V2Negate (&AE); V2Sub (&M, &A, &AM);
  69.  
  70.     if (fabs(DETERMINANT(AB, CD)) < EPSILON)               /* case AB // CD */
  71.     {
  72.         V2Sub (&AB, &CD, &Vector);
  73.         v = DETERMINANT(AM, Vector) / DETERMINANT(AD, Vector);
  74.         if ((v >= 0.0) && (v <= 1.0)) {
  75.             b = DETERMINANT(AB, AD) - DETERMINANT(AM, AE);
  76.             c = DETERMINANT (AM, AD);
  77.             u = ABS(b) < EPSILON ? -1 : c/b;
  78.             IsInside = ((u >= 0.0) && (u <= 1.0));
  79.         }
  80.     }
  81.     else if (fabs(DETERMINANT(BC, AD)) < EPSILON)          /* case AD // BC */
  82.     {
  83.         V2Add (&AD, &BC, &Vector);
  84.         u = DETERMINANT(AM, Vector) / DETERMINANT(AB, Vector);
  85.         if ((u >= 0.0) && (u <= 1.0)) {
  86.             b = DETERMINANT(AD, AB) - DETERMINANT(AM, AE);
  87.             c = DETERMINANT (AM, AB);
  88.             v = ABS(b) < EPSILON ? -1 : c/b;
  89.             IsInside = ((v >= 0.0) && (v <= 1.0));
  90.         }
  91.     }
  92.     else                                                    /* general case */
  93.     {
  94.         a = DETERMINANT(AB, AE); c = - DETERMINANT (AM,AD);
  95.         b = DETERMINANT(AB, AD) - DETERMINANT(AM, AE);
  96.         a = -0.5/a; b *= a; c *= (a + a); SqrtDelta = b*b + c;
  97.         if (SqrtDelta >= 0.0) {
  98.             SqrtDelta = sqrt(SqrtDelta);
  99.             u = b - SqrtDelta;
  100.             if ((u < 0.0) || (u > 1.0))      /* to choose u between 0 and 1 */
  101.                 u = b + SqrtDelta;
  102.             if ((u >= 0.0) && (u <= 1.0)) {
  103.                 v = AD.x + u * AE.x;
  104.                 if (ABS(v) < EPSILON)
  105.                     v = (AM.y - u * AB.y) / (AD.y + u * AE.y);
  106.                 else
  107.                     v = (AM.x - u * AB.x) / v;
  108.                 IsInside = ((v >= 0.0) && (v <= 1.0));
  109.             }
  110.         }
  111.     }
  112.  
  113.     if (IsInside) {
  114.         Hit->u = u;
  115.         Hit->v = v;
  116.     }
  117.     return (IsInside);
  118. }
  119.  
  120. /*
  121. ** Search for an intersection between a facet and a ray
  122. */
  123. boolean hit_ray_quad (RAY *Ray, QUAD *Quad, HIT *Hit)
  124. {
  125.     Point3     Point;
  126.  
  127.     /* if the ray is parallel to the facet, there is no intersection */
  128.     Hit->Distance = V3Dot (&(Ray->Vector), &(Quad->Normal));
  129.     if (ABS(Hit->Distance) < EPSILON) return (FALSE);
  130.  
  131.     /* compute ray intersection with the plane of the facet */
  132.     V3Sub (&(Quad->A), &(Ray->Point), &Point);
  133.     Hit->Distance = V3Dot (&Point, &(Quad->Normal)) / Hit->Distance;
  134.     V3_LIN (Hit->Point, Ray->Point, Hit->Distance, Ray->Vector);
  135.  
  136.     /* is the intersection point inside the facet */
  137.     return (point_in_quad(Quad, Hit));
  138. }
  139.  
  140. /* ------------------------------------------------------------------------- */
  141.