home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: Graphics / Graphics.zip / pov22f.zip / source / boxes.c < prev    next >
C/C++ Source or Header  |  1993-10-13  |  11KB  |  418 lines

  1. /****************************************************************************
  2. *                boxes.c
  3. *
  4. *  This module implements the box primitive.
  5. *  This file was written by Alexander Enzmann.    He wrote the code for
  6. *  boxes 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 Box_Methods =
  31.   { 
  32.   All_Box_Intersections,
  33.   Inside_Box, Box_Normal,
  34.   Copy_Box, Translate_Box, Rotate_Box, Scale_Box, Transform_Box,
  35.   Invert_Box, Destroy_Box
  36. };
  37.  
  38. extern long Ray_Box_Tests, Ray_Box_Tests_Succeeded;
  39.  
  40. #define close(x, y) (fabs(x-y) < EPSILON ? 1 : 0)
  41.  
  42. int All_Box_Intersections (Object, Ray, Depth_Stack)
  43. OBJECT *Object;
  44. RAY *Ray;
  45. ISTACK *Depth_Stack;
  46.   {
  47.   DBL Depth1, Depth2;
  48.   VECTOR IPoint;
  49.   register int Intersection_Found;
  50.  
  51.   Intersection_Found = FALSE;
  52.  
  53.   if (Intersect_Boxx (Ray, (BOX *)Object, &Depth1, &Depth2))
  54.     {
  55.     VScale (IPoint, Ray->Direction, Depth1);
  56.     VAddEq (IPoint, Ray->Initial);
  57.  
  58.     if (Point_In_Clip (&IPoint, Object->Clip))
  59.       {
  60.       push_entry(Depth1,IPoint,Object,Depth_Stack);
  61.       Intersection_Found = TRUE;
  62.       }
  63.  
  64.     if (Depth2 != Depth1)
  65.       {
  66.       VScale (IPoint, Ray->Direction, Depth2);
  67.       VAddEq (IPoint, Ray->Initial);
  68.  
  69.       if (Point_In_Clip (&IPoint, Object->Clip))
  70.         {
  71.         push_entry(Depth2,IPoint,Object,Depth_Stack);
  72.         Intersection_Found = TRUE;
  73.         }
  74.       }
  75.     }
  76.   return (Intersection_Found);
  77.   }
  78.  
  79. int Intersect_Boxx (Ray, box, Depth1, Depth2)
  80. RAY *Ray;
  81. BOX *box;
  82. DBL *Depth1, *Depth2;
  83.   {
  84.   DBL t, tmin, tmax;
  85.   VECTOR P, D;
  86.  
  87.   Ray_Box_Tests++;
  88.  
  89.   /* Transform the point into the boxes space */
  90.   if (box->Trans != NULL) 
  91.     {
  92.     MInvTransPoint(&P, &Ray->Initial, box->Trans);
  93.     MInvTransDirection(&D, &Ray->Direction, box->Trans);
  94.     }
  95.   else 
  96.     {
  97.     P.x = Ray->Initial.x;
  98.     P.y = Ray->Initial.y;
  99.     P.z = Ray->Initial.z;
  100.     D.x = Ray->Direction.x;
  101.     D.y = Ray->Direction.y;
  102.     D.z = Ray->Direction.z;
  103.     }
  104.  
  105.     tmin = 0.0;
  106.   tmax = HUGE_VAL;
  107.  
  108.   /* Sides first */
  109.   if (D.x < -EPSILON) 
  110.     {
  111.     t = (box->bounds[0].x - P.x) / D.x;
  112.     if (t < tmin)
  113.       return 0;
  114.     if (t <= tmax)
  115.       tmax = t;
  116.     t = (box->bounds[1].x - P.x) / D.x;
  117.     if (t >= tmin) 
  118.       {
  119.       if (t > tmax)
  120.         return 0;
  121.       tmin = t;
  122.       }
  123.     }
  124.   else if (D.x > EPSILON) 
  125.     {
  126.     t = (box->bounds[1].x - P.x) / D.x;
  127.     if (t < tmin)
  128.       return 0;
  129.     if (t <= tmax)
  130.       tmax = t;
  131.     t = (box->bounds[0].x - P.x) / D.x;
  132.     if (t >= tmin) 
  133.       {
  134.       if (t > tmax)
  135.         return 0;
  136.       tmin = t;
  137.       }
  138.     }
  139.   else if (P.x < box->bounds[0].x || P.x > box->bounds[1].x)
  140.     return 0;
  141.  
  142.   /* Check Top/Bottom */
  143.   if (D.y < -EPSILON) 
  144.     {
  145.     t = (box->bounds[0].y - P.y) / D.y;
  146.     if (t < tmin)
  147.       return 0;
  148.     if (t <= tmax)
  149.       tmax = t;
  150.     t = (box->bounds[1].y - P.y) / D.y;
  151.     if (t >= tmin) 
  152.       {
  153.       if (t > tmax)
  154.         return 0;
  155.       tmin = t;
  156.       }
  157.     }
  158.   else if (D.y > EPSILON) 
  159.     {
  160.     t = (box->bounds[1].y - P.y) / D.y;
  161.     if (t < tmin)
  162.       return 0;
  163.     if (t <= tmax)
  164.       tmax = t;
  165.     t = (box->bounds[0].y - P.y) / D.y;
  166.     if (t >= tmin) 
  167.       {
  168.       if (t > tmax)
  169.         return 0;
  170.       tmin = t;
  171.       }
  172.     }
  173.   else if (P.y < box->bounds[0].y || P.y > box->bounds[1].y)
  174.     return 0;
  175.  
  176.   /* Now front/back */
  177.   if (D.z < -EPSILON) 
  178.     {
  179.     t = (box->bounds[0].z - P.z) / D.z;
  180.     if (t < tmin)
  181.       return 0;
  182.     if (t <= tmax)
  183.       tmax = t;
  184.     t = (box->bounds[1].z - P.z) / D.z;
  185.     if (t >= tmin) 
  186.       {
  187.       if (t > tmax)
  188.         return 0;
  189.       tmin = t;
  190.       }
  191.     }
  192.   else if (D.z > EPSILON) 
  193.     {
  194.     t = (box->bounds[1].z - P.z) / D.z;
  195.     if (t < tmin)
  196.       return 0;
  197.     if (t <= tmax)
  198.       tmax = t;
  199.     t = (box->bounds[0].z - P.z) / D.z;
  200.     if (t >= tmin) 
  201.       {
  202.       if (t > tmax)
  203.         return 0;
  204.       tmin = t;
  205.       }
  206.     }
  207.   else if (P.z < box->bounds[0].z || P.z > box->bounds[1].z)
  208.     return 0;
  209.  
  210.   *Depth1 = tmin;
  211.   *Depth2 = tmax;
  212.  
  213.   /* printf("Box intersects: %g, %g\n", *Depth1, *Depth2); */
  214.   if ((*Depth1 < Small_Tolerance) || (*Depth1 > Max_Distance))
  215.     if ((*Depth2 < Small_Tolerance) || (*Depth2 > Max_Distance))
  216.       return (FALSE);
  217.     else
  218.       *Depth1 = *Depth2;
  219.   else
  220.     if ((*Depth2 < Small_Tolerance) || (*Depth2 > Max_Distance))
  221.       *Depth2 = *Depth1;
  222.  
  223.   Ray_Box_Tests_Succeeded++;
  224.   return (TRUE);
  225.   }
  226.  
  227. int Inside_Box (IPoint, Object)
  228. VECTOR *IPoint;
  229. OBJECT *Object;
  230.   {
  231.   VECTOR New_Point;
  232.   BOX *box = (BOX *) Object;
  233.  
  234.   /* Transform the point into the boxes space */
  235.   if (box->Trans != NULL)
  236.     MInvTransPoint(&New_Point, IPoint, box->Trans);
  237.   else
  238.     New_Point = *IPoint;
  239.  
  240.   /* Test to see if we are inside the box */
  241.   if (New_Point.x < box->bounds[0].x || New_Point.x > box->bounds[1].x)
  242.     return ((int) box->Inverted);
  243.   if (New_Point.y < box->bounds[0].y || New_Point.y > box->bounds[1].y)
  244.     return ((int) box->Inverted);
  245.   if (New_Point.z < box->bounds[0].z || New_Point.z > box->bounds[1].z)
  246.     return ((int)box->Inverted);
  247.   /* Inside the box */
  248.   return 1-box->Inverted;
  249.   }
  250.  
  251. void Box_Normal (Result, Object, IPoint)
  252. OBJECT *Object;
  253. VECTOR *Result, *IPoint;
  254.   {
  255.   VECTOR New_Point;
  256.   BOX *box = (BOX *) Object;
  257.  
  258.   /* Transform the point into the boxes space */
  259.   if (box->Trans != NULL)
  260.     MInvTransPoint(&New_Point, IPoint, box->Trans);
  261.   else 
  262.     {
  263.     New_Point.x = IPoint->x;
  264.     New_Point.y = IPoint->y;
  265.     New_Point.z = IPoint->z;
  266.     }
  267.  
  268.     Result->x = 0.0; Result->y = 0.0; Result->z = 0.0;
  269.   if (close(New_Point.x, box->bounds[1].x))
  270.     Result->x = 1.0;
  271.   else if (close(New_Point.x, box->bounds[0].x))
  272.     Result->x = -1.0;
  273.   else if (close(New_Point.y, box->bounds[1].y))
  274.     Result->y = 1.0;
  275.   else if (close(New_Point.y, box->bounds[0].y))
  276.     Result->y = -1.0;
  277.   else if (close(New_Point.z, box->bounds[1].z))
  278.     Result->z = 1.0;
  279.   else if (close(New_Point.z, box->bounds[0].z))
  280.     Result->z = -1.0;
  281.   else 
  282.     {
  283.     /* Bad result, should we do something with it? */
  284.       Result->x = 1.0;
  285.     }
  286.  
  287.   /* Transform the point into the boxes space */
  288.   if (box->Trans != NULL) 
  289.     {
  290.     MTransNormal(Result, Result, box->Trans);
  291.     VNormalize(*Result, *Result);
  292.     }
  293.   }
  294.  
  295. void *Copy_Box (Object)
  296. OBJECT *Object;
  297.   {
  298.   BOX *New;
  299.  
  300.   New  = Create_Box();
  301.   *New = *((BOX *) Object);
  302.  
  303.   New->Trans = Copy_Transform(((BOX *)Object)->Trans);
  304.  
  305.   return (New);
  306.   }
  307.  
  308. void Translate_Box (Object, Vector)
  309. OBJECT *Object;
  310. VECTOR *Vector;
  311.   {
  312.   TRANSFORM Trans;
  313.  
  314.   if (((BOX *)Object)->Trans == NULL)
  315.     {
  316.     VAddEq(((BOX *)Object)->bounds[0], *Vector);
  317.     VAddEq(((BOX *)Object)->bounds[1], *Vector);
  318.     Object->Bounds.Lower_Left = ((BOX *)Object)->bounds[0];
  319.     }
  320.   else
  321.     {
  322.     Compute_Translation_Transform(&Trans, Vector);
  323.     Transform_Box(Object, &Trans);
  324.     }
  325.   }
  326.  
  327. void Rotate_Box (Object, Vector)
  328. OBJECT *Object;
  329. VECTOR *Vector;
  330.   {
  331.   TRANSFORM Trans;
  332.   Compute_Rotation_Transform(&Trans, Vector);
  333.   Transform_Box(Object, &Trans);
  334.   }
  335.  
  336. void Scale_Box (Object, Vector)
  337. OBJECT *Object;
  338. VECTOR *Vector;
  339.   {
  340.   BOX *Box = (BOX *)Object;
  341.   TRANSFORM Trans;
  342.   DBL temp;
  343.  
  344.   if (((BOX *)Object)->Trans == NULL)
  345.     {
  346.     VEvaluateEq(Box->bounds[0], *Vector);
  347.     VEvaluateEq(Box->bounds[1], *Vector);
  348.     if (Box->bounds[0].x > Box->bounds[1].x) {
  349.        temp = Box->bounds[0].x;
  350.        Box->bounds[0].x = Box->bounds[1].x;
  351.        Box->bounds[1].x = temp;
  352.        }
  353.     if (Box->bounds[0].y > Box->bounds[1].y) {
  354.        temp = Box->bounds[0].y;
  355.        Box->bounds[0].y = Box->bounds[1].y;
  356.        Box->bounds[1].y = temp;
  357.        }
  358.     if (Box->bounds[0].z > Box->bounds[1].z) {
  359.        temp = Box->bounds[0].z;
  360.        Box->bounds[0].z = Box->bounds[1].z;
  361.        Box->bounds[1].z = temp;
  362.        }
  363.     Box->Bounds.Lower_Left = Box->bounds[0];
  364.     VSub(Object->Bounds.Lengths, Box->bounds[1], Box->bounds[0]);
  365.     }
  366.   else
  367.     {
  368.     Compute_Scaling_Transform(&Trans, Vector);
  369.     Transform_Box(Object, &Trans);
  370.     }
  371.   }
  372.  
  373. void Invert_Box (Object)
  374. OBJECT *Object;
  375.   {
  376.   ((BOX *)Object)->Inverted = 1 - ((BOX *)Object)->Inverted;
  377.   }
  378.  
  379. void Transform_Box (Object, Trans)
  380. OBJECT *Object;
  381. TRANSFORM *Trans;
  382.   {
  383.   BOX *box = (BOX *)Object;
  384.   if (box->Trans == NULL)
  385.     box->Trans = Create_Transform();
  386.   Compose_Transforms(box->Trans, Trans);
  387.   Object->Bounds.Lower_Left = box->bounds[0];
  388.   VSub(Object->Bounds.Lengths, box->bounds[1], box->bounds[0]);
  389.   recompute_bbox(&Object->Bounds, box->Trans);
  390.   }
  391.  
  392. BOX *Create_Box ()
  393.   {
  394.   BOX *New;
  395.  
  396.   if ((New = (BOX *) malloc (sizeof (BOX))) == NULL)
  397.     MAError ("box");
  398.  
  399.   INIT_OBJECT_FIELDS(New, BOX_OBJECT, &Box_Methods)
  400.  
  401.     Make_Vector (&(New->bounds[0]), -1.0, -1.0, -1.0);
  402.   Make_Vector (&(New->bounds[1]),  1.0,  1.0,  1.0);
  403.   /* Recalculate the bounds */
  404.   Make_Vector(&New->Bounds.Lower_Left, -1.0, -1.0, -1.0);
  405.   Make_Vector(&New->Bounds.Lengths, 2.0, 2.0, 2.0);
  406.   /* Unlike HField, we don't always have a trans here */
  407.   New->Trans = NULL;
  408.   New->Inverted = FALSE;
  409.   return (New);
  410.   }
  411.  
  412. void Destroy_Box (Object)
  413. OBJECT *Object;
  414.   {
  415.   Destroy_Transform(((BOX *)Object)->Trans);
  416.   free (Object);
  417.   }
  418.