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