DISCS.C 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. /****************************************************************************
  2. * discs.c
  3. *
  4. * This module implements the disc primitive.
  5. * This file was written by Alexander Enzmann. He wrote the code for
  6. * discs and generously provided us these enhancements.
  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. *****************************************************************************/
  25. #include "frame.h"
  26. #include "povray.h"
  27. #include "vector.h"
  28. #include "povproto.h"
  29. #include "bbox.h"
  30. #include "discs.h"
  31. #include "matrices.h"
  32. #include "objects.h"
  33. /*****************************************************************************
  34. * Local preprocessor defines
  35. ******************************************************************************/
  36. /*****************************************************************************
  37. * Static functions
  38. ******************************************************************************/
  39. static int Intersect_Disc (RAY *Ray, DISC *Disc, DBL *Depth);
  40. static int All_Disc_Intersections (OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack);
  41. static int Inside_Disc (VECTOR point, OBJECT *Object);
  42. static void Disc_Normal (VECTOR Result, OBJECT *Object, INTERSECTION *Inter);
  43. static DISC *Copy_Disc (OBJECT *Object);
  44. static void Translate_Disc (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
  45. static void Rotate_Disc (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
  46. static void Scale_Disc (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
  47. static void Transform_Disc (OBJECT *Object, TRANSFORM *Trans);
  48. static void Invert_Disc (OBJECT *Object);
  49. static void Destroy_Disc (OBJECT *Object);
  50. static void Compute_Disc_BBox (DISC *Disc);
  51. /*****************************************************************************
  52. * Local variables
  53. ******************************************************************************/
  54. static METHODS Disc_Methods =
  55. {
  56. All_Disc_Intersections,
  57. Inside_Disc, Disc_Normal,
  58. (COPY_METHOD)Copy_Disc, Translate_Disc, Rotate_Disc, Scale_Disc, Transform_Disc,
  59. Invert_Disc, Destroy_Disc
  60. };
  61. /*****************************************************************************
  62. *
  63. * FUNCTION
  64. *
  65. * All_Disc_Intersections
  66. *
  67. * INPUT
  68. *
  69. * OUTPUT
  70. *
  71. * RETURNS
  72. *
  73. * AUTHOR
  74. *
  75. * Alexander Enzmann
  76. *
  77. * DESCRIPTION
  78. *
  79. * -
  80. *
  81. * CHANGES
  82. *
  83. * -
  84. *
  85. ******************************************************************************/
  86. static int All_Disc_Intersections (OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack)
  87. {
  88. int Intersection_Found;
  89. DBL Depth;
  90. VECTOR IPoint;
  91. Intersection_Found = FALSE;
  92. if (Intersect_Disc (Ray, (DISC *)Object, &Depth))
  93. {
  94. VEvaluateRay(IPoint, Ray->Initial, Depth, Ray->Direction);
  95. if (Point_In_Clip (IPoint, Object->Clip))
  96. {
  97. push_entry(Depth,IPoint,Object,Depth_Stack);
  98. Intersection_Found = TRUE;
  99. }
  100. }
  101. return (Intersection_Found);
  102. }
  103. /*****************************************************************************
  104. *
  105. * FUNCTION
  106. *
  107. * Intersect_Disc
  108. *
  109. * INPUT
  110. *
  111. * OUTPUT
  112. *
  113. * RETURNS
  114. *
  115. * AUTHOR
  116. *
  117. * Alexander Enzmann
  118. *
  119. * DESCRIPTION
  120. *
  121. * -
  122. *
  123. * CHANGES
  124. *
  125. * -
  126. *
  127. ******************************************************************************/
  128. static int Intersect_Disc (RAY *Ray, DISC *disc, DBL *Depth)
  129. {
  130. DBL t, u, v, r2, len;
  131. VECTOR P, D;
  132. Increase_Counter(stats[Ray_Disc_Tests]);
  133. /* Transform the point into the discs space */
  134. MInvTransPoint(P, Ray->Initial, disc->Trans);
  135. MInvTransDirection(D, Ray->Direction, disc->Trans);
  136. VLength(len, D);
  137. VInverseScaleEq(D, len);
  138. if (fabs(D[Z]) > EPSILON)
  139. {
  140. t = -P[Z] / D[Z];
  141. if (t >= 0.0)
  142. {
  143. u = P[X] + t * D[X];
  144. v = P[Y] + t * D[Y];
  145. r2 = Sqr(u) + Sqr(v);
  146. if ((r2 >= disc->iradius2) && (r2 <= disc->oradius2))
  147. {
  148. *Depth = t / len;
  149. if ((*Depth > Small_Tolerance) && (*Depth < Max_Distance))
  150. {
  151. Increase_Counter(stats[Ray_Disc_Tests_Succeeded]);
  152. return (TRUE);
  153. }
  154. }
  155. }
  156. }
  157. return (FALSE);
  158. }
  159. /*****************************************************************************
  160. *
  161. * FUNCTION
  162. *
  163. * Inside_Disc
  164. *
  165. * INPUT
  166. *
  167. * OUTPUT
  168. *
  169. * RETURNS
  170. *
  171. * AUTHOR
  172. *
  173. * Alexander Enzmann
  174. *
  175. * DESCRIPTION
  176. *
  177. * -
  178. *
  179. * CHANGES
  180. *
  181. * -
  182. *
  183. ******************************************************************************/
  184. static int Inside_Disc (VECTOR IPoint, OBJECT *Object)
  185. {
  186. VECTOR New_Point;
  187. DISC *disc = (DISC *) Object;
  188. /* Transform the point into the discs space */
  189. MInvTransPoint(New_Point, IPoint, disc->Trans);
  190. if (New_Point[Z] >= 0.0)
  191. {
  192. /* We are outside. */
  193. return (Test_Flag(disc, INVERTED_FLAG));
  194. }
  195. else
  196. {
  197. /* We are inside. */
  198. return (!Test_Flag(disc, INVERTED_FLAG));
  199. }
  200. }
  201. /*****************************************************************************
  202. *
  203. * FUNCTION
  204. *
  205. * Disc_Normal
  206. *
  207. * INPUT
  208. *
  209. * OUTPUT
  210. *
  211. * RETURNS
  212. *
  213. * AUTHOR
  214. *
  215. * Alexander Enzmann
  216. *
  217. * DESCRIPTION
  218. *
  219. * -
  220. *
  221. * CHANGES
  222. *
  223. * -
  224. *
  225. ******************************************************************************/
  226. static void Disc_Normal (VECTOR Result, OBJECT *Object, INTERSECTION *Inter)
  227. {
  228. Assign_Vector(Result, ((DISC *)Object)->normal);
  229. }
  230. /*****************************************************************************
  231. *
  232. * FUNCTION
  233. *
  234. * Translate_Disc
  235. *
  236. * INPUT
  237. *
  238. * OUTPUT
  239. *
  240. * RETURNS
  241. *
  242. * AUTHOR
  243. *
  244. * Alexander Enzmann
  245. *
  246. * DESCRIPTION
  247. *
  248. * -
  249. *
  250. * CHANGES
  251. *
  252. * -
  253. *
  254. ******************************************************************************/
  255. static void Translate_Disc (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
  256. {
  257. Transform_Disc(Object, Trans);
  258. }
  259. /*****************************************************************************
  260. *
  261. * FUNCTION
  262. *
  263. * Rotate_Disc
  264. *
  265. * INPUT
  266. *
  267. * OUTPUT
  268. *
  269. * RETURNS
  270. *
  271. * AUTHOR
  272. *
  273. * Alexander Enzmann
  274. *
  275. * DESCRIPTION
  276. *
  277. * -
  278. *
  279. * CHANGES
  280. *
  281. * -
  282. *
  283. ******************************************************************************/
  284. static void Rotate_Disc(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
  285. {
  286. Transform_Disc(Object, Trans);
  287. }
  288. /*****************************************************************************
  289. *
  290. * FUNCTION
  291. *
  292. * Scale_Disc
  293. *
  294. * INPUT
  295. *
  296. * OUTPUT
  297. *
  298. * RETURNS
  299. *
  300. * AUTHOR
  301. *
  302. * Alexander Enzmann
  303. *
  304. * DESCRIPTION
  305. *
  306. * -
  307. *
  308. * CHANGES
  309. *
  310. * -
  311. *
  312. ******************************************************************************/
  313. static void Scale_Disc(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
  314. {
  315. Transform_Disc(Object, Trans);
  316. }
  317. /*****************************************************************************
  318. *
  319. * FUNCTION
  320. *
  321. * Invert_Disc
  322. *
  323. * INPUT
  324. *
  325. * OUTPUT
  326. *
  327. * RETURNS
  328. *
  329. * AUTHOR
  330. *
  331. * Alexander Enzmann
  332. *
  333. * DESCRIPTION
  334. *
  335. * -
  336. *
  337. * CHANGES
  338. *
  339. * -
  340. *
  341. ******************************************************************************/
  342. static void Invert_Disc (OBJECT *Object)
  343. {
  344. Invert_Flag(Object, INVERTED_FLAG);
  345. }
  346. /*****************************************************************************
  347. *
  348. * FUNCTION
  349. *
  350. * Transform_Disc
  351. *
  352. * INPUT
  353. *
  354. * OUTPUT
  355. *
  356. * RETURNS
  357. *
  358. * AUTHOR
  359. *
  360. * Alexander Enzmann
  361. *
  362. * DESCRIPTION
  363. *
  364. * -
  365. *
  366. * CHANGES
  367. *
  368. * -
  369. *
  370. ******************************************************************************/
  371. static void Transform_Disc (OBJECT *Object, TRANSFORM *Trans)
  372. {
  373. DISC *Disc = (DISC *)Object;
  374. MTransNormal(((DISC *)Object)->normal, ((DISC *)Object)->normal, Trans);
  375. VNormalize(((DISC *)Object)->normal, ((DISC *)Object)->normal);
  376. Compose_Transforms(Disc->Trans, Trans);
  377. /* Recalculate the bounds */
  378. Compute_Disc_BBox(Disc);
  379. }
  380. /*****************************************************************************
  381. *
  382. * FUNCTION
  383. *
  384. * Create_Disc
  385. *
  386. * INPUT
  387. *
  388. * OUTPUT
  389. *
  390. * RETURNS
  391. *
  392. * AUTHOR
  393. *
  394. * Alexander Enzmann
  395. *
  396. * DESCRIPTION
  397. *
  398. * -
  399. *
  400. * CHANGES
  401. *
  402. * -
  403. *
  404. ******************************************************************************/
  405. DISC *Create_Disc ()
  406. {
  407. DISC *New;
  408. New = (DISC *)POV_MALLOC(sizeof (DISC), "disc");
  409. INIT_OBJECT_FIELDS(New, DISC_OBJECT, &Disc_Methods)
  410. Make_Vector (New->center, 0.0, 0.0, 0.0);
  411. Make_Vector (New->normal, 0.0, 0.0, 1.0);
  412. New->iradius2 = 0.0;
  413. New->oradius2 = 1.0;
  414. New->d = 0.0;
  415. New->Trans = Create_Transform();
  416. /* Default bounds */
  417. Make_BBox(New->BBox, -1.0, -1.0, -Small_Tolerance, 2.0, 2.0, 2.0 * Small_Tolerance);
  418. return (New);
  419. }
  420. /*****************************************************************************
  421. *
  422. * FUNCTION
  423. *
  424. * Copy_Disc
  425. *
  426. * INPUT
  427. *
  428. * OUTPUT
  429. *
  430. * RETURNS
  431. *
  432. * AUTHOR
  433. *
  434. * Alexander Enzmann
  435. *
  436. * DESCRIPTION
  437. *
  438. * -
  439. *
  440. * CHANGES
  441. *
  442. * Sep 1994 : Fixed memory leakage [DB]
  443. *
  444. ******************************************************************************/
  445. static DISC *Copy_Disc (OBJECT *Object)
  446. {
  447. DISC *New;
  448. New = Create_Disc();
  449. /* Get rid of the transformation created in Create_Disc(). */
  450. Destroy_Transform(New->Trans);
  451. /* Copy disc. */
  452. *New = *((DISC *) Object);
  453. New->Trans = Copy_Transform(((DISC *)Object)->Trans);
  454. return (New);
  455. }
  456. /*****************************************************************************
  457. *
  458. * FUNCTION
  459. *
  460. * Destroy_Disc
  461. *
  462. * INPUT
  463. *
  464. * OUTPUT
  465. *
  466. * RETURNS
  467. *
  468. * AUTHOR
  469. *
  470. * Alexander Enzmann
  471. *
  472. * DESCRIPTION
  473. *
  474. * -
  475. *
  476. * CHANGES
  477. *
  478. * -
  479. *
  480. ******************************************************************************/
  481. static void Destroy_Disc (OBJECT *Object)
  482. {
  483. Destroy_Transform(((DISC *)Object)->Trans);
  484. POV_FREE (Object);
  485. }
  486. /*****************************************************************************
  487. *
  488. * FUNCTION
  489. *
  490. * Compute_Disc
  491. *
  492. * INPUT
  493. *
  494. * Disc - Disc
  495. *
  496. * OUTPUT
  497. *
  498. * Disc
  499. *
  500. * RETURNS
  501. *
  502. * AUTHOR
  503. *
  504. * Dieter Bayer
  505. *
  506. * DESCRIPTION
  507. *
  508. * Calculate the transformation that scales, rotates, and translates
  509. * the disc to the desired location and orientation.
  510. *
  511. * CHANGES
  512. *
  513. * Aug 1994 : Creation.
  514. *
  515. ******************************************************************************/
  516. void Compute_Disc(DISC *Disc)
  517. {
  518. Compute_Coordinate_Transform(Disc->Trans, Disc->center, Disc->normal, 1.0, 1.0);
  519. Compute_Disc_BBox(Disc);
  520. }
  521. /*****************************************************************************
  522. *
  523. * FUNCTION
  524. *
  525. * Compute_Disc_BBox
  526. *
  527. * INPUT
  528. *
  529. * Disc - Disc
  530. *
  531. * OUTPUT
  532. *
  533. * Disc
  534. *
  535. * RETURNS
  536. *
  537. * AUTHOR
  538. *
  539. * Dieter Bayer
  540. *
  541. * DESCRIPTION
  542. *
  543. * Calculate the bounding box of a disc.
  544. *
  545. * CHANGES
  546. *
  547. * Aug 1994 : Creation.
  548. *
  549. ******************************************************************************/
  550. static void Compute_Disc_BBox(DISC *Disc)
  551. {
  552. DBL rad;
  553. rad = sqrt(Disc->oradius2);
  554. Make_BBox(Disc->BBox, -rad, -rad, -Small_Tolerance, 2.0*rad, 2.0*rad, 2.0*Small_Tolerance);
  555. Recompute_BBox(&Disc->BBox, Disc->Trans);
  556. }