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

  1. /****************************************************************************
  2. *                boxes.c
  3. *
  4. *  This module implements the box primitive.
  5. *
  6. *  This file was written by Alexander Enzmann.    He wrote the code for
  7. *  boxes and generously provided us these enhancements.
  8. *
  9. *  from Persistence of Vision Raytracer 
  10. *  Copyright 1991 Persistence of Vision Team
  11. *---------------------------------------------------------------------------
  12. *  Copying, distribution and legal info is in the file povlegal.doc which
  13. *  should be distributed with this file. If povlegal.doc is not available
  14. *  or for more info please contact:
  15. *
  16. *       Drew Wells [POV-Team Leader] 
  17. *       CIS: 73767,1244  Internet: 73767.1244@compuserve.com
  18. *       Phone: (213) 254-4041
  19. * This program is based on the popular DKB raytracer version 2.12.
  20. * DKBTrace was originally written by David K. Buck.
  21. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  22. *
  23. *****************************************************************************/
  24.  
  25. #include "frame.h"
  26. #include "vector.h"
  27. #include "povproto.h"
  28.  
  29. METHODS Box_Methods =
  30. { Object_Intersect, All_Box_Intersections,
  31.    Inside_Box, Box_Normal,
  32.    Copy_Box,
  33.    Translate_Box, Rotate_Box,
  34.    Scale_Box, Invert_Box};
  35.  
  36. extern BOX *Get_Box_Shape();
  37.  
  38. extern RAY *VP_Ray;
  39. extern long Ray_Box_Tests, Ray_Box_Tests_Succeeded;
  40.  
  41. #define close(x, y) (fabs(x-y) < EPSILON ? 1 : 0)
  42.  
  43. int All_Box_Intersections (Object, Ray, Depth_Queue)
  44. OBJECT *Object;
  45. RAY *Ray;
  46. PRIOQ *Depth_Queue;
  47. {
  48.    DBL Depth1, Depth2;
  49.    VECTOR Intersection_Point;
  50.    INTERSECTION Local_Element;
  51.    register int Intersection_Found;
  52.    BOX *Shape = (BOX *) Object;
  53.  
  54.    Intersection_Found = FALSE;
  55.    if (Intersect_Boxx (Ray, Shape, &Depth1, &Depth2))
  56.    {
  57.       Local_Element.Depth = Depth1;
  58.       Local_Element.Object = Shape -> Parent_Object;
  59.       VScale (Intersection_Point, Ray -> Direction, Depth1);
  60.       VAdd (Intersection_Point, Intersection_Point, Ray -> Initial);
  61.       Local_Element.Point = Intersection_Point;
  62.       Local_Element.Shape = (SHAPE *)Shape;
  63.       pq_add (Depth_Queue, &Local_Element);
  64.       Intersection_Found = TRUE;
  65.  
  66.       if (Depth2 != Depth1)
  67.       {
  68.          Local_Element.Depth = Depth2;
  69.          Local_Element.Object = Shape -> Parent_Object;
  70.          VScale (Intersection_Point, Ray -> Direction, Depth2);
  71.          VAdd (Intersection_Point, Intersection_Point, Ray -> Initial);
  72.          Local_Element.Point = Intersection_Point;
  73.          Local_Element.Shape = (SHAPE *) Shape;
  74.          pq_add (Depth_Queue, &Local_Element);
  75.          Intersection_Found = TRUE;
  76.       }
  77.    }
  78.    return (Intersection_Found);
  79. }
  80.  
  81. int Intersect_Boxx (Ray, box, Depth1, Depth2)
  82. RAY *Ray;
  83. BOX *box;
  84. DBL *Depth1, *Depth2;
  85. {
  86.    DBL t, tmin, tmax;
  87.    VECTOR P, D;
  88.  
  89.    Ray_Box_Tests++;
  90.  
  91.    /* Transform the point into the boxes space */
  92.    if (box->Transform != NULL) {
  93.       MInverseTransformVector(&P, &Ray->Initial, box->Transform);
  94.       MInvTransVector(&D, &Ray->Direction, box->Transform);
  95.    }
  96.    else {
  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.       t = (box->bounds[0].x - P.x) / D.x;
  111.       if (t < tmin)
  112.          return 0;
  113.       if (t <= tmax)
  114.          tmax = t;
  115.       t = (box->bounds[1].x - P.x) / D.x;
  116.       if (t >= tmin) {
  117.          if (t > tmax)
  118.             return 0;
  119.          tmin = t;
  120.       }
  121.    }
  122.    else if (D.x > EPSILON) {
  123.       t = (box->bounds[1].x - P.x) / D.x;
  124.       if (t < tmin)
  125.          return 0;
  126.       if (t <= tmax)
  127.          tmax = t;
  128.       t = (box->bounds[0].x - P.x) / D.x;
  129.       if (t >= tmin) {
  130.          if (t > tmax)
  131.             return 0;
  132.          tmin = t;
  133.       }
  134.    }
  135.    else if (P.x < box->bounds[0].x || P.x > box->bounds[1].x)
  136.       return 0;
  137.  
  138.    /* Check Top/Bottom */
  139.    if (D.y < -EPSILON) {
  140.       t = (box->bounds[0].y - P.y) / D.y;
  141.       if (t < tmin)
  142.          return 0;
  143.       if (t <= tmax)
  144.          tmax = t;
  145.       t = (box->bounds[1].y - P.y) / D.y;
  146.       if (t >= tmin) {
  147.          if (t > tmax)
  148.             return 0;
  149.          tmin = t;
  150.       }
  151.    }
  152.    else if (D.y > EPSILON) {
  153.       t = (box->bounds[1].y - P.y) / D.y;
  154.       if (t < tmin)
  155.          return 0;
  156.       if (t <= tmax)
  157.          tmax = t;
  158.       t = (box->bounds[0].y - P.y) / D.y;
  159.       if (t >= tmin) {
  160.          if (t > tmax)
  161.             return 0;
  162.          tmin = t;
  163.       }
  164.    }
  165.    else if (P.y < box->bounds[0].y || P.y > box->bounds[1].y)
  166.       return 0;
  167.  
  168.    /* Now front/back */
  169.    if (D.z < -EPSILON) {
  170.       t = (box->bounds[0].z - P.z) / D.z;
  171.       if (t < tmin)
  172.          return 0;
  173.       if (t <= tmax)
  174.          tmax = t;
  175.       t = (box->bounds[1].z - P.z) / D.z;
  176.       if (t >= tmin) {
  177.          if (t > tmax)
  178.             return 0;
  179.          tmin = t;
  180.       }
  181.    }
  182.    else if (D.z > EPSILON) {
  183.       t = (box->bounds[1].z - P.z) / D.z;
  184.       if (t < tmin)
  185.          return 0;
  186.       if (t <= tmax)
  187.          tmax = t;
  188.       t = (box->bounds[0].z - P.z) / D.z;
  189.       if (t >= tmin) {
  190.          if (t > tmax)
  191.             return 0;
  192.          tmin = t;
  193.       }
  194.    }
  195.    else if (P.z < box->bounds[0].z || P.z > box->bounds[1].z)
  196.       return 0;
  197.  
  198.    *Depth1 = tmin;
  199.    *Depth2 = tmax;
  200.  
  201.    /* printf("Box intersects: %g, %g\n", *Depth1, *Depth2); */
  202.    if ((*Depth1 < Small_Tolerance) || (*Depth1 > Max_Distance))
  203.       if ((*Depth2 < Small_Tolerance) || (*Depth2 > Max_Distance))
  204.          return (FALSE);
  205.       else
  206.          *Depth1 = *Depth2;
  207.    else
  208.       if ((*Depth2 < Small_Tolerance) || (*Depth2 > Max_Distance))
  209.          *Depth2 = *Depth1;
  210.  
  211.    Ray_Box_Tests_Succeeded++;
  212.    return (TRUE);
  213. }
  214.  
  215. int Inside_Box (Test_Point, Object)
  216. VECTOR *Test_Point;
  217. OBJECT *Object;
  218. {
  219.    VECTOR New_Point;
  220.    BOX *box = (BOX *) Object;
  221.  
  222.    /* Transform the point into the boxes space */
  223.    if (box->Transform != NULL)
  224.       MInverseTransformVector(&New_Point, Test_Point, box->Transform);
  225.    else
  226.       New_Point = *Test_Point;
  227.  
  228.    /* Test to see if we are inside the box */
  229.    if (New_Point.x < box->bounds[0].x || New_Point.x > box->bounds[1].x)
  230.       return ((int) box->Inverted);
  231.    if (New_Point.y < box->bounds[0].y || New_Point.y > box->bounds[1].y)
  232.       return ((int) box->Inverted);
  233.    if (New_Point.z < box->bounds[0].z || New_Point.z > box->bounds[1].z)
  234.       return ((int)box->Inverted);
  235.    /* Inside the box */
  236.    return 1-box->Inverted;
  237. }
  238.  
  239. void Box_Normal (Result, Object, Intersection_Point)
  240. OBJECT *Object;
  241. VECTOR *Result, *Intersection_Point;
  242. {
  243.    VECTOR New_Point;
  244.    BOX *box = (BOX *) Object;
  245.  
  246.    /* Transform the point into the boxes space */
  247.    if (box->Transform != NULL)
  248.       MInverseTransformVector(&New_Point, Intersection_Point, box->Transform);
  249.    else {
  250.       New_Point.x = Intersection_Point->x;
  251.       New_Point.y = Intersection_Point->y;
  252.       New_Point.z = Intersection_Point->z;
  253.    }
  254.  
  255.       Result->x = 0.0; Result->y = 0.0; Result->z = 0.0;
  256.    if (close(New_Point.x, box->bounds[1].x))
  257.       Result->x = 1.0;
  258.    else if (close(New_Point.x, box->bounds[0].x))
  259.       Result->x = -1.0;
  260.    else if (close(New_Point.y, box->bounds[1].y))
  261.       Result->y = 1.0;
  262.    else if (close(New_Point.y, box->bounds[0].y))
  263.       Result->y = -1.0;
  264.    else if (close(New_Point.z, box->bounds[1].z))
  265.       Result->z = 1.0;
  266.    else if (close(New_Point.z, box->bounds[0].z))
  267.       Result->z = -1.0;
  268.    else {
  269.       /* Bad result, should we do something with it? */
  270.          Result->x = 1.0;
  271.    }
  272.  
  273.    /* Transform the point into the boxes space */
  274.    if (box->Transform != NULL) {
  275.       MTransNormal(Result, Result, box->Transform);
  276.       VNormalize(*Result, *Result);
  277.    }
  278. }
  279.  
  280. void *Copy_Box (Object)
  281. OBJECT *Object;
  282. {
  283.    BOX *New_Shape;
  284.    TRANSFORMATION *Tr;
  285.  
  286.    New_Shape = Get_Box_Shape ();
  287.    *New_Shape = *((BOX *) Object);
  288.    New_Shape -> Next_Object = NULL;
  289.  
  290.    /* Copy any associated transformation */
  291.    if (New_Shape->Transform != NULL) {
  292.       Tr = Get_Transformation();
  293.       memcpy(Tr, New_Shape->Transform, sizeof(TRANSFORMATION));
  294.       New_Shape->Transform = Tr;
  295.    }
  296.  
  297.    if (New_Shape->Shape_Texture != NULL)
  298.       New_Shape->Shape_Texture = Copy_Texture (New_Shape->Shape_Texture);
  299.  
  300.    return (New_Shape);
  301. }
  302.  
  303. void Translate_Box (Object, Vector)
  304. OBJECT *Object;
  305. VECTOR *Vector;
  306. {
  307.    TRANSFORMATION Transform;
  308.    BOX *box = (BOX *)Object;
  309.    if (box->Transform == NULL)
  310.       box->Transform = Get_Transformation();
  311.    Get_Translation_Transformation(&Transform, Vector);
  312.    Compose_Transformations(box->Transform, &Transform);
  313.  
  314.    Translate_Texture (&((BOX *) Object)->Shape_Texture, Vector);
  315. }
  316.  
  317. void Rotate_Box (Object, Vector)
  318. OBJECT *Object;
  319. VECTOR *Vector;
  320. {
  321.    TRANSFORMATION Transform;
  322.    BOX *box = (BOX *)Object;
  323.    if (box->Transform == NULL)
  324.       box->Transform = Get_Transformation();
  325.    Get_Rotation_Transformation(&Transform, Vector);
  326.    Compose_Transformations(box->Transform, &Transform);
  327.  
  328.    Rotate_Texture (&((BOX *) Object)->Shape_Texture, Vector);
  329. }
  330.  
  331. void Scale_Box (Object, Vector)
  332. OBJECT *Object;
  333. VECTOR *Vector;
  334. {
  335.    TRANSFORMATION Transform;
  336.    BOX *box = (BOX *)Object;
  337.    if (box->Transform == NULL)
  338.       box->Transform = Get_Transformation();
  339.    Get_Scaling_Transformation(&Transform, Vector);
  340.    Compose_Transformations(box->Transform, &Transform);
  341.  
  342.    Scale_Texture (&((BOX *) Object)->Shape_Texture, Vector);
  343. }
  344.  
  345.  
  346. void Invert_Box (Object)
  347. OBJECT *Object;
  348. {
  349.    ((BOX *) Object)->Inverted = 1 - ((BOX *)Object)->Inverted;
  350. }
  351.