home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / dirs / dkbtrace_397.lzh / DKBTrace / DKBSource.LZH / spheres.c < prev    next >
C/C++ Source or Header  |  1990-08-26  |  8KB  |  243 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. *     ATX              (613) 526-4141
  37. *     OMX              (613) 731-3419
  38. *     Mystic           (613) 731-0088 or (613) 731-6698
  39. *
  40. *  Fidonet:   1:163/109.9
  41. *  Internet:  David_Buck@Carleton.CA
  42. *
  43. *  IBM Port by Aaron A. Collins. Aaron may be reached on the following BBS'es:
  44. *
  45. *     Lattice BBS                      (708) 916-1200
  46. *     The Information Exchange BBS     (708) 945-5575
  47. *     Stillwaters BBS                  (708) 403-2826
  48. *
  49. *****************************************************************************/
  50.  
  51. #include "frame.h"
  52. #include "vector.h"
  53. #include "dkbproto.h"
  54.  
  55. #define Small_Tolerance 0.001
  56.  
  57. METHODS Sphere_Methods =
  58.    { Object_Intersect, All_Sphere_Intersections,
  59.      Inside_Sphere, Sphere_Normal,
  60.      Copy_Sphere,
  61.      Translate_Sphere, Rotate_Sphere,
  62.      Scale_Sphere, Invert_Sphere};
  63.  
  64. extern SPHERE *Get_Sphere_Shape();
  65.  
  66. extern RAY *VP_Ray;
  67. extern long Ray_Sphere_Tests, Ray_Sphere_Tests_Succeeded;
  68.  
  69. int All_Sphere_Intersections (Object, Ray, Depth_Queue)
  70.   OBJECT *Object;
  71.   RAY *Ray;
  72.   PRIOQ *Depth_Queue;
  73.   {
  74.   DBL Depth1, Depth2;
  75.   VECTOR Intersection_Point;
  76.   INTERSECTION Local_Element;
  77.   register int Intersection_Found;
  78.   SPHERE *Shape = (SPHERE *) Object;
  79.  
  80.   Intersection_Found = FALSE;
  81.   if (Intersect_Sphere (Ray, Shape, &Depth1, &Depth2))
  82.     {
  83.     Local_Element.Depth = Depth1;
  84.     Local_Element.Object = Shape -> Parent_Object;
  85.     VScale (Intersection_Point, Ray -> Direction, Depth1);
  86.     VAdd (Intersection_Point, Intersection_Point, Ray -> Initial);
  87.     Local_Element.Point = Intersection_Point;
  88.     Local_Element.Shape = (SHAPE *)Shape;
  89.     pq_add (Depth_Queue, &Local_Element);
  90.     Intersection_Found = TRUE;
  91.  
  92.     if (Depth2 != Depth1)
  93.       {
  94.       Local_Element.Depth = Depth2;
  95.       Local_Element.Object = Shape -> Parent_Object;
  96.       VScale (Intersection_Point, Ray -> Direction, Depth2);
  97.       VAdd (Intersection_Point, Intersection_Point, Ray -> Initial);
  98.       Local_Element.Point = Intersection_Point;
  99.       Local_Element.Shape = (SHAPE *) Shape;
  100.       pq_add (Depth_Queue, &Local_Element);
  101.       Intersection_Found = TRUE;
  102.       }
  103.     }
  104.   return (Intersection_Found);
  105.   }
  106.  
  107. int Intersect_Sphere (Ray, Sphere, Depth1, Depth2)
  108.    RAY *Ray;
  109.    SPHERE *Sphere;
  110.    DBL *Depth1, *Depth2;
  111.    {
  112.    VECTOR Origin_To_Center;
  113.    DBL OCSquared, t_Closest_Approach, Half_Chord, t_Half_Chord_Squared;
  114.    short inside;
  115.  
  116.    Ray_Sphere_Tests++;
  117.    if (Ray == VP_Ray) {
  118.       if (!Sphere->VPCached) {
  119.          VSub (Sphere->VPOtoC, Sphere->Center, Ray->Initial);
  120.          VDot (Sphere->VPOCSquared, Sphere->VPOtoC, Sphere->VPOtoC);
  121.          Sphere->VPinside = (Sphere->VPOCSquared < Sphere->Radius_Squared);
  122.          Sphere->VPCached = TRUE;
  123.          }
  124.       VDot (t_Closest_Approach, Sphere->VPOtoC, Ray->Direction);
  125.       if (!Sphere->VPinside && (t_Closest_Approach < Small_Tolerance))
  126.          return (FALSE);      
  127.       t_Half_Chord_Squared = Sphere->Radius_Squared - Sphere->VPOCSquared +
  128.                         (t_Closest_Approach * t_Closest_Approach);
  129.       }
  130.    else {
  131.       VSub (Origin_To_Center, Sphere->Center, Ray->Initial);
  132.       VDot (OCSquared, Origin_To_Center, Origin_To_Center);
  133.       inside = (OCSquared < Sphere->Radius_Squared);
  134.       VDot (t_Closest_Approach, Origin_To_Center, Ray->Direction);
  135.       if (!inside && (t_Closest_Approach < Small_Tolerance))
  136.          return (FALSE);
  137.  
  138.       t_Half_Chord_Squared = Sphere->Radius_Squared - OCSquared +
  139.                         (t_Closest_Approach * t_Closest_Approach);
  140.       }
  141.  
  142.    if (t_Half_Chord_Squared < Small_Tolerance)
  143.       return (FALSE);
  144.  
  145.    Half_Chord = sqrt (t_Half_Chord_Squared);
  146.    *Depth1 = t_Closest_Approach + Half_Chord;
  147.    *Depth2 = t_Closest_Approach - Half_Chord;
  148.  
  149.    if ((*Depth1 < Small_Tolerance) || (*Depth1 > Max_Distance))
  150.       if ((*Depth2 < Small_Tolerance) || (*Depth2 > Max_Distance))
  151.          return (FALSE);
  152.       else
  153.          *Depth1 = *Depth2;
  154.    else
  155.       if ((*Depth2 < Small_Tolerance) || (*Depth2 > Max_Distance))
  156.         *Depth2 = *Depth1;
  157.  
  158.    Ray_Sphere_Tests_Succeeded++;
  159.    return (TRUE);
  160.    }
  161.  
  162. int Inside_Sphere (Point, Object)
  163.    VECTOR *Point;
  164.    OBJECT *Object;
  165.    {
  166.    VECTOR Origin_To_Center;
  167.    DBL OCSquared;
  168.    SPHERE *Sphere = (SPHERE *) Object;
  169.  
  170.    VSub (Origin_To_Center, Sphere->Center, *Point);
  171.    VDot (OCSquared, Origin_To_Center, Origin_To_Center);
  172.  
  173.    if (Sphere->Inverted)
  174.       return (OCSquared - Sphere->Radius_Squared > Small_Tolerance);
  175.    else
  176.       return (OCSquared - Sphere->Radius_Squared < Small_Tolerance);
  177.    }
  178.  
  179. void Sphere_Normal (Result, Object, Intersection_Point)
  180.    OBJECT *Object;
  181.    VECTOR *Result, *Intersection_Point;
  182.    {
  183.    SPHERE *Sphere = (SPHERE *) Object;
  184.  
  185.    VSub (*Result, *Intersection_Point, Sphere->Center);
  186.    VScale (*Result, *Result, Sphere->Inverse_Radius);
  187.    Perturb_Normal (Result, Sphere -> Parent_Object,
  188.                    Intersection_Point, Result);
  189.   }
  190.  
  191. void *Copy_Sphere (Object)
  192.    OBJECT *Object;
  193.    {
  194.    SPHERE *New_Shape;
  195.  
  196.    New_Shape = Get_Sphere_Shape ();
  197.    *New_Shape = *((SPHERE *) Object);
  198.    New_Shape -> Next_Object = NULL;
  199.    return (New_Shape);
  200.    }
  201.  
  202. void Translate_Sphere (Object, Vector)
  203.    OBJECT *Object;
  204.    VECTOR *Vector;
  205.    {
  206.    VAdd (((SPHERE *) Object)->Center, ((SPHERE *) Object)->Center, *Vector);
  207.    }
  208.  
  209. void Rotate_Sphere (Object, Vector)
  210.    OBJECT *Object;
  211.    VECTOR *Vector;
  212.    {
  213.    TRANSFORMATION Transformation;
  214.  
  215.    Get_Rotation_Transformation (&Transformation, Vector);
  216.    MTransformVector (&((SPHERE *) Object)->Center,
  217.                      &((SPHERE *) Object)->Center, &Transformation);
  218.    }
  219.  
  220. void Scale_Sphere (Object, Vector)
  221.    OBJECT *Object;
  222.    VECTOR *Vector;
  223.    {
  224.    SPHERE *Sphere = (SPHERE *) Object;
  225.  
  226.    if ((Vector->x != Vector->y) ||
  227.        (Vector->x != Vector->z)) {
  228.       printf ("Error - you cannot scale a sphere unevenly\n");
  229.       exit (1);
  230.       }
  231.  
  232.    VScale (Sphere->Center, Sphere->Center, Vector->x);
  233.    Sphere->Radius *= Vector->x;
  234.    Sphere->Radius_Squared = Sphere->Radius * Sphere->Radius;
  235.    Sphere->Inverse_Radius = 1.0 / Sphere->Radius;
  236.    }
  237.  
  238. void Invert_Sphere (Object)
  239.    OBJECT *Object;
  240.    {
  241.    ((SPHERE *) Object)->Inverted ^= TRUE;
  242.    }
  243.