Simple test for asyncio.library.
[AROS-Contrib.git] / gfx / povray / super.c
blobc368c578f93900003ecbc62fc03b6b845579c25c
1 /****************************************************************************
2 * super.c
4 * This module implements functions that manipulate superellipsoids.
6 * Original code written by Alexander Enzmann.
7 * Adaption to POV-Ray by Dieter Bayer [DB].
9 * from Persistence of Vision(tm) Ray Tracer
10 * Copyright 1996,1999 Persistence of Vision Team
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 Team. There are strict rules under
15 * which you are permitted to use this file. The rules are in the file
16 * named POVLEGAL.DOC which should be distributed with this file.
17 * If POVLEGAL.DOC is not available or for more info please contact the POV-Ray
18 * Team Coordinator by email to team-coord@povray.org or visit us on the web at
19 * http://www.povray.org. The latest version of POV-Ray may be found at this site.
21 * This program is based on the popular DKB raytracer version 2.12.
22 * DKBTrace was originally written by David K. Buck.
23 * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
25 *****************************************************************************/
27 /****************************************************************************
29 * Explanation:
31 * Superellipsoids are defined by the implicit equation
33 * f(x,y,z) = (|x|^(2/e) + |y|^(2/e))^(e/n) + |z|^(2/n) - 1
35 * Where e is the east/west exponent and n is the north/south exponent.
37 * NOTE: The exponents are precomputed and stored in the Power element.
39 * NOTE: Values of e and n that are close to degenerate (e.g.,
40 * below around 0.1) appear to give the root solver fits.
41 * Not sure quite where the problem lays just yet.
43 * Syntax:
45 * superellipsoid { <e, n> }
48 * ---
50 * Oct 1994 : Creation.
52 *****************************************************************************/
54 #include "frame.h"
55 #include "povray.h"
56 #include "vector.h"
57 #include "povproto.h"
58 #include "bbox.h"
59 #include "matrices.h"
60 #include "objects.h"
61 #include "super.h"
65 /*****************************************************************************
66 * Local preprocessor defines
67 ******************************************************************************/
69 /* Minimal intersection depth for a valid intersection. */
71 #define DEPTH_TOLERANCE 1.0e-4
73 /* If |x| < ZERO_TOLERANCE it is regarded to be 0. */
75 #define ZERO_TOLERANCE 1.0e-10
77 /* This is not the signum function because SGNX(0) is 1. */
79 #define SGNX(x) (((x) >= 0.0) ? 1.0 : -1.0)
81 #define MIN_VALUE -1.0
82 #define MAX_VALUE 1.0
84 #define MAX_ITERATIONS 20
86 #define PLANECOUNT 9
90 /*****************************************************************************
91 * Local typedefs
92 ******************************************************************************/
96 /*****************************************************************************
97 * Static functions
98 ******************************************************************************/
100 static int intersect_superellipsoid (RAY *Ray, SUPERELLIPSOID *Superellipsoid, ISTACK *Depth_Stack);
101 static int intersect_box (VECTOR P, VECTOR D, DBL *dmin, DBL *dmax);
102 static DBL power (DBL x, DBL e);
103 static DBL evaluate_superellipsoid (VECTOR P, SUPERELLIPSOID *Superellipsoid);
104 static int compdists (CONST void *in_a, CONST void *in_b);
106 static int find_ray_plane_points (VECTOR P, VECTOR D, int cnt, DBL *dists, DBL mindist, DBL maxdist);
107 static void solve_hit1 (SUPERELLIPSOID *Super, DBL v0, VECTOR tP0, DBL v1, VECTOR tP1, VECTOR P);
108 static int check_hit2 (SUPERELLIPSOID *Super, VECTOR P, VECTOR D, DBL t0, VECTOR P0, DBL v0, DBL t1, DBL *t, VECTOR Q);
109 static int insert_hit (OBJECT *Object, RAY *Ray, DBL Depth, ISTACK *Depth_Stack);
111 static int All_Superellipsoid_Intersections (OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack);
112 static int Inside_Superellipsoid (VECTOR point, OBJECT *Object);
113 static void Superellipsoid_Normal (VECTOR Result, OBJECT *Object, INTERSECTION *Inter);
114 static SUPERELLIPSOID *Copy_Superellipsoid (OBJECT *Object);
115 static void Translate_Superellipsoid (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
116 static void Rotate_Superellipsoid (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
117 static void Scale_Superellipsoid (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
118 static void Transform_Superellipsoid (OBJECT *Object, TRANSFORM *Trans);
119 static void Invert_Superellipsoid (OBJECT *Object);
120 static void Destroy_Superellipsoid (OBJECT *Object);
122 /*****************************************************************************
123 * Local variables
124 ******************************************************************************/
126 static METHODS Superellipsoid_Methods =
128 All_Superellipsoid_Intersections,
129 Inside_Superellipsoid, Superellipsoid_Normal,
130 (COPY_METHOD)Copy_Superellipsoid,
131 Translate_Superellipsoid, Rotate_Superellipsoid,
132 Scale_Superellipsoid, Transform_Superellipsoid, Invert_Superellipsoid, Destroy_Superellipsoid
135 static DBL planes[PLANECOUNT][4] =
136 {{1, 1, 0, 0}, {1,-1, 0, 0},
137 {1, 0, 1, 0}, {1, 0,-1, 0},
138 {0, 1, 1, 0}, {0, 1,-1, 0},
139 {1, 0, 0, 0},
140 {0, 1, 0, 0},
141 {0, 0, 1, 0}};
145 /*****************************************************************************
147 * FUNCTION
149 * All_Superellipsoid_Intersections
151 * INPUT
153 * Object - Object
154 * Ray - Ray
155 * Depth_Stack - Intersection stack
157 * OUTPUT
159 * Depth_Stack
161 * RETURNS
163 * int - TRUE, if a intersection was found
165 * AUTHOR
167 * Dieter Bayer
169 * DESCRIPTION
171 * Determine ray/superellipsoid intersection and clip intersection found.
173 * CHANGES
175 * Oct 1994 : Creation.
177 ******************************************************************************/
179 static int All_Superellipsoid_Intersections(OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack)
181 Increase_Counter(stats[Ray_Superellipsoid_Tests]);
183 if (intersect_superellipsoid(Ray, (SUPERELLIPSOID *)Object, Depth_Stack))
185 Increase_Counter(stats[Ray_Superellipsoid_Tests_Succeeded]);
187 return(TRUE);
189 else
191 return(FALSE);
197 /*****************************************************************************
199 * FUNCTION
201 * intersect_superellipsoid
203 * INPUT
205 * Ray - Ray
206 * Superellipsoid - Superellipsoid
207 * Depth_Stack - Depth stack
209 * OUTPUT
211 * Intersection
213 * RETURNS
215 * int - TRUE if intersections were found.
217 * AUTHOR
219 * Alexander Enzmann, Dieter Bayer
221 * DESCRIPTION
223 * Determine ray/superellipsoid intersection.
225 * CHANGES
227 * Oct 1994 : Creation.
229 ******************************************************************************/
231 static int intersect_superellipsoid(RAY *Ray, SUPERELLIPSOID *Superellipsoid, ISTACK *Depth_Stack)
233 int i, cnt, Found = FALSE;
234 DBL dists[PLANECOUNT+2];
235 DBL t, t1, t2, v0, v1, len;
236 VECTOR P, D, P0, P1, P2, P3;
238 /* Transform the ray into the superellipsoid space. */
240 MInvTransPoint(P, Ray->Initial, Superellipsoid->Trans);
242 MInvTransDirection(D, Ray->Direction, Superellipsoid->Trans);
244 VLength(len, D);
246 VInverseScaleEq(D, len);
248 /* Intersect superellipsoid's bounding box. */
250 if (!intersect_box(P, D, &t1, &t2))
252 return(FALSE);
255 /* Test if superellipsoid lies 'behind' the ray origin. */
257 if (t2 < DEPTH_TOLERANCE)
259 return(FALSE);
262 cnt = 0;
264 if (t1 < DEPTH_TOLERANCE)
266 t1 = DEPTH_TOLERANCE;
269 dists[cnt++] = t1;
270 dists[cnt++] = t2;
272 /* Intersect ray with planes cutting superellipsoids in pieces. */
274 cnt = find_ray_plane_points(P, D, cnt, dists, t1, t2);
276 if (cnt <= 1)
278 return(FALSE);
281 VEvaluateRay(P0, P, dists[0], D)
283 v0 = evaluate_superellipsoid(P0, Superellipsoid);
285 if (fabs(v0) < ZERO_TOLERANCE)
287 if (insert_hit((OBJECT *)Superellipsoid, Ray, dists[0] / len, Depth_Stack))
289 if (Superellipsoid->Type & IS_CHILD_OBJECT)
291 Found = TRUE;
293 else
295 return(TRUE);
300 for (i = 1; i < cnt; i++)
302 VEvaluateRay(P1, P, dists[i], D)
304 v1 = evaluate_superellipsoid(P1, Superellipsoid);
306 if (fabs(v1) < ZERO_TOLERANCE)
308 if (insert_hit((OBJECT *)Superellipsoid, Ray, dists[i] / len, Depth_Stack))
310 if (Superellipsoid->Type & IS_CHILD_OBJECT)
312 Found = TRUE;
314 else
316 return(TRUE);
320 else
322 if (v0 * v1 < 0.0)
324 /* Opposite signs, there must be a root between */
326 solve_hit1(Superellipsoid, v0, P0, v1, P1, P2);
328 VSub(P3, P2, P);
330 VLength(t, P3);
332 if (insert_hit((OBJECT *)Superellipsoid, Ray, t / len, Depth_Stack))
334 if (Superellipsoid->Type & IS_CHILD_OBJECT)
336 Found = TRUE;
338 else
340 return(TRUE);
344 else
347 * Although there was no sign change, we may actually be approaching
348 * the surface. In this case, we are being fooled by the shape of the
349 * surface into thinking there isn't a root between sample points.
352 if (check_hit2(Superellipsoid, P, D, dists[i-1], P0, v0, dists[i], &t, P2))
354 if (insert_hit((OBJECT *)Superellipsoid, Ray, t / len, Depth_Stack))
356 if (Superellipsoid->Type & IS_CHILD_OBJECT)
358 Found = TRUE;
360 else
362 return(TRUE);
365 else
367 break;
373 v0 = v1;
375 Assign_Vector(P0, P1);
378 return(Found);
383 /*****************************************************************************
385 * FUNCTION
387 * Inside_Superellipsoid
389 * INPUT
391 * IPoint - Intersection point
392 * Object - Object
394 * OUTPUT
396 * RETURNS
398 * int - TRUE if inside
400 * AUTHOR
402 * Dieter Bayer
404 * DESCRIPTION
406 * Test if a point lies inside the superellipsoid.
408 * CHANGES
410 * Oct 1994 : Creation.
412 ******************************************************************************/
414 static int Inside_Superellipsoid(VECTOR IPoint, OBJECT *Object)
416 DBL val;
417 VECTOR P;
418 SUPERELLIPSOID *Superellipsoid = (SUPERELLIPSOID *)Object;
420 /* Transform the point into the superellipsoid space. */
422 MInvTransPoint(P, IPoint, Superellipsoid->Trans);
424 val = evaluate_superellipsoid(P, Superellipsoid);
426 if (val < EPSILON)
428 return(!Test_Flag(Superellipsoid, INVERTED_FLAG));
430 else
432 return(Test_Flag(Superellipsoid, INVERTED_FLAG));
438 /*****************************************************************************
440 * FUNCTION
442 * Superellipsoid_Normal
444 * INPUT
446 * Result - Normal vector
447 * Object - Object
448 * Inter - Intersection found
450 * OUTPUT
452 * Result
454 * RETURNS
456 * AUTHOR
458 * Dieter Bayer
460 * DESCRIPTION
462 * Calculate the normal of the superellipsoid in a given point.
464 * CHANGES
466 * Oct 1994 : Creation.
468 ******************************************************************************/
470 static void Superellipsoid_Normal(VECTOR Result, OBJECT *Object, INTERSECTION *Inter)
472 DBL k, x, y, z;
473 VECTOR P, N, E;
474 SUPERELLIPSOID *Superellipsoid = (SUPERELLIPSOID *)Object;
476 /* Transform the point into the superellipsoid space. */
478 MInvTransPoint(P, Inter->IPoint, Superellipsoid->Trans);
480 Assign_Vector(E, Superellipsoid->Power);
482 x = fabs(P[X]);
483 y = fabs(P[Y]);
484 z = fabs(P[Z]);
486 k = power(power(x, E[X]) + power(y, E[X]), E[Y] - 1.0);
488 N[X] = k * SGNX(P[X]) * power(x, E[X] - 1.0);
489 N[Y] = k * SGNX(P[Y]) * power(y, E[X] - 1.0);
490 N[Z] = SGNX(P[Z]) * power(z, E[Z] - 1.0);
492 /* Transform the normalt out of the superellipsoid space. */
494 MTransNormal(Result, N, Superellipsoid->Trans);
496 VNormalize(Result, Result);
501 /*****************************************************************************
503 * FUNCTION
505 * Translate_Superellipsoid
507 * INPUT
509 * Object - Object
510 * Vector - Translation vector
512 * OUTPUT
514 * Object
516 * RETURNS
518 * AUTHOR
520 * Dieter Bayer
522 * DESCRIPTION
524 * Translate a superellipsoid.
526 * CHANGES
528 * Oct 1994 : Creation.
530 ******************************************************************************/
532 static void Translate_Superellipsoid(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
534 Transform_Superellipsoid(Object, Trans);
539 /*****************************************************************************
541 * FUNCTION
543 * Rotate_Superellipsoid
545 * INPUT
547 * Object - Object
548 * Vector - Rotation vector
550 * OUTPUT
552 * Object
554 * RETURNS
556 * AUTHOR
558 * Dieter Bayer
560 * DESCRIPTION
562 * Rotate a superellipsoid.
564 * CHANGES
566 * Oct 1994 : Creation.
568 ******************************************************************************/
570 static void Rotate_Superellipsoid(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
572 Transform_Superellipsoid(Object, Trans);
577 /*****************************************************************************
579 * FUNCTION
581 * Scale_Superellipsoid
583 * INPUT
585 * Object - Object
586 * Vector - Scaling vector
588 * OUTPUT
590 * Object
592 * RETURNS
594 * AUTHOR
596 * Dieter Bayer
598 * DESCRIPTION
600 * Scale a superellipsoid.
602 * CHANGES
604 * Oct 1994 : Creation.
606 ******************************************************************************/
608 static void Scale_Superellipsoid(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
610 Transform_Superellipsoid(Object, Trans);
615 /*****************************************************************************
617 * FUNCTION
619 * Transform_Superellipsoid
621 * INPUT
623 * Object - Object
624 * Trans - Transformation to apply
626 * OUTPUT
628 * Object
630 * RETURNS
632 * AUTHOR
634 * Dieter Bayer
636 * DESCRIPTION
638 * Transform a superellipsoid and recalculate its bounding box.
640 * CHANGES
642 * Oct 1994 : Creation.
644 ******************************************************************************/
646 static void Transform_Superellipsoid(OBJECT *Object, TRANSFORM *Trans)
648 Compose_Transforms(((SUPERELLIPSOID *)Object)->Trans, Trans);
650 Compute_Superellipsoid_BBox((SUPERELLIPSOID *)Object);
655 /*****************************************************************************
657 * FUNCTION
659 * Invert_Superellipsoid
661 * INPUT
663 * Object - Object
665 * OUTPUT
667 * Object
669 * RETURNS
671 * AUTHOR
673 * Dieter Bayer
675 * DESCRIPTION
677 * Invert a superellipsoid.
679 * CHANGES
681 * Oct 1994 : Creation.
683 ******************************************************************************/
685 static void Invert_Superellipsoid(OBJECT *Object)
687 Invert_Flag(Object, INVERTED_FLAG);
692 /*****************************************************************************
694 * FUNCTION
696 * Create_Superellipsoid
698 * INPUT
700 * OUTPUT
702 * RETURNS
704 * SUPERELLIPSOID * - new superellipsoid
706 * AUTHOR
708 * Dieter Bayer
710 * DESCRIPTION
712 * Create a new superellipsoid.
714 * CHANGES
716 * Oct 1994 : Creation.
718 ******************************************************************************/
720 SUPERELLIPSOID *Create_Superellipsoid()
722 SUPERELLIPSOID *New;
724 New = (SUPERELLIPSOID *)POV_MALLOC(sizeof(SUPERELLIPSOID), "superellipsoid");
726 INIT_OBJECT_FIELDS(New,SUPERELLIPSOID_OBJECT,&Superellipsoid_Methods)
728 New->Trans = Create_Transform();
730 Make_Vector(New->Power, 2.0, 2.0, 2.0);
732 return(New);
737 /*****************************************************************************
739 * FUNCTION
741 * Copy_Superellipsoid
743 * INPUT
745 * Object - Object
747 * OUTPUT
749 * RETURNS
751 * void * - New superellipsoid
753 * AUTHOR
755 * Dieter Bayer
757 * DESCRIPTION
759 * Copy a superellipsoid structure.
761 * CHANGES
763 * Oct 1994 : Creation.
765 ******************************************************************************/
767 static SUPERELLIPSOID *Copy_Superellipsoid(OBJECT *Object)
769 SUPERELLIPSOID *New, *Superellipsoid = (SUPERELLIPSOID *)Object;
771 New = Create_Superellipsoid();
773 /* Get rid of the transformation created in Create_Superellipsoid(). */
775 Destroy_Transform(New->Trans);
777 /* Copy superellipsoid. */
779 *New = *Superellipsoid;
781 New->Trans = Copy_Transform(Superellipsoid->Trans);
783 return(New);
788 /*****************************************************************************
790 * FUNCTION
792 * Destroy_Superellipsoid
794 * INPUT
796 * Object - Object
798 * OUTPUT
800 * Object
802 * RETURNS
804 * AUTHOR
806 * Dieter Bayer
808 * DESCRIPTION
810 * Destroy a superellipsoid.
812 * CHANGES
814 * Oct 1994 : Creation.
816 ******************************************************************************/
818 static void Destroy_Superellipsoid(OBJECT *Object)
820 SUPERELLIPSOID *Superellipsoid = (SUPERELLIPSOID *)Object;
822 Destroy_Transform(Superellipsoid->Trans);
824 POV_FREE (Object);
829 /*****************************************************************************
831 * FUNCTION
833 * Compute_Superellipsoid_BBox
835 * INPUT
837 * Superellipsoid - Superellipsoid
839 * OUTPUT
841 * Superellipsoid
843 * RETURNS
845 * AUTHOR
847 * Dieter Bayer
849 * DESCRIPTION
851 * Calculate the bounding box of a superellipsoid.
853 * CHANGES
855 * Oct 1994 : Creation.
857 ******************************************************************************/
859 void Compute_Superellipsoid_BBox(SUPERELLIPSOID *Superellipsoid)
861 Make_BBox(Superellipsoid->BBox, -1.0001, -1.0001, -1.0001, 2.0002, 2.0002, 2.0002);
863 Recompute_BBox(&Superellipsoid->BBox, Superellipsoid->Trans);
868 /*****************************************************************************
870 * FUNCTION
872 * intersect_box
874 * INPUT
876 * P, D - Ray origin and direction
877 * dmin, dmax - Intersection depths
879 * OUTPUT
881 * dmin, dmax
883 * RETURNS
885 * int - TRUE, if hit
887 * AUTHOR
889 * Dieter Bayer
891 * DESCRIPTION
893 * Intersect a ray with an axis aligned unit box.
895 * CHANGES
897 * Oct 1994 : Creation.
899 ******************************************************************************/
901 static int intersect_box(VECTOR P, VECTOR D, DBL *dmin, DBL *dmax)
903 DBL tmin = 0.0, tmax = 0.0;
905 /* Left/right. */
907 if (fabs(D[X]) > EPSILON)
909 if (D[X] > EPSILON)
911 *dmin = (MIN_VALUE - P[X]) / D[X];
913 *dmax = (MAX_VALUE - P[X]) / D[X];
915 if (*dmax < EPSILON) return(FALSE);
917 else
919 *dmax = (MIN_VALUE - P[X]) / D[X];
921 if (*dmax < EPSILON) return(FALSE);
923 *dmin = (MAX_VALUE - P[X]) / D[X];
926 if (*dmin > *dmax) return(FALSE);
928 else
930 if ((P[X] < MIN_VALUE) || (P[X] > MAX_VALUE))
932 return(FALSE);
935 *dmin = -BOUND_HUGE;
936 *dmax = BOUND_HUGE;
939 /* Top/bottom. */
941 if (fabs(D[Y]) > EPSILON)
943 if (D[Y] > EPSILON)
945 tmin = (MIN_VALUE - P[Y]) / D[Y];
947 tmax = (MAX_VALUE - P[Y]) / D[Y];
949 else
951 tmax = (MIN_VALUE - P[Y]) / D[Y];
953 tmin = (MAX_VALUE - P[Y]) / D[Y];
956 if (tmax < *dmax)
958 if (tmax < EPSILON) return(FALSE);
960 if (tmin > *dmin)
962 if (tmin > tmax) return(FALSE);
964 *dmin = tmin;
966 else
968 if (*dmin > tmax) return(FALSE);
971 *dmax = tmax;
973 else
975 if (tmin > *dmin)
977 if (tmin > *dmax) return(FALSE);
979 *dmin = tmin;
983 else
985 if ((P[Y] < MIN_VALUE) || (P[Y] > MAX_VALUE))
987 return(FALSE);
991 /* Front/back. */
993 if (fabs(D[Z]) > EPSILON)
995 if (D[Z] > EPSILON)
997 tmin = (MIN_VALUE - P[Z]) / D[Z];
999 tmax = (MAX_VALUE - P[Z]) / D[Z];
1001 else
1003 tmax = (MIN_VALUE - P[Z]) / D[Z];
1005 tmin = (MAX_VALUE - P[Z]) / D[Z];
1008 if (tmax < *dmax)
1010 if (tmax < EPSILON) return(FALSE);
1012 if (tmin > *dmin)
1014 if (tmin > tmax) return(FALSE);
1016 *dmin = tmin;
1018 else
1020 if (*dmin > tmax) return(FALSE);
1023 *dmax = tmax;
1025 else
1027 if (tmin > *dmin)
1029 if (tmin > *dmax) return(FALSE);
1031 *dmin = tmin;
1035 else
1037 if ((P[Z] < MIN_VALUE) || (P[Z] > MAX_VALUE))
1039 return(FALSE);
1043 *dmin = tmin;
1044 *dmax = tmax;
1046 return(TRUE);
1051 /*****************************************************************************
1053 * FUNCTION
1055 * evaluate_superellipsoid
1057 * INPUT
1059 * P - Point to evaluate
1060 * Superellipsoid - Pointer to superellipsoid
1062 * OUTPUT
1064 * RETURNS
1066 * DBL
1068 * AUTHOR
1070 * Dieter Bayer
1072 * DESCRIPTION
1074 * Get superellipsoid value in the given point.
1076 * CHANGES
1078 * Oct 1994 : Creation.
1080 ******************************************************************************/
1082 static DBL evaluate_superellipsoid(VECTOR P, SUPERELLIPSOID *Superellipsoid)
1084 VECTOR V1;
1086 V1[X] = power(fabs(P[X]), Superellipsoid->Power[X]);
1087 V1[Y] = power(fabs(P[Y]), Superellipsoid->Power[X]);
1088 V1[Z] = power(fabs(P[Z]), Superellipsoid->Power[Z]);
1090 return(power(V1[X] + V1[Y], Superellipsoid->Power[Y]) + V1[Z] - 1.0);
1095 /*****************************************************************************
1097 * FUNCTION
1099 * power
1101 * INPUT
1103 * x - Argument
1104 * e - Power
1106 * OUTPUT
1108 * RETURNS
1110 * DBL
1112 * AUTHOR
1114 * Dieter Bayer
1116 * DESCRIPTION
1118 * Raise x to the power of e.
1120 * CHANGES
1122 * Oct 1994 : Creation.
1124 ******************************************************************************/
1126 static DBL power(DBL x, DBL e)
1128 register int i;
1129 register DBL b;
1131 b = x;
1133 i = (int)e;
1135 /* Test if we have an integer power. */
1137 if (e == (DBL)i)
1139 switch (i)
1141 case 0: return(1.0);
1143 case 1: return(b);
1145 case 2: return(Sqr(b));
1147 case 3: return(Sqr(b) * b);
1149 case 4: b *= b; return(Sqr(b));
1151 case 5: b *= b; return(Sqr(b) * x);
1153 case 6: b *= b; return(Sqr(b) * b);
1155 default: return(pow(x, e));
1158 else
1160 return(pow(x, e));
1166 /*****************************************************************************
1168 * FUNCTION
1170 * insert_hit
1172 * INPUT
1174 * Object - Object
1175 * Ray - Ray
1176 * Depth - Intersection depth
1177 * Depth_Stack - Intersection stack
1179 * OUTPUT
1181 * Depth_Stack
1183 * RETURNS
1185 * int - TRUE, if intersection is valid
1187 * AUTHOR
1189 * Dieter Bayer
1191 * DESCRIPTION
1193 * Push an intersection onto the depth stack if it is valid.
1195 * CHANGES
1197 * Nov 1994 : Creation.
1199 ******************************************************************************/
1201 static int insert_hit(OBJECT *Object, RAY *Ray, DBL Depth, ISTACK *Depth_Stack)
1203 VECTOR IPoint;
1205 if ((Depth > DEPTH_TOLERANCE) && (Depth < Max_Distance))
1207 VEvaluateRay(IPoint, Ray->Initial, Depth, Ray->Direction);
1209 if (Point_In_Clip(IPoint, Object->Clip))
1211 push_entry(Depth, IPoint, Object, Depth_Stack);
1213 return(TRUE);
1217 return(FALSE);
1222 /*****************************************************************************
1224 * FUNCTION
1226 * compdists
1228 * INPUT
1230 * OUTPUT
1232 * RETURNS
1234 * AUTHOR
1236 * Alexander Enzmann
1238 * DESCRIPTION
1240 * Compare two slabs.
1242 * CHANGES
1244 * Nov 1994 : Creation.
1246 ******************************************************************************/
1248 static int compdists(CONST void *in_a, CONST void *in_b)
1250 DBL a, b;
1252 a = *((DBL *)in_a);
1253 b = *((DBL *)in_b);
1255 if (a < b)
1257 return(-1);
1260 if (a == b)
1262 return(0);
1264 else
1266 return(1);
1272 /*****************************************************************************
1274 * FUNCTION
1276 * find_ray_plane_points
1278 * INPUT
1280 * OUTPUT
1282 * RETURNS
1284 * AUTHOR
1286 * Alexander Enzmann
1288 * DESCRIPTION
1290 * Find all the places where the ray intersects the set of
1291 * subdividing planes through the superquadric. Return the
1292 * number of valid hits (within the bounding box).
1294 * CHANGES
1296 * Nov 1994 : Creation.
1298 ******************************************************************************/
1300 static int find_ray_plane_points(VECTOR P, VECTOR D, int cnt, DBL *dists, DBL mindist, DBL maxdist)
1302 int i;
1303 DBL t, d;
1305 /* Since min and max dist are the distance to two of the bounding planes
1306 we are considering, there is a high probablity of missing them due to
1307 round off error. Therefore we adjust min and max. */
1309 t = EPSILON * (maxdist - mindist);
1311 mindist -= t;
1312 maxdist += t;
1314 /* Check the sets of planes that cut apart the superquadric. */
1316 for (i = 0; i < PLANECOUNT; i++)
1318 d = (D[0] * planes[i][0] + D[1] * planes[i][1] + D[2] * planes[i][2]);
1320 if (fabs(d) < EPSILON)
1322 /* Can't possibly get a hit for this combination of ray and plane. */
1324 continue;
1327 t = (planes[i][3] - (P[0] * planes[i][0] + P[1] * planes[i][1] + P[2] * planes[i][2])) / d;
1329 if ((t >= mindist) && (t <= maxdist))
1331 dists[cnt++] = t;
1335 /* Sort the results for further processing. */
1337 QSORT((void *)(dists), (size_t)cnt, sizeof(DBL), compdists);
1339 return(cnt);
1344 /*****************************************************************************
1346 * FUNCTION
1348 * solve_hit1
1350 * INPUT
1352 * OUTPUT
1354 * RETURNS
1356 * AUTHOR
1358 * Alexander Enzmann
1360 * DESCRIPTION
1362 * Home in on the root of a superquadric using a combination of
1363 * secant and bisection methods. This routine requires that
1364 * the sign of the function be different at P0 and P1, it will
1365 * fail drastically if this isn't the case.
1367 * CHANGES
1369 * Nov 1994 : Creation.
1371 ******************************************************************************/
1373 static void solve_hit1(SUPERELLIPSOID *Super, DBL v0, VECTOR tP0, DBL v1, VECTOR tP1, VECTOR P)
1375 int i;
1376 DBL x, v2, v3;
1377 VECTOR P0, P1, P2, P3;
1379 Assign_Vector(P0, tP0);
1380 Assign_Vector(P1, tP1);
1382 /* The sign of v0 and v1 changes between P0 and P1, this
1383 means there is an intersection point in there somewhere. */
1385 for (i = 0; i < MAX_ITERATIONS; i++)
1387 if (fabs(v0) < ZERO_TOLERANCE)
1389 /* Near point is close enough to an intersection - just use it. */
1391 Assign_Vector(P, P0);
1393 break;
1396 if (fabs(v1) < ZERO_TOLERANCE)
1398 /* Far point is close enough to an intersection. */
1400 Assign_Vector(P, P1);
1402 break;
1405 /* Look at the chord connecting P0 and P1. */
1407 /* Assume a line between the points. */
1409 x = fabs(v0) / fabs(v1 - v0);
1411 VSub(P2, P1, P0);
1413 VAddScaled(P2, P0, x, P2);
1415 v2 = evaluate_superellipsoid(P2, Super);
1417 /* Look at the midpoint between P0 and P1. */
1419 VSub(P3, P1, P0);
1421 VAddScaled(P3, P0, 0.5, P3);
1423 v3 = evaluate_superellipsoid(P3, Super);
1425 if (v0 * v2 > 0.0)
1427 if (v1 * v2 > 0.0)
1429 /* This should be impossible, since v0 and v1 were opposite signs,
1430 v2 must be either 0 or opposite in sign to either v0 or v1. */
1432 Error("internal failure in function solve_sq_hit1: %d, %g, %g, %g", i, v0, v1, v2);
1434 else
1436 if (v0 * v3 > 0.0)
1438 if (x < 0.5)
1440 Assign_Vector(P0, P3);
1442 else
1444 Assign_Vector(P0, P2);
1447 else
1449 /* We can move both ends. */
1451 Assign_Vector(P0, P2);
1453 Assign_Vector(P1, P3);
1457 else
1459 if (v0 * v3 > 0.0)
1461 /* We can move both ends. */
1463 Assign_Vector(P0, P3);
1465 Assign_Vector(P1, P2);
1467 else
1469 if (x < 0.5)
1471 Assign_Vector(P1, P2);
1473 else
1475 Assign_Vector(P1, P3);
1481 if (i == MAX_ITERATIONS)
1483 /* The loop never quite closed in on the result - just use the point
1484 closest to zero. This really shouldn't happen since the max number
1485 of iterations is enough to converge with straight bisection. */
1487 if (fabs(v0) < fabs(v1))
1489 Assign_Vector(P, P0);
1491 else
1493 Assign_Vector(P, P1);
1501 /*****************************************************************************
1503 * FUNCTION
1505 * check_hit2
1507 * INPUT
1509 * OUTPUT
1511 * RETURNS
1513 * AUTHOR
1515 * Alexander Enzmann
1517 * DESCRIPTION
1519 * Try to find the root of a superquadric using Newtons method.
1521 * CHANGES
1523 * Nov 1994 : Creation.
1525 ******************************************************************************/
1527 static int check_hit2(SUPERELLIPSOID *Super, VECTOR P, VECTOR D, DBL t0, VECTOR P0, DBL v0, DBL t1, DBL *t, VECTOR Q)
1529 int i;
1530 DBL dt0, dt1, v1, deltat, maxdelta;
1531 VECTOR P1;
1533 dt0 = t0;
1534 dt1 = t0 + 0.0001 * (t1 - t0);
1536 maxdelta = t1 - t0;
1538 for (i = 0; (dt0 < t1) && (i < MAX_ITERATIONS); i++)
1540 VEvaluateRay(P1, P, dt1, D)
1542 v1 = evaluate_superellipsoid(P1, Super);
1544 if (v0 * v1 < 0)
1546 /* Found a crossing point, go back and use normal root solving. */
1548 solve_hit1(Super, v0, P0, v1, P1, Q);
1550 VSub(P0, Q, P);
1552 VLength(*t, P0);
1554 return(TRUE);
1556 else
1558 if (fabs(v1) < ZERO_TOLERANCE)
1560 VEvaluateRay(Q, P, dt1, D)
1562 *t = dt1;
1564 return(TRUE);
1566 else
1568 if (((v0 > 0.0) && (v1 > v0)) || ((v0 < 0.0) && (v1 < v0)))
1570 /* We definitely failed */
1572 break;
1574 else
1576 if (v1 == v0)
1578 break;
1580 else
1582 deltat = v1 * (dt1 - dt0) / (v1 - v0);
1588 if (fabs(deltat) > maxdelta)
1590 break;
1593 v0 = v1;
1595 dt0 = dt1;
1597 dt1 -= deltat;
1600 return(FALSE);