1 /****************************************************************************
4 * This module implements functions that manipulate torii.
6 * This module was written by Dieter Bayer [DB].
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.
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.
24 *****************************************************************************/
26 /****************************************************************************
32 * June 1994 : Creation. [DB]
34 *****************************************************************************/
48 /*****************************************************************************
49 * Local preprocessor defines
50 ******************************************************************************/
52 /* Minimal depth for a valid intersection. */
54 #define DEPTH_TOLERANCE 1.0e-4
56 /* Tolerance used for order reduction during root finding. */
58 #define ROOT_TOLERANCE 1.0e-4
62 /*****************************************************************************
64 ******************************************************************************/
66 static int intersect_torus (RAY
*Ray
, TORUS
*Torus
, DBL
*Depth
);
67 static int All_Torus_Intersections (OBJECT
*Object
, RAY
*Ray
, ISTACK
*Depth_Stack
);
68 static int Inside_Torus (VECTOR point
, OBJECT
*Object
);
69 static void Torus_Normal (VECTOR Result
, OBJECT
*Object
, INTERSECTION
*Inter
);
70 static TORUS
*Copy_Torus (OBJECT
*Object
);
71 static void Translate_Torus (OBJECT
*Object
, VECTOR Vector
, TRANSFORM
*Trans
);
72 static void Rotate_Torus (OBJECT
*Object
, VECTOR Vector
, TRANSFORM
*Trans
);
73 static void Scale_Torus (OBJECT
*Object
, VECTOR Vector
, TRANSFORM
*Trans
);
74 static void Transform_Torus (OBJECT
*Object
, TRANSFORM
*Trans
);
75 static void Invert_Torus (OBJECT
*Object
);
76 static void Destroy_Torus (OBJECT
*Object
);
80 /*****************************************************************************
82 ******************************************************************************/
84 static METHODS Torus_Methods
=
86 All_Torus_Intersections
, Inside_Torus
, Torus_Normal
,
87 (COPY_METHOD
)Copy_Torus
, Translate_Torus
, Rotate_Torus
,
88 Scale_Torus
, Transform_Torus
, Invert_Torus
, Destroy_Torus
92 /*****************************************************************************
96 * All_Torus_Intersections
102 * Depth_Stack - Intersection stack
110 * int - TRUE, if an intersection was found
118 * Determine ray/torus intersection and clip intersection found.
122 * Jun 1994 : Creation.
124 ******************************************************************************/
126 static int All_Torus_Intersections(OBJECT
*Object
, RAY
*Ray
, ISTACK
*Depth_Stack
)
134 if ((max_i
= intersect_torus(Ray
, (TORUS
*)Object
, Depth
)) > 0)
136 for (i
= 0; i
< max_i
; i
++)
138 if ((Depth
[i
] > DEPTH_TOLERANCE
) && (Depth
[i
] < Max_Distance
))
140 VEvaluateRay(IPoint
, Ray
->Initial
, Depth
[i
], Ray
->Direction
);
142 if (Point_In_Clip(IPoint
, Object
->Clip
))
144 push_entry(Depth
[i
], IPoint
, Object
, Depth_Stack
);
157 /*****************************************************************************
167 * Depth - Intersections found
175 * int - Number of intersections found
183 * Determine ray/torus intersection.
185 * Note that the torus is rotated about the y-axis!
189 * Jun 1994 : Creation.
191 ******************************************************************************/
193 static int intersect_torus(RAY
*Ray
, TORUS
*Torus
, DBL
*Depth
)
196 DBL len
, R2
, Py2
, Dy2
, PDy2
, k1
, k2
;
201 Increase_Counter(stats
[Ray_Torus_Tests
]);
203 /* Transform the ray into the torus space. */
205 MInvTransPoint(P
, Ray
->Initial
, Torus
->Trans
);
207 MInvTransDirection(D
, Ray
->Direction
, Torus
->Trans
);
211 VInverseScaleEq(D
, len
);
217 r1
= Sqr(Torus
->R
- Torus
->r
);
218 r2
= Sqr(Torus
->R
+ Torus
->r
);
220 #ifdef TORUS_EXTRA_STATS
221 Increase_Counter(stats
[Torus_Bound_Tests
]);
224 if (Test_Thick_Cylinder(P
, D
, y1
, y2
, r1
, r2
))
226 #ifdef TORUS_EXTRA_STATS
227 Increase_Counter(stats
[Torus_Bound_Tests_Succeeded
]);
237 k1
= P
[X
] * P
[X
] + P
[Z
] * P
[Z
] + Py2
- R2
- r2
;
238 k2
= P
[X
] * D
[X
] + P
[Z
] * D
[Z
] + PDy2
;
244 c
[2] = 2.0 * (k1
+ 2.0 * (k2
* k2
+ R2
* Dy2
));
246 c
[3] = 4.0 * (k2
* k1
+ 2.0 * R2
* PDy2
);
248 c
[4] = k1
* k1
+ 4.0 * R2
* (Py2
- r2
);
250 n
= Solve_Polynomial(4, c
, r
, Test_Flag(Torus
, STURM_FLAG
), ROOT_TOLERANCE
);
254 Depth
[i
++] = r
[n
] / len
;
260 Increase_Counter(stats
[Ray_Torus_Tests_Succeeded
]);
268 /*****************************************************************************
276 * IPoint - Intersection point
283 * int - TRUE if inside
291 * Test if a point lies inside the torus.
295 * Jun 1994 : Creation.
297 ******************************************************************************/
299 static int Inside_Torus(VECTOR IPoint
, OBJECT
*Object
)
303 TORUS
*Torus
= (TORUS
*)Object
;
305 /* Transform the point into the torus space. */
307 MInvTransPoint(P
, IPoint
, Torus
->Trans
);
309 r
= sqrt(Sqr(P
[X
]) + Sqr(P
[Z
]));
311 r2
= Sqr(P
[Y
]) + Sqr(r
- Torus
->R
);
313 if (r2
<= Sqr(Torus
->r
))
315 return(!Test_Flag(Torus
, INVERTED_FLAG
));
319 return(Test_Flag(Torus
, INVERTED_FLAG
));
325 /*****************************************************************************
333 * Result - Normal vector
335 * Inter - Intersection found
349 * Calculate the normal of the torus in a given point.
353 * Jun 1994 : Creation.
355 ******************************************************************************/
357 static void Torus_Normal(VECTOR Result
, OBJECT
*Object
, INTERSECTION
*Inter
)
361 TORUS
*Torus
= (TORUS
*)Object
;
363 /* Transform the point into the torus space. */
365 MInvTransPoint(P
, Inter
->IPoint
, Torus
->Trans
);
367 /* Get normal from derivatives. */
369 dist
= sqrt(P
[X
] * P
[X
] + P
[Z
] * P
[Z
]);
373 M
[X
] = Torus
->R
* P
[X
] / dist
;
375 M
[Z
] = Torus
->R
* P
[Z
] / dist
;
379 Make_Vector(M
, 0.0, 0.0, 0.0);
384 /* Transform the normalt out of the torus space. */
386 MTransNormal(Result
, N
, Torus
->Trans
);
388 VNormalize(Result
, Result
);
393 /*****************************************************************************
402 * Vector - Translation vector
420 * Jun 1994 : Creation.
422 ******************************************************************************/
424 static void Translate_Torus(OBJECT
*Object
, VECTOR Vector
, TRANSFORM
*Trans
)
426 Transform_Torus(Object
, Trans
);
431 /*****************************************************************************
440 * Vector - Rotation vector
458 * Jun 1994 : Creation.
460 ******************************************************************************/
462 static void Rotate_Torus(OBJECT
*Object
, VECTOR Vector
, TRANSFORM
*Trans
)
464 Transform_Torus(Object
, Trans
);
469 /*****************************************************************************
478 * Vector - Scaling vector
496 * Jun 1994 : Creation.
498 ******************************************************************************/
500 static void Scale_Torus(OBJECT
*Object
, VECTOR Vector
, TRANSFORM
*Trans
)
502 Transform_Torus(Object
, Trans
);
507 /*****************************************************************************
516 * Trans - Transformation to apply
530 * Transform a torus and recalculate its bounding box.
534 * Jun 1994 : Creation.
536 ******************************************************************************/
538 static void Transform_Torus(OBJECT
*Object
, TRANSFORM
*Trans
)
540 Compose_Transforms(((TORUS
*)Object
)->Trans
, Trans
);
542 Compute_Torus_BBox((TORUS
*)Object
);
547 /*****************************************************************************
573 * Jun 1994 : Creation.
575 ******************************************************************************/
577 static void Invert_Torus(OBJECT
*Object
)
579 Invert_Flag(Object
, INVERTED_FLAG
);
584 /*****************************************************************************
596 * TORUS * - new torus
604 * Create a new torus.
608 * Jun 1994 : Creation.
610 ******************************************************************************/
612 TORUS
*Create_Torus()
616 New
= (TORUS
*)POV_MALLOC(sizeof(TORUS
), "torus");
618 INIT_OBJECT_FIELDS(New
,TORUS_OBJECT
,&Torus_Methods
)
620 New
->Trans
= Create_Transform();
630 /*****************************************************************************
656 * Jun 1994 : Creation.
658 * Sep 1994 : fixed memory leakage [DB]
660 ******************************************************************************/
662 static TORUS
*Copy_Torus(OBJECT
*Object
)
664 TORUS
*New
, *Torus
= (TORUS
*)Object
;
666 New
= Create_Torus();
668 /* Get rid of the transformation created in Create_Torus(). */
670 Destroy_Transform(New
->Trans
);
676 New
->Trans
= Copy_Transform(Torus
->Trans
);
683 /*****************************************************************************
709 * Jun 1994 : Creation.
711 ******************************************************************************/
713 static void Destroy_Torus (OBJECT
*Object
)
715 Destroy_Transform(((TORUS
*)Object
)->Trans
);
722 /*****************************************************************************
744 * Calculate the bounding box of a torus.
748 * Jun 1994 : Creation.
750 ******************************************************************************/
752 void Compute_Torus_BBox(TORUS
*Torus
)
757 r2
= Torus
->R
+ Torus
->r
;
759 Make_BBox(Torus
->BBox
, -r2
, -r1
, -r2
, 2.0 * r2
, 2.0 * r1
, 2.0 * r2
);
761 Recompute_BBox(&Torus
->BBox
, Torus
->Trans
);
766 /*****************************************************************************
770 * Test_Thick_Cylinder
778 * r1 - Square of inner radius
779 * r2 - Square of outer radius
793 * Test if a given ray defined in the lathe's coordinate system
794 * intersects a "thick" cylinder (rotated about y-axis).
798 * Jun 1994 : Creation.
800 ******************************************************************************/
802 int Test_Thick_Cylinder(VECTOR P
, VECTOR D
, DBL h1
, DBL h2
, DBL r1
, DBL r2
)
807 if (fabs(D
[Y
]) < EPSILON
)
809 if ((P
[Y
] < h1
) || (P
[Y
] > h2
))
816 /* Intersect ray with the cap-plane. */
818 k
= (h2
- P
[Y
]) / D
[Y
];
823 if ((k
> EPSILON
) && (k
< Max_Distance
))
827 if ((r
>= r1
) && (r
<= r2
))
833 /* Intersectionersect ray with the base-plane. */
835 k
= (h1
- P
[Y
]) / D
[Y
];
840 if ((k
> EPSILON
) && (k
< Max_Distance
))
844 if ((r
>= r1
) && (r
<= r2
))
851 a
= D
[X
] * D
[X
] + D
[Z
] * D
[Z
];
855 /* Intersect with outer cylinder. */
857 b
= P
[X
] * D
[X
] + P
[Z
] * D
[Z
];
859 c
= P
[X
] * P
[X
] + P
[Z
] * P
[Z
] - r2
;
869 if ((k
> EPSILON
) && (k
< Max_Distance
))
873 if ((h
>= h1
) && (h
<= h2
))
881 if ((k
> EPSILON
) && (k
< Max_Distance
))
885 if ((h
>= h1
) && (h
<= h2
))
892 /* Intersect with inner cylinder. */
894 c
= P
[X
] * P
[X
] + P
[Z
] * P
[Z
] - r1
;
904 if ((k
> EPSILON
) && (k
< Max_Distance
))
908 if ((h
>= h1
) && (h
<= h2
))
916 if ((k
> EPSILON
) && (k
< Max_Distance
))
920 if ((h
>= h1
) && (h
<= h2
))