1 /****************************************************************************
2  *               planes.cpp
3  *
4  * This module implements functions that manipulate planes.
5  *
6  * from Persistence of Vision(tm) Ray Tracer version 3.6.
7  * Copyright 1991-2003 Persistence of Vision Team
8  * Copyright 2003-2004 Persistence of Vision Raytracer Pty. Ltd.
9  *---------------------------------------------------------------------------
10  * NOTICE: This source code file is provided so that users may experiment
11  * with enhancements to POV-Ray and to port the software to platforms other
12  * than those supported by the POV-Ray developers. There are strict rules
13  * regarding how you are permitted to use this file. These rules are contained
14  * in the distribution and derivative versions licenses which should have been
15  * provided with this file.
16  *
17  * These licences may be found online, linked from the end-user license
18  * agreement that is located at http://www.povray.org/povlegal.html
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  * $File: //depot/povray/3.6-release/source/planes.cpp $
25  * $Revision: #3 $
26  * $Change: 3032 $
27  * $DateTime: 2004/08/02 18:43:41 $
28  * $Author: chrisc $
29  * $Log$
30  *****************************************************************************/
31 
32 #include "frame.h"
33 #include "povray.h"
34 #include "vector.h"
35 #include "matrices.h"
36 #include "objects.h"
37 #include "planes.h"
38 
39 BEGIN_POV_NAMESPACE
40 
41 /*****************************************************************************
42 * Local preprocessor defines
43 ******************************************************************************/
44 
45 const DBL DEPTH_TOLERANCE = 1.0e-6;
46 
47 /*****************************************************************************
48 * Static functions
49 ******************************************************************************/
50 
51 static int   Intersect_Plane (RAY *Ray, PLANE *Plane, DBL *Depth);
52 static int   All_Plane_Intersections (OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack);
53 static int   Inside_Plane (VECTOR point, OBJECT *Object);
54 static void  Plane_Normal (VECTOR Result, OBJECT *Object, INTERSECTION *Inter);
55 static PLANE *Copy_Plane (OBJECT *Object);
56 static void  Translate_Plane (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
57 static void  Rotate_Plane (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
58 static void  Scale_Plane (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
59 static void  Transform_Plane (OBJECT *Object, TRANSFORM *Trans);
60 static void  Invert_Plane (OBJECT *Object);
61 static void  Destroy_Plane (OBJECT *Object);
62 
63 /*****************************************************************************
64 * Local variables
65 ******************************************************************************/
66 
67 METHODS Plane_Methods =
68 {
69   All_Plane_Intersections,
70   Inside_Plane, Plane_Normal, Default_UVCoord,
71   (COPY_METHOD)Copy_Plane,
72   Translate_Plane, Rotate_Plane,
73   Scale_Plane, Transform_Plane, Invert_Plane, Destroy_Plane
74 };
75 
76 
77 /*****************************************************************************
78 *
79 * FUNCTION
80 *
81 *   All_Plane_Intersections
82 *
83 * INPUT
84 *
85 * OUTPUT
86 *
87 * RETURNS
88 *
89 * AUTHOR
90 *
91 *   POV-Ray Team
92 *
93 * DESCRIPTION
94 *
95 *   -
96 *
97 * CHANGES
98 *
99 *   -
100 *
101 ******************************************************************************/
102 
All_Plane_Intersections(OBJECT * Object,RAY * Ray,ISTACK * Depth_Stack)103 static int All_Plane_Intersections (OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack)
104 {
105   DBL Depth;
106   VECTOR IPoint;
107 
108   if (Intersect_Plane(Ray, (PLANE *)Object, &Depth))
109   {
110     VEvaluateRay(IPoint, Ray->Initial, Depth, Ray->Direction);
111 
112     if (Point_In_Clip(IPoint, Object->Clip))
113     {
114       push_entry(Depth,IPoint,Object,Depth_Stack);
115 
116       return(true);
117     }
118   }
119 
120   return(false);
121 }
122 
123 
124 
125 /*****************************************************************************
126 *
127 * FUNCTION
128 *
129 *   Intersect_Plane
130 *
131 * INPUT
132 *
133 * OUTPUT
134 *
135 * RETURNS
136 *
137 * AUTHOR
138 *
139 *   POV-Ray Team
140 *
141 * DESCRIPTION
142 *
143 *   -
144 *
145 * CHANGES
146 *
147 *   -
148 *
149 ******************************************************************************/
150 
Intersect_Plane(RAY * Ray,PLANE * Plane,DBL * Depth)151 static int Intersect_Plane (RAY *Ray, PLANE *Plane, DBL *Depth)
152 {
153   DBL NormalDotOrigin, NormalDotDirection;
154   VECTOR P, D;
155 
156   Increase_Counter(stats[Ray_Plane_Tests]);
157 
158   if (Plane->Trans == NULL)
159   {
160     VDot(NormalDotDirection, Plane->Normal_Vector, Ray->Direction);
161 
162     if (fabs(NormalDotDirection) < EPSILON)
163     {
164       return(false);
165     }
166 
167     VDot(NormalDotOrigin, Plane->Normal_Vector, Ray->Initial);
168   }
169   else
170   {
171     MInvTransPoint(P, Ray->Initial, Plane->Trans);
172     MInvTransDirection(D, Ray->Direction, Plane->Trans);
173 
174     VDot(NormalDotDirection, Plane->Normal_Vector, D);
175 
176     if (fabs(NormalDotDirection) < EPSILON)
177     {
178       return(false);
179     }
180 
181     VDot(NormalDotOrigin, Plane->Normal_Vector, P);
182   }
183 
184   *Depth = -(NormalDotOrigin + Plane->Distance) / NormalDotDirection;
185 
186   if ((*Depth >= DEPTH_TOLERANCE) && (*Depth <= Max_Distance))
187   {
188     Increase_Counter(stats[Ray_Plane_Tests_Succeeded]);
189 
190     return (true);
191   }
192   else
193   {
194     return (false);
195   }
196 }
197 
198 
199 
200 /*****************************************************************************
201 *
202 * FUNCTION
203 *
204 *   Inside_Plane
205 *
206 * INPUT
207 *
208 * OUTPUT
209 *
210 * RETURNS
211 *
212 * AUTHOR
213 *
214 *   POV-Ray Team
215 *
216 * DESCRIPTION
217 *
218 *   -
219 *
220 * CHANGES
221 *
222 *   -
223 *
224 ******************************************************************************/
225 
Inside_Plane(VECTOR IPoint,OBJECT * Object)226 static int Inside_Plane (VECTOR IPoint, OBJECT *Object)
227 {
228   DBL Temp;
229   VECTOR P;
230 
231   if (((PLANE *)Object)->Trans == NULL)
232   {
233     VDot (Temp, IPoint, ((PLANE *)Object)->Normal_Vector);
234   }
235   else
236   {
237     MInvTransPoint(P, IPoint, ((PLANE *)Object)->Trans);
238 
239     VDot (Temp, P, ((PLANE *)Object)->Normal_Vector);
240   }
241 
242   return((Temp + ((PLANE *)Object)->Distance) < EPSILON);
243 }
244 
245 
246 
247 /*****************************************************************************
248 *
249 * FUNCTION
250 *
251 *   Plane_Normal
252 *
253 * INPUT
254 *
255 * OUTPUT
256 *
257 * RETURNS
258 *
259 * AUTHOR
260 *
261 *   POV-Ray Team
262 *
263 * DESCRIPTION
264 *
265 *   -
266 *
267 * CHANGES
268 *
269 *   -
270 *
271 ******************************************************************************/
272 
Plane_Normal(VECTOR Result,OBJECT * Object,INTERSECTION *)273 static void Plane_Normal (VECTOR Result, OBJECT *Object, INTERSECTION *)
274 {
275   Assign_Vector(Result,((PLANE *)Object)->Normal_Vector);
276 
277   if (((PLANE *)Object)->Trans != NULL)
278   {
279     MTransNormal(Result, Result, ((PLANE *)Object)->Trans);
280 
281     VNormalize(Result, Result);
282   }
283 }
284 
285 
286 
287 /*****************************************************************************
288 *
289 * FUNCTION
290 *
291 *   Translate_Plane
292 *
293 * INPUT
294 *
295 * OUTPUT
296 *
297 * RETURNS
298 *
299 * AUTHOR
300 *
301 *   POV-Ray Team
302 *
303 * DESCRIPTION
304 *
305 *   -
306 *
307 * CHANGES
308 *
309 *   -
310 *
311 ******************************************************************************/
312 
Translate_Plane(OBJECT * Object,VECTOR Vector,TRANSFORM * Trans)313 static void Translate_Plane (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
314 {
315   VECTOR Translation;
316   PLANE *Plane = (PLANE *)Object;
317 
318   if (Plane->Trans == NULL)
319   {
320     VEvaluate (Translation, ((PLANE *)Object)->Normal_Vector, Vector);
321 
322     ((PLANE *)Object)->Distance -= Translation[X] + Translation[Y] + Translation[Z];
323 
324     Compute_Plane_BBox((PLANE *)Object);
325   }
326   else
327   {
328     Transform_Plane(Object, Trans);
329   }
330 }
331 
332 
333 
334 /*****************************************************************************
335 *
336 * FUNCTION
337 *
338 *   Rotate_Plane
339 *
340 * INPUT
341 *
342 * OUTPUT
343 *
344 * RETURNS
345 *
346 * AUTHOR
347 *
348 *   POV-Ray Team
349 *
350 * DESCRIPTION
351 *
352 *   -
353 *
354 * CHANGES
355 *
356 *   -
357 *
358 ******************************************************************************/
359 
Rotate_Plane(OBJECT * Object,VECTOR,TRANSFORM * Trans)360 static void Rotate_Plane (OBJECT *Object, VECTOR, TRANSFORM *Trans)
361 {
362   if (((PLANE *)Object)->Trans == NULL)
363   {
364     MTransDirection(((PLANE *)Object)->Normal_Vector, ((PLANE *)Object)->Normal_Vector, Trans);
365 
366     Compute_Plane_BBox(((PLANE *)Object));
367   }
368   else
369   {
370     Transform_Plane (Object, Trans);
371   }
372 }
373 
374 
375 
376 /*****************************************************************************
377 *
378 * FUNCTION
379 *
380 *   Scale_Plane
381 *
382 * INPUT
383 *
384 * OUTPUT
385 *
386 * RETURNS
387 *
388 * AUTHOR
389 *
390 *   POV-Ray Team
391 *
392 * DESCRIPTION
393 *
394 *   -
395 *
396 * CHANGES
397 *
398 *   -
399 *
400 ******************************************************************************/
401 
Scale_Plane(OBJECT * Object,VECTOR Vector,TRANSFORM * Trans)402 static void Scale_Plane (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
403 {
404   DBL Length;
405   PLANE *Plane = (PLANE  *) Object;
406 
407   if (Plane->Trans == NULL)
408   {
409     VDivEq(Plane->Normal_Vector, Vector);
410 
411     VLength(Length, ((PLANE *)Object)->Normal_Vector);
412 
413     VInverseScaleEq (((PLANE *)Object)->Normal_Vector, Length);
414 
415     ((PLANE *)Object)->Distance /= Length;
416 
417     Compute_Plane_BBox(Plane);
418   }
419   else
420   {
421     Transform_Plane (Object, Trans);
422   }
423 }
424 
425 
426 
427 /*****************************************************************************
428 *
429 * FUNCTION
430 *
431 *   Invert_Plane
432 *
433 * INPUT
434 *
435 * OUTPUT
436 *
437 * RETURNS
438 *
439 * AUTHOR
440 *
441 *   POV-Ray Team
442 *
443 * DESCRIPTION
444 *
445 *   -
446 *
447 * CHANGES
448 *
449 *   -
450 *
451 ******************************************************************************/
452 
Invert_Plane(OBJECT * Object)453 static void Invert_Plane (OBJECT *Object)
454 {
455   VScaleEq(((PLANE *)Object)->Normal_Vector, -1.0);
456 
457   ((PLANE *)Object)->Distance *= -1.0;
458 }
459 
460 
461 
462 /*****************************************************************************
463 *
464 * FUNCTION
465 *
466 *   Transform_Plane
467 *
468 * INPUT
469 *
470 * OUTPUT
471 *
472 * RETURNS
473 *
474 * AUTHOR
475 *
476 *   POV-Ray Team
477 *
478 * DESCRIPTION
479 *
480 *   -
481 *
482 * CHANGES
483 *
484 *   -
485 *
486 ******************************************************************************/
487 
Transform_Plane(OBJECT * Object,TRANSFORM * Trans)488 static void Transform_Plane(OBJECT *Object, TRANSFORM *Trans)
489 {
490   PLANE *Plane = (PLANE  *) Object;
491 
492   if (Plane->Trans == NULL)
493   {
494     Plane->Trans = Create_Transform();
495   }
496 
497   Compose_Transforms(Plane->Trans, Trans);
498 
499   Compute_Plane_BBox(Plane);
500 }
501 
502 
503 
504 /*****************************************************************************
505 *
506 * FUNCTION
507 *
508 *   Create_Plane
509 *
510 * INPUT
511 *
512 * OUTPUT
513 *
514 * RETURNS
515 *
516 * AUTHOR
517 *
518 *   POV-Ray Team
519 *
520 * DESCRIPTION
521 *
522 *   -
523 *
524 * CHANGES
525 *
526 *   -
527 *
528 ******************************************************************************/
529 
Create_Plane()530 PLANE *Create_Plane()
531 {
532   PLANE *New;
533 
534   New = (PLANE *)POV_MALLOC(sizeof (PLANE), "plane");
535 
536   INIT_OBJECT_FIELDS(New,PLANE_OBJECT,&Plane_Methods)
537 
538   Make_Vector(New->Normal_Vector, 0.0, 1.0, 0.0);
539 
540   New ->Distance = 0.0;
541 
542   New->Trans = NULL;
543 
544   return(New);
545 }
546 
547 
548 
549 /*****************************************************************************
550 *
551 * FUNCTION
552 *
553 *   Copy_Plane
554 *
555 * INPUT
556 *
557 * OUTPUT
558 *
559 * RETURNS
560 *
561 * AUTHOR
562 *
563 *   POV-Ray Team
564 *
565 * DESCRIPTION
566 *
567 *   -
568 *
569 * CHANGES
570 *
571 *   -
572 *
573 ******************************************************************************/
574 
Copy_Plane(OBJECT * Object)575 static PLANE *Copy_Plane (OBJECT *Object)
576 {
577   PLANE *New;
578 
579   New = Create_Plane();
580 
581   Destroy_Transform(New->Trans);
582 
583   *New = *((PLANE *)Object);
584 
585   New->Trans = Copy_Transform(((PLANE *)Object)->Trans);
586 
587   return(New);
588 }
589 
590 
591 
592 /*****************************************************************************
593 *
594 * FUNCTION
595 *
596 *   Destroy_Plane
597 *
598 * INPUT
599 *
600 * OUTPUT
601 *
602 * RETURNS
603 *
604 * AUTHOR
605 *
606 *   POV-Ray Team
607 *
608 * DESCRIPTION
609 *
610 *   -
611 *
612 * CHANGES
613 *
614 *   -
615 *
616 ******************************************************************************/
617 
Destroy_Plane(OBJECT * Object)618 static void Destroy_Plane(OBJECT *Object)
619 {
620 #if(DUMP_OBJECT_DATA == 1)
621   Debug_Info("{ // PLANE \n");
622   DUMP_OBJECT_FIELDS(Object);
623   Debug_Info("\t{ %f, %f, %f }, // Normal_Vector\n", \
624              (DBL)((PLANE *)Object)->Normal_Vector[X], \
625              (DBL)((PLANE *)Object)->Normal_Vector[Y], \
626              (DBL)((PLANE *)Object)->Normal_Vector[Z]); \
627   Debug_Info("\t%f // Distance\n", (DBL)((PLANE *)Object)->Distance);
628   Debug_Info("}\n");
629 #endif
630 
631   Destroy_Transform(((PLANE *)Object)->Trans);
632 
633   POV_FREE(Object);
634 }
635 
636 
637 
638 /*****************************************************************************
639 *
640 * FUNCTION
641 *
642 *   Compute_Plane_BBox
643 *
644 * INPUT
645 *
646 *   Plane - Plane
647 *
648 * OUTPUT
649 *
650 *   Plane
651 *
652 * RETURNS
653 *
654 * AUTHOR
655 *
656 *   Dieter Bayer
657 *
658 * DESCRIPTION
659 *
660 *   Calculate the bounding box of a plane (it's always infinite).
661 *
662 * CHANGES
663 *
664 *   Aug 1994 : Creation.
665 *
666 ******************************************************************************/
667 
Compute_Plane_BBox(PLANE * Plane)668 void Compute_Plane_BBox(PLANE *Plane)
669 {
670   Make_BBox(Plane->BBox, -BOUND_HUGE/2, -BOUND_HUGE/2, -BOUND_HUGE/2,
671     BOUND_HUGE, BOUND_HUGE, BOUND_HUGE);
672 
673   if (Plane->Clip != NULL)
674   {
675     Plane->BBox = Plane->Clip->BBox;
676   }
677 }
678 
679 END_POV_NAMESPACE
680