Simple test for asyncio.library.
[AROS-Contrib.git] / gfx / povray / torus.c
bloba64ea2c09076145bf6968c22023d02664466d4dc
1 /****************************************************************************
2 * torus.c
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 /****************************************************************************
28 * Explanation:
30 * ---
32 * June 1994 : Creation. [DB]
34 *****************************************************************************/
36 #include "frame.h"
37 #include "povray.h"
38 #include "vector.h"
39 #include "povproto.h"
40 #include "bbox.h"
41 #include "polysolv.h"
42 #include "matrices.h"
43 #include "objects.h"
44 #include "torus.h"
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 /*****************************************************************************
63 * Static functions
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 /*****************************************************************************
81 * Local variables
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 /*****************************************************************************
94 * FUNCTION
96 * All_Torus_Intersections
98 * INPUT
100 * Object - Object
101 * Ray - Ray
102 * Depth_Stack - Intersection stack
104 * OUTPUT
106 * Depth_Stack
108 * RETURNS
110 * int - TRUE, if an intersection was found
112 * AUTHOR
114 * Dieter Bayer
116 * DESCRIPTION
118 * Determine ray/torus intersection and clip intersection found.
120 * CHANGES
122 * Jun 1994 : Creation.
124 ******************************************************************************/
126 static int All_Torus_Intersections(OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack)
128 int i, max_i, Found;
129 DBL Depth[4];
130 VECTOR IPoint;
132 Found = FALSE;
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);
146 Found = TRUE;
152 return(Found);
157 /*****************************************************************************
159 * FUNCTION
161 * intersect_torus
163 * INPUT
165 * Ray - Ray
166 * Torus - Torus
167 * Depth - Intersections found
169 * OUTPUT
171 * Depth
173 * RETURNS
175 * int - Number of intersections found
177 * AUTHOR
179 * Dieter Bayer
181 * DESCRIPTION
183 * Determine ray/torus intersection.
185 * Note that the torus is rotated about the y-axis!
187 * CHANGES
189 * Jun 1994 : Creation.
191 ******************************************************************************/
193 static int intersect_torus(RAY *Ray, TORUS *Torus, DBL *Depth)
195 int i, n;
196 DBL len, R2, Py2, Dy2, PDy2, k1, k2;
197 DBL y1, y2, r1, r2;
198 DBL c[5], r[4];
199 VECTOR P, D;
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);
209 VLength(len, D);
211 VInverseScaleEq(D, len);
213 i = 0;
215 y1 = -Torus->r;
216 y2 = Torus->r;
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]);
222 #endif
224 if (Test_Thick_Cylinder(P, D, y1, y2, r1, r2))
226 #ifdef TORUS_EXTRA_STATS
227 Increase_Counter(stats[Torus_Bound_Tests_Succeeded]);
228 #endif
230 R2 = Sqr(Torus->R);
231 r2 = Sqr(Torus->r);
233 Py2 = P[Y] * P[Y];
234 Dy2 = D[Y] * D[Y];
235 PDy2 = P[Y] * D[Y];
237 k1 = P[X] * P[X] + P[Z] * P[Z] + Py2 - R2 - r2;
238 k2 = P[X] * D[X] + P[Z] * D[Z] + PDy2;
240 c[0] = 1.0;
242 c[1] = 4.0 * k2;
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);
252 while(n--)
254 Depth[i++] = r[n] / len;
258 if (i)
260 Increase_Counter(stats[Ray_Torus_Tests_Succeeded]);
263 return(i);
268 /*****************************************************************************
270 * FUNCTION
272 * Inside_Torus
274 * INPUT
276 * IPoint - Intersection point
277 * Object - Object
279 * OUTPUT
281 * RETURNS
283 * int - TRUE if inside
285 * AUTHOR
287 * Dieter Bayer
289 * DESCRIPTION
291 * Test if a point lies inside the torus.
293 * CHANGES
295 * Jun 1994 : Creation.
297 ******************************************************************************/
299 static int Inside_Torus(VECTOR IPoint, OBJECT *Object)
301 DBL r, r2;
302 VECTOR P;
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));
317 else
319 return(Test_Flag(Torus, INVERTED_FLAG));
325 /*****************************************************************************
327 * FUNCTION
329 * Torus_Normal
331 * INPUT
333 * Result - Normal vector
334 * Object - Object
335 * Inter - Intersection found
337 * OUTPUT
339 * Result
341 * RETURNS
343 * AUTHOR
345 * Dieter Bayer
347 * DESCRIPTION
349 * Calculate the normal of the torus in a given point.
351 * CHANGES
353 * Jun 1994 : Creation.
355 ******************************************************************************/
357 static void Torus_Normal(VECTOR Result, OBJECT *Object, INTERSECTION *Inter)
359 DBL dist;
360 VECTOR P, N, M;
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]);
371 if (dist > EPSILON)
373 M[X] = Torus->R * P[X] / dist;
374 M[Y] = 0.0;
375 M[Z] = Torus->R * P[Z] / dist;
377 else
379 Make_Vector(M, 0.0, 0.0, 0.0);
382 VSub(N, P, M);
384 /* Transform the normalt out of the torus space. */
386 MTransNormal(Result, N, Torus->Trans);
388 VNormalize(Result, Result);
393 /*****************************************************************************
395 * FUNCTION
397 * Translate_Torus
399 * INPUT
401 * Object - Object
402 * Vector - Translation vector
404 * OUTPUT
406 * Object
408 * RETURNS
410 * AUTHOR
412 * Dieter Bayer
414 * DESCRIPTION
416 * Translate a torus.
418 * CHANGES
420 * Jun 1994 : Creation.
422 ******************************************************************************/
424 static void Translate_Torus(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
426 Transform_Torus(Object, Trans);
431 /*****************************************************************************
433 * FUNCTION
435 * Rotate_Torus
437 * INPUT
439 * Object - Object
440 * Vector - Rotation vector
442 * OUTPUT
444 * Object
446 * RETURNS
448 * AUTHOR
450 * Dieter Bayer
452 * DESCRIPTION
454 * Rotate a torus.
456 * CHANGES
458 * Jun 1994 : Creation.
460 ******************************************************************************/
462 static void Rotate_Torus(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
464 Transform_Torus(Object, Trans);
469 /*****************************************************************************
471 * FUNCTION
473 * Scale_Torus
475 * INPUT
477 * Object - Object
478 * Vector - Scaling vector
480 * OUTPUT
482 * Object
484 * RETURNS
486 * AUTHOR
488 * Dieter Bayer
490 * DESCRIPTION
492 * Scale a torus.
494 * CHANGES
496 * Jun 1994 : Creation.
498 ******************************************************************************/
500 static void Scale_Torus(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
502 Transform_Torus(Object, Trans);
507 /*****************************************************************************
509 * FUNCTION
511 * Transform_Torus
513 * INPUT
515 * Object - Object
516 * Trans - Transformation to apply
518 * OUTPUT
520 * Object
522 * RETURNS
524 * AUTHOR
526 * Dieter Bayer
528 * DESCRIPTION
530 * Transform a torus and recalculate its bounding box.
532 * CHANGES
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 /*****************************************************************************
549 * FUNCTION
551 * Invert_Torus
553 * INPUT
555 * Object - Object
557 * OUTPUT
559 * Object
561 * RETURNS
563 * AUTHOR
565 * Dieter Bayer
567 * DESCRIPTION
569 * Invert a torus.
571 * CHANGES
573 * Jun 1994 : Creation.
575 ******************************************************************************/
577 static void Invert_Torus(OBJECT *Object)
579 Invert_Flag(Object, INVERTED_FLAG);
584 /*****************************************************************************
586 * FUNCTION
588 * Create_Torus
590 * INPUT
592 * OUTPUT
594 * RETURNS
596 * TORUS * - new torus
598 * AUTHOR
600 * Dieter Bayer
602 * DESCRIPTION
604 * Create a new torus.
606 * CHANGES
608 * Jun 1994 : Creation.
610 ******************************************************************************/
612 TORUS *Create_Torus()
614 TORUS *New;
616 New = (TORUS *)POV_MALLOC(sizeof(TORUS), "torus");
618 INIT_OBJECT_FIELDS(New,TORUS_OBJECT,&Torus_Methods)
620 New->Trans = Create_Transform();
622 New->R =
623 New->r = 0.0;
625 return (New);
630 /*****************************************************************************
632 * FUNCTION
634 * Copy_Torus
636 * INPUT
638 * Object - Object
640 * OUTPUT
642 * RETURNS
644 * void * - New torus
646 * AUTHOR
648 * Dieter Bayer
650 * DESCRIPTION
652 * Copy a torus.
654 * CHANGES
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);
672 /* Copy torus. */
674 *New = *Torus;
676 New->Trans = Copy_Transform(Torus->Trans);
678 return (New);
683 /*****************************************************************************
685 * FUNCTION
687 * Destroy_Torus
689 * INPUT
691 * Object - Object
693 * OUTPUT
695 * Object
697 * RETURNS
699 * AUTHOR
701 * Dieter Bayer
703 * DESCRIPTION
705 * Destroy a torus.
707 * CHANGES
709 * Jun 1994 : Creation.
711 ******************************************************************************/
713 static void Destroy_Torus (OBJECT *Object)
715 Destroy_Transform(((TORUS *)Object)->Trans);
717 POV_FREE (Object);
722 /*****************************************************************************
724 * FUNCTION
726 * Compute_Torus_BBox
728 * INPUT
730 * Torus - Torus
732 * OUTPUT
734 * Torus
736 * RETURNS
738 * AUTHOR
740 * Dieter Bayer
742 * DESCRIPTION
744 * Calculate the bounding box of a torus.
746 * CHANGES
748 * Jun 1994 : Creation.
750 ******************************************************************************/
752 void Compute_Torus_BBox(TORUS *Torus)
754 DBL r1, r2;
756 r1 = Torus->r;
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 /*****************************************************************************
768 * FUNCTION
770 * Test_Thick_Cylinder
772 * INPUT
774 * P - Ray initial
775 * D - Ray direction
776 * h1 - Height 1
777 * h2 - Height 2
778 * r1 - Square of inner radius
779 * r2 - Square of outer radius
781 * OUTPUT
783 * RETURNS
785 * int - TRUE, if hit
787 * AUTHOR
789 * Dieter Bayer
791 * DESCRIPTION
793 * Test if a given ray defined in the lathe's coordinate system
794 * intersects a "thick" cylinder (rotated about y-axis).
796 * CHANGES
798 * Jun 1994 : Creation.
800 ******************************************************************************/
802 int Test_Thick_Cylinder(VECTOR P, VECTOR D, DBL h1, DBL h2, DBL r1, DBL r2)
804 DBL a, b, c, d;
805 DBL u, v, k, r, h;
807 if (fabs(D[Y]) < EPSILON)
809 if ((P[Y] < h1) || (P[Y] > h2))
811 return(FALSE);
814 else
816 /* Intersect ray with the cap-plane. */
818 k = (h2 - P[Y]) / D[Y];
820 u = P[X] + k * D[X];
821 v = P[Z] + k * D[Z];
823 if ((k > EPSILON) && (k < Max_Distance))
825 r = u * u + v * v;
827 if ((r >= r1) && (r <= r2))
829 return(TRUE);
833 /* Intersectionersect ray with the base-plane. */
835 k = (h1 - P[Y]) / D[Y];
837 u = P[X] + k * D[X];
838 v = P[Z] + k * D[Z];
840 if ((k > EPSILON) && (k < Max_Distance))
842 r = u * u + v * v;
844 if ((r >= r1) && (r <= r2))
846 return(TRUE);
851 a = D[X] * D[X] + D[Z] * D[Z];
853 if (a > EPSILON)
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;
861 d = b * b - a * c;
863 if (d >= 0.0)
865 d = sqrt(d);
867 k = (-b + d) / a;
869 if ((k > EPSILON) && (k < Max_Distance))
871 h = P[Y] + k * D[Y];
873 if ((h >= h1) && (h <= h2))
875 return(TRUE);
879 k = (-b - d) / a;
881 if ((k > EPSILON) && (k < Max_Distance))
883 h = P[Y] + k * D[Y];
885 if ((h >= h1) && (h <= h2))
887 return(TRUE);
892 /* Intersect with inner cylinder. */
894 c = P[X] * P[X] + P[Z] * P[Z] - r1;
896 d = b * b - a * c;
898 if (d >= 0.0)
900 d = sqrt(d);
902 k = (-b + d) / a;
904 if ((k > EPSILON) && (k < Max_Distance))
906 h = P[Y] + k * D[Y];
908 if ((h >= h1) && (h <= h2))
910 return(TRUE);
914 k = (-b - d) / a;
916 if ((k > EPSILON) && (k < Max_Distance))
918 h = P[Y] + k * D[Y];
920 if ((h >= h1) && (h <= h2))
922 return(TRUE);
928 return(FALSE);