LATHE.C 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476
  1. /****************************************************************************
  2. * lathe.c
  3. *
  4. * This module implements functions that manipulate lathes.
  5. *
  6. * This module was written by Dieter Bayer [DB].
  7. *
  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.
  19. *
  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.
  23. *
  24. * Modification from Thomas Willhalm, March 1999, used with permission
  25. *
  26. *****************************************************************************/
  27. /****************************************************************************
  28. *
  29. * Explanation:
  30. *
  31. * The lathe primitive is defined by a set of points in 2d space which
  32. * are interpolated by linear, quadratic, or cubic splines. The resulting
  33. * 2d curve is rotated about an axis to form the final lathe object.
  34. *
  35. * All calculations are done in the object's (u,v,w)-coordinate system
  36. * with the (w)-axis being the rotation axis.
  37. *
  38. * One spline segment in the (r,w)-plane is given by the equations
  39. *
  40. * fw(t) = Aw * t^3 + Bw * t^2 + Cw * t + Dw and
  41. * fr(t) = Ar * t^3 + Br * t^2 + Cr * t + Dr,
  42. *
  43. * with the parameter t ranging from 0 to 1 and r = sqrt(u*u+v*v).
  44. *
  45. * To intersect a ray R = P + k * D transformed into the object's
  46. * coordinate system with the lathe object, the equations
  47. *
  48. * (Pu + k * Du)^2 + (Pv + k * Dv)^2 = (fr(t))^2
  49. * (Pw + k * Dw) = fw(t)
  50. *
  51. * have to be solved for t. For valid intersections (0 <= t <= 1)
  52. * the corresponding k can be calculated from one of the above equations.
  53. *
  54. * Note that the degree of the polynomal to solve is two times the
  55. * degree of the spline segments used.
  56. *
  57. * Note that Pu, Pv, Pw and Du, Dv, Dw denote the coordinates
  58. * of the vectors P and D.
  59. *
  60. * Syntax:
  61. *
  62. * lathe
  63. * {
  64. * [ linear_spline | quadratic_spline | cubic_spline ]
  65. *
  66. * number_of_points,
  67. *
  68. * <P[0]>, <P[1], ..., <P[n-1]>
  69. *
  70. * [ sturm ]
  71. * }
  72. *
  73. * Note that the P[i] are 2d vectors.
  74. *
  75. * Linear interpolation is used by default. In this case all n Points
  76. * are used. In the quadratic case the first point is used to determine
  77. * the derivates at the starting point P[1]. In the cubic case
  78. * the first and last points are used to determine the derivatives at
  79. * the starting point P[1] and ending point P[n-2].
  80. *
  81. * To get a closed (and smooth) curve you have make sure that
  82. *
  83. * P[0] = P[n-1] in the linear case,
  84. *
  85. * P[0] = P[n-2] and P[1] = P[n-1] in the quadratic case, and
  86. *
  87. * P[0] = P[n-3] and P[1] = P[n-2] and P[2] = P[n-1] in the cubic case.
  88. *
  89. * Note that the x coordinate of a point corresponds to the r coordinate
  90. * and the y coordinate to the w coordinate;
  91. *
  92. * ---
  93. *
  94. * Ideas for the lathe were taken from:
  95. *
  96. * P. Burger and D. Gillies, "Rapid Ray Tracing of General Surfaces
  97. * of Revolution", New Advances in Computer Graphics, Proceedings
  98. * of CG International '89, R. A. Earnshaw, B. Wyvill (Eds.),
  99. * Springer, ..., pp. 523-531
  100. *
  101. * P. Burger and D. Gillies, "Swept Surfaces", Interactive Computer
  102. * Graphics, Addison-Wesley, 1989, pp. 376-380
  103. *
  104. * ---
  105. *
  106. * Jun 1994 : Creation. [DB]
  107. *
  108. *****************************************************************************/
  109. #include "frame.h"
  110. #include "povray.h"
  111. #include "vector.h"
  112. #include "povproto.h"
  113. #include "bbox.h"
  114. #include "bcyl.h"
  115. #include "lathe.h"
  116. #include "polysolv.h"
  117. #include "matrices.h"
  118. #include "objects.h"
  119. #include "torus.h"
  120. /*****************************************************************************
  121. * Local preprocessor defines
  122. ******************************************************************************/
  123. /* Minimal intersection depth for a valid intersection. */
  124. #define DEPTH_TOLERANCE 1.0e-4
  125. /* Max. number of intersecions per spline segment. */
  126. #define MAX_INTERSECTIONS_PER_SEGMENT 4
  127. /*****************************************************************************
  128. * Local typedefs
  129. ******************************************************************************/
  130. /*****************************************************************************
  131. * Static functions
  132. ******************************************************************************/
  133. static int intersect_lathe (RAY *Ray, LATHE *Lathe, ISTACK *Depth_Stack);
  134. static int All_Lathe_Intersections (OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack);
  135. static int Inside_Lathe (VECTOR point, OBJECT *Object);
  136. static void Lathe_Normal (VECTOR Result, OBJECT *Object, INTERSECTION *Inter);
  137. static LATHE *Copy_Lathe (OBJECT *Object);
  138. static void Translate_Lathe (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
  139. static void Rotate_Lathe (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
  140. static void Scale_Lathe (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
  141. static void Transform_Lathe (OBJECT *Object, TRANSFORM *Trans);
  142. static void Invert_Lathe (OBJECT *Object);
  143. static void Destroy_Lathe (OBJECT *Object);
  144. static int test_hit (LATHE *, RAY *, ISTACK *, DBL, DBL, int);
  145. /*****************************************************************************
  146. * Local variables
  147. ******************************************************************************/
  148. static METHODS Lathe_Methods =
  149. {
  150. All_Lathe_Intersections,
  151. Inside_Lathe, Lathe_Normal,
  152. (COPY_METHOD)Copy_Lathe,
  153. Translate_Lathe, Rotate_Lathe,
  154. Scale_Lathe, Transform_Lathe, Invert_Lathe, Destroy_Lathe
  155. };
  156. /*****************************************************************************
  157. *
  158. * FUNCTION
  159. *
  160. * All_Lathe_Intersections
  161. *
  162. * INPUT
  163. *
  164. * Object - Object
  165. * Ray - Ray
  166. * Depth_Stack - Intersection stack
  167. *
  168. * OUTPUT
  169. *
  170. * Depth_Stack
  171. *
  172. * RETURNS
  173. *
  174. * int - TRUE, if a intersection was found
  175. *
  176. * AUTHOR
  177. *
  178. * Dieter Bayer
  179. *
  180. * DESCRIPTION
  181. *
  182. * Determine ray/lathe intersection and clip intersection found.
  183. *
  184. * CHANGES
  185. *
  186. * Jun 1994 : Creation.
  187. * Oct 1996 : Changed code to include faster version. [DB]
  188. *
  189. ******************************************************************************/
  190. static int All_Lathe_Intersections(OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack)
  191. {
  192. Increase_Counter(stats[Ray_Lathe_Tests]);
  193. if (intersect_lathe(Ray, (LATHE *)Object, Depth_Stack))
  194. {
  195. Increase_Counter(stats[Ray_Lathe_Tests_Succeeded]);
  196. return(TRUE);
  197. }
  198. return(FALSE);
  199. }
  200. /*****************************************************************************
  201. *
  202. * FUNCTION
  203. *
  204. * intersect_lathe
  205. *
  206. * INPUT
  207. *
  208. * Ray - Ray
  209. * Lathe - Lathe
  210. * Intersection - Lathe intersection structure
  211. *
  212. * OUTPUT
  213. *
  214. * Intersection
  215. *
  216. * RETURNS
  217. *
  218. * int - Number of intersections found
  219. *
  220. * AUTHOR
  221. *
  222. * Dieter Bayer
  223. *
  224. * DESCRIPTION
  225. *
  226. * Determine ray/lathe intersection.
  227. *
  228. * NOTE: The curve is rotated about the y-axis!
  229. * Order of the polynomial must not be used!
  230. *
  231. * CHANGES
  232. *
  233. * Jun 1994 : Creation.
  234. * Oct 1996 : Changed code to include faster version. [DB]
  235. *
  236. ******************************************************************************/
  237. static int intersect_lathe(RAY *Ray, LATHE *Lathe, ISTACK *Depth_Stack)
  238. {
  239. int cnt;
  240. int found, j, n1, n2;
  241. DBL k, len, r, m, w, Dy2, r0;
  242. DBL x1[7], x2[3], y1[6], y2[2];
  243. DBL best;
  244. VECTOR P, D;
  245. BCYL_INT *intervals;
  246. LATHE_SPLINE_ENTRY *Entry;
  247. /* Transform the ray into the lathe space. */
  248. MInvTransPoint(P, Ray->Initial, Lathe->Trans);
  249. MInvTransDirection(D, Ray->Direction, Lathe->Trans);
  250. VLength(len, D);
  251. VInverseScaleEq(D, len);
  252. /* Test if ray misses lathe's cylindrical bound. */
  253. #ifdef LATHE_EXTRA_STATS
  254. Increase_Counter(stats[Lathe_Bound_Tests]);
  255. #endif
  256. if (((D[Y] >= 0.0) && (P[Y] > Lathe->Height2)) ||
  257. ((D[Y] <= 0.0) && (P[Y] < Lathe->Height1)) ||
  258. ((D[X] >= 0.0) && (P[X] > Lathe->Radius2)) ||
  259. ((D[X] <= 0.0) && (P[X] < -Lathe->Radius2)))
  260. {
  261. return(FALSE);
  262. }
  263. /* Get distance r0 of the ray from rotation axis (i.e. y axis). */
  264. r0 = fabs(P[X] * D[Z] - P[Z] * D[X]);
  265. r = D[X] * D[X] + D[Z] * D[Z];
  266. if (r > 0.0)
  267. {
  268. r0 /= sqrt(r);
  269. }
  270. /* Test if ray misses lathe's cylindrical bound. */
  271. if (r0 > Lathe->Radius2)
  272. {
  273. return(FALSE);
  274. }
  275. /* Intersect all cylindrical bounds. */
  276. if ((cnt = Intersect_BCyl(Lathe->Spline->BCyl, P, D)) == 0)
  277. {
  278. return(FALSE);
  279. }
  280. #ifdef LATHE_EXTRA_STATS
  281. Increase_Counter(stats[Lathe_Bound_Tests_Succeeded]);
  282. #endif
  283. /* Precalculate some constants that are ray-dependant only. */
  284. m = D[X] * P[X] + D[Z] * P[Z];
  285. Dy2 = D[Y] * D[Y];
  286. /* Step through the list of intersections. */
  287. found = FALSE;
  288. best = BOUND_HUGE;
  289. intervals = Lathe->Spline->BCyl->intervals;
  290. for (j = 0; j < cnt; j++)
  291. {
  292. /* Get current segment. */
  293. Entry = &Lathe->Spline->Entry[intervals[j].n];
  294. /* If we already have the best intersection we may exit. */
  295. if (!(Lathe->Type & IS_CHILD_OBJECT) && (intervals[j].d[0] > best))
  296. {
  297. break;
  298. }
  299. /* Init number of roots found. */
  300. n1 = 0;
  301. /* Intersect segment. */
  302. switch (Lathe->Spline_Type)
  303. {
  304. /***********************************************************************
  305. * Linear spline.
  306. ************************************************************************/
  307. case LINEAR_SPLINE:
  308. /* Solve 2th order polynomial. */
  309. x1[0] = Entry->C[Y] * Entry->C[Y] * r - Entry->C[X] * Entry->C[X] * Dy2;
  310. x1[1] = 2.0 * (Entry->C[Y] * ((Entry->D[Y] - P[Y]) * r + D[Y] * m) - Entry->C[X] * Entry->D[X] * Dy2);
  311. 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]);
  312. n1 = Solve_Polynomial(2, x1, y1, FALSE, 0.0);
  313. break;
  314. /***********************************************************************
  315. * Quadratic spline.
  316. ************************************************************************/
  317. case QUADRATIC_SPLINE:
  318. /* Solve 4th order polynomial. */
  319. x1[0] = Entry->B[Y] * Entry->B[Y] * r - Entry->B[X] * Entry->B[X] * Dy2;
  320. x1[1] = 2.0 * (Entry->B[Y] * Entry->C[Y] * r - Entry->B[X] * Entry->C[X] * Dy2);
  321. 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;
  322. x1[3] = 2.0 * (Entry->C[Y] * ((Entry->D[Y] - P[Y]) * r + D[Y] * m) - Entry->C[X] * Entry->D[X] * Dy2);
  323. 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]);
  324. n1 = Solve_Polynomial(4, x1, y1, Test_Flag(Lathe, STURM_FLAG), 0.0);
  325. break;
  326. /***********************************************************************
  327. * Cubic spline.
  328. ************************************************************************/
  329. case BEZIER_SPLINE:
  330. case CUBIC_SPLINE:
  331. /* Solve 6th order polynomial. */
  332. x1[0] = Entry->A[Y] * Entry->A[Y] * r - Entry->A[X] * Entry->A[X] * Dy2;
  333. x1[1] = 2.0 * (Entry->A[Y] * Entry->B[Y] * r - Entry->A[X] * Entry->B[X] * Dy2);
  334. 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;
  335. 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);
  336. 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;
  337. x1[5] = 2.0 * (Entry->C[Y] * ((Entry->D[Y] - P[Y]) * r + D[Y] * m) - Entry->C[X] * Entry->D[X] * Dy2);
  338. 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]);
  339. n1 = Solve_Polynomial(6, x1, y1, Test_Flag(Lathe, STURM_FLAG), 0.0);
  340. break;
  341. }
  342. /* Test roots for valid intersections. */
  343. while (n1--)
  344. {
  345. w = y1[n1];
  346. if ((w >= 0.0) && (w <= 1.0))
  347. {
  348. if (fabs(D[Y]) > EPSILON)
  349. {
  350. k = (w * (w * (w * Entry->A[Y] + Entry->B[Y]) + Entry->C[Y]) + Entry->D[Y] - P[Y]) / D[Y];
  351. if (test_hit(Lathe, Ray, Depth_Stack, k / len, w, intervals[j].n))
  352. {
  353. found = TRUE;
  354. if (k < best)
  355. {
  356. best = k;
  357. }
  358. }
  359. }
  360. else
  361. {
  362. k = w * (w * (w * Entry->A[X] + Entry->B[X]) + Entry->C[X]) + Entry->D[X];
  363. x2[0] = r;
  364. x2[1] = 2.0 * m;
  365. x2[2] = P[X] * P[X] + P[Z] * P[Z] - k * k;
  366. n2 = Solve_Polynomial(2, x2, y2, FALSE, 0.0);
  367. while (n2--)
  368. {
  369. k = y2[n2];
  370. if (test_hit(Lathe, Ray, Depth_Stack, k / len, w, intervals[j].n))
  371. {
  372. found = TRUE;
  373. if (k < best)
  374. {
  375. best = k;
  376. }
  377. }
  378. }
  379. }
  380. }
  381. }
  382. }
  383. return(found);
  384. }
  385. /*****************************************************************************
  386. *
  387. * FUNCTION
  388. *
  389. * Inside_Lathe
  390. *
  391. * INPUT
  392. *
  393. * IPoint - Intersection point
  394. * Object - Object
  395. *
  396. * OUTPUT
  397. *
  398. * RETURNS
  399. *
  400. * int - TRUE if inside
  401. *
  402. * AUTHOR
  403. *
  404. * Dieter Bayer
  405. *
  406. * DESCRIPTION
  407. *
  408. * Test if a point lies inside the lathe.
  409. *
  410. * CHANGES
  411. *
  412. * Jun 1994 : Creation.
  413. *
  414. ******************************************************************************/
  415. static int Inside_Lathe(VECTOR IPoint, OBJECT *Object)
  416. {
  417. int i, n, NC;
  418. DBL r, k, w;
  419. DBL x[4], y[3];
  420. DBL *height;
  421. VECTOR P;
  422. BCYL_ENTRY *entry;
  423. LATHE_SPLINE_ENTRY *Entry;
  424. LATHE *Lathe = (LATHE *)Object;
  425. height = Lathe->Spline->BCyl->height;
  426. entry = Lathe->Spline->BCyl->entry;
  427. /* Transform the point into the lathe space. */
  428. MInvTransPoint(P, IPoint, Lathe->Trans);
  429. /* Number of crossings. */
  430. NC = 0;
  431. if ((P[Y] >= Lathe->Height1) && (P[Y] <= Lathe->Height2))
  432. {
  433. r = sqrt(P[X] * P[X] + P[Z] * P[Z]);
  434. if ((r >= Lathe->Radius1) && (r <= Lathe->Radius2))
  435. {
  436. for (i = 0; i < Lathe->Number; i++)
  437. {
  438. Entry = &Lathe->Spline->Entry[i];
  439. /* Test if we are inside the segments cylindrical bound. */
  440. if ((P[Y] >= height[entry[i].h1] - EPSILON) &&
  441. (P[Y] <= height[entry[i].h2] + EPSILON))
  442. {
  443. x[0] = Entry->A[Y];
  444. x[1] = Entry->B[Y];
  445. x[2] = Entry->C[Y];
  446. x[3] = Entry->D[Y] - P[Y];
  447. n = Solve_Polynomial(3, x, y, Test_Flag(Lathe, STURM_FLAG), 0.0);
  448. while (n--)
  449. {
  450. w = y[n];
  451. if ((w >= 0.0) && (w <= 1.0))
  452. {
  453. k = w * (w * (w * Entry->A[X] + Entry->B[X]) + Entry->C[X]) + Entry->D[X] - r;
  454. if (k >= 0.0)
  455. {
  456. NC++;
  457. }
  458. }
  459. }
  460. }
  461. }
  462. }
  463. }
  464. if (NC & 1)
  465. {
  466. return(!Test_Flag(Lathe, INVERTED_FLAG));
  467. }
  468. else
  469. {
  470. return(Test_Flag(Lathe, INVERTED_FLAG));
  471. }
  472. }
  473. /*****************************************************************************
  474. *
  475. * FUNCTION
  476. *
  477. * Lathe_Normal
  478. *
  479. * INPUT
  480. *
  481. * Result - Normal vector
  482. * Object - Object
  483. * Inter - Intersection found
  484. *
  485. * OUTPUT
  486. *
  487. * Result
  488. *
  489. * RETURNS
  490. *
  491. * AUTHOR
  492. *
  493. * Dieter Bayer
  494. *
  495. * DESCRIPTION
  496. *
  497. * Calculate the normal of the lathe in a given point.
  498. *
  499. * CHANGES
  500. *
  501. * Jun 1994 : Creation.
  502. *
  503. ******************************************************************************/
  504. static void Lathe_Normal(VECTOR Result, OBJECT *Object, INTERSECTION *Inter)
  505. {
  506. DBL r, dx, dy;
  507. VECTOR P, N;
  508. LATHE *Lathe = (LATHE *)Object;
  509. LATHE_SPLINE_ENTRY *Entry;
  510. Entry = &Lathe->Spline->Entry[Inter->i1];
  511. /* Transform the point into the lathe space. */
  512. MInvTransPoint(P, Inter->IPoint, Lathe->Trans);
  513. /* Get distance from rotation axis. */
  514. r = P[X] * P[X] + P[Z] * P[Z];
  515. if (r > EPSILON)
  516. {
  517. r = sqrt(r);
  518. /* Get derivatives. */
  519. dx = Inter->d1 * (3.0 * Entry->A[X] * Inter->d1 + 2.0 * Entry->B[X]) + Entry->C[X];
  520. dy = Inter->d1 * (3.0 * Entry->A[Y] * Inter->d1 + 2.0 * Entry->B[Y]) + Entry->C[Y];
  521. /* Get normal by rotation. */
  522. N[X] = dy * P[X];
  523. N[Y] = -dx * r;
  524. N[Z] = dy * P[Z];
  525. }
  526. else
  527. {
  528. N[X] = N[Z] = 0.0; N[Y] = 1.0;
  529. }
  530. /* Transform the normalt out of the lathe space. */
  531. MTransNormal(Result, N, Lathe->Trans);
  532. VNormalize(Result, Result);
  533. }
  534. /*****************************************************************************
  535. *
  536. * FUNCTION
  537. *
  538. * Translate_Lathe
  539. *
  540. * INPUT
  541. *
  542. * Object - Object
  543. * Vector - Translation vector
  544. *
  545. * OUTPUT
  546. *
  547. * Object
  548. *
  549. * RETURNS
  550. *
  551. * AUTHOR
  552. *
  553. * Dieter Bayer
  554. *
  555. * DESCRIPTION
  556. *
  557. * Translate a lathe.
  558. *
  559. * CHANGES
  560. *
  561. * Jun 1994 : Creation.
  562. *
  563. ******************************************************************************/
  564. static void Translate_Lathe(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
  565. {
  566. Transform_Lathe(Object, Trans);
  567. }
  568. /*****************************************************************************
  569. *
  570. * FUNCTION
  571. *
  572. * Rotate_Lathe
  573. *
  574. * INPUT
  575. *
  576. * Object - Object
  577. * Vector - Rotation vector
  578. *
  579. * OUTPUT
  580. *
  581. * Object
  582. *
  583. * RETURNS
  584. *
  585. * AUTHOR
  586. *
  587. * Dieter Bayer
  588. *
  589. * DESCRIPTION
  590. *
  591. * Rotate a lathe.
  592. *
  593. * CHANGES
  594. *
  595. * Jun 1994 : Creation.
  596. *
  597. ******************************************************************************/
  598. static void Rotate_Lathe(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
  599. {
  600. Transform_Lathe(Object, Trans);
  601. }
  602. /*****************************************************************************
  603. *
  604. * FUNCTION
  605. *
  606. * Scale_Lathe
  607. *
  608. * INPUT
  609. *
  610. * Object - Object
  611. * Vector - Scaling vector
  612. *
  613. * OUTPUT
  614. *
  615. * Object
  616. *
  617. * RETURNS
  618. *
  619. * AUTHOR
  620. *
  621. * Dieter Bayer
  622. *
  623. * DESCRIPTION
  624. *
  625. * Scale a lathe.
  626. *
  627. * CHANGES
  628. *
  629. * Jun 1994 : Creation.
  630. *
  631. ******************************************************************************/
  632. static void Scale_Lathe(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
  633. {
  634. Transform_Lathe(Object, Trans);
  635. }
  636. /*****************************************************************************
  637. *
  638. * FUNCTION
  639. *
  640. * Transform_Lathe
  641. *
  642. * INPUT
  643. *
  644. * Object - Object
  645. * Trans - Transformation to apply
  646. *
  647. * OUTPUT
  648. *
  649. * Object
  650. *
  651. * RETURNS
  652. *
  653. * AUTHOR
  654. *
  655. * Dieter Bayer
  656. *
  657. * DESCRIPTION
  658. *
  659. * Transform a lathe and recalculate its bounding box.
  660. *
  661. * CHANGES
  662. *
  663. * Jun 1994 : Creation.
  664. *
  665. ******************************************************************************/
  666. static void Transform_Lathe(OBJECT *Object, TRANSFORM *Trans)
  667. {
  668. Compose_Transforms(((LATHE *)Object)->Trans, Trans);
  669. Compute_Lathe_BBox((LATHE *)Object);
  670. }
  671. /*****************************************************************************
  672. *
  673. * FUNCTION
  674. *
  675. * Invert_Lathe
  676. *
  677. * INPUT
  678. *
  679. * Object - Object
  680. *
  681. * OUTPUT
  682. *
  683. * Object
  684. *
  685. * RETURNS
  686. *
  687. * AUTHOR
  688. *
  689. * Dieter Bayer
  690. *
  691. * DESCRIPTION
  692. *
  693. * Invert a lathe.
  694. *
  695. * CHANGES
  696. *
  697. * Jun 1994 : Creation.
  698. *
  699. ******************************************************************************/
  700. static void Invert_Lathe(OBJECT *Object)
  701. {
  702. Invert_Flag(Object, INVERTED_FLAG);
  703. }
  704. /*****************************************************************************
  705. *
  706. * FUNCTION
  707. *
  708. * Create_Lathe
  709. *
  710. * INPUT
  711. *
  712. * OUTPUT
  713. *
  714. * RETURNS
  715. *
  716. * LATHE * - new lathe
  717. *
  718. * AUTHOR
  719. *
  720. * Dieter Bayer
  721. *
  722. * DESCRIPTION
  723. *
  724. * Create a new lathe.
  725. *
  726. * CHANGES
  727. *
  728. * Jun 1994 : Creation.
  729. *
  730. ******************************************************************************/
  731. LATHE *Create_Lathe()
  732. {
  733. LATHE *New;
  734. New = (LATHE *)POV_MALLOC(sizeof(LATHE), "lathe");
  735. INIT_OBJECT_FIELDS(New,LATHE_OBJECT,&Lathe_Methods)
  736. New->Trans = Create_Transform();
  737. New->Spline_Type = LINEAR_SPLINE;
  738. New->Number = 0;
  739. New->Spline = NULL;
  740. New->Radius1 =
  741. New->Radius2 =
  742. New->Height1 =
  743. New->Height2 = 0.0;
  744. return(New);
  745. }
  746. /*****************************************************************************
  747. *
  748. * FUNCTION
  749. *
  750. * Copy_Lathe
  751. *
  752. * INPUT
  753. *
  754. * Object - Object
  755. *
  756. * OUTPUT
  757. *
  758. * RETURNS
  759. *
  760. * void * - New lathe
  761. *
  762. * AUTHOR
  763. *
  764. * Dieter Bayer
  765. *
  766. * DESCRIPTION
  767. *
  768. * Copy a lathe structure.
  769. *
  770. * NOTE: The splines are not copied, only the number of references is
  771. * counted, so that Destray_Lathe() knows if they can be destroyed.
  772. *
  773. * CHANGES
  774. *
  775. * Jun 1994 : Creation.
  776. *
  777. * Sep 1994 : Fixed memory leakage bug. [DB]
  778. *
  779. ******************************************************************************/
  780. static LATHE *Copy_Lathe(OBJECT *Object)
  781. {
  782. LATHE *New, *Lathe = (LATHE *)Object;
  783. New = Create_Lathe();
  784. /* Get rid of the transformation created in Create_Lathe(). */
  785. Destroy_Transform(New->Trans);
  786. /* Copy lathe. */
  787. *New = *Lathe;
  788. New->Trans = Copy_Transform(Lathe->Trans);
  789. New->Spline->References++;
  790. return(New);
  791. }
  792. /*****************************************************************************
  793. *
  794. * FUNCTION
  795. *
  796. * Destroy_Lathe
  797. *
  798. * INPUT
  799. *
  800. * Object - Object
  801. *
  802. * OUTPUT
  803. *
  804. * Object
  805. *
  806. * RETURNS
  807. *
  808. * AUTHOR
  809. *
  810. * Dieter Bayer
  811. *
  812. * DESCRIPTION
  813. *
  814. * Destroy a lathe.
  815. *
  816. * NOTE: The splines are destroyed if they are no longer used by any copy.
  817. *
  818. * CHANGES
  819. *
  820. * Jun 1994 : Creation.
  821. * Oct 1996 : Changed code to include faster version. [DB]
  822. *
  823. ******************************************************************************/
  824. static void Destroy_Lathe(OBJECT *Object)
  825. {
  826. LATHE *Lathe = (LATHE *)Object;
  827. Destroy_Transform(Lathe->Trans);
  828. if (--(Lathe->Spline->References) == 0)
  829. {
  830. Destroy_BCyl(Lathe->Spline->BCyl);
  831. POV_FREE(Lathe->Spline->Entry);
  832. POV_FREE(Lathe->Spline);
  833. }
  834. POV_FREE (Object);
  835. }
  836. /*****************************************************************************
  837. *
  838. * FUNCTION
  839. *
  840. * Compute_Lathe_BBox
  841. *
  842. * INPUT
  843. *
  844. * Lathe - Lathe
  845. *
  846. * OUTPUT
  847. *
  848. * Lathe
  849. *
  850. * RETURNS
  851. *
  852. * AUTHOR
  853. *
  854. * Dieter Bayer
  855. *
  856. * DESCRIPTION
  857. *
  858. * Calculate the bounding box of a lathe.
  859. *
  860. * CHANGES
  861. *
  862. * Jun 1994 : Creation.
  863. *
  864. ******************************************************************************/
  865. void Compute_Lathe_BBox(LATHE *Lathe)
  866. {
  867. Make_BBox(Lathe->BBox, -Lathe->Radius2, Lathe->Height1, -Lathe->Radius2,
  868. 2.0 * Lathe->Radius2, Lathe->Height2 - Lathe->Height1, 2.0 * Lathe->Radius2);
  869. Recompute_BBox(&Lathe->BBox, Lathe->Trans);
  870. }
  871. /*****************************************************************************
  872. *
  873. * FUNCTION
  874. *
  875. * Compute_Lathe
  876. *
  877. * INPUT
  878. *
  879. * Lathe - Lathe
  880. * P - Points defining lathe
  881. *
  882. * OUTPUT
  883. *
  884. * Lathe
  885. *
  886. * RETURNS
  887. *
  888. * AUTHOR
  889. *
  890. * Dieter Bayer
  891. *
  892. * DESCRIPTION
  893. *
  894. * Calculate the spline segments of a lathe from a set of points.
  895. *
  896. * Note that the number of points in the lathe has to be set.
  897. *
  898. * CHANGES
  899. *
  900. * Jun 1994 : Creation.
  901. * Oct 1996 : Changed code to include faster version. [DB]
  902. *
  903. ******************************************************************************/
  904. void Compute_Lathe(LATHE *Lathe, UV_VECT *P)
  905. {
  906. int i, i1, i2, i3, n, segment, number_of_segments;
  907. DBL x[4], xmin, xmax;
  908. DBL y[4], ymin, ymax;
  909. DBL c[3], r[2];
  910. DBL *tmp_r1;
  911. DBL *tmp_r2;
  912. DBL *tmp_h1;
  913. DBL *tmp_h2;
  914. UV_VECT A, B, C, D;
  915. /* Get number of segments. */
  916. switch (Lathe->Spline_Type)
  917. {
  918. case LINEAR_SPLINE:
  919. number_of_segments = Lathe->Number - 1;
  920. break;
  921. case QUADRATIC_SPLINE:
  922. number_of_segments = Lathe->Number - 2;
  923. break;
  924. case CUBIC_SPLINE:
  925. number_of_segments = Lathe->Number - 3;
  926. break;
  927. case BEZIER_SPLINE:
  928. number_of_segments = Lathe->Number / 4;
  929. break;
  930. default: /* tw */
  931. number_of_segments = 0; /* tw */
  932. }
  933. /* Allocate segments. */
  934. if (Lathe->Spline == NULL)
  935. {
  936. Lathe->Spline = (LATHE_SPLINE *)POV_MALLOC(sizeof(LATHE_SPLINE), "spline segments of lathe");
  937. /* Init spline. */
  938. Lathe->Spline->References = 1;
  939. Lathe->Spline->Entry = (LATHE_SPLINE_ENTRY *)POV_MALLOC(number_of_segments*sizeof(LATHE_SPLINE_ENTRY), "spline segments of lathe");
  940. }
  941. else
  942. {
  943. /* This should never happen! */
  944. Error("Lathe segments are already defined.\n");
  945. }
  946. /* Allocate temporary lists. */
  947. tmp_r1 = (DBL *)POV_MALLOC(number_of_segments * sizeof(DBL), "temp lathe data");
  948. tmp_r2 = (DBL *)POV_MALLOC(number_of_segments * sizeof(DBL), "temp lathe data");
  949. tmp_h1 = (DBL *)POV_MALLOC(number_of_segments * sizeof(DBL), "temp lathe data");
  950. tmp_h2 = (DBL *)POV_MALLOC(number_of_segments * sizeof(DBL), "temp lathe data");
  951. /***************************************************************************
  952. * Calculate segments.
  953. ****************************************************************************/
  954. /* We want to know the size of the overall bounding cylinder. */
  955. xmax = ymax = -BOUND_HUGE;
  956. xmin = ymin = BOUND_HUGE;
  957. for (i = segment = 0; segment < number_of_segments; )
  958. {
  959. i1 = i + 1;
  960. i2 = i + 2;
  961. i3 = i + 3;
  962. switch (Lathe->Spline_Type)
  963. {
  964. /*************************************************************************
  965. * Linear spline (nothing more than a simple polygon).
  966. **************************************************************************/
  967. case LINEAR_SPLINE:
  968. /* Use linear interpolation. */
  969. A[X] = 0.0;
  970. B[X] = 0.0;
  971. C[X] = -1.0 * P[i][X] + 1.0 * P[i1][X];
  972. D[X] = 1.0 * P[i][X];
  973. A[Y] = 0.0;
  974. B[Y] = 0.0;
  975. C[Y] = -1.0 * P[i][Y] + 1.0 * P[i1][Y];
  976. D[Y] = 1.0 * P[i][Y];
  977. /* Get maximum coordinates in current segment. */
  978. x[0] = x[2] = P[i][X];
  979. x[1] = x[3] = P[i1][X];
  980. y[0] = y[2] = P[i][Y];
  981. y[1] = y[3] = P[i1][Y];
  982. break;
  983. /*************************************************************************
  984. * Quadratic spline.
  985. **************************************************************************/
  986. case QUADRATIC_SPLINE:
  987. /* Use quadratic interpolation. */
  988. A[X] = 0.0;
  989. B[X] = 0.5 * P[i][X] - 1.0 * P[i1][X] + 0.5 * P[i2][X];
  990. C[X] = -0.5 * P[i][X] + 0.5 * P[i2][X];
  991. D[X] = 1.0 * P[i1][X];
  992. A[Y] = 0.0;
  993. B[Y] = 0.5 * P[i][Y] - 1.0 * P[i1][Y] + 0.5 * P[i2][Y];
  994. C[Y] = -0.5 * P[i][Y] + 0.5 * P[i2][Y];
  995. D[Y] = 1.0 * P[i1][Y];
  996. /* Get maximum coordinates in current segment. */
  997. x[0] = x[2] = P[i1][X];
  998. x[1] = x[3] = P[i2][X];
  999. y[0] = y[2] = P[i1][Y];
  1000. y[1] = y[3] = P[i2][Y];
  1001. break;
  1002. /*************************************************************************
  1003. * Cubic spline.
  1004. **************************************************************************/
  1005. case CUBIC_SPLINE:
  1006. /* Use cubic interpolation. */
  1007. A[X] = -0.5 * P[i][X] + 1.5 * P[i1][X] - 1.5 * P[i2][X] + 0.5 * P[i3][X];
  1008. B[X] = P[i][X] - 2.5 * P[i1][X] + 2.0 * P[i2][X] - 0.5 * P[i3][X];
  1009. C[X] = -0.5 * P[i][X] + 0.5 * P[i2][X];
  1010. D[X] = P[i1][X];
  1011. A[Y] = -0.5 * P[i][Y] + 1.5 * P[i1][Y] - 1.5 * P[i2][Y] + 0.5 * P[i3][Y];
  1012. B[Y] = P[i][Y] - 2.5 * P[i1][Y] + 2.0 * P[i2][Y] - 0.5 * P[i3][Y];
  1013. C[Y] = -0.5 * P[i][Y] + 0.5 * P[i2][Y];
  1014. D[Y] = P[i1][Y];
  1015. /* Get maximum coordinates in current segment. */
  1016. x[0] = x[2] = P[i1][X];
  1017. x[1] = x[3] = P[i2][X];
  1018. y[0] = y[2] = P[i1][Y];
  1019. y[1] = y[3] = P[i2][Y];
  1020. break;
  1021. /*************************************************************************
  1022. * Bezier spline.
  1023. **************************************************************************/
  1024. case BEZIER_SPLINE:
  1025. /* Use Bernstein interpolation. */
  1026. A[X] = P[i][X] - 3.0 * P[i1][X] + 3.0 * P[i2][X] - P[i3][X];
  1027. B[X] = 3.0 * P[i1][X] - 6.0 * P[i2][X] + 3.0 * P[i3][X];
  1028. C[X] = 3.0 * P[i2][X] - 3.0 * P[i3][X];
  1029. D[X] = P[i3][X];
  1030. A[Y] = P[i][Y] - 3.0 * P[i1][Y] + 3.0 * P[i2][Y] - P[i3][Y];
  1031. B[Y] = 3.0 * P[i1][Y] - 6.0 * P[i2][Y] + 3.0 * P[i3][Y];
  1032. C[Y] = 3.0 * P[i2][Y] - 3.0 * P[i3][Y];
  1033. D[Y] = P[i3][Y];
  1034. x[0] = P[i][X];
  1035. x[1] = P[i1][X];
  1036. x[2] = P[i2][X];
  1037. x[3] = P[i3][X];
  1038. y[0] = P[i][Y];
  1039. y[1] = P[i1][Y];
  1040. y[2] = P[i2][Y];
  1041. y[3] = P[i3][Y];
  1042. break;
  1043. default:
  1044. Error("Unknown lathe type in Compute_Lathe().\n");
  1045. }
  1046. Assign_UV_Vect(Lathe->Spline->Entry[segment].A, A);
  1047. Assign_UV_Vect(Lathe->Spline->Entry[segment].B, B);
  1048. Assign_UV_Vect(Lathe->Spline->Entry[segment].C, C);
  1049. Assign_UV_Vect(Lathe->Spline->Entry[segment].D, D);
  1050. if ((Lathe->Spline_Type == QUADRATIC_SPLINE) ||
  1051. (Lathe->Spline_Type == CUBIC_SPLINE))
  1052. {
  1053. /* Get maximum coordinates in current segment. */
  1054. c[0] = 3.0 * A[X];
  1055. c[1] = 2.0 * B[X];
  1056. c[2] = C[X];
  1057. n = Solve_Polynomial(2, c, r, FALSE, 0.0);
  1058. while (n--)
  1059. {
  1060. if ((r[n] >= 0.0) && (r[n] <= 1.0))
  1061. {
  1062. x[n] = r[n] * (r[n] * (r[n] * A[X] + B[X]) + C[X]) + D[X];
  1063. }
  1064. }
  1065. c[0] = 3.0 * A[Y];
  1066. c[1] = 2.0 * B[Y];
  1067. c[2] = C[Y];
  1068. n = Solve_Polynomial(2, c, r, FALSE, 0.0);
  1069. while (n--)
  1070. {
  1071. if ((r[n] >= 0.0) && (r[n] <= 1.0))
  1072. {
  1073. y[n] = r[n] * (r[n] * (r[n] * A[Y] + B[Y]) + C[Y]) + D[Y];
  1074. }
  1075. }
  1076. }
  1077. /* Set current segment's bounding cylinder. */
  1078. tmp_r1[segment] = min(min(x[0], x[1]), min(x[2], x[3]));
  1079. tmp_r2[segment] = max(max(x[0], x[1]), max(x[2], x[3]));
  1080. tmp_h1[segment] = min(min(y[0], y[1]), min(y[2], y[3]));
  1081. tmp_h2[segment] = max(max(y[0], y[1]), max(y[2], y[3]));
  1082. /* Keep track of overall bounding cylinder. */
  1083. xmin = min(xmin, tmp_r1[segment]);
  1084. xmax = max(xmax, tmp_r2[segment]);
  1085. ymin = min(ymin, tmp_h1[segment]);
  1086. ymax = max(ymax, tmp_h2[segment]);
  1087. /*
  1088. fprintf(stderr, "bound spline segment %d: ", i);
  1089. fprintf(stderr, "r = %f - %f, h = %f - %f\n", tmp_r1[segment], tmp_r2[segment], tmp_h1[segment], tmp_h2[segment]);
  1090. */
  1091. /* Advance to next segment. */
  1092. switch (Lathe->Spline_Type)
  1093. {
  1094. case LINEAR_SPLINE:
  1095. case QUADRATIC_SPLINE:
  1096. case CUBIC_SPLINE:
  1097. i++;
  1098. break;
  1099. case BEZIER_SPLINE:
  1100. i += 4;
  1101. break;
  1102. }
  1103. segment++;
  1104. }
  1105. Lathe->Number = number_of_segments;
  1106. /* Set overall bounding cylinder. */
  1107. Lathe->Radius1 = xmin;
  1108. Lathe->Radius2 = xmax;
  1109. Lathe->Height1 = ymin;
  1110. Lathe->Height2 = ymax;
  1111. /* Get bounding cylinder. */
  1112. Lathe->Spline->BCyl = Create_BCyl(Lathe->Number, tmp_r1, tmp_r2, tmp_h1, tmp_h2);
  1113. /* Get rid of temp. memory. */
  1114. POV_FREE(tmp_h2);
  1115. POV_FREE(tmp_h1);
  1116. POV_FREE(tmp_r2);
  1117. POV_FREE(tmp_r1);
  1118. }
  1119. /*****************************************************************************
  1120. *
  1121. * FUNCTION
  1122. *
  1123. * test_hit
  1124. *
  1125. * INPUT
  1126. *
  1127. * Lathe - Pointer to lathe structure
  1128. * Ray - Current ray
  1129. * Depth_Stack - Current depth stack
  1130. * d, w, n - Intersection depth, parameter and segment number
  1131. *
  1132. * OUTPUT
  1133. *
  1134. * Depth_Stack
  1135. *
  1136. * RETURNS
  1137. *
  1138. * AUTHOR
  1139. *
  1140. * Dieter Bayer
  1141. *
  1142. * DESCRIPTION
  1143. *
  1144. * Test if a hit is valid and push if on the intersection depth.
  1145. *
  1146. * CHANGES
  1147. *
  1148. * Oct 1996 : Creation.
  1149. *
  1150. ******************************************************************************/
  1151. static int test_hit(LATHE *Lathe, RAY *Ray, ISTACK *Depth_Stack, DBL d, DBL w, int n)
  1152. {
  1153. VECTOR IPoint;
  1154. if ((d > DEPTH_TOLERANCE) && (d < Max_Distance))
  1155. {
  1156. VEvaluateRay(IPoint, Ray->Initial, d, Ray->Direction);
  1157. if (Point_In_Clip(IPoint, ((OBJECT *)Lathe)->Clip))
  1158. {
  1159. push_entry_i1_d1(d, IPoint, (OBJECT *)Lathe, n, w, Depth_Stack);
  1160. return(TRUE);
  1161. }
  1162. }
  1163. return(FALSE);
  1164. }