home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / source / povsrc.sit / SOURCE / SPHERES.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-03  |  6.5 KB  |  222 lines

  1. /****************************************************************************
  2. *                spheres.c
  3. *
  4. *  This module implements the sphere primitive.
  5. *
  6. *  from Persistence of Vision Raytracer 
  7. *  Copyright 1992 Persistence of Vision Team
  8. *---------------------------------------------------------------------------
  9. *  Copying, distribution and legal info is in the file povlegal.doc which
  10. *  should be distributed with this file. If povlegal.doc is not available
  11. *  or for more info please contact:
  12. *
  13. *       Drew Wells [POV-Team Leader] 
  14. *       CIS: 73767,1244  Internet: 73767.1244@compuserve.com
  15. *       Phone: (213) 254-4041
  16. * This program is based on the popular DKB raytracer version 2.12.
  17. * DKBTrace was originally written by David K. Buck.
  18. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  19. *
  20. *****************************************************************************/
  21.  
  22. #include "frame.h"
  23. #include "vector.h"
  24. #include "povproto.h"
  25.  
  26. METHODS Sphere_Methods =
  27. { Object_Intersect, All_Sphere_Intersections,
  28.    Inside_Sphere, Sphere_Normal,
  29.    Copy_Sphere,
  30.    Translate_Sphere, Rotate_Sphere,
  31.    Scale_Sphere, Invert_Sphere};
  32.  
  33. extern SPHERE *Get_Sphere_Shape();
  34.  
  35. extern RAY *VP_Ray;
  36. extern long Ray_Sphere_Tests, Ray_Sphere_Tests_Succeeded;
  37.  
  38. int All_Sphere_Intersections (Object, Ray, Depth_Queue)
  39. OBJECT *Object;
  40. RAY *Ray;
  41. PRIOQ *Depth_Queue;
  42. {
  43.    DBL Depth1, Depth2;
  44.    VECTOR Intersection_Point;
  45.    INTERSECTION Local_Element;
  46.    register int Intersection_Found;
  47.    SPHERE *Shape = (SPHERE *) Object;
  48.  
  49.    Intersection_Found = FALSE;
  50.    if (Intersect_Sphere (Ray, Shape, &Depth1, &Depth2))
  51.    {
  52.       Local_Element.Depth = Depth1;
  53.       Local_Element.Object = Shape -> Parent_Object;
  54.       VScale (Intersection_Point, Ray -> Direction, Depth1);
  55.       VAdd (Intersection_Point, Intersection_Point, Ray -> Initial);
  56.       Local_Element.Point = Intersection_Point;
  57.       Local_Element.Shape = (SHAPE *)Shape;
  58.       pq_add (Depth_Queue, &Local_Element);
  59.       Intersection_Found = TRUE;
  60.  
  61.       if (Depth2 != Depth1)
  62.       {
  63.          Local_Element.Depth = Depth2;
  64.          Local_Element.Object = Shape -> Parent_Object;
  65.          VScale (Intersection_Point, Ray -> Direction, Depth2);
  66.          VAdd (Intersection_Point, Intersection_Point, Ray -> Initial);
  67.          Local_Element.Point = Intersection_Point;
  68.          Local_Element.Shape = (SHAPE *) Shape;
  69.          pq_add (Depth_Queue, &Local_Element);
  70.          Intersection_Found = TRUE;
  71.       }
  72.    }
  73.    return (Intersection_Found);
  74. }
  75.  
  76. int Intersect_Sphere (Ray, Sphere, Depth1, Depth2)
  77. RAY *Ray;
  78. SPHERE *Sphere;
  79. DBL *Depth1, *Depth2;
  80. {
  81.    VECTOR Origin_To_Center;
  82.    DBL OCSquared, t_Closest_Approach, Half_Chord, t_Half_Chord_Squared;
  83.    short inside;
  84.  
  85.    Ray_Sphere_Tests++;
  86.    if (Ray == VP_Ray) {
  87.       if (!Sphere->VPCached) {
  88.          VSub (Sphere->VPOtoC, Sphere->Center, Ray->Initial);
  89.          VDot (Sphere->VPOCSquared, Sphere->VPOtoC, Sphere->VPOtoC);
  90.          Sphere->VPinside = (Sphere->VPOCSquared < Sphere->Radius_Squared);
  91.          Sphere->VPCached = TRUE;
  92.       }
  93.       VDot (t_Closest_Approach, Sphere->VPOtoC, Ray->Direction);
  94.       if (!Sphere->VPinside && (t_Closest_Approach < Small_Tolerance))
  95.          return (FALSE);      
  96.       t_Half_Chord_Squared = Sphere->Radius_Squared - Sphere->VPOCSquared +
  97.       (t_Closest_Approach * t_Closest_Approach);
  98.    }
  99.    else {
  100.       VSub (Origin_To_Center, Sphere->Center, Ray->Initial);
  101.       VDot (OCSquared, Origin_To_Center, Origin_To_Center);
  102.       inside = (OCSquared < Sphere->Radius_Squared);
  103.       VDot (t_Closest_Approach, Origin_To_Center, Ray->Direction);
  104.       if (!inside && (t_Closest_Approach < Small_Tolerance))
  105.          return (FALSE);
  106.  
  107.       t_Half_Chord_Squared = Sphere->Radius_Squared - OCSquared +
  108.       (t_Closest_Approach * t_Closest_Approach);
  109.    }
  110.  
  111.    if (t_Half_Chord_Squared < Small_Tolerance)
  112.       return (FALSE);
  113.  
  114.    Half_Chord = sqrt (t_Half_Chord_Squared);
  115.    *Depth1 = t_Closest_Approach + Half_Chord;
  116.    *Depth2 = t_Closest_Approach - Half_Chord;
  117.  
  118.    if ((*Depth1 < Small_Tolerance) || (*Depth1 > Max_Distance))
  119.       if ((*Depth2 < Small_Tolerance) || (*Depth2 > Max_Distance))
  120.          return (FALSE);
  121.       else
  122.          *Depth1 = *Depth2;
  123.    else
  124.       if ((*Depth2 < Small_Tolerance) || (*Depth2 > Max_Distance))
  125.          *Depth2 = *Depth1;
  126.  
  127.    Ray_Sphere_Tests_Succeeded++;
  128.    return (TRUE);
  129. }
  130.  
  131. int Inside_Sphere (Test_Point, Object)
  132. VECTOR *Test_Point;
  133. OBJECT *Object;
  134. {
  135.    VECTOR Origin_To_Center;
  136.    DBL OCSquared;
  137.    SPHERE *Sphere = (SPHERE *) Object;
  138.  
  139.    VSub (Origin_To_Center, Sphere->Center, *Test_Point);
  140.    VDot (OCSquared, Origin_To_Center, Origin_To_Center);
  141.  
  142.    if (Sphere->Inverted)
  143.       return (OCSquared - Sphere->Radius_Squared > Small_Tolerance);
  144.    else
  145.       return (OCSquared - Sphere->Radius_Squared < Small_Tolerance);
  146. }
  147.  
  148. void Sphere_Normal (Result, Object, Intersection_Point)
  149. OBJECT *Object;
  150. VECTOR *Result, *Intersection_Point;
  151. {
  152.    SPHERE *Sphere = (SPHERE *) Object;
  153.  
  154.    VSub (*Result, *Intersection_Point, Sphere->Center);
  155.    VScale (*Result, *Result, Sphere->Inverse_Radius);
  156. }
  157.  
  158. void *Copy_Sphere (Object)
  159. OBJECT *Object;
  160. {
  161.    SPHERE *New_Shape;
  162.  
  163.    New_Shape = Get_Sphere_Shape ();
  164.    *New_Shape = *((SPHERE *) Object);
  165.    New_Shape -> Next_Object = NULL;
  166.  
  167.    if (New_Shape->Shape_Texture != NULL)
  168.       New_Shape->Shape_Texture = Copy_Texture (New_Shape->Shape_Texture);
  169.  
  170.    return (New_Shape);
  171. }
  172.  
  173. void Translate_Sphere (Object, Vector)
  174. OBJECT *Object;
  175. VECTOR *Vector;
  176. {
  177.    VAdd (((SPHERE *) Object)->Center, ((SPHERE *) Object)->Center, *Vector);
  178.  
  179.    Translate_Texture (&((SPHERE *) Object)->Shape_Texture, Vector);
  180. }
  181.  
  182. void Rotate_Sphere (Object, Vector)
  183. OBJECT *Object;
  184. VECTOR *Vector;
  185. {
  186.    TRANSFORMATION Transformation;
  187.  
  188.    Get_Rotation_Transformation (&Transformation, Vector);
  189.    MTransformVector (&((SPHERE *) Object)->Center,
  190.       &((SPHERE *) Object)->Center, &Transformation);
  191.  
  192.    Rotate_Texture (&((SPHERE *) Object)->Shape_Texture, Vector);
  193. }
  194.  
  195. void Scale_Sphere (Object, Vector)
  196. OBJECT *Object;
  197. VECTOR *Vector;
  198. {
  199.    SPHERE *Sphere = (SPHERE *) Object;
  200.  
  201.    if ((Vector->x != Vector->y) ||
  202.       (Vector->x != Vector->z)) {
  203.       fprintf (stderr, "Error - you cannot scale a sphere unevenly\n");
  204.       exit (1);
  205.    }
  206.  
  207.    VScale (Sphere->Center, Sphere->Center, Vector->x);
  208.    Sphere->Radius *= Vector->x;
  209.    Sphere->Radius_Squared = Sphere->Radius * Sphere->Radius;
  210.    Sphere->Inverse_Radius = 1.0 / Sphere->Radius;
  211.  
  212.  
  213.    Scale_Texture (&((SPHERE *) Object)->Shape_Texture, Vector);
  214. }
  215.  
  216. void Invert_Sphere (Object)
  217. OBJECT *Object;
  218. {
  219.    ((SPHERE *) Object)->Inverted ^= TRUE;
  220. }
  221.