home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: Graphics / Graphics.zip / povsrc31.zip / boxes.c < prev    next >
C/C++ Source or Header  |  2001-01-31  |  22KB  |  1,129 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(tm) Ray Tracer
  9. *  Copyright 1996,1999 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.
  16. *  If POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  17. *  Team Coordinator by email to team-coord@povray.org or visit us on the web at
  18. *  http://www.povray.org. The latest version of POV-Ray may be found at this site.
  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 "povray.h"
  28. #include "vector.h"
  29. #include "povproto.h"
  30. #include "bbox.h"
  31. #include "boxes.h"
  32. #include "matrices.h"
  33. #include "objects.h"
  34.  
  35.  
  36.  
  37. /*****************************************************************************
  38. * Local preprocessor defines
  39. ******************************************************************************/
  40.  
  41. /* Minimal intersection depth. */
  42.  
  43. #define DEPTH_TOLERANCE 1.0e-6
  44.  
  45. /* Two values are equal if their difference is small than CLOSE_TOLERANCE. */
  46.  
  47. #define CLOSE_TOLERANCE 1.0e-6
  48.  
  49. /* Side hit. */
  50.  
  51. #define SIDE_X_0 1
  52. #define SIDE_X_1 2
  53. #define SIDE_Y_0 3
  54. #define SIDE_Y_1 4
  55. #define SIDE_Z_0 5
  56. #define SIDE_Z_1 6
  57.  
  58.  
  59.  
  60. /*****************************************************************************
  61. * Static functions
  62. ******************************************************************************/
  63. static int  All_Box_Intersections (OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack);
  64. static int  Inside_Box (VECTOR point, OBJECT *Object);
  65. static void Box_Normal (VECTOR Result, OBJECT *Object, INTERSECTION *Inter);
  66. static void Box_UVCoord (UV_VECT Result, OBJECT *Object, INTERSECTION *Inter);
  67. static void Translate_Box (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
  68. static void Rotate_Box (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
  69. static void Scale_Box (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
  70. static void Transform_Box (OBJECT *Object, TRANSFORM *Trans);
  71. static void Invert_Box (OBJECT *Object);
  72.  
  73.  
  74.  
  75. /*****************************************************************************
  76. * Local variables
  77. ******************************************************************************/
  78.  
  79. METHODS Box_Methods =
  80. {
  81.   All_Box_Intersections,
  82.   Inside_Box, Box_Normal, Box_UVCoord,
  83.   (COPY_METHOD)Copy_Box, Translate_Box, Rotate_Box, Scale_Box, Transform_Box,
  84.   Invert_Box, Destroy_Box
  85. };
  86.  
  87.  
  88.  
  89. /*****************************************************************************
  90. *
  91. * FUNCTION
  92. *
  93. *   All_Box_Intersections
  94. *
  95. * INPUT
  96. *
  97. * OUTPUT
  98. *
  99. * RETURNS
  100. *
  101. * AUTHOR
  102. *
  103. *   Alexander Enzmann
  104. *
  105. * DESCRIPTION
  106. *
  107. *   -
  108. *
  109. * CHANGES
  110. *
  111. *   -
  112. *
  113. ******************************************************************************/
  114.  
  115. static int All_Box_Intersections(OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack)
  116. {
  117.   int Intersection_Found;
  118.   int Side1, Side2;
  119.   DBL Depth1, Depth2;
  120.   VECTOR IPoint;
  121.  
  122.   Increase_Counter(stats[Ray_Box_Tests]);
  123.  
  124.   Intersection_Found = FALSE;
  125.  
  126.   if (Intersect_Box(Ray, (BOX *)Object, &Depth1, &Depth2, &Side1, &Side2))
  127.   {
  128.     if (Depth1 > DEPTH_TOLERANCE)
  129.     {
  130.       VEvaluateRay(IPoint, Ray->Initial, Depth1, Ray->Direction);
  131.  
  132.       if (Point_In_Clip(IPoint, Object->Clip))
  133.       {
  134.         push_entry_i1(Depth1,IPoint,Object,Side1,Depth_Stack);
  135.  
  136.         Intersection_Found = TRUE;
  137.       }
  138.     }
  139.  
  140.     VEvaluateRay(IPoint, Ray->Initial, Depth2, Ray->Direction);
  141.  
  142.     if (Point_In_Clip(IPoint, Object->Clip))
  143.     {
  144.       push_entry_i1(Depth2,IPoint,Object,Side2,Depth_Stack);
  145.  
  146.       Intersection_Found = TRUE;
  147.     }
  148.   }
  149.  
  150.   if (Intersection_Found)
  151.   {
  152.     Increase_Counter(stats[Ray_Box_Tests_Succeeded]);
  153.   }
  154.  
  155.   return (Intersection_Found);
  156. }
  157.  
  158.  
  159.  
  160. /*****************************************************************************
  161. *
  162. * FUNCTION
  163. *
  164. *   Intersect_Box
  165. *
  166. * INPUT
  167. *
  168. * OUTPUT
  169. *
  170. * RETURNS
  171. *
  172. * AUTHOR
  173. *
  174. *   Alexander Enzmann
  175. *
  176. * DESCRIPTION
  177. *
  178. *   -
  179. *
  180. * CHANGES
  181. *
  182. *   Sep 1994 : Added code to decide which side was hit in the case
  183. *              intersection points are close to each other. This removes
  184. *              some ugly artefacts one could observe at the corners of
  185. *              boxes due to the usage of the wrong normal vector. [DB]
  186. *
  187. ******************************************************************************/
  188.  
  189. int Intersect_Box(RAY *Ray, BOX *box, DBL *Depth1, DBL  *Depth2, int *Side1, int  *Side2)
  190. {
  191.   int smin = 0, smax = 0;    /* Side hit for min/max intersection. */
  192.   DBL t, tmin, tmax;
  193.   VECTOR P, D;
  194.  
  195.   /* Transform the point into the boxes space */
  196.  
  197.   if (box->Trans != NULL)
  198.   {
  199.     MInvTransPoint(P, Ray->Initial, box->Trans);
  200.     MInvTransDirection(D, Ray->Direction, box->Trans);
  201.   }
  202.   else
  203.   {
  204.     Assign_Vector(P, Ray->Initial);
  205.     Assign_Vector(D, Ray->Direction);
  206.   }
  207.  
  208.   tmin = 0.0;
  209.   tmax = BOUND_HUGE;
  210.  
  211.   /*
  212.    * Sides first.
  213.    */
  214.  
  215.   if (D[X] < -EPSILON)
  216.   {
  217.     t = (box->bounds[0][X] - P[X]) / D[X];
  218.  
  219.     if (t < tmin) return(FALSE);
  220.  
  221.     if (t <= tmax)
  222.     {
  223.       smax = SIDE_X_0;
  224.       tmax = t;
  225.     }
  226.  
  227.     t = (box->bounds[1][X] - P[X]) / D[X];
  228.  
  229.     if (t >= tmin)
  230.     {
  231.       if (t > tmax) return(FALSE);
  232.  
  233.       smin = SIDE_X_1;
  234.       tmin = t;
  235.     }
  236.   }
  237.   else
  238.   {
  239.     if (D[X] > EPSILON)
  240.     {
  241.       t = (box->bounds[1][X] - P[X]) / D[X];
  242.  
  243.       if (t < tmin) return(FALSE);
  244.  
  245.       if (t <= tmax)
  246.       {
  247.         smax = SIDE_X_1;
  248.         tmax = t;
  249.       }
  250.  
  251.       t = (box->bounds[0][X] - P[X]) / D[X];
  252.  
  253.       if (t >= tmin)
  254.       {
  255.         if (t > tmax) return(FALSE);
  256.  
  257.         smin = SIDE_X_0;
  258.         tmin = t;
  259.       }
  260.     }
  261.     else
  262.     {
  263.       if ((P[X] < box->bounds[0][X]) || (P[X] > box->bounds[1][X]))
  264.       {
  265.         return(FALSE);
  266.       }
  267.     }
  268.   }
  269.  
  270.   /*
  271.    * Check Top/Bottom.
  272.    */
  273.  
  274.   if (D[Y] < -EPSILON)
  275.   {
  276.     t = (box->bounds[0][Y] - P[Y]) / D[Y];
  277.  
  278.     if (t < tmin) return(FALSE);
  279.  
  280.     if (t <= tmax - CLOSE_TOLERANCE)
  281.     {
  282.       smax = SIDE_Y_0;
  283.       tmax = t;
  284.     }
  285.     else
  286.     {
  287.       /*
  288.        * If intersection points are close to each other find out
  289.        * which side to use, i.e. is most probably hit. [DB 9/94]
  290.        */
  291.  
  292.       if (t <= tmax + CLOSE_TOLERANCE)
  293.       {
  294.         if (-D[Y] > fabs(D[X])) smax = SIDE_Y_0;
  295.       }
  296.     }
  297.  
  298.     t = (box->bounds[1][Y] - P[Y]) / D[Y];
  299.  
  300.     if (t >= tmin + CLOSE_TOLERANCE)
  301.     {
  302.       if (t > tmax) return(FALSE);
  303.  
  304.       smin = SIDE_Y_1;
  305.       tmin = t;
  306.     }
  307.     else
  308.     {
  309.       /*
  310.        * If intersection points are close to each other find out
  311.        * which side to use, i.e. is most probably hit. [DB 9/94]
  312.        */
  313.  
  314.       if (t >= tmin - CLOSE_TOLERANCE)
  315.       {
  316.         if (-D[Y] > fabs(D[X])) smin = SIDE_Y_1;
  317.       }
  318.     }
  319.   }
  320.   else
  321.   {
  322.     if (D[Y] > EPSILON)
  323.     {
  324.       t = (box->bounds[1][Y] - P[Y]) / D[Y];
  325.  
  326.       if (t < tmin) return(FALSE);
  327.  
  328.       if (t <= tmax - CLOSE_TOLERANCE)
  329.       {
  330.         smax = SIDE_Y_1;
  331.         tmax = t;
  332.       }
  333.       else
  334.       {
  335.         /*
  336.          * If intersection points are close to each other find out
  337.          * which side to use, i.e. is most probably hit. [DB 9/94]
  338.          */
  339.  
  340.         if (t <= tmax + CLOSE_TOLERANCE)
  341.         {
  342.           if (D[Y] > fabs(D[X])) smax = SIDE_Y_1;
  343.         }
  344.       }
  345.  
  346.       t = (box->bounds[0][Y] - P[Y]) / D[Y];
  347.  
  348.       if (t >= tmin + CLOSE_TOLERANCE)
  349.       {
  350.         if (t > tmax) return(FALSE);
  351.  
  352.         smin = SIDE_Y_0;
  353.         tmin = t;
  354.       }
  355.       else
  356.       {
  357.         /*
  358.          * If intersection points are close to each other find out
  359.          * which side to use, i.e. is most probably hit. [DB 9/94]
  360.          */
  361.  
  362.         if (t >= tmin - CLOSE_TOLERANCE)
  363.         {
  364.           if (D[Y] > fabs(D[X])) smin = SIDE_Y_0;
  365.         }
  366.       }
  367.     }
  368.     else
  369.     {
  370.       if ((P[Y] < box->bounds[0][Y]) || (P[Y] > box->bounds[1][Y]))
  371.       {
  372.         return(FALSE);
  373.       }
  374.     }
  375.   }
  376.  
  377.   /* Now front/back */
  378.  
  379.   if (D[Z] < -EPSILON)
  380.   {
  381.     t = (box->bounds[0][Z] - P[Z]) / D[Z];
  382.  
  383.     if (t < tmin) return(FALSE);
  384.  
  385.     if (t <= tmax - CLOSE_TOLERANCE)
  386.     {
  387.       smax = SIDE_Z_0;
  388.       tmax = t;
  389.     }
  390.     else
  391.     {
  392.       /*
  393.        * If intersection points are close to each other find out
  394.        * which side to use, i.e. is most probably hit. [DB 9/94]
  395.        */
  396.  
  397.       if (t <= tmax + CLOSE_TOLERANCE)
  398.       {
  399.         switch (smax)
  400.         {
  401.           case SIDE_X_0 :
  402.           case SIDE_X_1 : if (-D[Z] > fabs(D[X])) smax = SIDE_Z_0; break;
  403.  
  404.           case SIDE_Y_0 :
  405.           case SIDE_Y_1 : if (-D[Z] > fabs(D[Y])) smax = SIDE_Z_0; break;
  406.         }
  407.       }
  408.     }
  409.  
  410.     t = (box->bounds[1][Z] - P[Z]) / D[Z];
  411.  
  412.     if (t >= tmin + CLOSE_TOLERANCE)
  413.     {
  414.       if (t > tmax) return(FALSE);
  415.  
  416.       smin = SIDE_Z_1;
  417.       tmin = t;
  418.     }
  419.     else
  420.     {
  421.       /*
  422.        * If intersection points are close to each other find out
  423.        * which side to use, i.e. is most probably hit. [DB 9/94]
  424.        */
  425.  
  426.       if (t >= tmin - CLOSE_TOLERANCE)
  427.       {
  428.         switch (smin)
  429.         {
  430.           case SIDE_X_0 :
  431.           case SIDE_X_1 : if (-D[Z] > fabs(D[X])) smin = SIDE_Z_1; break;
  432.  
  433.           case SIDE_Y_0 :
  434.           case SIDE_Y_1 : if (-D[Z] > fabs(D[Y])) smin = SIDE_Z_1; break;
  435.         }
  436.       }
  437.     }
  438.   }
  439.   else
  440.   {
  441.     if (D[Z] > EPSILON)
  442.     {
  443.       t = (box->bounds[1][Z] - P[Z]) / D[Z];
  444.  
  445.       if (t < tmin) return(FALSE);
  446.  
  447.       if (t <= tmax - CLOSE_TOLERANCE)
  448.       {
  449.         smax = SIDE_Z_1;
  450.         tmax = t;
  451.       }
  452.       else
  453.       {
  454.         /*
  455.          * If intersection points are close to each other find out
  456.          * which side to use, i.e. is most probably hit. [DB 9/94]
  457.          */
  458.  
  459.         if (t <= tmax + CLOSE_TOLERANCE)
  460.         {
  461.           switch (smax)
  462.           {
  463.             case SIDE_X_0 :
  464.             case SIDE_X_1 : if (D[Z] > fabs(D[X])) smax = SIDE_Z_1; break;
  465.  
  466.             case SIDE_Y_0 :
  467.             case SIDE_Y_1 : if (D[Z] > fabs(D[Y])) smax = SIDE_Z_1; break;
  468.           }
  469.         }
  470.       }
  471.  
  472.       t = (box->bounds[0][Z] - P[Z]) / D[Z];
  473.  
  474.       if (t >= tmin + CLOSE_TOLERANCE)
  475.       {
  476.         if (t > tmax) return(FALSE);
  477.  
  478.         smin = SIDE_Z_0;
  479.         tmin = t;
  480.       }
  481.       else
  482.       {
  483.         /*
  484.          * If intersection points are close to each other find out
  485.          * which side to use, i.e. is most probably hit. [DB 9/94]
  486.          */
  487.  
  488.         if (t >= tmin - CLOSE_TOLERANCE)
  489.         {
  490.           switch (smin)
  491.           {
  492.             case SIDE_X_0 :
  493.             case SIDE_X_1 : if (D[Z] > fabs(D[X])) smin = SIDE_Z_0; break;
  494.  
  495.             case SIDE_Y_0 :
  496.             case SIDE_Y_1 : if (D[Z] > fabs(D[Y])) smin = SIDE_Z_0; break;
  497.           }
  498.         }
  499.       }
  500.     }
  501.     else
  502.     {
  503.       if ((P[Z] < box->bounds[0][Z]) || (P[Z] > box->bounds[1][Z]))
  504.       {
  505.         return(FALSE);
  506.       }
  507.     }
  508.   }
  509.  
  510.   if (tmax < DEPTH_TOLERANCE)
  511.   {
  512.     return (FALSE);
  513.   }
  514.  
  515.   *Depth1 = tmin;
  516.   *Depth2 = tmax;
  517.  
  518.   *Side1 = smin;
  519.   *Side2 = smax;
  520.  
  521.   return(TRUE);
  522. }
  523.  
  524.  
  525.  
  526. /*****************************************************************************
  527. *
  528. * FUNCTION
  529. *
  530. *   Inside_Box
  531. *
  532. * INPUT
  533. *
  534. * OUTPUT
  535. *
  536. * RETURNS
  537. *
  538. * AUTHOR
  539. *
  540. *   Alexander Enzmann
  541. *
  542. * DESCRIPTION
  543. *
  544. *   -
  545. *
  546. * CHANGES
  547. *
  548. *   -
  549. *
  550. ******************************************************************************/
  551.  
  552. static int Inside_Box(VECTOR IPoint, OBJECT *Object)
  553. {
  554.   VECTOR New_Point;
  555.   BOX *box = (BOX *) Object;
  556.  
  557.   /* Transform the point into box space. */
  558.  
  559.   if (box->Trans != NULL)
  560.   {
  561.     MInvTransPoint(New_Point, IPoint, box->Trans);
  562.   }
  563.   else
  564.   {
  565.     Assign_Vector(New_Point,IPoint);
  566.   }
  567.  
  568.   /* Test to see if we are outside the box. */
  569.  
  570.   if ((New_Point[X] < box->bounds[0][X]) || (New_Point[X] > box->bounds[1][X]))
  571.   {
  572.     return (Test_Flag(box, INVERTED_FLAG));
  573.   }
  574.  
  575.   if ((New_Point[Y] < box->bounds[0][Y]) || (New_Point[Y] > box->bounds[1][Y]))
  576.   {
  577.     return (Test_Flag(box, INVERTED_FLAG));
  578.   }
  579.  
  580.   if ((New_Point[Z] < box->bounds[0][Z]) || (New_Point[Z] > box->bounds[1][Z]))
  581.   {
  582.     return (Test_Flag(box, INVERTED_FLAG));
  583.   }
  584.  
  585.   /* Inside the box. */
  586.  
  587.   return (!Test_Flag(box, INVERTED_FLAG));
  588. }
  589.  
  590.  
  591.  
  592. /*****************************************************************************
  593. *
  594. * FUNCTION
  595. *
  596. *   Box_Normal
  597. *
  598. * INPUT
  599. *
  600. * OUTPUT
  601. *
  602. * RETURNS
  603. *
  604. * AUTHOR
  605. *
  606. *   Alexander Enzmann
  607. *
  608. * DESCRIPTION
  609. *
  610. *   -
  611. *
  612. * CHANGES
  613. *
  614. *   -
  615. *
  616. ******************************************************************************/
  617.  
  618. static void Box_Normal(VECTOR Result, OBJECT *Object, INTERSECTION *Inter)
  619. {
  620.   switch (Inter->i1)
  621.   {
  622.     case SIDE_X_0: Make_Vector(Result, -1.0,  0.0,  0.0); break;
  623.     case SIDE_X_1: Make_Vector(Result,  1.0,  0.0,  0.0); break;
  624.     case SIDE_Y_0: Make_Vector(Result,  0.0, -1.0,  0.0); break;
  625.     case SIDE_Y_1: Make_Vector(Result,  0.0,  1.0,  0.0); break;
  626.     case SIDE_Z_0: Make_Vector(Result,  0.0,  0.0, -1.0); break;
  627.     case SIDE_Z_1: Make_Vector(Result,  0.0,  0.0,  1.0); break;
  628.  
  629.     default: Error("Unknown box side in Box_Normal().\n");
  630.   }
  631.  
  632.   /* Transform the point into the boxes space. */
  633.  
  634.   if (((BOX *)Object)->Trans != NULL)
  635.   {
  636.     MTransNormal(Result, Result, ((BOX *)Object)->Trans);
  637.  
  638.     VNormalize(Result, Result);
  639.   }
  640. }
  641.  
  642.  
  643.  
  644. /*****************************************************************************
  645. *
  646. * FUNCTION
  647. *
  648. *   Translate_Box
  649. *
  650. * INPUT
  651. *
  652. * OUTPUT
  653. *
  654. * RETURNS
  655. *
  656. * AUTHOR
  657. *
  658. *   Alexander Enzmann
  659. *
  660. * DESCRIPTION
  661. *
  662. *   -
  663. *
  664. * CHANGES
  665. *
  666. *   -
  667. *
  668. ******************************************************************************/
  669.  
  670. static void Translate_Box(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
  671. {
  672.   if (((BOX *)Object)->Trans == NULL)
  673.   {
  674.     VAddEq(((BOX *)Object)->bounds[0], Vector);
  675.  
  676.     VAddEq(((BOX *)Object)->bounds[1], Vector);
  677.  
  678.     Compute_Box_BBox((BOX *)Object);
  679.   }
  680.   else
  681.   {
  682.     Transform_Box(Object, Trans);
  683.   }
  684. }
  685.  
  686.  
  687.  
  688. /*****************************************************************************
  689. *
  690. * FUNCTION
  691. *
  692. *   Rotate_Box
  693. *
  694. * INPUT
  695. *
  696. * OUTPUT
  697. *
  698. * RETURNS
  699. *
  700. * AUTHOR
  701. *
  702. *   Alexander Enzmann
  703. *
  704. * DESCRIPTION
  705. *
  706. *   -
  707. *
  708. * CHANGES
  709. *
  710. *   -
  711. *
  712. ******************************************************************************/
  713.  
  714. static void Rotate_Box(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
  715. {
  716.   Transform_Box(Object, Trans);
  717. }
  718.  
  719.  
  720.  
  721. /*****************************************************************************
  722. *
  723. * FUNCTION
  724. *
  725. *   Scale_Box
  726. *
  727. * INPUT
  728. *
  729. * OUTPUT
  730. *
  731. * RETURNS
  732. *
  733. * AUTHOR
  734. *
  735. *   Alexander Enzmann
  736. *
  737. * DESCRIPTION
  738. *
  739. *   -
  740. *
  741. * CHANGES
  742. *
  743. *   -
  744. *
  745. ******************************************************************************/
  746.  
  747. static void Scale_Box(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
  748. {
  749.   DBL temp;
  750.   BOX *Box = (BOX *)Object;
  751.  
  752.   if (((BOX *)Object)->Trans == NULL)
  753.   {
  754.     VEvaluateEq(Box->bounds[0], Vector);
  755.     VEvaluateEq(Box->bounds[1], Vector);
  756.  
  757.     if (Box->bounds[0][X] > Box->bounds[1][X])
  758.     {
  759.       temp = Box->bounds[0][X];
  760.  
  761.       Box->bounds[0][X] = Box->bounds[1][X];
  762.       Box->bounds[1][X] = temp;
  763.     }
  764.  
  765.     if (Box->bounds[0][Y] > Box->bounds[1][Y])
  766.     {
  767.       temp = Box->bounds[0][Y];
  768.  
  769.       Box->bounds[0][Y] = Box->bounds[1][Y];
  770.       Box->bounds[1][Y] = temp;
  771.     }
  772.  
  773.     if (Box->bounds[0][Z] > Box->bounds[1][Z])
  774.     {
  775.       temp = Box->bounds[0][Z];
  776.  
  777.       Box->bounds[0][Z] = Box->bounds[1][Z];
  778.       Box->bounds[1][Z] = temp;
  779.     }
  780.  
  781.     Compute_Box_BBox((BOX *)Object);
  782.   }
  783.   else
  784.   {
  785.     Transform_Box(Object, Trans);
  786.   }
  787. }
  788.  
  789.  
  790.  
  791. /*****************************************************************************
  792. *
  793. * FUNCTION
  794. *
  795. *   Invert_Box
  796. *
  797. * INPUT
  798. *
  799. * OUTPUT
  800. *
  801. * RETURNS
  802. *
  803. * AUTHOR
  804. *
  805. *   Alexander Enzmann
  806. *
  807. * DESCRIPTION
  808. *
  809. *   -
  810. *
  811. * CHANGES
  812. *
  813. *   -
  814. *
  815. ******************************************************************************/
  816.  
  817. static void Invert_Box(OBJECT *Object)
  818. {
  819.   Invert_Flag(Object, INVERTED_FLAG);
  820. }
  821.  
  822.  
  823.  
  824. /*****************************************************************************
  825. *
  826. * FUNCTION
  827. *
  828. *   Transform_Box
  829. *
  830. * INPUT
  831. *
  832. * OUTPUT
  833. *
  834. * RETURNS
  835. *
  836. * AUTHOR
  837. *
  838. *   Alexander Enzmann
  839. *
  840. * DESCRIPTION
  841. *
  842. *   -
  843. *
  844. * CHANGES
  845. *
  846. *   -
  847. *
  848. ******************************************************************************/
  849.  
  850. static void Transform_Box(OBJECT *Object, TRANSFORM *Trans)
  851. {
  852.   BOX *box = (BOX *)Object;
  853.  
  854.   if (box->Trans == NULL)
  855.   {
  856.     box->Trans = Create_Transform();
  857.   }
  858.  
  859.   Compose_Transforms(box->Trans, Trans);
  860.  
  861.   Compute_Box_BBox(box);
  862. }
  863.  
  864.  
  865.  
  866. /*****************************************************************************
  867. *
  868. * FUNCTION
  869. *
  870. *   Create_Box
  871. *
  872. * INPUT
  873. *
  874. * OUTPUT
  875. *
  876. * RETURNS
  877. *
  878. * AUTHOR
  879. *
  880. *   Alexander Enzmann
  881. *
  882. * DESCRIPTION
  883. *
  884. *   -
  885. *
  886. * CHANGES
  887. *
  888. *   -
  889. *
  890. ******************************************************************************/
  891.  
  892. BOX *Create_Box()
  893. {
  894.   BOX *New;
  895.  
  896.   New = (BOX *)POV_MALLOC(sizeof(BOX), "box");
  897.  
  898.   INIT_OBJECT_FIELDS(New, BOX_OBJECT, &Box_Methods)
  899.  
  900.   Make_Vector(New->bounds[0], -1.0, -1.0, -1.0);
  901.   Make_Vector(New->bounds[1],  1.0,  1.0,  1.0);
  902.  
  903.   Make_BBox(New->BBox, -1.0, -1.0, -1.0, 2.0, 2.0, 2.0);
  904.  
  905.   New->Trans = NULL;
  906.  
  907.   return (New);
  908. }
  909.  
  910.  
  911.  
  912. /*****************************************************************************
  913. *
  914. * FUNCTION
  915. *
  916. *   Copy_Box
  917. *
  918. * INPUT
  919. *
  920. * OUTPUT
  921. *
  922. * RETURNS
  923. *
  924. * AUTHOR
  925. *
  926. *   Alexander Enzmann
  927. *
  928. * DESCRIPTION
  929. *
  930. *   -
  931. *
  932. * CHANGES
  933. *
  934. *   -
  935. *
  936. ******************************************************************************/
  937.  
  938. BOX *Copy_Box(OBJECT *Object)
  939. {
  940.   BOX *New;
  941.  
  942.   New  = Create_Box();
  943.  
  944.   /* Copy box. */
  945.  
  946.   *New = *((BOX *)Object);
  947.  
  948.   New->Trans = Copy_Transform(((BOX *)Object)->Trans);
  949.  
  950.   return (New);
  951. }
  952.  
  953.  
  954.  
  955. /*****************************************************************************
  956. *
  957. * FUNCTION
  958. *
  959. *   Destroy_Box
  960. *
  961. * INPUT
  962. *
  963. * OUTPUT
  964. *
  965. * RETURNS
  966. *
  967. * AUTHOR
  968. *
  969. *   Alexander Enzmann
  970. *
  971. * DESCRIPTION
  972. *
  973. *   -
  974. *
  975. * CHANGES
  976. *
  977. *   -
  978. *
  979. ******************************************************************************/
  980.  
  981. void Destroy_Box(OBJECT *Object)
  982. {
  983.   Destroy_Transform(((BOX *)Object)->Trans);
  984.  
  985.   POV_FREE (Object);
  986. }
  987.  
  988.  
  989.  
  990. /*****************************************************************************
  991. *
  992. * FUNCTION
  993. *
  994. *   Compute_Box_BBox
  995. *
  996. * INPUT
  997. *
  998. *   Box - Box
  999. *
  1000. * OUTPUT
  1001. *
  1002. *   Box
  1003. *
  1004. * RETURNS
  1005. *
  1006. * AUTHOR
  1007. *
  1008. *   Dieter Bayer
  1009. *
  1010. * DESCRIPTION
  1011. *
  1012. *   Calculate the bounding box of a box.
  1013. *
  1014. * CHANGES
  1015. *
  1016. *   Aug 1994 : Creation.
  1017. *
  1018. ******************************************************************************/
  1019.  
  1020. void Compute_Box_BBox(BOX *Box)
  1021. {
  1022.   Assign_BBox_Vect(Box->BBox.Lower_Left, Box->bounds[0]);
  1023.  
  1024.   VSub(Box->BBox.Lengths, Box->bounds[1], Box->bounds[0]);
  1025.  
  1026.   if (Box->Trans != NULL)
  1027.   {
  1028.     Recompute_BBox(&Box->BBox, Box->Trans);
  1029.   }
  1030. }
  1031.  
  1032. /*****************************************************************************
  1033. *
  1034. * FUNCTION
  1035. *
  1036. *   Box_UVCoord
  1037. *
  1038. * INPUT
  1039. *
  1040. * OUTPUT
  1041. *
  1042. * RETURNS
  1043. *
  1044. * AUTHOR
  1045. *
  1046. *   Nathan Kopp
  1047. *
  1048. * DESCRIPTION
  1049. *
  1050. *        +-----+
  1051. *        ^  4  |
  1052. *        z     |
  1053. *  +-----+--x>-#--z>-+-<x--+
  1054. *  |     ^     |     |     |
  1055. *  |  1  y  5  |  2  |  6  |
  1056. *  |     |     |     |     |
  1057. *  +-----O--x>-+-----+-----+
  1058. *        |     |
  1059. *        |  3  |
  1060. *        +-----+
  1061. *
  1062. *  planes:
  1063. *  1: min x   2: max x
  1064. *  3: min y   4: max y
  1065. *  5: min z   6: max z
  1066. *
  1067. *  O : Origin
  1068. *  # : <1,1,0>
  1069. *
  1070. * CHANGES
  1071. *
  1072. *   -
  1073. *
  1074. ******************************************************************************/
  1075.  
  1076. static void Box_UVCoord(UV_VECT Result, OBJECT *Object, INTERSECTION *Inter)
  1077. {
  1078.   VECTOR P, Box_Diff;
  1079.   BOX *Box = (BOX *)Object;
  1080.  
  1081.   /* Transform the point into the cube's space */
  1082.   if (Box->Trans != NULL)
  1083.     MInvTransPoint(P, Inter->IPoint, Box->Trans);
  1084.   else
  1085.     Assign_Vector(P, Inter->IPoint);
  1086.  
  1087.   VSub(Box_Diff,Box->bounds[1],Box->bounds[0]);
  1088.  
  1089.   /* this line moves the bottom,left,front corner of the box to <0,0,0> */
  1090.   VSubEq(P, Box->bounds[0]);
  1091.   /* this line normalizes the face offsets */
  1092.   VDivEq(P, Box_Diff);
  1093.  
  1094.   /* if no normalize above, then we should use Box->UV_Trans and also
  1095.      inverse-transform the bounds */
  1096.  
  1097.   switch (Inter->i1)
  1098.   {
  1099.     case SIDE_X_0:
  1100.       Result[U] = -P[Z];
  1101.       Result[V] = P[Y];
  1102.       break;
  1103.     case SIDE_X_1:
  1104.       Result[U] = P[Z]+1.0;
  1105.       Result[V] = P[Y];
  1106.       break;
  1107.     case SIDE_Y_0:
  1108.       Result[U] = P[X];
  1109.       Result[V] = -P[Z];
  1110.       break;
  1111.     case SIDE_Y_1:
  1112.       Result[U] = P[X];
  1113.       Result[V] = P[Z]+1.0;
  1114.       break;
  1115.     case SIDE_Z_0:
  1116.       Result[U] = P[X];
  1117.       Result[V] = P[Y];
  1118.       break;
  1119.     case SIDE_Z_1:
  1120.       Result[U] = 3.0-P[X];
  1121.       Result[V] = P[Y];
  1122.       break;
  1123.  
  1124.     default: Error("Unknown box side in Box_Normal().\n");
  1125.   }
  1126.  
  1127. }
  1128.  
  1129.