home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / gfx / dkb212sr.lzh / spheres.c < prev    next >
C/C++ Source or Header  |  1991-04-30  |  8KB  |  249 lines

  1. /*****************************************************************************
  2. *
  3. *                                      spheres.c
  4. *
  5. *   from DKBTrace (c) 1990  David Buck
  6. *
  7. *  This module implements the sphere primitive.
  8. *
  9. * This software is freely distributable. The source and/or object code may be
  10. * copied or uploaded to communications services so long as this notice remains
  11. * at the top of each file.  If any changes are made to the program, you must
  12. * clearly indicate in the documentation and in the programs startup message
  13. * who it was who made the changes. The documentation should also describe what
  14. * those changes were. This software may not be included in whole or in
  15. * part into any commercial package without the express written consent of the
  16. * author.  It may, however, be included in other public domain or freely
  17. * distributed software so long as the proper credit for the software is given.
  18. *
  19. * This software is provided as is without any guarantees or warranty. Although
  20. * the author has attempted to find and correct any bugs in the software, he
  21. * is not responsible for any damage caused by the use of the software.  The
  22. * author is under no obligation to provide service, corrections, or upgrades
  23. * to this package.
  24. *
  25. * Despite all the legal stuff above, if you do find bugs, I would like to hear
  26. * about them.  Also, if you have any comments or questions, you may contact me
  27. * at the following address:
  28. *
  29. *     David Buck
  30. *     22C Sonnet Cres.
  31. *     Nepean Ontario
  32. *     Canada, K2H 8W7
  33. *
  34. *  I can also be reached on the following bulleton boards:
  35. *
  36. *     OMX              (613) 731-3419
  37. *     Mystic           (613) 596-4249  or  (613) 596-4772
  38. *
  39. *  Fidonet:   1:163/109.9
  40. *  Internet:  dbuck@ccs.carleton.ca
  41. *  The "You Can Call Me RAY" BBS    (708) 358-5611
  42. *
  43. *  IBM Port by Aaron A. Collins. Aaron may be reached on the following BBS'es:
  44. *
  45. *     The "You Can Call Me RAY" BBS (708) 358-5611
  46. *     The Information Exchange BBS  (708) 945-5575
  47. *
  48. *****************************************************************************/
  49.  
  50. #include "frame.h"
  51. #include "vector.h"
  52. #include "dkbproto.h"
  53.  
  54. METHODS Sphere_Methods =
  55.    { Object_Intersect, All_Sphere_Intersections,
  56.      Inside_Sphere, Sphere_Normal,
  57.      Copy_Sphere,
  58.      Translate_Sphere, Rotate_Sphere,
  59.      Scale_Sphere, Invert_Sphere};
  60.  
  61. extern SPHERE *Get_Sphere_Shape();
  62.  
  63. extern RAY *VP_Ray;
  64. extern long Ray_Sphere_Tests, Ray_Sphere_Tests_Succeeded;
  65.  
  66. int All_Sphere_Intersections (Object, Ray, Depth_Queue)
  67.   OBJECT *Object;
  68.   RAY *Ray;
  69.   PRIOQ *Depth_Queue;
  70.   {
  71.   DBL Depth1, Depth2;
  72.   VECTOR Intersection_Point;
  73.   INTERSECTION Local_Element;
  74.   register int Intersection_Found;
  75.   SPHERE *Shape = (SPHERE *) Object;
  76.  
  77.   Intersection_Found = FALSE;
  78.   if (Intersect_Sphere (Ray, Shape, &Depth1, &Depth2))
  79.     {
  80.     Local_Element.Depth = Depth1;
  81.     Local_Element.Object = Shape -> Parent_Object;
  82.     VScale (Intersection_Point, Ray -> Direction, Depth1);
  83.     VAdd (Intersection_Point, Intersection_Point, Ray -> Initial);
  84.     Local_Element.Point = Intersection_Point;
  85.     Local_Element.Shape = (SHAPE *)Shape;
  86.     pq_add (Depth_Queue, &Local_Element);
  87.     Intersection_Found = TRUE;
  88.  
  89.     if (Depth2 != Depth1)
  90.       {
  91.       Local_Element.Depth = Depth2;
  92.       Local_Element.Object = Shape -> Parent_Object;
  93.       VScale (Intersection_Point, Ray -> Direction, Depth2);
  94.       VAdd (Intersection_Point, Intersection_Point, Ray -> Initial);
  95.       Local_Element.Point = Intersection_Point;
  96.       Local_Element.Shape = (SHAPE *) Shape;
  97.       pq_add (Depth_Queue, &Local_Element);
  98.       Intersection_Found = TRUE;
  99.       }
  100.     }
  101.   return (Intersection_Found);
  102.   }
  103.  
  104. int Intersect_Sphere (Ray, Sphere, Depth1, Depth2)
  105.    RAY *Ray;
  106.    SPHERE *Sphere;
  107.    DBL *Depth1, *Depth2;
  108.    {
  109.    VECTOR Origin_To_Center;
  110.    DBL OCSquared, t_Closest_Approach, Half_Chord, t_Half_Chord_Squared;
  111.    short inside;
  112.  
  113.    Ray_Sphere_Tests++;
  114.    if (Ray == VP_Ray) {
  115.       if (!Sphere->VPCached) {
  116.          VSub (Sphere->VPOtoC, Sphere->Center, Ray->Initial);
  117.          VDot (Sphere->VPOCSquared, Sphere->VPOtoC, Sphere->VPOtoC);
  118.          Sphere->VPinside = (Sphere->VPOCSquared < Sphere->Radius_Squared);
  119.          Sphere->VPCached = TRUE;
  120.          }
  121.       VDot (t_Closest_Approach, Sphere->VPOtoC, Ray->Direction);
  122.       if (!Sphere->VPinside && (t_Closest_Approach < Small_Tolerance))
  123.          return (FALSE);      
  124.       t_Half_Chord_Squared = Sphere->Radius_Squared - Sphere->VPOCSquared +
  125.                         (t_Closest_Approach * t_Closest_Approach);
  126.       }
  127.    else {
  128.       VSub (Origin_To_Center, Sphere->Center, Ray->Initial);
  129.       VDot (OCSquared, Origin_To_Center, Origin_To_Center);
  130.       inside = (OCSquared < Sphere->Radius_Squared);
  131.       VDot (t_Closest_Approach, Origin_To_Center, Ray->Direction);
  132.       if (!inside && (t_Closest_Approach < Small_Tolerance))
  133.          return (FALSE);
  134.  
  135.       t_Half_Chord_Squared = Sphere->Radius_Squared - OCSquared +
  136.                         (t_Closest_Approach * t_Closest_Approach);
  137.       }
  138.  
  139.    if (t_Half_Chord_Squared < Small_Tolerance)
  140.       return (FALSE);
  141.  
  142.    Half_Chord = sqrt (t_Half_Chord_Squared);
  143.    *Depth1 = t_Closest_Approach + Half_Chord;
  144.    *Depth2 = t_Closest_Approach - Half_Chord;
  145.  
  146.    if ((*Depth1 < Small_Tolerance) || (*Depth1 > Max_Distance))
  147.       if ((*Depth2 < Small_Tolerance) || (*Depth2 > Max_Distance))
  148.          return (FALSE);
  149.       else
  150.          *Depth1 = *Depth2;
  151.    else
  152.       if ((*Depth2 < Small_Tolerance) || (*Depth2 > Max_Distance))
  153.         *Depth2 = *Depth1;
  154.  
  155.    Ray_Sphere_Tests_Succeeded++;
  156.    return (TRUE);
  157.    }
  158.  
  159. int Inside_Sphere (Test_Point, Object)
  160.    VECTOR *Test_Point;
  161.    OBJECT *Object;
  162.    {
  163.    VECTOR Origin_To_Center;
  164.    DBL OCSquared;
  165.    SPHERE *Sphere = (SPHERE *) Object;
  166.  
  167.    VSub (Origin_To_Center, Sphere->Center, *Test_Point);
  168.    VDot (OCSquared, Origin_To_Center, Origin_To_Center);
  169.  
  170.    if (Sphere->Inverted)
  171.       return (OCSquared - Sphere->Radius_Squared > Small_Tolerance);
  172.    else
  173.       return (OCSquared - Sphere->Radius_Squared < Small_Tolerance);
  174.    }
  175.  
  176. void Sphere_Normal (Result, Object, Intersection_Point)
  177.    OBJECT *Object;
  178.    VECTOR *Result, *Intersection_Point;
  179.    {
  180.    SPHERE *Sphere = (SPHERE *) Object;
  181.  
  182.    VSub (*Result, *Intersection_Point, Sphere->Center);
  183.    VScale (*Result, *Result, Sphere->Inverse_Radius);
  184.    }
  185.  
  186. void *Copy_Sphere (Object)
  187.    OBJECT *Object;
  188.    {
  189.    SPHERE *New_Shape;
  190.  
  191.    New_Shape = Get_Sphere_Shape ();
  192.    *New_Shape = *((SPHERE *) Object);
  193.    New_Shape -> Next_Object = NULL;
  194.  
  195.        if (New_Shape->Shape_Texture != NULL)
  196.       New_Shape->Shape_Texture = Copy_Texture (New_Shape->Shape_Texture);
  197.  
  198.    return (New_Shape);
  199.    }
  200.  
  201. void Translate_Sphere (Object, Vector)
  202.    OBJECT *Object;
  203.    VECTOR *Vector;
  204.    {
  205.    VAdd (((SPHERE *) Object)->Center, ((SPHERE *) Object)->Center, *Vector);
  206.  
  207.    Translate_Texture (&((SPHERE *) Object)->Shape_Texture, Vector);
  208.    }
  209.  
  210. void Rotate_Sphere (Object, Vector)
  211.    OBJECT *Object;
  212.    VECTOR *Vector;
  213.    {
  214.    TRANSFORMATION Transformation;
  215.  
  216.    Get_Rotation_Transformation (&Transformation, Vector);
  217.    MTransformVector (&((SPHERE *) Object)->Center,
  218.                      &((SPHERE *) Object)->Center, &Transformation);
  219.  
  220.    Rotate_Texture (&((SPHERE *) Object)->Shape_Texture, Vector);
  221.    }
  222.  
  223. void Scale_Sphere (Object, Vector)
  224.    OBJECT *Object;
  225.    VECTOR *Vector;
  226.    {
  227.    SPHERE *Sphere = (SPHERE *) Object;
  228.  
  229.    if ((Vector->x != Vector->y) ||
  230.        (Vector->x != Vector->z)) {
  231.       fprintf (stderr, "Error - you cannot scale a sphere unevenly\n");
  232.       exit (1);
  233.       }
  234.  
  235.    VScale (Sphere->Center, Sphere->Center, Vector->x);
  236.    Sphere->Radius *= Vector->x;
  237.    Sphere->Radius_Squared = Sphere->Radius * Sphere->Radius;
  238.    Sphere->Inverse_Radius = 1.0 / Sphere->Radius;
  239.  
  240.  
  241.    Scale_Texture (&((SPHERE *) Object)->Shape_Texture, Vector);
  242.    }
  243.  
  244. void Invert_Sphere (Object)
  245.    OBJECT *Object;
  246.    {
  247.    ((SPHERE *) Object)->Inverted ^= TRUE;
  248.    }
  249.