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