BCYL.C 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735
  1. /*****************************************************************************
  2. * bbcyl.c
  3. *
  4. * This file contains all functions for bounding
  5. * cylinders used by lathe and sor objects.
  6. *
  7. * from Persistence of Vision(tm) Ray Tracer
  8. * Copyright 1996,1999 Persistence of Vision Team
  9. *---------------------------------------------------------------------------
  10. * NOTICE: This source code file is provided so that users may experiment
  11. * with enhancements to POV-Ray and to port the software to platforms other
  12. * than those supported by the POV-Ray Team. There are strict rules under
  13. * which you are permitted to use this file. The rules are in the file
  14. * named POVLEGAL.DOC which should be distributed with this file.
  15. * If POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  16. * Team Coordinator by email to team-coord@povray.org or visit us on the web at
  17. * http://www.povray.org. The latest version of POV-Ray may be found at this site.
  18. *
  19. * This program is based on the popular DKB raytracer version 2.12.
  20. * DKBTrace was originally written by David K. Buck.
  21. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  22. *
  23. *****************************************************************************/
  24. #include "frame.h"
  25. #include "vector.h"
  26. #include "povproto.h"
  27. #include "bcyl.h"
  28. /*****************************************************************************
  29. * Local preprocessor defines
  30. ******************************************************************************/
  31. /*****************************************************************************
  32. * Local typedefs
  33. ******************************************************************************/
  34. /*****************************************************************************
  35. * Static functions
  36. ******************************************************************************/
  37. static int intersect_thick_cylinder (BCYL *BCyl, BCYL_ENTRY *Entry, DBL *dist);
  38. static void insert_hit (BCYL_INT *Element, BCYL_INT *intervals, int *cnt);
  39. static void intersect_bound_elements (BCYL *BCyl, VECTOR P, VECTOR D);
  40. /*****************************************************************************
  41. * Local variables
  42. ******************************************************************************/
  43. /*****************************************************************************
  44. *
  45. * FUNCTION
  46. *
  47. * intersect_thick_cylinder
  48. *
  49. * INPUT
  50. *
  51. * BCyl - Pointer to lathe structure
  52. * Entry - Segment whos bounding cylinder to intersect
  53. * dist - List of sorted intersection depths
  54. *
  55. * OUTPUT
  56. *
  57. * RETURNS
  58. *
  59. * int - number of intersections found
  60. *
  61. * AUTHOR
  62. *
  63. * Dieter Bayer
  64. *
  65. * DESCRIPTION
  66. *
  67. * Find all intersections of the current ray with the bounding
  68. * cylinder of the given segment. The intersection tests are
  69. * done in intersect_bound_elements() and the results stored
  70. * in the lathe structure are evaluated here.
  71. *
  72. * CHANGES
  73. *
  74. * Oct 1996 : Creation.
  75. *
  76. ******************************************************************************/
  77. static int intersect_thick_cylinder(BCYL *BCyl, BCYL_ENTRY *Entry, DBL *dist)
  78. {
  79. int i, j, n;
  80. DBL k, r, h;
  81. n = 0;
  82. /* Intersect ray with the cap-plane. */
  83. if (BCyl->hint[Entry->h2].n)
  84. {
  85. r = BCyl->hint[Entry->h2].w[0];
  86. if ((r >= BCyl->radius[Entry->r1]) &&
  87. (r <= BCyl->radius[Entry->r2]))
  88. {
  89. dist[n++] = BCyl->hint[Entry->h2].d[0];
  90. }
  91. }
  92. /* Intersect ray with the base-plane. */
  93. if (BCyl->hint[Entry->h1].n)
  94. {
  95. r = BCyl->hint[Entry->h1].w[0];
  96. if ((r >= BCyl->radius[Entry->r1]) &&
  97. (r <= BCyl->radius[Entry->r2]))
  98. {
  99. dist[n++] = BCyl->hint[Entry->h1].d[0];
  100. }
  101. }
  102. /* Intersect with inner cylinder. */
  103. if (BCyl->rint[Entry->r1].n)
  104. {
  105. h = BCyl->rint[Entry->r1].w[0];
  106. if ((h >= BCyl->height[Entry->h1]) &&
  107. (h <= BCyl->height[Entry->h2]))
  108. {
  109. dist[n++] = BCyl->rint[Entry->r1].d[0];
  110. }
  111. h = BCyl->rint[Entry->r1].w[1];
  112. if ((h >= BCyl->height[Entry->h1]) &&
  113. (h <= BCyl->height[Entry->h2]))
  114. {
  115. dist[n++] = BCyl->rint[Entry->r1].d[1];
  116. }
  117. }
  118. /* Intersect with outer cylinder. */
  119. if (BCyl->rint[Entry->r2].n)
  120. {
  121. h = BCyl->rint[Entry->r2].w[0];
  122. if ((h >= BCyl->height[Entry->h1]) &&
  123. (h <= BCyl->height[Entry->h2]))
  124. {
  125. dist[n++] = BCyl->rint[Entry->r2].d[0];
  126. }
  127. h = BCyl->rint[Entry->r2].w[1];
  128. if ((h >= BCyl->height[Entry->h1]) &&
  129. (h <= BCyl->height[Entry->h2]))
  130. {
  131. dist[n++] = BCyl->rint[Entry->r2].d[1];
  132. }
  133. }
  134. /* Sort intersections. */
  135. for (i = 0; i < n; i++)
  136. {
  137. for (j = 0; j < n - i - 1; j++)
  138. {
  139. if (dist[j] > dist[j+1])
  140. {
  141. k = dist[j];
  142. dist[j] = dist[j+1];
  143. dist[j+1] = k;
  144. }
  145. }
  146. }
  147. return(n);
  148. }
  149. /*****************************************************************************
  150. *
  151. * FUNCTION
  152. *
  153. * intersect_bound_elements
  154. *
  155. * INPUT
  156. *
  157. * BCyl - Pointer to lathe structure
  158. * P, D - Current ray
  159. *
  160. * OUTPUT
  161. *
  162. * RETURNS
  163. *
  164. * AUTHOR
  165. *
  166. * Dieter Bayer
  167. *
  168. * DESCRIPTION
  169. *
  170. * Intersect all bounding discs and cylinders and store
  171. * the intersections found in the lathe structure.
  172. *
  173. * By intersecting all different discs and cylinders once
  174. * we avoid testing the same cylinders and discs more than
  175. * once. This happened when we tested one bounding cylinder
  176. * after the other.
  177. *
  178. * CHANGES
  179. *
  180. * Oct 1996 : Creation.
  181. *
  182. ******************************************************************************/
  183. static void intersect_bound_elements(BCYL *BCyl, VECTOR P, VECTOR D)
  184. {
  185. int i;
  186. DBL a, b, bb, b2, c, d, k;
  187. /* Init constants. */
  188. a = D[X] * D[X] + D[Z] * D[Z];
  189. b = P[X] * D[X] + P[Z] * D[Z];
  190. bb = b * b;
  191. b2 = 2.0 * b;
  192. c = P[X] * P[X] + P[Z] * P[Z];
  193. /* Intersect all rings. */
  194. if ((D[Y] < -EPSILON) || (D[Y] > EPSILON))
  195. {
  196. for (i = 0; i < BCyl->nheight; i++)
  197. {
  198. k = (BCyl->height[i] - P[Y]) / D[Y];
  199. BCyl->hint[i].n = 1;
  200. BCyl->hint[i].d[0] = k;
  201. BCyl->hint[i].w[0] = k * (a * k + b2) + c;
  202. }
  203. }
  204. else
  205. {
  206. for (i = 0; i < BCyl->nheight; i++)
  207. {
  208. BCyl->hint[i].n = 0;
  209. }
  210. }
  211. /* Intersect all cylinders. */
  212. for (i = 0; i < BCyl->nradius; i++)
  213. {
  214. BCyl->rint[i].n = 0;
  215. if (BCyl->radius[i] > EPSILON)
  216. {
  217. d = bb - a * (c - BCyl->radius[i]);
  218. if (d > 0.0)
  219. {
  220. d = sqrt(d);
  221. k = (-b + d) / a;
  222. BCyl->rint[i].n = 2;
  223. BCyl->rint[i].d[0] = k;
  224. BCyl->rint[i].w[0] = P[Y] + k * D[Y];
  225. k = (-b - d) / a;
  226. BCyl->rint[i].d[1] = k;
  227. BCyl->rint[i].w[1] = P[Y] + k * D[Y];
  228. }
  229. }
  230. }
  231. }
  232. /*****************************************************************************
  233. *
  234. * FUNCTION
  235. *
  236. * insert_hit
  237. *
  238. * INPUT
  239. *
  240. * element - Intersection to insert
  241. * intervals - List of intervals
  242. * cnt - Number of elements in the list
  243. *
  244. * OUTPUT
  245. *
  246. * intervals, cnt
  247. *
  248. * RETURNS
  249. *
  250. * AUTHOR
  251. *
  252. * Dieter Bayer
  253. *
  254. * DESCRIPTION
  255. *
  256. * Insert an intersection into the depth sorted intersection list.
  257. *
  258. * CHANGES
  259. *
  260. * Oct 1996 : Creation.
  261. *
  262. ******************************************************************************/
  263. static void insert_hit(BCYL_INT *element, BCYL_INT *intervals, int *cnt)
  264. {
  265. int k;
  266. intervals[*cnt] = *element;
  267. for (k = 0; element->d[0] > intervals[k].d[0]; k++);
  268. if (k < *cnt)
  269. {
  270. POV_MEMMOVE(&intervals[k+1], &intervals[k], (*cnt-k)*sizeof(BCYL_INT));
  271. intervals[k] = *element;
  272. }
  273. (*cnt)++;
  274. }
  275. /*****************************************************************************
  276. *
  277. * FUNCTION
  278. *
  279. * Intersect_All_Bounds
  280. *
  281. * INPUT
  282. *
  283. * BCyl - Pointer to lathe structure
  284. * P, D - Current ray
  285. * intervals - List of intervals
  286. * cnt - Number of elements in the list
  287. *
  288. * OUTPUT
  289. *
  290. * intervals, cnt
  291. *
  292. * RETURNS
  293. *
  294. * AUTHOR
  295. *
  296. * Dieter Bayer
  297. *
  298. * DESCRIPTION
  299. *
  300. * Intersect given ray with all bounding cylinders of the given lathe
  301. * and return a sorted list of intersection depths and segments hit.
  302. *
  303. * CHANGES
  304. *
  305. * Oct 1996 : Creation.
  306. *
  307. ******************************************************************************/
  308. int Intersect_BCyl(BCYL *BCyl, VECTOR P, VECTOR D)
  309. {
  310. int i, cnt;
  311. DBL dist[8];
  312. BCYL_INT Inter;
  313. BCYL_INT *intervals;
  314. BCYL_ENTRY *Entry;
  315. cnt = 0;
  316. Inter.d[1] = 0.0;
  317. /* Intersect all cylinder and plane elements. */
  318. intersect_bound_elements(BCyl, P, D);
  319. /* Intersect all spline segments. */
  320. intervals = BCyl->intervals;
  321. for (i = 0; i < BCyl->number; i++)
  322. {
  323. Entry = &BCyl->entry[i];
  324. switch (intersect_thick_cylinder(BCyl, Entry, dist))
  325. {
  326. case 0:
  327. break;
  328. case 2:
  329. if (dist[0] > EPSILON)
  330. {
  331. Inter.d[0] = dist[0];
  332. Inter.n = i;
  333. insert_hit(&Inter, intervals, &cnt);
  334. }
  335. else
  336. {
  337. if (dist[1] > EPSILON)
  338. {
  339. Inter.d[0] = 0.0;
  340. Inter.n = i;
  341. insert_hit(&Inter, intervals, &cnt);
  342. }
  343. }
  344. break;
  345. case 4:
  346. if (dist[0] > EPSILON)
  347. {
  348. Inter.d[0] = dist[0];
  349. Inter.n = i;
  350. insert_hit(&Inter, intervals, &cnt);
  351. }
  352. else
  353. {
  354. if (dist[1] > EPSILON)
  355. {
  356. Inter.d[0] = 0.0;
  357. Inter.n = i;
  358. insert_hit(&Inter, intervals, &cnt);
  359. }
  360. else
  361. {
  362. if (dist[2] > EPSILON)
  363. {
  364. Inter.d[0] = dist[2];
  365. Inter.n = i;
  366. insert_hit(&Inter, intervals, &cnt);
  367. }
  368. else
  369. {
  370. if (dist[3] > EPSILON)
  371. {
  372. Inter.d[0] = 0.0;
  373. Inter.n = i;
  374. insert_hit(&Inter, intervals, &cnt);
  375. }
  376. }
  377. }
  378. }
  379. break;
  380. default:
  381. /*
  382. * We weren't able to find an even number of intersections. Thus
  383. * we can't tell where the ray enters and leaves the bounding
  384. * cylinder. To avoid problems we assume that the ray is always
  385. * inside the cylinder in that case.
  386. */
  387. Inter.d[0] = dist[0];
  388. Inter.n = i;
  389. insert_hit(&Inter, intervals, &cnt);
  390. break;
  391. }
  392. }
  393. return(cnt);
  394. }
  395. /*****************************************************************************
  396. *
  397. * FUNCTION
  398. *
  399. * Create_BCyl
  400. *
  401. * INPUT
  402. *
  403. * number - number of cylindrical segments
  404. * r1, r2 - list of segment radii
  405. * h1, h2 - list of segment heights
  406. *
  407. * OUTPUT
  408. *
  409. * RETURNS
  410. *
  411. * BCYL * - created bounding cylinder.
  412. *
  413. * AUTHOR
  414. *
  415. * Dieter Bayer
  416. *
  417. * DESCRIPTION
  418. *
  419. * Create a bounding cylinder data structure from the given
  420. * radii and heights.
  421. *
  422. * CHANGES
  423. *
  424. * Oct 1996 : Creation.
  425. *
  426. ******************************************************************************/
  427. BCYL *Create_BCyl(int number, DBL *tmp_r1, DBL *tmp_r2, DBL *tmp_h1, DBL *tmp_h2)
  428. {
  429. int i, j, nr, nh;
  430. int *tmp_r1_index;
  431. int *tmp_r2_index;
  432. int *tmp_h1_index;
  433. int *tmp_h2_index;
  434. DBL *tmp_radius;
  435. DBL *tmp_height;
  436. BCYL *bcyl;
  437. /* Allocate bounding cylinder. */
  438. bcyl = (BCYL *)POV_MALLOC(sizeof(BCYL), "bounding cylinder");
  439. /* Allocate entries. */
  440. bcyl->number = number;
  441. bcyl->entry = (BCYL_ENTRY *)POV_MALLOC(bcyl->number*sizeof(BCYL_ENTRY), "bounding cylinder data");
  442. /* Allocate intersection lists. */
  443. bcyl->hint = (BCYL_INT *)POV_MALLOC(2*bcyl->number*sizeof(BCYL_INT), "lathe intersection list");
  444. bcyl->rint = (BCYL_INT *)POV_MALLOC(2*bcyl->number*sizeof(BCYL_INT), "lathe intersection list");
  445. bcyl->intervals = (BCYL_INT *)POV_MALLOC(4*bcyl->number*sizeof(BCYL_INT), "lathe intersection list");
  446. /* Allocate temporary lists. */
  447. tmp_r1_index = (int *)POV_MALLOC(bcyl->number * sizeof(int), "temp lathe data");
  448. tmp_r2_index = (int *)POV_MALLOC(bcyl->number * sizeof(int), "temp lathe data");
  449. tmp_h1_index = (int *)POV_MALLOC(bcyl->number * sizeof(int), "temp lathe data");
  450. tmp_h2_index = (int *)POV_MALLOC(bcyl->number * sizeof(int), "temp lathe data");
  451. tmp_radius = (DBL *)POV_MALLOC(2 * bcyl->number * sizeof(DBL), "temp lathe data");
  452. tmp_height = (DBL *)POV_MALLOC(2 * bcyl->number * sizeof(DBL), "temp lathe data");
  453. /* Get different bounding radii and heights. */
  454. nr = 0;
  455. nh = 0;
  456. for (i = 0; i < bcyl->number; i++)
  457. {
  458. tmp_r1_index[i] = -1;
  459. tmp_r2_index[i] = -1;
  460. tmp_h1_index[i] = -1;
  461. tmp_h2_index[i] = -1;
  462. for (j = 0; j < nr; j++)
  463. {
  464. if (tmp_r1[i] == tmp_radius[j])
  465. {
  466. break;
  467. }
  468. }
  469. if (j == nr)
  470. {
  471. tmp_radius[nr++] = tmp_r1[i];
  472. }
  473. tmp_r1_index[i] = j;
  474. for (j = 0; j < nr; j++)
  475. {
  476. if (tmp_r2[i] == tmp_radius[j])
  477. {
  478. break;
  479. }
  480. }
  481. if (j == nr)
  482. {
  483. tmp_radius[nr++] = tmp_r2[i];
  484. }
  485. tmp_r2_index[i] = j;
  486. for (j = 0; j < nh; j++)
  487. {
  488. if (tmp_h1[i] == tmp_height[j])
  489. {
  490. break;
  491. }
  492. }
  493. if (j == nh)
  494. {
  495. tmp_height[nh++] = tmp_h1[i];
  496. }
  497. tmp_h1_index[i] = j;
  498. for (j = 0; j < nh; j++)
  499. {
  500. if (tmp_h2[i] == tmp_height[j])
  501. {
  502. break;
  503. }
  504. }
  505. if (j == nh)
  506. {
  507. tmp_height[nh++] = tmp_h2[i];
  508. }
  509. tmp_h2_index[i] = j;
  510. }
  511. /* Copy lists into the lathe. */
  512. bcyl->radius = (DBL *)POV_MALLOC(nr * sizeof(DBL), "bounding cylinder data");
  513. bcyl->height = (DBL *)POV_MALLOC(nh * sizeof(DBL), "bounding cylinder data");
  514. for (i = 0; i < nr; i++)
  515. {
  516. bcyl->radius[i] = Sqr(tmp_radius[i]);
  517. }
  518. for (i = 0; i < nh; i++)
  519. {
  520. bcyl->height[i] = tmp_height[i];
  521. }
  522. /* Assign height and radius indices. */
  523. bcyl->nradius = nr;
  524. bcyl->nheight = nh;
  525. for (i = 0; i < bcyl->number; i++)
  526. {
  527. bcyl->entry[i].r1 = tmp_r1_index[i];
  528. bcyl->entry[i].r2 = tmp_r2_index[i];
  529. bcyl->entry[i].h1 = tmp_h1_index[i];
  530. bcyl->entry[i].h2 = tmp_h2_index[i];
  531. }
  532. /*
  533. fprintf(stderr, "number of different radii = %d\n", nr);
  534. fprintf(stderr, "number of different heights = %d\n", nh);
  535. */
  536. /* Get rid of temp. memory. */
  537. POV_FREE(tmp_height);
  538. POV_FREE(tmp_radius);
  539. POV_FREE(tmp_h2_index);
  540. POV_FREE(tmp_h1_index);
  541. POV_FREE(tmp_r2_index);
  542. POV_FREE(tmp_r1_index);
  543. return(bcyl);
  544. }
  545. /*****************************************************************************
  546. *
  547. * FUNCTION
  548. *
  549. * Destroy_BCyl
  550. *
  551. * INPUT
  552. *
  553. * BCyl - bounding cylinder
  554. *
  555. * OUTPUT
  556. *
  557. * RETURNS
  558. *
  559. * AUTHOR
  560. *
  561. * Dieter Bayer
  562. *
  563. * DESCRIPTION
  564. *
  565. * Destroy a bounding cylinder.
  566. *
  567. * CHANGES
  568. *
  569. * Oct 1996 : Creation.
  570. *
  571. ******************************************************************************/
  572. void Destroy_BCyl(BCYL *BCyl)
  573. {
  574. POV_FREE(BCyl->entry);
  575. POV_FREE(BCyl->radius);
  576. POV_FREE(BCyl->height);
  577. POV_FREE(BCyl->rint);
  578. POV_FREE(BCyl->hint);
  579. POV_FREE(BCyl->intervals);
  580. POV_FREE(BCyl);
  581. }