1 /****************************************************************************
4 * This module implements functions that manipulate lathes.
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 * Modification from Thomas Willhalm, March 1999, used with permission
26 *****************************************************************************/
28 /****************************************************************************
32 * The lathe primitive is defined by a set of points in 2d space which
33 * are interpolated by linear, quadratic, or cubic splines. The resulting
34 * 2d curve is rotated about an axis to form the final lathe object.
36 * All calculations are done in the object's (u,v,w)-coordinate system
37 * with the (w)-axis being the rotation axis.
39 * One spline segment in the (r,w)-plane is given by the equations
41 * fw(t) = Aw * t^3 + Bw * t^2 + Cw * t + Dw and
42 * fr(t) = Ar * t^3 + Br * t^2 + Cr * t + Dr,
44 * with the parameter t ranging from 0 to 1 and r = sqrt(u*u+v*v).
46 * To intersect a ray R = P + k * D transformed into the object's
47 * coordinate system with the lathe object, the equations
49 * (Pu + k * Du)^2 + (Pv + k * Dv)^2 = (fr(t))^2
50 * (Pw + k * Dw) = fw(t)
52 * have to be solved for t. For valid intersections (0 <= t <= 1)
53 * the corresponding k can be calculated from one of the above equations.
55 * Note that the degree of the polynomal to solve is two times the
56 * degree of the spline segments used.
58 * Note that Pu, Pv, Pw and Du, Dv, Dw denote the coordinates
59 * of the vectors P and D.
65 * [ linear_spline | quadratic_spline | cubic_spline ]
69 * <P[0]>, <P[1], ..., <P[n-1]>
74 * Note that the P[i] are 2d vectors.
76 * Linear interpolation is used by default. In this case all n Points
77 * are used. In the quadratic case the first point is used to determine
78 * the derivates at the starting point P[1]. In the cubic case
79 * the first and last points are used to determine the derivatives at
80 * the starting point P[1] and ending point P[n-2].
82 * To get a closed (and smooth) curve you have make sure that
84 * P[0] = P[n-1] in the linear case,
86 * P[0] = P[n-2] and P[1] = P[n-1] in the quadratic case, and
88 * P[0] = P[n-3] and P[1] = P[n-2] and P[2] = P[n-1] in the cubic case.
90 * Note that the x coordinate of a point corresponds to the r coordinate
91 * and the y coordinate to the w coordinate;
95 * Ideas for the lathe were taken from:
97 * P. Burger and D. Gillies, "Rapid Ray Tracing of General Surfaces
98 * of Revolution", New Advances in Computer Graphics, Proceedings
99 * of CG International '89, R. A. Earnshaw, B. Wyvill (Eds.),
100 * Springer, ..., pp. 523-531
102 * P. Burger and D. Gillies, "Swept Surfaces", Interactive Computer
103 * Graphics, Addison-Wesley, 1989, pp. 376-380
107 * Jun 1994 : Creation. [DB]
109 *****************************************************************************/
114 #include "povproto.h"
118 #include "polysolv.h"
119 #include "matrices.h"
125 /*****************************************************************************
126 * Local preprocessor defines
127 ******************************************************************************/
129 /* Minimal intersection depth for a valid intersection. */
131 #define DEPTH_TOLERANCE 1.0e-4
133 /* Max. number of intersecions per spline segment. */
135 #define MAX_INTERSECTIONS_PER_SEGMENT 4
139 /*****************************************************************************
141 ******************************************************************************/
145 /*****************************************************************************
147 ******************************************************************************/
149 static int intersect_lathe (RAY
*Ray
, LATHE
*Lathe
, ISTACK
*Depth_Stack
);
150 static int All_Lathe_Intersections (OBJECT
*Object
, RAY
*Ray
, ISTACK
*Depth_Stack
);
151 static int Inside_Lathe (VECTOR point
, OBJECT
*Object
);
152 static void Lathe_Normal (VECTOR Result
, OBJECT
*Object
, INTERSECTION
*Inter
);
153 static LATHE
*Copy_Lathe (OBJECT
*Object
);
154 static void Translate_Lathe (OBJECT
*Object
, VECTOR Vector
, TRANSFORM
*Trans
);
155 static void Rotate_Lathe (OBJECT
*Object
, VECTOR Vector
, TRANSFORM
*Trans
);
156 static void Scale_Lathe (OBJECT
*Object
, VECTOR Vector
, TRANSFORM
*Trans
);
157 static void Transform_Lathe (OBJECT
*Object
, TRANSFORM
*Trans
);
158 static void Invert_Lathe (OBJECT
*Object
);
159 static void Destroy_Lathe (OBJECT
*Object
);
161 static int test_hit (LATHE
*, RAY
*, ISTACK
*, DBL
, DBL
, int);
164 /*****************************************************************************
166 ******************************************************************************/
168 static METHODS Lathe_Methods
=
170 All_Lathe_Intersections
,
171 Inside_Lathe
, Lathe_Normal
,
172 (COPY_METHOD
)Copy_Lathe
,
173 Translate_Lathe
, Rotate_Lathe
,
174 Scale_Lathe
, Transform_Lathe
, Invert_Lathe
, Destroy_Lathe
179 /*****************************************************************************
183 * All_Lathe_Intersections
189 * Depth_Stack - Intersection stack
197 * int - TRUE, if a intersection was found
205 * Determine ray/lathe intersection and clip intersection found.
209 * Jun 1994 : Creation.
210 * Oct 1996 : Changed code to include faster version. [DB]
212 ******************************************************************************/
214 static int All_Lathe_Intersections(OBJECT
*Object
, RAY
*Ray
, ISTACK
*Depth_Stack
)
216 Increase_Counter(stats
[Ray_Lathe_Tests
]);
218 if (intersect_lathe(Ray
, (LATHE
*)Object
, Depth_Stack
))
220 Increase_Counter(stats
[Ray_Lathe_Tests_Succeeded
]);
230 /*****************************************************************************
240 * Intersection - Lathe intersection structure
248 * int - Number of intersections found
256 * Determine ray/lathe intersection.
258 * NOTE: The curve is rotated about the y-axis!
259 * Order of the polynomial must not be used!
263 * Jun 1994 : Creation.
264 * Oct 1996 : Changed code to include faster version. [DB]
266 ******************************************************************************/
268 static int intersect_lathe(RAY
*Ray
, LATHE
*Lathe
, ISTACK
*Depth_Stack
)
271 int found
, j
, n1
, n2
;
272 DBL k
, len
, r
, m
, w
, Dy2
, r0
;
273 DBL x1
[7], x2
[3], y1
[6], y2
[2];
277 LATHE_SPLINE_ENTRY
*Entry
;
279 /* Transform the ray into the lathe space. */
281 MInvTransPoint(P
, Ray
->Initial
, Lathe
->Trans
);
283 MInvTransDirection(D
, Ray
->Direction
, Lathe
->Trans
);
287 VInverseScaleEq(D
, len
);
289 /* Test if ray misses lathe's cylindrical bound. */
291 #ifdef LATHE_EXTRA_STATS
292 Increase_Counter(stats
[Lathe_Bound_Tests
]);
295 if (((D
[Y
] >= 0.0) && (P
[Y
] > Lathe
->Height2
)) ||
296 ((D
[Y
] <= 0.0) && (P
[Y
] < Lathe
->Height1
)) ||
297 ((D
[X
] >= 0.0) && (P
[X
] > Lathe
->Radius2
)) ||
298 ((D
[X
] <= 0.0) && (P
[X
] < -Lathe
->Radius2
)))
303 /* Get distance r0 of the ray from rotation axis (i.e. y axis). */
305 r0
= fabs(P
[X
] * D
[Z
] - P
[Z
] * D
[X
]);
307 r
= D
[X
] * D
[X
] + D
[Z
] * D
[Z
];
314 /* Test if ray misses lathe's cylindrical bound. */
316 if (r0
> Lathe
->Radius2
)
321 /* Intersect all cylindrical bounds. */
323 if ((cnt
= Intersect_BCyl(Lathe
->Spline
->BCyl
, P
, D
)) == 0)
328 #ifdef LATHE_EXTRA_STATS
329 Increase_Counter(stats
[Lathe_Bound_Tests_Succeeded
]);
332 /* Precalculate some constants that are ray-dependant only. */
334 m
= D
[X
] * P
[X
] + D
[Z
] * P
[Z
];
338 /* Step through the list of intersections. */
344 intervals
= Lathe
->Spline
->BCyl
->intervals
;
346 for (j
= 0; j
< cnt
; j
++)
348 /* Get current segment. */
350 Entry
= &Lathe
->Spline
->Entry
[intervals
[j
].n
];
352 /* If we already have the best intersection we may exit. */
354 if (!(Lathe
->Type
& IS_CHILD_OBJECT
) && (intervals
[j
].d
[0] > best
))
359 /* Init number of roots found. */
363 /* Intersect segment. */
365 switch (Lathe
->Spline_Type
)
367 /***********************************************************************
369 ************************************************************************/
373 /* Solve 2th order polynomial. */
375 x1
[0] = Entry
->C
[Y
] * Entry
->C
[Y
] * r
- Entry
->C
[X
] * Entry
->C
[X
] * Dy2
;
377 x1
[1] = 2.0 * (Entry
->C
[Y
] * ((Entry
->D
[Y
] - P
[Y
]) * r
+ D
[Y
] * m
) - Entry
->C
[X
] * Entry
->D
[X
] * Dy2
);
379 x1
[2] = (Entry
->D
[Y
] - P
[Y
]) * ((Entry
->D
[Y
] - P
[Y
]) * r
+ 2.0 * D
[Y
] * m
) + Dy2
* (P
[X
] * P
[X
] + P
[Z
] * P
[Z
] - Entry
->D
[X
] * Entry
->D
[X
]);
381 n1
= Solve_Polynomial(2, x1
, y1
, FALSE
, 0.0);
385 /***********************************************************************
387 ************************************************************************/
389 case QUADRATIC_SPLINE
:
391 /* Solve 4th order polynomial. */
393 x1
[0] = Entry
->B
[Y
] * Entry
->B
[Y
] * r
- Entry
->B
[X
] * Entry
->B
[X
] * Dy2
;
395 x1
[1] = 2.0 * (Entry
->B
[Y
] * Entry
->C
[Y
] * r
- Entry
->B
[X
] * Entry
->C
[X
] * Dy2
);
397 x1
[2] = r
* (2.0 * Entry
->B
[Y
] * (Entry
->D
[Y
] - P
[Y
]) + Entry
->C
[Y
] * Entry
->C
[Y
]) + 2.0 * Entry
->B
[Y
] * D
[Y
] * m
- (2.0 * Entry
->B
[X
] * Entry
->D
[X
] + Entry
->C
[X
] * Entry
->C
[X
]) * Dy2
;
399 x1
[3] = 2.0 * (Entry
->C
[Y
] * ((Entry
->D
[Y
] - P
[Y
]) * r
+ D
[Y
] * m
) - Entry
->C
[X
] * Entry
->D
[X
] * Dy2
);
401 x1
[4] = (Entry
->D
[Y
] - P
[Y
]) * ((Entry
->D
[Y
] - P
[Y
]) * r
+ 2.0 * D
[Y
] * m
) + Dy2
* (P
[X
] * P
[X
] + P
[Z
] * P
[Z
] - Entry
->D
[X
] * Entry
->D
[X
]);
403 n1
= Solve_Polynomial(4, x1
, y1
, Test_Flag(Lathe
, STURM_FLAG
), 0.0);
407 /***********************************************************************
409 ************************************************************************/
414 /* Solve 6th order polynomial. */
416 x1
[0] = Entry
->A
[Y
] * Entry
->A
[Y
] * r
- Entry
->A
[X
] * Entry
->A
[X
] * Dy2
;
418 x1
[1] = 2.0 * (Entry
->A
[Y
] * Entry
->B
[Y
] * r
- Entry
->A
[X
] * Entry
->B
[X
] * Dy2
);
420 x1
[2] = (2.0 * Entry
->A
[Y
] * Entry
->C
[Y
] + Entry
->B
[Y
] * Entry
->B
[Y
]) * r
- (2.0 * Entry
->A
[X
] * Entry
->C
[X
] + Entry
->B
[X
] * Entry
->B
[X
]) * Dy2
;
422 x1
[3] = 2.0 * ((Entry
->A
[Y
] * Entry
->D
[Y
] + Entry
->B
[Y
] * Entry
->C
[Y
] - Entry
->A
[Y
] * P
[Y
]) * r
+ Entry
->A
[Y
] * D
[Y
] * m
- (Entry
->A
[X
] * Entry
->D
[X
] + Entry
->B
[X
] * Entry
->C
[X
]) * Dy2
);
424 x1
[4] = (2.0 * Entry
->B
[Y
] * (Entry
->D
[Y
] - P
[Y
]) + Entry
->C
[Y
] * Entry
->C
[Y
]) * r
+ 2.0 * Entry
->B
[Y
] * D
[Y
] * m
- (2.0 * Entry
->B
[X
] * Entry
->D
[X
] + Entry
->C
[X
] * Entry
->C
[X
]) * Dy2
;
426 x1
[5] = 2.0 * (Entry
->C
[Y
] * ((Entry
->D
[Y
] - P
[Y
]) * r
+ D
[Y
] * m
) - Entry
->C
[X
] * Entry
->D
[X
] * Dy2
);
428 x1
[6] = (Entry
->D
[Y
] - P
[Y
]) * ((Entry
->D
[Y
] - P
[Y
]) * r
+ 2.0 * D
[Y
] * m
) + Dy2
* (P
[X
] * P
[X
] + P
[Z
] * P
[Z
] - Entry
->D
[X
] * Entry
->D
[X
]);
430 n1
= Solve_Polynomial(6, x1
, y1
, Test_Flag(Lathe
, STURM_FLAG
), 0.0);
435 /* Test roots for valid intersections. */
441 if ((w
>= 0.0) && (w
<= 1.0))
443 if (fabs(D
[Y
]) > EPSILON
)
445 k
= (w
* (w
* (w
* Entry
->A
[Y
] + Entry
->B
[Y
]) + Entry
->C
[Y
]) + Entry
->D
[Y
] - P
[Y
]) / D
[Y
];
447 if (test_hit(Lathe
, Ray
, Depth_Stack
, k
/ len
, w
, intervals
[j
].n
))
459 k
= w
* (w
* (w
* Entry
->A
[X
] + Entry
->B
[X
]) + Entry
->C
[X
]) + Entry
->D
[X
];
464 x2
[2] = P
[X
] * P
[X
] + P
[Z
] * P
[Z
] - k
* k
;
466 n2
= Solve_Polynomial(2, x2
, y2
, FALSE
, 0.0);
472 if (test_hit(Lathe
, Ray
, Depth_Stack
, k
/ len
, w
, intervals
[j
].n
))
492 /*****************************************************************************
500 * IPoint - Intersection point
507 * int - TRUE if inside
515 * Test if a point lies inside the lathe.
519 * Jun 1994 : Creation.
521 ******************************************************************************/
523 static int Inside_Lathe(VECTOR IPoint
, OBJECT
*Object
)
531 LATHE_SPLINE_ENTRY
*Entry
;
532 LATHE
*Lathe
= (LATHE
*)Object
;
534 height
= Lathe
->Spline
->BCyl
->height
;
536 entry
= Lathe
->Spline
->BCyl
->entry
;
538 /* Transform the point into the lathe space. */
540 MInvTransPoint(P
, IPoint
, Lathe
->Trans
);
542 /* Number of crossings. */
546 if ((P
[Y
] >= Lathe
->Height1
) && (P
[Y
] <= Lathe
->Height2
))
548 r
= sqrt(P
[X
] * P
[X
] + P
[Z
] * P
[Z
]);
550 if ((r
>= Lathe
->Radius1
) && (r
<= Lathe
->Radius2
))
552 for (i
= 0; i
< Lathe
->Number
; i
++)
554 Entry
= &Lathe
->Spline
->Entry
[i
];
556 /* Test if we are inside the segments cylindrical bound. */
558 if ((P
[Y
] >= height
[entry
[i
].h1
] - EPSILON
) &&
559 (P
[Y
] <= height
[entry
[i
].h2
] + EPSILON
))
564 x
[3] = Entry
->D
[Y
] - P
[Y
];
566 n
= Solve_Polynomial(3, x
, y
, Test_Flag(Lathe
, STURM_FLAG
), 0.0);
572 if ((w
>= 0.0) && (w
<= 1.0))
574 k
= w
* (w
* (w
* Entry
->A
[X
] + Entry
->B
[X
]) + Entry
->C
[X
]) + Entry
->D
[X
] - r
;
589 return(!Test_Flag(Lathe
, INVERTED_FLAG
));
593 return(Test_Flag(Lathe
, INVERTED_FLAG
));
599 /*****************************************************************************
607 * Result - Normal vector
609 * Inter - Intersection found
623 * Calculate the normal of the lathe in a given point.
627 * Jun 1994 : Creation.
629 ******************************************************************************/
631 static void Lathe_Normal(VECTOR Result
, OBJECT
*Object
, INTERSECTION
*Inter
)
635 LATHE
*Lathe
= (LATHE
*)Object
;
636 LATHE_SPLINE_ENTRY
*Entry
;
638 Entry
= &Lathe
->Spline
->Entry
[Inter
->i1
];
640 /* Transform the point into the lathe space. */
642 MInvTransPoint(P
, Inter
->IPoint
, Lathe
->Trans
);
644 /* Get distance from rotation axis. */
646 r
= P
[X
] * P
[X
] + P
[Z
] * P
[Z
];
652 /* Get derivatives. */
654 dx
= Inter
->d1
* (3.0 * Entry
->A
[X
] * Inter
->d1
+ 2.0 * Entry
->B
[X
]) + Entry
->C
[X
];
655 dy
= Inter
->d1
* (3.0 * Entry
->A
[Y
] * Inter
->d1
+ 2.0 * Entry
->B
[Y
]) + Entry
->C
[Y
];
657 /* Get normal by rotation. */
665 N
[X
] = N
[Z
] = 0.0; N
[Y
] = 1.0;
668 /* Transform the normalt out of the lathe space. */
670 MTransNormal(Result
, N
, Lathe
->Trans
);
672 VNormalize(Result
, Result
);
677 /*****************************************************************************
686 * Vector - Translation vector
704 * Jun 1994 : Creation.
706 ******************************************************************************/
708 static void Translate_Lathe(OBJECT
*Object
, VECTOR Vector
, TRANSFORM
*Trans
)
710 Transform_Lathe(Object
, Trans
);
715 /*****************************************************************************
724 * Vector - Rotation vector
742 * Jun 1994 : Creation.
744 ******************************************************************************/
746 static void Rotate_Lathe(OBJECT
*Object
, VECTOR Vector
, TRANSFORM
*Trans
)
748 Transform_Lathe(Object
, Trans
);
753 /*****************************************************************************
762 * Vector - Scaling vector
780 * Jun 1994 : Creation.
782 ******************************************************************************/
784 static void Scale_Lathe(OBJECT
*Object
, VECTOR Vector
, TRANSFORM
*Trans
)
786 Transform_Lathe(Object
, Trans
);
791 /*****************************************************************************
800 * Trans - Transformation to apply
814 * Transform a lathe and recalculate its bounding box.
818 * Jun 1994 : Creation.
820 ******************************************************************************/
822 static void Transform_Lathe(OBJECT
*Object
, TRANSFORM
*Trans
)
824 Compose_Transforms(((LATHE
*)Object
)->Trans
, Trans
);
826 Compute_Lathe_BBox((LATHE
*)Object
);
831 /*****************************************************************************
857 * Jun 1994 : Creation.
859 ******************************************************************************/
861 static void Invert_Lathe(OBJECT
*Object
)
863 Invert_Flag(Object
, INVERTED_FLAG
);
868 /*****************************************************************************
880 * LATHE * - new lathe
888 * Create a new lathe.
892 * Jun 1994 : Creation.
894 ******************************************************************************/
896 LATHE
*Create_Lathe()
900 New
= (LATHE
*)POV_MALLOC(sizeof(LATHE
), "lathe");
902 INIT_OBJECT_FIELDS(New
,LATHE_OBJECT
,&Lathe_Methods
)
904 New
->Trans
= Create_Transform();
906 New
->Spline_Type
= LINEAR_SPLINE
;
922 /*****************************************************************************
944 * Copy a lathe structure.
946 * NOTE: The splines are not copied, only the number of references is
947 * counted, so that Destray_Lathe() knows if they can be destroyed.
951 * Jun 1994 : Creation.
953 * Sep 1994 : Fixed memory leakage bug. [DB]
955 ******************************************************************************/
957 static LATHE
*Copy_Lathe(OBJECT
*Object
)
959 LATHE
*New
, *Lathe
= (LATHE
*)Object
;
961 New
= Create_Lathe();
963 /* Get rid of the transformation created in Create_Lathe(). */
965 Destroy_Transform(New
->Trans
);
971 New
->Trans
= Copy_Transform(Lathe
->Trans
);
973 New
->Spline
->References
++;
980 /*****************************************************************************
1004 * NOTE: The splines are destroyed if they are no longer used by any copy.
1008 * Jun 1994 : Creation.
1009 * Oct 1996 : Changed code to include faster version. [DB]
1011 ******************************************************************************/
1013 static void Destroy_Lathe(OBJECT
*Object
)
1015 LATHE
*Lathe
= (LATHE
*)Object
;
1017 Destroy_Transform(Lathe
->Trans
);
1019 if (--(Lathe
->Spline
->References
) == 0)
1021 Destroy_BCyl(Lathe
->Spline
->BCyl
);
1023 POV_FREE(Lathe
->Spline
->Entry
);
1025 POV_FREE(Lathe
->Spline
);
1033 /*****************************************************************************
1037 * Compute_Lathe_BBox
1055 * Calculate the bounding box of a lathe.
1059 * Jun 1994 : Creation.
1061 ******************************************************************************/
1063 void Compute_Lathe_BBox(LATHE
*Lathe
)
1065 Make_BBox(Lathe
->BBox
, -Lathe
->Radius2
, Lathe
->Height1
, -Lathe
->Radius2
,
1066 2.0 * Lathe
->Radius2
, Lathe
->Height2
- Lathe
->Height1
, 2.0 * Lathe
->Radius2
);
1068 Recompute_BBox(&Lathe
->BBox
, Lathe
->Trans
);
1073 /*****************************************************************************
1082 * P - Points defining lathe
1096 * Calculate the spline segments of a lathe from a set of points.
1098 * Note that the number of points in the lathe has to be set.
1102 * Jun 1994 : Creation.
1103 * Oct 1996 : Changed code to include faster version. [DB]
1105 ******************************************************************************/
1107 void Compute_Lathe(LATHE
*Lathe
, UV_VECT
*P
)
1109 int i
, i1
, i2
, i3
, n
, segment
, number_of_segments
;
1110 DBL x
[4], xmin
, xmax
;
1111 DBL y
[4], ymin
, ymax
;
1119 /* Get number of segments. */
1121 switch (Lathe
->Spline_Type
)
1125 number_of_segments
= Lathe
->Number
- 1;
1129 case QUADRATIC_SPLINE
:
1131 number_of_segments
= Lathe
->Number
- 2;
1137 number_of_segments
= Lathe
->Number
- 3;
1143 number_of_segments
= Lathe
->Number
/ 4;
1149 number_of_segments
= 0; /* tw */
1153 /* Allocate segments. */
1155 if (Lathe
->Spline
== NULL
)
1157 Lathe
->Spline
= (LATHE_SPLINE
*)POV_MALLOC(sizeof(LATHE_SPLINE
), "spline segments of lathe");
1161 Lathe
->Spline
->References
= 1;
1163 Lathe
->Spline
->Entry
= (LATHE_SPLINE_ENTRY
*)POV_MALLOC(number_of_segments
*sizeof(LATHE_SPLINE_ENTRY
), "spline segments of lathe");
1167 /* This should never happen! */
1169 Error("Lathe segments are already defined.\n");
1172 /* Allocate temporary lists. */
1174 tmp_r1
= (DBL
*)POV_MALLOC(number_of_segments
* sizeof(DBL
), "temp lathe data");
1175 tmp_r2
= (DBL
*)POV_MALLOC(number_of_segments
* sizeof(DBL
), "temp lathe data");
1176 tmp_h1
= (DBL
*)POV_MALLOC(number_of_segments
* sizeof(DBL
), "temp lathe data");
1177 tmp_h2
= (DBL
*)POV_MALLOC(number_of_segments
* sizeof(DBL
), "temp lathe data");
1179 /***************************************************************************
1180 * Calculate segments.
1181 ****************************************************************************/
1183 /* We want to know the size of the overall bounding cylinder. */
1185 xmax
= ymax
= -BOUND_HUGE
;
1186 xmin
= ymin
= BOUND_HUGE
;
1188 for (i
= segment
= 0; segment
< number_of_segments
; )
1194 switch (Lathe
->Spline_Type
)
1196 /*************************************************************************
1197 * Linear spline (nothing more than a simple polygon).
1198 **************************************************************************/
1202 /* Use linear interpolation. */
1206 C
[X
] = -1.0 * P
[i
][X
] + 1.0 * P
[i1
][X
];
1207 D
[X
] = 1.0 * P
[i
][X
];
1211 C
[Y
] = -1.0 * P
[i
][Y
] + 1.0 * P
[i1
][Y
];
1212 D
[Y
] = 1.0 * P
[i
][Y
];
1214 /* Get maximum coordinates in current segment. */
1216 x
[0] = x
[2] = P
[i
][X
];
1217 x
[1] = x
[3] = P
[i1
][X
];
1219 y
[0] = y
[2] = P
[i
][Y
];
1220 y
[1] = y
[3] = P
[i1
][Y
];
1225 /*************************************************************************
1227 **************************************************************************/
1229 case QUADRATIC_SPLINE
:
1231 /* Use quadratic interpolation. */
1234 B
[X
] = 0.5 * P
[i
][X
] - 1.0 * P
[i1
][X
] + 0.5 * P
[i2
][X
];
1235 C
[X
] = -0.5 * P
[i
][X
] + 0.5 * P
[i2
][X
];
1236 D
[X
] = 1.0 * P
[i1
][X
];
1239 B
[Y
] = 0.5 * P
[i
][Y
] - 1.0 * P
[i1
][Y
] + 0.5 * P
[i2
][Y
];
1240 C
[Y
] = -0.5 * P
[i
][Y
] + 0.5 * P
[i2
][Y
];
1241 D
[Y
] = 1.0 * P
[i1
][Y
];
1243 /* Get maximum coordinates in current segment. */
1245 x
[0] = x
[2] = P
[i1
][X
];
1246 x
[1] = x
[3] = P
[i2
][X
];
1248 y
[0] = y
[2] = P
[i1
][Y
];
1249 y
[1] = y
[3] = P
[i2
][Y
];
1254 /*************************************************************************
1256 **************************************************************************/
1260 /* Use cubic interpolation. */
1262 A
[X
] = -0.5 * P
[i
][X
] + 1.5 * P
[i1
][X
] - 1.5 * P
[i2
][X
] + 0.5 * P
[i3
][X
];
1263 B
[X
] = P
[i
][X
] - 2.5 * P
[i1
][X
] + 2.0 * P
[i2
][X
] - 0.5 * P
[i3
][X
];
1264 C
[X
] = -0.5 * P
[i
][X
] + 0.5 * P
[i2
][X
];
1267 A
[Y
] = -0.5 * P
[i
][Y
] + 1.5 * P
[i1
][Y
] - 1.5 * P
[i2
][Y
] + 0.5 * P
[i3
][Y
];
1268 B
[Y
] = P
[i
][Y
] - 2.5 * P
[i1
][Y
] + 2.0 * P
[i2
][Y
] - 0.5 * P
[i3
][Y
];
1269 C
[Y
] = -0.5 * P
[i
][Y
] + 0.5 * P
[i2
][Y
];
1272 /* Get maximum coordinates in current segment. */
1274 x
[0] = x
[2] = P
[i1
][X
];
1275 x
[1] = x
[3] = P
[i2
][X
];
1277 y
[0] = y
[2] = P
[i1
][Y
];
1278 y
[1] = y
[3] = P
[i2
][Y
];
1282 /*************************************************************************
1284 **************************************************************************/
1288 /* Use Bernstein interpolation. */
1290 A
[X
] = P
[i
][X
] - 3.0 * P
[i1
][X
] + 3.0 * P
[i2
][X
] - P
[i3
][X
];
1291 B
[X
] = 3.0 * P
[i1
][X
] - 6.0 * P
[i2
][X
] + 3.0 * P
[i3
][X
];
1292 C
[X
] = 3.0 * P
[i2
][X
] - 3.0 * P
[i3
][X
];
1295 A
[Y
] = P
[i
][Y
] - 3.0 * P
[i1
][Y
] + 3.0 * P
[i2
][Y
] - P
[i3
][Y
];
1296 B
[Y
] = 3.0 * P
[i1
][Y
] - 6.0 * P
[i2
][Y
] + 3.0 * P
[i3
][Y
];
1297 C
[Y
] = 3.0 * P
[i2
][Y
] - 3.0 * P
[i3
][Y
];
1314 Error("Unknown lathe type in Compute_Lathe().\n");
1318 Assign_UV_Vect(Lathe
->Spline
->Entry
[segment
].A
, A
);
1319 Assign_UV_Vect(Lathe
->Spline
->Entry
[segment
].B
, B
);
1320 Assign_UV_Vect(Lathe
->Spline
->Entry
[segment
].C
, C
);
1321 Assign_UV_Vect(Lathe
->Spline
->Entry
[segment
].D
, D
);
1323 if ((Lathe
->Spline_Type
== QUADRATIC_SPLINE
) ||
1324 (Lathe
->Spline_Type
== CUBIC_SPLINE
))
1326 /* Get maximum coordinates in current segment. */
1332 n
= Solve_Polynomial(2, c
, r
, FALSE
, 0.0);
1336 if ((r
[n
] >= 0.0) && (r
[n
] <= 1.0))
1338 x
[n
] = r
[n
] * (r
[n
] * (r
[n
] * A
[X
] + B
[X
]) + C
[X
]) + D
[X
];
1346 n
= Solve_Polynomial(2, c
, r
, FALSE
, 0.0);
1350 if ((r
[n
] >= 0.0) && (r
[n
] <= 1.0))
1352 y
[n
] = r
[n
] * (r
[n
] * (r
[n
] * A
[Y
] + B
[Y
]) + C
[Y
]) + D
[Y
];
1357 /* Set current segment's bounding cylinder. */
1359 tmp_r1
[segment
] = min(min(x
[0], x
[1]), min(x
[2], x
[3]));
1360 tmp_r2
[segment
] = max(max(x
[0], x
[1]), max(x
[2], x
[3]));
1362 tmp_h1
[segment
] = min(min(y
[0], y
[1]), min(y
[2], y
[3]));
1363 tmp_h2
[segment
] = max(max(y
[0], y
[1]), max(y
[2], y
[3]));
1365 /* Keep track of overall bounding cylinder. */
1367 xmin
= min(xmin
, tmp_r1
[segment
]);
1368 xmax
= max(xmax
, tmp_r2
[segment
]);
1370 ymin
= min(ymin
, tmp_h1
[segment
]);
1371 ymax
= max(ymax
, tmp_h2
[segment
]);
1374 fprintf(stderr, "bound spline segment %d: ", i);
1375 fprintf(stderr, "r = %f - %f, h = %f - %f\n", tmp_r1[segment], tmp_r2[segment], tmp_h1[segment], tmp_h2[segment]);
1378 /* Advance to next segment. */
1380 switch (Lathe
->Spline_Type
)
1383 case QUADRATIC_SPLINE
:
1400 Lathe
->Number
= number_of_segments
;
1402 /* Set overall bounding cylinder. */
1404 Lathe
->Radius1
= xmin
;
1405 Lathe
->Radius2
= xmax
;
1407 Lathe
->Height1
= ymin
;
1408 Lathe
->Height2
= ymax
;
1410 /* Get bounding cylinder. */
1412 Lathe
->Spline
->BCyl
= Create_BCyl(Lathe
->Number
, tmp_r1
, tmp_r2
, tmp_h1
, tmp_h2
);
1414 /* Get rid of temp. memory. */
1423 /*****************************************************************************
1431 * Lathe - Pointer to lathe structure
1433 * Depth_Stack - Current depth stack
1434 * d, w, n - Intersection depth, parameter and segment number
1448 * Test if a hit is valid and push if on the intersection depth.
1452 * Oct 1996 : Creation.
1454 ******************************************************************************/
1456 static int test_hit(LATHE
*Lathe
, RAY
*Ray
, ISTACK
*Depth_Stack
, DBL d
, DBL w
, int n
)
1460 if ((d
> DEPTH_TOLERANCE
) && (d
< Max_Distance
))
1462 VEvaluateRay(IPoint
, Ray
->Initial
, d
, Ray
->Direction
);
1464 if (Point_In_Clip(IPoint
, ((OBJECT
*)Lathe
)->Clip
))
1466 push_entry_i1_d1(d
, IPoint
, (OBJECT
*)Lathe
, n
, w
, Depth_Stack
);