SOR.C 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284
  1. /****************************************************************************
  2. * sor.c
  3. *
  4. * This module implements functions that manipulate surfaces of revolution.
  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. * Modifications by Thomas Willhalm, March 1999, used with permission
  25. *
  26. *****************************************************************************/
  27. /****************************************************************************
  28. *
  29. * Explanation:
  30. *
  31. * The surface of revolution primitive is defined by a set of points
  32. * in 2d space wich are interpolated by cubic splines. The resulting
  33. * 2d function is rotated about an axis to form the final 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 equation
  39. *
  40. * r^2 = f(w) = A * w * w * w + B * w * w + C * w + D.
  41. *
  42. * To intersect a ray R = P + k * D transformed into the object's
  43. * coordinate system with the surface of revolution, the equation
  44. *
  45. * (Pu + k * Du)^2 + (Pv + k * Dv)^2 = f(Pw + k * Dw)
  46. *
  47. * has to be solved for k (cubic polynomial in k).
  48. *
  49. * Note that Pu, Pv, Pw and Du, Dv, Dw denote the coordinates
  50. * of the vectors P and D.
  51. *
  52. * Syntax:
  53. *
  54. * revolution
  55. * {
  56. * number_of_points,
  57. *
  58. * <P[0]>, <P[1]>, ..., <P[n-1]>
  59. *
  60. * [ open ]
  61. * }
  62. *
  63. * Note that the P[i] are 2d vectors where u corresponds to the radius
  64. * and v to the height.
  65. *
  66. * Note that the first and last point, i.e. P[0] and P[n-1], are used
  67. * to determine the derivatives at the end point.
  68. *
  69. * Note that the x coordinate of a point corresponds to the radius and
  70. * the y coordinate to the height; the z coordinate isn't used.
  71. *
  72. * ---
  73. *
  74. * Ideas for the surface of revolution were taken from:
  75. *
  76. * P. Burger and D. Gillies, "Rapid Ray Tracing of General Surfaces
  77. * of Revolution", New Advances in Computer Graphics, Proceedings
  78. * of CG International '89, R. A. Earnshaw, B. Wyvill (Eds.),
  79. * Springer, ..., pp. 523-531
  80. *
  81. * ---
  82. *
  83. * May 1994 : Creation. [DB]
  84. *
  85. *****************************************************************************/
  86. #include "frame.h"
  87. #include "povray.h"
  88. #include "vector.h"
  89. #include "povproto.h"
  90. #include "bbox.h"
  91. #include "polysolv.h"
  92. #include "matrices.h"
  93. #include "objects.h"
  94. #include "sor.h"
  95. /*****************************************************************************
  96. * Local preprocessor defines
  97. ******************************************************************************/
  98. /* Minimal intersection depth for a valid intersection. */
  99. #define DEPTH_TOLERANCE 1.0e-4
  100. /* |Coefficients| < COEFF_LIMIT are regarded to be 0. */
  101. #define COEFF_LIMIT 1.0e-20
  102. /* Part of the surface of revolution hit. */
  103. #define BASE_PLANE 1
  104. #define CAP_PLANE 2
  105. #define CURVE 3
  106. /* Max. number of intersecions per spline segment. */
  107. #define MAX_INTERSECTIONS_PER_SEGMENT 4
  108. /*****************************************************************************
  109. * Local typedefs
  110. ******************************************************************************/
  111. /*****************************************************************************
  112. * Static functions
  113. ******************************************************************************/
  114. static int intersect_sor (RAY *Ray, SOR *Sor, ISTACK *Depth_Stack);
  115. static int All_Sor_Intersections (OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack);
  116. static int Inside_Sor (VECTOR point, OBJECT *Object);
  117. static void Sor_Normal (VECTOR Result, OBJECT *Object, INTERSECTION *Inter);
  118. static SOR *Copy_Sor (OBJECT *Object);
  119. static void Translate_Sor (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
  120. static void Rotate_Sor (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
  121. static void Scale_Sor (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
  122. static void Transform_Sor (OBJECT *Object, TRANSFORM *Trans);
  123. static void Invert_Sor (OBJECT *Object);
  124. static void Destroy_Sor (OBJECT *Object);
  125. static int test_hit (SOR *, RAY *, ISTACK *, DBL, int, int);
  126. /*****************************************************************************
  127. * Local variables
  128. ******************************************************************************/
  129. static METHODS Sor_Methods =
  130. {
  131. All_Sor_Intersections,
  132. Inside_Sor, Sor_Normal,
  133. (COPY_METHOD)Copy_Sor,
  134. Translate_Sor, Rotate_Sor,
  135. Scale_Sor, Transform_Sor, Invert_Sor, Destroy_Sor
  136. };
  137. /*****************************************************************************
  138. *
  139. * FUNCTION
  140. *
  141. * All_Sor_Intersections
  142. *
  143. * INPUT
  144. *
  145. * Object - Object
  146. * Ray - Ray
  147. * Depth_Stack - Intersection stack
  148. *
  149. * OUTPUT
  150. *
  151. * Depth_Stack
  152. *
  153. * RETURNS
  154. *
  155. * int - TRUE, if a intersection was found
  156. *
  157. * AUTHOR
  158. *
  159. * Dieter Bayer
  160. *
  161. * DESCRIPTION
  162. *
  163. * Determine ray/surface of revolution intersection and
  164. * clip intersection found.
  165. *
  166. * CHANGES
  167. *
  168. * May 1994 : Creation.
  169. * Oct 1996 : Changed code to include faster version. [DB]
  170. *
  171. ******************************************************************************/
  172. static int All_Sor_Intersections(OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack)
  173. {
  174. Increase_Counter(stats[Ray_Sor_Tests]);
  175. if (intersect_sor(Ray, (SOR *)Object, Depth_Stack))
  176. {
  177. Increase_Counter(stats[Ray_Sor_Tests_Succeeded]);
  178. return(TRUE);
  179. }
  180. return(FALSE);
  181. }
  182. /*****************************************************************************
  183. *
  184. * FUNCTION
  185. *
  186. * intersect_sor
  187. *
  188. * INPUT
  189. *
  190. * Ray - Ray
  191. * Sor - Sor
  192. * Intersection - Sor intersection structure
  193. *
  194. * OUTPUT
  195. *
  196. * Intersection
  197. *
  198. * RETURNS
  199. *
  200. * int - Number of intersections found
  201. *
  202. * AUTHOR
  203. *
  204. * Dieter Bayer
  205. *
  206. * DESCRIPTION
  207. *
  208. * Determine ray/surface of revolution intersection.
  209. *
  210. * NOTE: The curve is rotated about the y-axis!
  211. * Order reduction cannot be used.
  212. *
  213. * CHANGES
  214. *
  215. * May 1994 : Creation.
  216. * Oct 1996 : Changed code to include faster version. [DB]
  217. *
  218. ******************************************************************************/
  219. static int intersect_sor(RAY *Ray, SOR *Sor, ISTACK *Depth_Stack)
  220. {
  221. int cnt;
  222. int found, j, n;
  223. DBL a, b, k, h, len, u, v, r0;
  224. DBL x[4], y[3];
  225. DBL best;
  226. VECTOR P, D;
  227. BCYL_INT *intervals;
  228. SOR_SPLINE_ENTRY *Entry;
  229. /* Transform the ray into the surface of revolution space. */
  230. MInvTransPoint(P, Ray->Initial, Sor->Trans);
  231. MInvTransDirection(D, Ray->Direction, Sor->Trans);
  232. VLength(len, D);
  233. VInverseScaleEq(D, len);
  234. /* Test if ray misses object's bounds. */
  235. #ifdef SOR_EXTRA_STATS
  236. Increase_Counter(stats[Sor_Bound_Tests]);
  237. #endif
  238. if (((D[Y] >= 0.0) && (P[Y] > Sor->Height2)) ||
  239. ((D[Y] <= 0.0) && (P[Y] < Sor->Height1)) ||
  240. ((D[X] >= 0.0) && (P[X] > Sor->Radius2)) ||
  241. ((D[X] <= 0.0) && (P[X] < -Sor->Radius2)))
  242. {
  243. return(FALSE);
  244. }
  245. /* Get distance of the ray from rotation axis (= y axis). */
  246. r0 = P[X] * D[Z] - P[Z] * D[X];
  247. if ((a = D[X] * D[X] + D[Z] * D[Z]) > 0.0)
  248. {
  249. r0 /= sqrt(a);
  250. }
  251. /* Test if ray misses object's bounds. */
  252. if (r0 > Sor->Radius2)
  253. {
  254. return(FALSE);
  255. }
  256. /* Intersect all cylindrical bounds. */
  257. if ((cnt = Intersect_BCyl(Sor->Spline->BCyl, P, D)) == 0)
  258. {
  259. return(FALSE);
  260. }
  261. #ifdef SOR_EXTRA_STATS
  262. Increase_Counter(stats[Sor_Bound_Tests_Succeeded]);
  263. #endif
  264. /* Test base/cap plane. */
  265. found = FALSE;
  266. best = BOUND_HUGE;
  267. if (Test_Flag(Sor, CLOSED_FLAG) && (fabs(D[Y]) > EPSILON))
  268. {
  269. /* Test base plane. */
  270. if (Sor->Base_Radius_Squared > DEPTH_TOLERANCE)
  271. {
  272. k = (Sor->Height1 - P[Y]) / D[Y];
  273. u = P[X] + k * D[X];
  274. v = P[Z] + k * D[Z];
  275. b = u * u + v * v;
  276. if (b <= Sor->Base_Radius_Squared)
  277. {
  278. if (test_hit(Sor, Ray, Depth_Stack, k / len, BASE_PLANE, 0))
  279. {
  280. found = TRUE;
  281. if (k < best)
  282. {
  283. best = k;
  284. }
  285. }
  286. }
  287. }
  288. /* Test cap plane. */
  289. if (Sor->Cap_Radius_Squared > DEPTH_TOLERANCE)
  290. {
  291. k = (Sor->Height2 - P[Y]) / D[Y];
  292. u = P[X] + k * D[X];
  293. v = P[Z] + k * D[Z];
  294. b = u * u + v * v;
  295. if (b <= Sor->Cap_Radius_Squared)
  296. {
  297. if (test_hit(Sor, Ray, Depth_Stack, k / len, CAP_PLANE, 0))
  298. {
  299. found = TRUE;
  300. if (k < best)
  301. {
  302. best = k;
  303. }
  304. }
  305. }
  306. }
  307. }
  308. /* Step through the list of intersections. */
  309. intervals = Sor->Spline->BCyl->intervals;
  310. for (j = 0; j < cnt; j++)
  311. {
  312. /* Get current segment. */
  313. Entry = &Sor->Spline->Entry[intervals[j].n];
  314. /* If we already have the best intersection we may exit. */
  315. if (!(Sor->Type & IS_CHILD_OBJECT) && (intervals[j].d[0] > best))
  316. {
  317. break;
  318. }
  319. /* Cubic curve. */
  320. x[0] = Entry->A * D[Y] * D[Y] * D[Y];
  321. /*
  322. x[1] = D[Y] * D[Y] * (3.0 * Entry->A * P[Y] + Entry->B) - D[X] * D[X] - D[Z] * D[Z];
  323. */
  324. x[1] = D[Y] * D[Y] * (3.0 * Entry->A * P[Y] + Entry->B) - a;
  325. x[2] = D[Y] * (P[Y] * (3.0 * Entry->A * P[Y] + 2.0 * Entry->B) + Entry->C) - 2.0 * (P[X] * D[X] + P[Z] * D[Z]);
  326. x[3] = P[Y] * (P[Y] * (Entry->A * P[Y] + Entry->B) + Entry->C) + Entry->D - P[X] * P[X] - P[Z] * P[Z];
  327. n = Solve_Polynomial(3, x, y, Test_Flag(Sor, STURM_FLAG), 0.0);
  328. while (n--)
  329. {
  330. k = y[n];
  331. h = P[Y] + k * D[Y];
  332. if ((h >= Sor->Spline->BCyl->height[Sor->Spline->BCyl->entry[intervals[j].n].h1]) &&
  333. (h <= Sor->Spline->BCyl->height[Sor->Spline->BCyl->entry[intervals[j].n].h2]))
  334. {
  335. if (test_hit(Sor, Ray, Depth_Stack, k / len, CURVE, intervals[j].n))
  336. {
  337. found = TRUE;
  338. if (y[n] < best)
  339. {
  340. best = k;
  341. }
  342. }
  343. }
  344. }
  345. }
  346. return(found);
  347. }
  348. /*****************************************************************************
  349. *
  350. * FUNCTION
  351. *
  352. * Inside_Sor
  353. *
  354. * INPUT
  355. *
  356. * IPoint - Intersection point
  357. * Object - Object
  358. *
  359. * OUTPUT
  360. *
  361. * RETURNS
  362. *
  363. * int - TRUE if inside
  364. *
  365. * AUTHOR
  366. *
  367. * Dieter Bayer
  368. *
  369. * DESCRIPTION
  370. *
  371. * Return true if point lies inside the surface of revolution.
  372. *
  373. * CHANGES
  374. *
  375. * May 1994 : Creation.
  376. *
  377. ******************************************************************************/
  378. static int Inside_Sor(VECTOR IPoint, OBJECT *Object)
  379. {
  380. int i;
  381. DBL r0, r;
  382. VECTOR P;
  383. SOR *Sor = (SOR *)Object;
  384. SOR_SPLINE_ENTRY *Entry = NULL; /* tw */
  385. /* Transform the point into the surface of revolution space. */
  386. MInvTransPoint(P, IPoint, Sor->Trans);
  387. /* Test if we are inside the cylindrical bound. */
  388. if ((P[Y] >= Sor->Height1) && (P[Y] <= Sor->Height2))
  389. {
  390. r0 = P[X] * P[X] + P[Z] * P[Z];
  391. /* Test if we are inside the cylindrical bound. */
  392. if (r0 <= Sqr(Sor->Radius2))
  393. {
  394. /* Now find the segment the point is in. */
  395. for (i = 0; i < Sor->Number; i++)
  396. {
  397. Entry = &Sor->Spline->Entry[i];
  398. if ((P[Y] >= Sor->Spline->BCyl->height[Sor->Spline->BCyl->entry[i].h1]) &&
  399. (P[Y] <= Sor->Spline->BCyl->height[Sor->Spline->BCyl->entry[i].h2]))
  400. {
  401. break;
  402. }
  403. }
  404. /* Have we found any segment? */
  405. if (i < Sor->Number)
  406. {
  407. r = P[Y] * (P[Y] * (P[Y] * Entry->A + Entry->B) + Entry->C) + Entry->D;
  408. if (r0 <= r)
  409. {
  410. /* We're inside. */
  411. return(!Test_Flag(Sor, INVERTED_FLAG));
  412. }
  413. }
  414. }
  415. }
  416. /* We're outside. */
  417. return(Test_Flag(Sor, INVERTED_FLAG));
  418. }
  419. /*****************************************************************************
  420. *
  421. * FUNCTION
  422. *
  423. * Sor_Normal
  424. *
  425. * INPUT
  426. *
  427. * Result - Normal vector
  428. * Object - Object
  429. * Inter - Intersection found
  430. *
  431. * OUTPUT
  432. *
  433. * Result
  434. *
  435. * RETURNS
  436. *
  437. * AUTHOR
  438. *
  439. * Dieter Bayer
  440. *
  441. * DESCRIPTION
  442. *
  443. * Calculate the normal of the surface of revolution in a given point.
  444. *
  445. * CHANGES
  446. *
  447. * May 1994 : Creation.
  448. *
  449. ******************************************************************************/
  450. static void Sor_Normal(VECTOR Result, OBJECT *Object, INTERSECTION *Inter)
  451. {
  452. DBL k;
  453. VECTOR P;
  454. SOR *Sor = (SOR *)Object;
  455. SOR_SPLINE_ENTRY *Entry;
  456. VECTOR N;
  457. switch (Inter->i1)
  458. {
  459. case CURVE:
  460. /* Transform the intersection point into the surface of revolution space. */
  461. MInvTransPoint(P, Inter->IPoint, Sor->Trans);
  462. if (P[X] * P[X] + P[Z] * P[Z] > DEPTH_TOLERANCE)
  463. {
  464. Entry = &Sor->Spline->Entry[Inter->i2];
  465. k = 0.5 * (P[Y] * (3.0 * Entry->A * P[Y] + 2.0 * Entry->B) + Entry->C);
  466. N[X] = P[X];
  467. N[Y] = -k;
  468. N[Z] = P[Z];
  469. }
  470. break;
  471. case BASE_PLANE:
  472. Make_Vector(N, 0.0, -1.0, 0.0);
  473. break;
  474. case CAP_PLANE:
  475. Make_Vector(N, 0.0, 1.0, 0.0);
  476. break;
  477. }
  478. /* Transform the normal out of the surface of revolution space. */
  479. MTransNormal(Result, N, Sor->Trans);
  480. VNormalize(Result, Result);
  481. }
  482. /*****************************************************************************
  483. *
  484. * FUNCTION
  485. *
  486. * Translate_Sor
  487. *
  488. * INPUT
  489. *
  490. * Object - Object
  491. * Vector - Translation vector
  492. *
  493. * OUTPUT
  494. *
  495. * Object
  496. *
  497. * RETURNS
  498. *
  499. * AUTHOR
  500. *
  501. * Dieter Bayer
  502. *
  503. * DESCRIPTION
  504. *
  505. * Translate a surface of revolution.
  506. *
  507. * CHANGES
  508. *
  509. * May 1994 : Creation.
  510. *
  511. ******************************************************************************/
  512. static void Translate_Sor(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
  513. {
  514. Transform_Sor(Object, Trans);
  515. }
  516. /*****************************************************************************
  517. *
  518. * FUNCTION
  519. *
  520. * Rotate_Sor
  521. *
  522. * INPUT
  523. *
  524. * Object - Object
  525. * Vector - Rotation vector
  526. *
  527. * OUTPUT
  528. *
  529. * Object
  530. *
  531. * RETURNS
  532. *
  533. * AUTHOR
  534. *
  535. * Dieter Bayer
  536. *
  537. * DESCRIPTION
  538. *
  539. * Rotate a surface of revolution.
  540. *
  541. * CHANGES
  542. *
  543. * May 1994 : Creation.
  544. *
  545. ******************************************************************************/
  546. static void Rotate_Sor(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
  547. {
  548. Transform_Sor(Object, Trans);
  549. }
  550. /*****************************************************************************
  551. *
  552. * FUNCTION
  553. *
  554. * Scale_Sor
  555. *
  556. * INPUT
  557. *
  558. * Object - Object
  559. * Vector - Scaling vector
  560. *
  561. * OUTPUT
  562. *
  563. * Object
  564. *
  565. * RETURNS
  566. *
  567. * AUTHOR
  568. *
  569. * Dieter Bayer
  570. *
  571. * DESCRIPTION
  572. *
  573. * Scale a surface of revolution.
  574. *
  575. * CHANGES
  576. *
  577. * May 1994 : Creation.
  578. *
  579. ******************************************************************************/
  580. static void Scale_Sor(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
  581. {
  582. Transform_Sor(Object, Trans);
  583. }
  584. /*****************************************************************************
  585. *
  586. * FUNCTION
  587. *
  588. * Transform_Sor
  589. *
  590. * INPUT
  591. *
  592. * Object - Object
  593. * Trans - Transformation to apply
  594. *
  595. * OUTPUT
  596. *
  597. * Object
  598. *
  599. * RETURNS
  600. *
  601. * AUTHOR
  602. *
  603. * Dieter Bayer
  604. *
  605. * DESCRIPTION
  606. *
  607. * Transform a surface of revolution and recalculate its bounding box.
  608. *
  609. * CHANGES
  610. *
  611. * May 1994 : Creation.
  612. *
  613. ******************************************************************************/
  614. static void Transform_Sor(OBJECT *Object, TRANSFORM *Trans)
  615. {
  616. Compose_Transforms(((SOR *)Object)->Trans, Trans);
  617. Compute_Sor_BBox((SOR *)Object);
  618. }
  619. /*****************************************************************************
  620. *
  621. * FUNCTION
  622. *
  623. * Invert_Sor
  624. *
  625. * INPUT
  626. *
  627. * Object - Object
  628. *
  629. * OUTPUT
  630. *
  631. * Object
  632. *
  633. * RETURNS
  634. *
  635. * AUTHOR
  636. *
  637. * Dieter Bayer
  638. *
  639. * DESCRIPTION
  640. *
  641. * Invert a surface of revolution.
  642. *
  643. * CHANGES
  644. *
  645. * May 1994 : Creation.
  646. *
  647. ******************************************************************************/
  648. static void Invert_Sor(OBJECT *Object)
  649. {
  650. Invert_Flag(Object, INVERTED_FLAG);
  651. }
  652. /*****************************************************************************
  653. *
  654. * FUNCTION
  655. *
  656. * Create_Sor
  657. *
  658. * INPUT
  659. *
  660. * OUTPUT
  661. *
  662. * RETURNS
  663. *
  664. * SOR * - new surface of revolution
  665. *
  666. * AUTHOR
  667. *
  668. * Dieter Bayer
  669. *
  670. * DESCRIPTION
  671. *
  672. * Create a new surface of revolution.
  673. *
  674. * CHANGES
  675. *
  676. * May 1994 : Creation.
  677. *
  678. ******************************************************************************/
  679. SOR *Create_Sor()
  680. {
  681. SOR *New;
  682. New = (SOR *)POV_MALLOC(sizeof(SOR), "surface of revolution");
  683. INIT_OBJECT_FIELDS(New,SOR_OBJECT,&Sor_Methods)
  684. New->Trans = Create_Transform();
  685. New->Spline = NULL;
  686. New->Radius2 =
  687. New->Base_Radius_Squared =
  688. New->Cap_Radius_Squared = 0.0;
  689. /* SOR should have capped ends by default. CEY 3/98*/
  690. Set_Flag(New, CLOSED_FLAG);
  691. return(New);
  692. }
  693. /*****************************************************************************
  694. *
  695. * FUNCTION
  696. *
  697. * Copy_Sor
  698. *
  699. * INPUT
  700. *
  701. * Object - Object
  702. *
  703. * OUTPUT
  704. *
  705. * RETURNS
  706. *
  707. * void * - New surface of revolution
  708. *
  709. * AUTHOR
  710. *
  711. * Dieter Bayer
  712. *
  713. * DESCRIPTION
  714. *
  715. * Copy a surface of revolution structure.
  716. *
  717. * NOTE: The splines are not copied, only the number of references is
  718. * counted, so that Destray_Sor() knows if they can be destroyed.
  719. *
  720. * CHANGES
  721. *
  722. * May 1994 : Creation.
  723. *
  724. * Sep 1994 : fixed memory leakage [DB]
  725. *
  726. ******************************************************************************/
  727. static SOR *Copy_Sor(OBJECT *Object)
  728. {
  729. SOR *New, *Sor = (SOR *)Object;
  730. New = Create_Sor();
  731. /* Get rid of the transformation created in Create_Sor(). */
  732. Destroy_Transform(New->Trans);
  733. /* Copy surface of revolution. */
  734. *New = *Sor;
  735. New->Trans = Copy_Transform(Sor->Trans);
  736. New->Spline->References++;
  737. return(New);
  738. }
  739. /*****************************************************************************
  740. *
  741. * FUNCTION
  742. *
  743. * Destroy_Sor
  744. *
  745. * INPUT
  746. *
  747. * Object - Object
  748. *
  749. * OUTPUT
  750. *
  751. * Object
  752. *
  753. * RETURNS
  754. *
  755. * AUTHOR
  756. *
  757. * Dieter Bayer
  758. *
  759. * DESCRIPTION
  760. *
  761. * Destroy a surface of revolution.
  762. *
  763. * NOTE: The splines are destroyed if they are no longer used by any copy.
  764. *
  765. * CHANGES
  766. *
  767. * May 1994 : Creation.
  768. *
  769. ******************************************************************************/
  770. static void Destroy_Sor (OBJECT *Object)
  771. {
  772. SOR *Sor = (SOR *)Object;
  773. Destroy_Transform(Sor->Trans);
  774. if (--(Sor->Spline->References) == 0)
  775. {
  776. Destroy_BCyl(Sor->Spline->BCyl);
  777. POV_FREE(Sor->Spline->Entry);
  778. POV_FREE(Sor->Spline);
  779. }
  780. POV_FREE(Object);
  781. }
  782. /*****************************************************************************
  783. *
  784. * FUNCTION
  785. *
  786. * Compute_Sor_BBox
  787. *
  788. * INPUT
  789. *
  790. * Sor - Sor
  791. *
  792. * OUTPUT
  793. *
  794. * Sor
  795. *
  796. * RETURNS
  797. *
  798. * AUTHOR
  799. *
  800. * Dieter Bayer
  801. *
  802. * DESCRIPTION
  803. *
  804. * Calculate the bounding box of a surface of revolution.
  805. *
  806. * CHANGES
  807. *
  808. * May 1994 : Creation.
  809. *
  810. ******************************************************************************/
  811. void Compute_Sor_BBox(SOR *Sor)
  812. {
  813. Make_BBox(Sor->BBox, -Sor->Radius2, Sor->Height1, -Sor->Radius2,
  814. 2.0 * Sor->Radius2, Sor->Height2 - Sor->Height1, 2.0 * Sor->Radius2);
  815. Recompute_BBox(&Sor->BBox, Sor->Trans);
  816. }
  817. /*****************************************************************************
  818. *
  819. * FUNCTION
  820. *
  821. * Compute_Sor
  822. *
  823. * INPUT
  824. *
  825. * Sor - Sor
  826. * P - Points defining surface of revolution
  827. *
  828. * OUTPUT
  829. *
  830. * Sor
  831. *
  832. * RETURNS
  833. *
  834. * AUTHOR
  835. *
  836. * Dieter Bayer, June 1994
  837. *
  838. * DESCRIPTION
  839. *
  840. * Calculate the spline segments of a surface of revolution
  841. * from a set of points.
  842. *
  843. * Note that the number of points in the surface of revolution has to be set.
  844. *
  845. * CHANGES
  846. *
  847. * May 1994 : Creation.
  848. *
  849. ******************************************************************************/
  850. void Compute_Sor(SOR *Sor, UV_VECT *P)
  851. {
  852. int i, n;
  853. DBL *tmp_r1;
  854. DBL *tmp_r2;
  855. DBL *tmp_h1;
  856. DBL *tmp_h2;
  857. DBL A, B, C, D, w, k[4];
  858. DBL x[4], xmax, xmin;
  859. DBL y[2], ymax, ymin;
  860. DBL c[3], r[2];
  861. MATRIX Mat;
  862. /* Allocate Sor->Number segments. */
  863. if (Sor->Spline == NULL)
  864. {
  865. Sor->Spline = (SOR_SPLINE *)POV_MALLOC(sizeof(SOR_SPLINE), "spline segments of surface of revoluion");
  866. Sor->Spline->References = 1;
  867. Sor->Spline->Entry = (SOR_SPLINE_ENTRY *)POV_MALLOC(Sor->Number*sizeof(SOR_SPLINE_ENTRY), "spline segments of surface of revoluion");
  868. }
  869. else
  870. {
  871. Error("Surface of revolution segments are already defined.\n");
  872. }
  873. /* Allocate temporary lists. */
  874. tmp_r1 = (DBL *)POV_MALLOC(Sor->Number * sizeof(DBL), "temp lathe data");
  875. tmp_r2 = (DBL *)POV_MALLOC(Sor->Number * sizeof(DBL), "temp lathe data");
  876. tmp_h1 = (DBL *)POV_MALLOC(Sor->Number * sizeof(DBL), "temp lathe data");
  877. tmp_h2 = (DBL *)POV_MALLOC(Sor->Number * sizeof(DBL), "temp lathe data");
  878. /* We want to know the size of the overall bounding cylinder. */
  879. xmax = ymax = -BOUND_HUGE;
  880. xmin = ymin = BOUND_HUGE;
  881. /* Calculate segments, i.e. cubic patches. */
  882. for (i = 0; i < Sor->Number; i++)
  883. {
  884. if ((fabs(P[i+2][Y] - P[i][Y]) < EPSILON) ||
  885. (fabs(P[i+3][Y] - P[i+1][Y]) < EPSILON))
  886. {
  887. Error("Incorrect point in surface of revolution.\n");
  888. }
  889. /* Use cubic interpolation. */
  890. k[0] = P[i+1][X] * P[i+1][X];
  891. k[1] = P[i+2][X] * P[i+2][X];
  892. k[2] = (P[i+2][X] - P[i][X]) / (P[i+2][Y] - P[i][Y]);
  893. k[3] = (P[i+3][X] - P[i+1][X]) / (P[i+3][Y] - P[i+1][Y]);
  894. k[2] *= 2.0 * P[i+1][X];
  895. k[3] *= 2.0 * P[i+2][X];
  896. w = P[i+1][Y];
  897. Mat[0][0] = w * w * w;
  898. Mat[0][1] = w * w;
  899. Mat[0][2] = w;
  900. Mat[0][3] = 1.0;
  901. Mat[2][0] = 3.0 * w * w;
  902. Mat[2][1] = 2.0 * w;
  903. Mat[2][2] = 1.0;
  904. Mat[2][3] = 0.0;
  905. w = P[i+2][Y];
  906. Mat[1][0] = w * w * w;
  907. Mat[1][1] = w * w;
  908. Mat[1][2] = w;
  909. Mat[1][3] = 1.0;
  910. Mat[3][0] = 3.0 * w * w;
  911. Mat[3][1] = 2.0 * w;
  912. Mat[3][2] = 1.0;
  913. Mat[3][3] = 0.0;
  914. MInvers(Mat, Mat);
  915. /* Calculate coefficients of cubic patch. */
  916. A = k[0] * Mat[0][0] + k[1] * Mat[0][1] + k[2] * Mat[0][2] + k[3] * Mat[0][3];
  917. B = k[0] * Mat[1][0] + k[1] * Mat[1][1] + k[2] * Mat[1][2] + k[3] * Mat[1][3];
  918. C = k[0] * Mat[2][0] + k[1] * Mat[2][1] + k[2] * Mat[2][2] + k[3] * Mat[2][3];
  919. D = k[0] * Mat[3][0] + k[1] * Mat[3][1] + k[2] * Mat[3][2] + k[3] * Mat[3][3];
  920. if (fabs(A) < EPSILON) A = 0.0;
  921. if (fabs(B) < EPSILON) B = 0.0;
  922. if (fabs(C) < EPSILON) C = 0.0;
  923. if (fabs(D) < EPSILON) D = 0.0;
  924. Sor->Spline->Entry[i].A = A;
  925. Sor->Spline->Entry[i].B = B;
  926. Sor->Spline->Entry[i].C = C;
  927. Sor->Spline->Entry[i].D = D;
  928. /* Get minimum and maximum radius**2 in current segment. */
  929. y[0] = P[i+1][Y];
  930. y[1] = P[i+2][Y];
  931. x[0] = x[2] = P[i+1][X];
  932. x[1] = x[3] = P[i+2][X];
  933. c[0] = 3.0 * A;
  934. c[1] = 2.0 * B;
  935. c[2] = C;
  936. n = Solve_Polynomial(2, c, r, FALSE, 0.0);
  937. while (n--)
  938. {
  939. if ((r[n] >= y[0]) && (r[n] <= y[1]))
  940. {
  941. x[n] = sqrt(r[n] * (r[n] * (r[n] * A + B) + C) + D);
  942. }
  943. }
  944. /* Set current segment's bounding cylinder. */
  945. tmp_r1[i] = min(min(x[0], x[1]), min(x[2], x[3]));
  946. tmp_r2[i] = max(max(x[0], x[1]), max(x[2], x[3]));
  947. tmp_h1[i] = y[0];
  948. tmp_h2[i] = y[1];
  949. /* Keep track of overall bounding cylinder. */
  950. xmin = min(xmin, tmp_r1[i]);
  951. xmax = max(xmax, tmp_r2[i]);
  952. ymin = min(ymin, tmp_h1[i]);
  953. ymax = max(ymax, tmp_h2[i]);
  954. /*
  955. fprintf(stderr, "bound spline segment %d: ", i);
  956. fprintf(stderr, "r = %f - %f, h = %f - %f\n", tmp_r1[i], tmp_r2[i], tmp_h1[i], tmp_h2[i]);
  957. */
  958. }
  959. /* Set overall bounding cylinder. */
  960. Sor->Radius1 = ymax;
  961. Sor->Radius2 = xmax;
  962. Sor->Height1 = ymin;
  963. Sor->Height2 = ymax;
  964. /* Get cap radius. */
  965. w = tmp_h2[Sor->Number-1];
  966. A = Sor->Spline->Entry[Sor->Number-1].A;
  967. B = Sor->Spline->Entry[Sor->Number-1].B;
  968. C = Sor->Spline->Entry[Sor->Number-1].C;
  969. D = Sor->Spline->Entry[Sor->Number-1].D;
  970. if ((Sor->Cap_Radius_Squared = w * (w * (A * w + B) + C) + D) < 0.0)
  971. {
  972. Sor->Cap_Radius_Squared = 0.0;
  973. }
  974. /* Get base radius. */
  975. w = tmp_h1[0];
  976. A = Sor->Spline->Entry[0].A;
  977. B = Sor->Spline->Entry[0].B;
  978. C = Sor->Spline->Entry[0].C;
  979. D = Sor->Spline->Entry[0].D;
  980. if ((Sor->Base_Radius_Squared = w * (w * (A * w + B) + C) + D) < 0.0)
  981. {
  982. Sor->Base_Radius_Squared = 0.0;
  983. }
  984. /* Get bounding cylinder. */
  985. Sor->Spline->BCyl = Create_BCyl(Sor->Number, tmp_r1, tmp_r2, tmp_h1, tmp_h2);
  986. /* Get rid of temp. memory. */
  987. POV_FREE(tmp_h2);
  988. POV_FREE(tmp_h1);
  989. POV_FREE(tmp_r2);
  990. POV_FREE(tmp_r1);
  991. }
  992. /*****************************************************************************
  993. *
  994. * FUNCTION
  995. *
  996. * test_hit
  997. *
  998. * INPUT
  999. *
  1000. * Sor - Pointer to lathe structure
  1001. * Ray - Current ray
  1002. * Depth_Stack - Current depth stack
  1003. * d, t, n - Intersection depth, type and number
  1004. *
  1005. * OUTPUT
  1006. *
  1007. * Depth_Stack
  1008. *
  1009. * RETURNS
  1010. *
  1011. * AUTHOR
  1012. *
  1013. * Dieter Bayer
  1014. *
  1015. * DESCRIPTION
  1016. *
  1017. * Test if a hit is valid and push if on the intersection depth.
  1018. *
  1019. * CHANGES
  1020. *
  1021. * Oct 1996 : Creation.
  1022. *
  1023. ******************************************************************************/
  1024. static int test_hit(SOR *Sor, RAY *Ray, ISTACK *Depth_Stack, DBL d, int t, int n)
  1025. {
  1026. VECTOR IPoint;
  1027. if ((d > DEPTH_TOLERANCE) && (d < Max_Distance))
  1028. {
  1029. VEvaluateRay(IPoint, Ray->Initial, d, Ray->Direction);
  1030. if (Point_In_Clip(IPoint, ((OBJECT *)Sor)->Clip))
  1031. {
  1032. push_entry_i1_i2(d, IPoint, (OBJECT *)Sor, t, n, Depth_Stack);
  1033. return(TRUE);
  1034. }
  1035. }
  1036. return(FALSE);
  1037. }