1 /*******************************************************************************
2  * planes.cpp
3  *
4  * This module implements functions that manipulate planes.
5  *
6  * ---------------------------------------------------------------------------
7  * Persistence of Vision Ray Tracer ('POV-Ray') version 3.7.
8  * Copyright 1991-2013 Persistence of Vision Raytracer Pty. Ltd.
9  *
10  * POV-Ray is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU Affero General Public License as
12  * published by the Free Software Foundation, either version 3 of the
13  * License, or (at your option) any later version.
14  *
15  * POV-Ray is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Affero General Public License for more details.
19  *
20  * You should have received a copy of the GNU Affero General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  * ---------------------------------------------------------------------------
23  * POV-Ray is based on the popular DKB raytracer version 2.12.
24  * DKBTrace was originally written by David K. Buck.
25  * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
26  * ---------------------------------------------------------------------------
27  * $File: //depot/public/povray/3.x/source/backend/shape/planes.cpp $
28  * $Revision: #1 $
29  * $Change: 6069 $
30  * $DateTime: 2013/11/06 11:59:40 $
31  * $Author: chrisc $
32  *******************************************************************************/
33 
34 // frame.h must always be the first POV file included (pulls in platform config)
35 #include "backend/frame.h"
36 #include "backend/math/vector.h"
37 #include "backend/math/matrices.h"
38 #include "backend/scene/objects.h"
39 #include "backend/scene/threaddata.h"
40 #include "backend/shape/planes.h"
41 
42 // this must be the last file included
43 #include "base/povdebug.h"
44 
45 namespace pov
46 {
47 
48 /*****************************************************************************
49 * Local preprocessor defines
50 ******************************************************************************/
51 
52 const DBL DEPTH_TOLERANCE = 1.0e-6;
53 
54 
55 
56 /*****************************************************************************
57 *
58 * FUNCTION
59 *
60 *   All_Plane_Intersections
61 *
62 * INPUT
63 *
64 * OUTPUT
65 *
66 * RETURNS
67 *
68 * AUTHOR
69 *
70 *   POV-Ray Team
71 *
72 * DESCRIPTION
73 *
74 *   -
75 *
76 * CHANGES
77 *
78 *   -
79 *
80 ******************************************************************************/
81 
All_Intersections(const Ray & ray,IStack & Depth_Stack,TraceThreadData * Thread)82 bool Plane::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadData *Thread)
83 {
84 	DBL Depth;
85 	VECTOR IPoint;
86 
87 	if (Intersect(ray, &Depth, Thread))
88 	{
89 		VEvaluateRay(IPoint, ray.Origin, Depth, ray.Direction);
90 
91 		if (Clip.empty() || Point_In_Clip(IPoint, Clip, Thread))
92 		{
93 			Depth_Stack->push(Intersection(Depth,IPoint,this));
94 			return(true);
95 		}
96 	}
97 
98 	return(false);
99 }
100 
101 
102 
103 /*****************************************************************************
104 *
105 * FUNCTION
106 *
107 *   Intersect_Plane
108 *
109 * INPUT
110 *
111 * OUTPUT
112 *
113 * RETURNS
114 *
115 * AUTHOR
116 *
117 *   POV-Ray Team
118 *
119 * DESCRIPTION
120 *
121 *   -
122 *
123 * CHANGES
124 *
125 *   -
126 *
127 ******************************************************************************/
128 
Intersect(const Ray & ray,DBL * Depth,TraceThreadData * Thread) const129 bool Plane::Intersect(const Ray& ray, DBL *Depth, TraceThreadData *Thread) const
130 {
131 	DBL NormalDotOrigin, NormalDotDirection;
132 	VECTOR P, D;
133 
134 	Thread->Stats()[Ray_Plane_Tests]++;
135 
136 	if (Trans == NULL)
137 	{
138 		VDot(NormalDotDirection, Normal_Vector, ray.Direction);
139 
140 		if (fabs(NormalDotDirection) < EPSILON)
141 		{
142 			return(false);
143 		}
144 
145 		VDot(NormalDotOrigin, Normal_Vector, ray.Origin);
146 	}
147 	else
148 	{
149 		MInvTransPoint(P, ray.Origin, Trans);
150 		MInvTransDirection(D, ray.Direction, Trans);
151 
152 		VDot(NormalDotDirection, Normal_Vector, D);
153 
154 		if (fabs(NormalDotDirection) < EPSILON)
155 		{
156 			return(false);
157 		}
158 
159 		VDot(NormalDotOrigin, Normal_Vector, P);
160 	}
161 
162 	*Depth = -(NormalDotOrigin + Distance) / NormalDotDirection;
163 
164 	if ((*Depth >= DEPTH_TOLERANCE) && (*Depth <= MAX_DISTANCE))
165 	{
166 		Thread->Stats()[Ray_Plane_Tests_Succeeded]++;
167 		return (true);
168 	}
169 	else
170 	{
171 		return (false);
172 	}
173 }
174 
175 
176 
177 /*****************************************************************************
178 *
179 * FUNCTION
180 *
181 *   Inside_Plane
182 *
183 * INPUT
184 *
185 * OUTPUT
186 *
187 * RETURNS
188 *
189 * AUTHOR
190 *
191 *   POV-Ray Team
192 *
193 * DESCRIPTION
194 *
195 *   -
196 *
197 * CHANGES
198 *
199 *   -
200 *
201 ******************************************************************************/
202 
Inside(const VECTOR IPoint,TraceThreadData * Thread) const203 bool Plane::Inside(const VECTOR IPoint, TraceThreadData *Thread) const
204 {
205 	DBL Temp;
206 	VECTOR P;
207 
208 	if(Trans == NULL)
209 	{
210 		VDot(Temp, IPoint, Normal_Vector);
211 	}
212 	else
213 	{
214 		MInvTransPoint(P, IPoint, Trans);
215 
216 		VDot(Temp, P, Normal_Vector);
217 	}
218 
219 	return((Temp + Distance) < EPSILON);
220 }
221 
222 
223 
224 /*****************************************************************************
225 *
226 * FUNCTION
227 *
228 *   Plane_Normal
229 *
230 * INPUT
231 *
232 * OUTPUT
233 *
234 * RETURNS
235 *
236 * AUTHOR
237 *
238 *   POV-Ray Team
239 *
240 * DESCRIPTION
241 *
242 *   -
243 *
244 * CHANGES
245 *
246 *   -
247 *
248 ******************************************************************************/
249 
Normal(VECTOR Result,Intersection *,TraceThreadData *) const250 void Plane::Normal(VECTOR Result, Intersection *, TraceThreadData *) const
251 {
252 	Assign_Vector(Result, Normal_Vector);
253 
254 	if(Trans != NULL)
255 	{
256 		MTransNormal(Result, Result, Trans);
257 
258 		VNormalize(Result, Result);
259 	}
260 }
261 
262 
263 
264 /*****************************************************************************
265 *
266 * FUNCTION
267 *
268 *   Translate_Plane
269 *
270 * INPUT
271 *
272 * OUTPUT
273 *
274 * RETURNS
275 *
276 * AUTHOR
277 *
278 *   POV-Ray Team
279 *
280 * DESCRIPTION
281 *
282 *   -
283 *
284 * CHANGES
285 *
286 *   -
287 *
288 ******************************************************************************/
289 
Translate(const VECTOR Vector,const TRANSFORM * tr)290 void Plane::Translate(const VECTOR Vector, const TRANSFORM *tr)
291 {
292 	VECTOR Translation;
293 
294 	if(Trans == NULL)
295 	{
296 		VEvaluate (Translation, Normal_Vector, Vector);
297 
298 		Distance -= Translation[X] + Translation[Y] + Translation[Z];
299 
300 		Compute_BBox();
301 	}
302 	else
303 	{
304 		Transform(tr);
305 	}
306 }
307 
308 
309 
310 /*****************************************************************************
311 *
312 * FUNCTION
313 *
314 *   Rotate_Plane
315 *
316 * INPUT
317 *
318 * OUTPUT
319 *
320 * RETURNS
321 *
322 * AUTHOR
323 *
324 *   POV-Ray Team
325 *
326 * DESCRIPTION
327 *
328 *   -
329 *
330 * CHANGES
331 *
332 *   -
333 *
334 ******************************************************************************/
335 
Rotate(const VECTOR,const TRANSFORM * tr)336 void Plane::Rotate(const VECTOR, const TRANSFORM *tr)
337 {
338 	if(Trans == NULL)
339 	{
340 		MTransDirection(Normal_Vector, Normal_Vector, tr);
341 
342 		Compute_BBox();
343 	}
344 	else
345 	{
346 		Transform(tr);
347 	}
348 }
349 
350 
351 
352 /*****************************************************************************
353 *
354 * FUNCTION
355 *
356 *   Scale_Plane
357 *
358 * INPUT
359 *
360 * OUTPUT
361 *
362 * RETURNS
363 *
364 * AUTHOR
365 *
366 *   POV-Ray Team
367 *
368 * DESCRIPTION
369 *
370 *   -
371 *
372 * CHANGES
373 *
374 *   -
375 *
376 ******************************************************************************/
377 
Scale(const VECTOR Vector,const TRANSFORM * tr)378 void Plane::Scale(const VECTOR Vector, const TRANSFORM *tr)
379 {
380 	DBL Length;
381 
382 	if(Trans == NULL)
383 	{
384 		VDivEq(Normal_Vector, Vector);
385 
386 		VLength(Length, Normal_Vector);
387 
388 		VInverseScaleEq(Normal_Vector, Length);
389 
390 		Distance /= Length;
391 
392 		Compute_BBox();
393 	}
394 	else
395 	{
396 		Transform(tr);
397 	}
398 }
399 
400 
401 
402 /*****************************************************************************
403 *
404 * FUNCTION
405 *
406 *   Invert_Plane
407 *
408 * INPUT
409 *
410 * OUTPUT
411 *
412 * RETURNS
413 *
414 * AUTHOR
415 *
416 *   POV-Ray Team
417 *
418 * DESCRIPTION
419 *
420 *   -
421 *
422 * CHANGES
423 *
424 *   -
425 *
426 ******************************************************************************/
427 
Invert()428 void Plane::Invert()
429 {
430 	VScaleEq(Normal_Vector, -1.0);
431 
432 	Distance *= -1.0;
433 }
434 
435 
436 
437 /*****************************************************************************
438 *
439 * FUNCTION
440 *
441 *   Transform_Plane
442 *
443 * INPUT
444 *
445 * OUTPUT
446 *
447 * RETURNS
448 *
449 * AUTHOR
450 *
451 *   POV-Ray Team
452 *
453 * DESCRIPTION
454 *
455 *   -
456 *
457 * CHANGES
458 *
459 *   -
460 *
461 ******************************************************************************/
462 
Transform(const TRANSFORM * tr)463 void Plane::Transform(const TRANSFORM *tr)
464 {
465 	if(Trans == NULL)
466 		Trans = Create_Transform();
467 
468 	Compose_Transforms(Trans, tr);
469 
470 	Compute_BBox();
471 }
472 
473 
474 
475 /*****************************************************************************
476 *
477 * FUNCTION
478 *
479 *   Create_Plane
480 *
481 * INPUT
482 *
483 * OUTPUT
484 *
485 * RETURNS
486 *
487 * AUTHOR
488 *
489 *   POV-Ray Team
490 *
491 * DESCRIPTION
492 *
493 *   -
494 *
495 * CHANGES
496 *
497 *   -
498 *
499 ******************************************************************************/
500 
Plane()501 Plane::Plane() : ObjectBase(PLANE_OBJECT)
502 {
503 	Make_Vector(Normal_Vector, 0.0, 1.0, 0.0);
504 
505 	Distance = 0.0;
506 
507 	Trans = NULL;
508 }
509 
510 
511 
512 /*****************************************************************************
513 *
514 * FUNCTION
515 *
516 *   Copy_Plane
517 *
518 * INPUT
519 *
520 * OUTPUT
521 *
522 * RETURNS
523 *
524 * AUTHOR
525 *
526 *   POV-Ray Team
527 *
528 * DESCRIPTION
529 *
530 *   -
531 *
532 * CHANGES
533 *
534 *   -
535 *
536 ******************************************************************************/
537 
Copy()538 ObjectPtr Plane::Copy()
539 {
540 	Plane *New = new Plane();
541 	Destroy_Transform(New->Trans);
542 	*New = *this;
543 	New->Trans = Copy_Transform(Trans);
544 
545 	return(New);
546 }
547 
548 
549 
550 /*****************************************************************************
551 *
552 * FUNCTION
553 *
554 *   Destroy_Plane
555 *
556 * INPUT
557 *
558 * OUTPUT
559 *
560 * RETURNS
561 *
562 * AUTHOR
563 *
564 *   POV-Ray Team
565 *
566 * DESCRIPTION
567 *
568 *   -
569 *
570 * CHANGES
571 *
572 *   -
573 *
574 ******************************************************************************/
575 
~Plane()576 Plane::~Plane()
577 {
578 	Destroy_Transform(Trans);
579 }
580 
581 
582 
583 /*****************************************************************************
584 *
585 * FUNCTION
586 *
587 *   Compute_Plane_BBox
588 *
589 * INPUT
590 *
591 *   Plane - Plane
592 *
593 * OUTPUT
594 *
595 *   Plane
596 *
597 * RETURNS
598 *
599 * AUTHOR
600 *
601 *   Dieter Bayer
602 *
603 * DESCRIPTION
604 *
605 *   Calculate the bounding box of a plane (it's always infinite).
606 *
607 * CHANGES
608 *
609 *   Aug 1994 : Creation.
610 *
611 ******************************************************************************/
612 
Compute_BBox()613 void Plane::Compute_BBox()
614 {
615 	Make_BBox(BBox, -BOUND_HUGE/2, -BOUND_HUGE/2, -BOUND_HUGE/2,
616 		BOUND_HUGE, BOUND_HUGE, BOUND_HUGE);
617 
618 	if (!Clip.empty())
619 	{
620 		BBox = Clip[0]->BBox; // FIXME - only supports one clip object? [trf]
621 	}
622 }
623 
Intersect_BBox(BBoxDirection,const BBOX_VECT &,const BBOX_VECT &,BBOX_VAL) const624 bool Plane::Intersect_BBox(BBoxDirection, const BBOX_VECT&, const BBOX_VECT&, BBOX_VAL) const
625 {
626 	return true;
627 }
628 
629 }
630