home *** CD-ROM | disk | FTP | other *** search
/ Chestnut's Multimedia Mania / MM_MANIA.ISO / graphics / povsrc20 / discs.c < prev    next >
C/C++ Source or Header  |  1993-07-28  |  6KB  |  231 lines

  1. /****************************************************************************
  2. *                discs.c
  3. *
  4. *  This module implements the disc primitive.
  5. *  This file was written by Alexander Enzmann.    He wrote the code for
  6. *  discs and generously provided us these enhancements.
  7. *
  8. *  from Persistence of Vision Raytracer
  9. *  Copyright 1993 Persistence of Vision Team
  10. *---------------------------------------------------------------------------
  11. *  NOTICE: This source code file is provided so that users may experiment
  12. *  with enhancements to POV-Ray and to port the software to platforms other 
  13. *  than those supported by the POV-Ray Team.  There are strict rules under
  14. *  which you are permitted to use this file.  The rules are in the file
  15. *  named POVLEGAL.DOC which should be distributed with this file. If 
  16. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  17. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  18. *  Forum.  The latest version of POV-Ray may be found there as well.
  19. *
  20. * This program is based on the popular DKB raytracer version 2.12.
  21. * DKBTrace was originally written by David K. Buck.
  22. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  23. *
  24. *****************************************************************************/
  25.  
  26. #include "frame.h"
  27. #include "vector.h"
  28. #include "povproto.h"
  29.  
  30. METHODS Disc_Methods =
  31.   { 
  32.   All_Disc_Intersections,
  33.   Inside_Disc, Disc_Normal,
  34.   Copy_Disc, Translate_Disc, Rotate_Disc, Scale_Disc, Transform_Disc,
  35.   Invert_Disc, Destroy_Disc
  36. };
  37.  
  38. extern long Ray_Disc_Tests, Ray_Disc_Tests_Succeeded;
  39.  
  40. int All_Disc_Intersections (Object, Ray, Depth_Stack)
  41. OBJECT *Object;
  42. RAY *Ray;
  43. ISTACK *Depth_Stack;
  44.   {
  45.   DBL Depth;
  46.   VECTOR IPoint;
  47.   register int Intersection_Found;
  48.  
  49.   Intersection_Found = FALSE;
  50.  
  51.   if (Intersect_Disc (Ray, (DISC *)Object, &Depth))
  52.     {
  53.     VScale (IPoint, Ray->Direction, Depth);
  54.     VAddEq (IPoint, Ray->Initial);
  55.  
  56.     if (Point_In_Clip (&IPoint, Object->Clip))
  57.       {
  58.       push_entry(Depth,IPoint,Object,Depth_Stack);
  59.       Intersection_Found = TRUE;
  60.       }
  61.     }
  62.   return (Intersection_Found);
  63.   }
  64.  
  65. int Intersect_Disc (Ray, disc, Depth)
  66. RAY *Ray;
  67. DISC *disc;
  68. DBL *Depth;
  69.   {
  70.   DBL t1, t2, len, tmpf;
  71.   VECTOR P, D, tmpv;
  72.  
  73.   Ray_Disc_Tests++;
  74.  
  75.   /* Transform the point into the discs space */
  76.   MInvTransPoint(&P, &Ray->Initial, disc->Trans);
  77.   MInvTransDirection(&D, &Ray->Direction, disc->Trans);
  78.  
  79.   *Depth = HUGE_VAL;
  80.  
  81.   VLength(len, D);
  82.   VInverseScaleEq(D, len);
  83.  
  84.   /* Do the normal ray-plane intersection */
  85.   VDot(t1, disc->normal, D);
  86.   if (fabs(t1) < 1.0e-10)
  87.     return 0;
  88.   VDot(t2, disc->normal, P);
  89.   t2 = -(t2 + disc->d) / t1;
  90.   if (t2 < 0)
  91.     return 0;
  92.   VScale(tmpv, D, t2);
  93.   VAddEq(tmpv, P);
  94.   VSub(tmpv, tmpv, disc->center);
  95.   VDot(tmpf, tmpv, tmpv);
  96.   if (tmpf < disc->iradius2 || tmpf > disc->oradius2)
  97.     return 0;
  98.   else
  99.     *Depth = t2 / len;
  100.  
  101.   if (*Depth < Small_Tolerance || *Depth > Max_Distance)
  102.     return FALSE;
  103.  
  104.   Ray_Disc_Tests_Succeeded++;
  105.   return TRUE;
  106.   }
  107.  
  108. int Inside_Disc (IPoint, Object)
  109. VECTOR *IPoint;
  110. OBJECT *Object;
  111.   {
  112.   VECTOR New_Point;
  113.   DISC *disc = (DISC *) Object;
  114.   DBL tmpf, offset = (disc->Inverted ? -EPSILON : EPSILON);
  115.  
  116.   /* Transform the point into the discs space */
  117.   MInvTransPoint(&New_Point, IPoint, disc->Trans);
  118.  
  119.   VDot(tmpf, New_Point, disc->normal);
  120.   tmpf += disc->d;
  121.   if (tmpf+offset > 0)
  122.     return disc->Inverted;
  123.   else
  124.     return 1 - disc->Inverted;
  125.   }
  126.  
  127. void Disc_Normal (Result, Object, IPoint)
  128. OBJECT *Object;
  129. VECTOR *Result, *IPoint;
  130.   {
  131.   DISC *disc = (DISC *) Object;
  132.   MTransNormal(Result, &disc->normal, disc->Trans);
  133.   VNormalize(*Result, *Result);
  134.   }
  135.  
  136. void *Copy_Disc (Object)
  137. OBJECT *Object;
  138.   {
  139.   DISC *New;
  140.  
  141.   New  = Create_Disc();
  142.   *New = *((DISC *) Object);
  143.  
  144.   New->Trans = Copy_Transform(((DISC *)Object)->Trans);
  145.  
  146.   return (New);
  147.   }
  148.  
  149. void Translate_Disc (Object, Vector)
  150. OBJECT *Object;
  151. VECTOR *Vector;
  152.   {
  153.   TRANSFORM Trans;
  154.  
  155.   Compute_Translation_Transform(&Trans, Vector);
  156.   Transform_Disc(Object, &Trans);
  157.   }
  158.  
  159. void Rotate_Disc (Object, Vector)
  160. OBJECT *Object;
  161. VECTOR *Vector;
  162.   {
  163.   TRANSFORM Trans;
  164.   Compute_Rotation_Transform(&Trans, Vector);
  165.   Transform_Disc(Object, &Trans);
  166.   }
  167.  
  168. void Scale_Disc (Object, Vector)
  169. OBJECT *Object;
  170. VECTOR *Vector;
  171.   {
  172.   TRANSFORM Trans;
  173.  
  174.   Compute_Scaling_Transform(&Trans, Vector);
  175.   Transform_Disc(Object, &Trans);
  176.   }
  177.  
  178. void Invert_Disc (Object)
  179. OBJECT *Object;
  180.   {
  181.   ((DISC *)Object)->Inverted = 1 - ((DISC *)Object)->Inverted;
  182.   }
  183.  
  184. void Transform_Disc (Object, Trans)
  185. OBJECT *Object;
  186. TRANSFORM *Trans;
  187.   {
  188.   DISC *Disc = (DISC *)Object;
  189.   VECTOR lengths;
  190.   DBL len;
  191.  
  192.   Compose_Transforms(Disc->Trans, Trans);
  193.  
  194.   /* Recalculate the bounds */
  195.   len = sqrt(Disc->oradius2);
  196.   Make_Vector(&lengths, len, len, len);
  197.   VSub(Disc->Bounds.Lower_Left, Disc->center, lengths);
  198.   VScale(Disc->Bounds.Lengths, lengths, 2.0);
  199.   recompute_bbox(&Disc->Bounds, Disc->Trans);
  200.   }
  201.  
  202. DISC *Create_Disc ()
  203.   {
  204.   DISC *New;
  205.  
  206.   if ((New = (DISC *) malloc (sizeof (DISC))) == NULL)
  207.     MAError ("disc");
  208.  
  209.   INIT_OBJECT_FIELDS(New, DISC_OBJECT, &Disc_Methods)
  210.     Make_Vector (&(New->center), 0.0, 0.0, 0.0);
  211.   Make_Vector (&(New->normal), 0.0, 1.0, 0.0);
  212.   New->iradius2 = 0.0;
  213.   New->oradius2 = 1.0;
  214.   New->d = 0.0;
  215.   New->Trans = Create_Transform();
  216.   New->Inverted = 0;
  217.  
  218.   /* Default bounds */
  219.   Make_Vector(&New->Bounds.Lower_Left, -1.0, -EPSILON, -1.0);
  220.   Make_Vector(&New->Bounds.Lengths, 2.0, 2*EPSILON, 2.0);
  221.  
  222.   return New;
  223.   }
  224.  
  225. void Destroy_Disc (Object)
  226. OBJECT *Object;
  227.   {
  228.   Destroy_Transform(((DISC *)Object)->Trans);
  229.   free (Object);
  230.   }
  231.