CSG.C 21 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060
  1. /****************************************************************************
  2. * csg.c
  3. *
  4. * This module implements routines for constructive solid geometry.
  5. *
  6. * from Persistence of Vision(tm) Ray Tracer
  7. * Copyright 1996,1999 Persistence of Vision Team
  8. *---------------------------------------------------------------------------
  9. * NOTICE: This source code file is provided so that users may experiment
  10. * with enhancements to POV-Ray and to port the software to platforms other
  11. * than those supported by the POV-Ray Team. There are strict rules under
  12. * which you are permitted to use this file. The rules are in the file
  13. * named POVLEGAL.DOC which should be distributed with this file.
  14. * If POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  15. * Team Coordinator by email to team-coord@povray.org or visit us on the web at
  16. * http://www.povray.org. The latest version of POV-Ray may be found at this site.
  17. *
  18. * This program is based on the popular DKB raytracer version 2.12.
  19. * DKBTrace was originally written by David K. Buck.
  20. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  21. *
  22. *****************************************************************************/
  23. #include "frame.h"
  24. #include "povray.h"
  25. #include "vector.h"
  26. #include "povproto.h"
  27. #include "bbox.h"
  28. #include "csg.h"
  29. #include "hfield.h"
  30. #include "matrices.h"
  31. #include "objects.h"
  32. #include "planes.h"
  33. #include "quadrics.h"
  34. /*****************************************************************************
  35. * Local preprocessor defines
  36. ******************************************************************************/
  37. /*****************************************************************************
  38. * Static functions
  39. ******************************************************************************/
  40. static int All_CSG_Union_Intersections (OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack);
  41. static int All_CSG_Merge_Intersections (OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack);
  42. static int All_CSG_Intersect_Intersections (OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack);
  43. static int Inside_CSG_Union (VECTOR point, OBJECT *Object);
  44. static int Inside_CSG_Intersection (VECTOR point, OBJECT *Object);
  45. static CSG *Copy_CSG (OBJECT *Object);
  46. static void Translate_CSG (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
  47. static void Rotate_CSG (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
  48. static void Scale_CSG (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
  49. static void Transform_CSG (OBJECT *Object, TRANSFORM *Trans);
  50. static void Destroy_CSG (OBJECT *Object);
  51. static void Invert_CSG_Union (OBJECT *Object);
  52. static void Invert_CSG_Intersection (OBJECT *Object);
  53. /*****************************************************************************
  54. * Local variables
  55. ******************************************************************************/
  56. METHODS CSG_Union_Methods =
  57. {
  58. All_CSG_Union_Intersections,
  59. Inside_CSG_Union, NULL /*Normal*/,
  60. (COPY_METHOD)Copy_CSG,
  61. Translate_CSG, Rotate_CSG,
  62. Scale_CSG, Transform_CSG, Invert_CSG_Union, Destroy_CSG
  63. };
  64. METHODS CSG_Merge_Methods =
  65. {
  66. All_CSG_Merge_Intersections,
  67. Inside_CSG_Union, NULL /*Normal*/,
  68. (COPY_METHOD)Copy_CSG,
  69. Translate_CSG, Rotate_CSG,
  70. Scale_CSG, Transform_CSG, Invert_CSG_Union, Destroy_CSG
  71. };
  72. METHODS CSG_Intersection_Methods =
  73. {
  74. All_CSG_Intersect_Intersections,
  75. Inside_CSG_Intersection, NULL /*Normal*/,
  76. (COPY_METHOD)Copy_CSG,
  77. Translate_CSG, Rotate_CSG,
  78. Scale_CSG, Transform_CSG, Invert_CSG_Intersection, Destroy_CSG
  79. };
  80. /*****************************************************************************
  81. *
  82. * FUNCTION
  83. *
  84. * All_CSG_Union_Intersections
  85. *
  86. * INPUT
  87. *
  88. * OUTPUT
  89. *
  90. * RETURNS
  91. *
  92. * AUTHOR
  93. *
  94. * POV-Ray Team
  95. *
  96. * DESCRIPTION
  97. *
  98. * -
  99. *
  100. * CHANGES
  101. *
  102. * Sep 1994 : Added code to count intersection tests. [DB]
  103. *
  104. ******************************************************************************/
  105. static int All_CSG_Union_Intersections (OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack)
  106. {
  107. int Found;
  108. OBJECT *Current_Sib, *Clip;
  109. ISTACK *Local_Stack;
  110. INTERSECTION *Sibling_Intersection;
  111. Increase_Counter(stats[Ray_CSG_Union_Tests]);
  112. Found = FALSE;
  113. /* Use shortcut if no clip. */
  114. if ((Clip = Object->Clip) == NULL)
  115. {
  116. for (Current_Sib = ((CSG *)Object)->Children; Current_Sib != NULL; Current_Sib = Current_Sib->Sibling)
  117. {
  118. if (Ray_In_Bound (Ray, Current_Sib->Bound))
  119. {
  120. if (All_Intersections (Current_Sib, Ray, Depth_Stack))
  121. {
  122. Found = TRUE;
  123. }
  124. }
  125. }
  126. }
  127. else
  128. {
  129. Local_Stack = open_istack();
  130. for (Current_Sib = ((CSG *)Object)->Children; Current_Sib != NULL; Current_Sib = Current_Sib->Sibling)
  131. {
  132. if (Ray_In_Bound (Ray, Current_Sib->Bound))
  133. {
  134. if (All_Intersections (Current_Sib, Ray, Local_Stack))
  135. {
  136. while ((Sibling_Intersection = pop_entry(Local_Stack)) != NULL)
  137. {
  138. if (Point_In_Clip (Sibling_Intersection->IPoint, Clip))
  139. {
  140. push_copy (Depth_Stack, Sibling_Intersection);
  141. Found = TRUE;
  142. }
  143. }
  144. }
  145. }
  146. }
  147. close_istack (Local_Stack);
  148. }
  149. if (Found)
  150. {
  151. Increase_Counter(stats[Ray_CSG_Union_Tests_Succeeded]);
  152. }
  153. return (Found);
  154. }
  155. /*****************************************************************************
  156. *
  157. * FUNCTION
  158. *
  159. * All_CSG_Intersection_Intersections
  160. *
  161. * INPUT
  162. *
  163. * OUTPUT
  164. *
  165. * RETURNS
  166. *
  167. * AUTHOR
  168. *
  169. * POV-Ray Team
  170. *
  171. * DESCRIPTION
  172. *
  173. * -
  174. *
  175. * CHANGES
  176. *
  177. * Sep 1994 : Added code to count intersection tests. [DB]
  178. *
  179. ******************************************************************************/
  180. static int All_CSG_Intersect_Intersections (OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack)
  181. {
  182. int Maybe_Found, Found;
  183. OBJECT *Current_Sib, *Inside_Sib;
  184. ISTACK *Local_Stack;
  185. INTERSECTION *Sibling_Intersection;
  186. Increase_Counter(stats[Ray_CSG_Intersection_Tests]);
  187. Local_Stack = open_istack ();
  188. Found = FALSE;
  189. for (Current_Sib = ((CSG *)Object)->Children; Current_Sib != NULL; Current_Sib = Current_Sib->Sibling)
  190. {
  191. if (Ray_In_Bound (Ray, Current_Sib->Bound))
  192. {
  193. if (All_Intersections (Current_Sib, Ray, Local_Stack))
  194. {
  195. while ((Sibling_Intersection = pop_entry(Local_Stack)) != NULL)
  196. {
  197. Maybe_Found = TRUE;
  198. for (Inside_Sib = ((CSG *)Object)->Children; Inside_Sib != NULL; Inside_Sib = Inside_Sib->Sibling)
  199. {
  200. if (Inside_Sib != Current_Sib)
  201. {
  202. if (!Inside_Object (Sibling_Intersection->IPoint, Inside_Sib))
  203. {
  204. Maybe_Found = FALSE;
  205. break;
  206. }
  207. }
  208. }
  209. if (Maybe_Found)
  210. {
  211. if (Point_In_Clip (Sibling_Intersection->IPoint, Object->Clip))
  212. {
  213. push_copy(Depth_Stack, Sibling_Intersection);
  214. Found = TRUE;
  215. }
  216. }
  217. }
  218. }
  219. }
  220. }
  221. close_istack (Local_Stack);
  222. if (Found)
  223. {
  224. Increase_Counter(stats[Ray_CSG_Intersection_Tests_Succeeded]);
  225. }
  226. return (Found);
  227. }
  228. /*****************************************************************************
  229. *
  230. * FUNCTION
  231. *
  232. * All_CSG_Merge_Intersections
  233. *
  234. * INPUT
  235. *
  236. * OUTPUT
  237. *
  238. * RETURNS
  239. *
  240. * AUTHOR
  241. *
  242. * POV-Ray Team
  243. *
  244. * DESCRIPTION
  245. *
  246. * -
  247. *
  248. * CHANGES
  249. *
  250. * Sep 1994 : Added code to count intersection tests. [DB]
  251. *
  252. ******************************************************************************/
  253. static int All_CSG_Merge_Intersections (OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack)
  254. {
  255. int Found, inside_flag;
  256. OBJECT *Sib1, *Sib2;
  257. ISTACK *Local_Stack;
  258. INTERSECTION *Sibling_Intersection;
  259. Increase_Counter(stats[Ray_CSG_Merge_Tests]);
  260. Found = FALSE;
  261. Local_Stack = open_istack ();
  262. for (Sib1 = ((CSG *)Object)->Children; Sib1 != NULL; Sib1 = Sib1->Sibling)
  263. {
  264. if (Ray_In_Bound (Ray, Sib1->Bound))
  265. {
  266. if (All_Intersections (Sib1, Ray, Local_Stack))
  267. {
  268. while ((Sibling_Intersection = pop_entry (Local_Stack)) != NULL)
  269. {
  270. if (Point_In_Clip (Sibling_Intersection->IPoint, Object->Clip))
  271. {
  272. inside_flag = TRUE;
  273. for (Sib2 = ((CSG *)Object)->Children; Sib2 != NULL && inside_flag == TRUE; Sib2 = Sib2->Sibling)
  274. {
  275. if (Sib1 != Sib2)
  276. {
  277. if (Inside_Object(Sibling_Intersection->IPoint, Sib2))
  278. {
  279. inside_flag = FALSE;
  280. }
  281. }
  282. }
  283. if (inside_flag == TRUE)
  284. {
  285. Found = TRUE;
  286. push_copy (Depth_Stack, Sibling_Intersection);
  287. }
  288. }
  289. }
  290. }
  291. }
  292. }
  293. close_istack (Local_Stack);
  294. if (Found)
  295. {
  296. Increase_Counter(stats[Ray_CSG_Merge_Tests_Succeeded]);
  297. }
  298. return (Found);
  299. }
  300. /*****************************************************************************
  301. *
  302. * FUNCTION
  303. *
  304. * Inside_CSG_Union
  305. *
  306. * INPUT
  307. *
  308. * OUTPUT
  309. *
  310. * RETURNS
  311. *
  312. * AUTHOR
  313. *
  314. * POV-Ray Team
  315. *
  316. * DESCRIPTION
  317. *
  318. * -
  319. *
  320. * CHANGES
  321. *
  322. * -
  323. *
  324. ******************************************************************************/
  325. static int Inside_CSG_Union (VECTOR IPoint, OBJECT *Object)
  326. {
  327. OBJECT *Current_Sib;
  328. for (Current_Sib = ((CSG *)Object)->Children; Current_Sib != NULL; Current_Sib = Current_Sib->Sibling)
  329. {
  330. if (Inside_Object (IPoint, Current_Sib))
  331. {
  332. return (TRUE);
  333. }
  334. }
  335. return (FALSE);
  336. }
  337. /*****************************************************************************
  338. *
  339. * FUNCTION
  340. *
  341. * Inside_CSG_Intersection
  342. *
  343. * INPUT
  344. *
  345. * OUTPUT
  346. *
  347. * RETURNS
  348. *
  349. * AUTHOR
  350. *
  351. * POV-Ray Team
  352. *
  353. * DESCRIPTION
  354. *
  355. * -
  356. *
  357. * CHANGES
  358. *
  359. * -
  360. *
  361. ******************************************************************************/
  362. static int Inside_CSG_Intersection (VECTOR IPoint, OBJECT *Object)
  363. {
  364. OBJECT *Current_Sib;
  365. for (Current_Sib = ((CSG *)Object)->Children; Current_Sib != NULL; Current_Sib = Current_Sib->Sibling)
  366. {
  367. if (!Inside_Object (IPoint, Current_Sib))
  368. {
  369. return (FALSE);
  370. }
  371. }
  372. return (TRUE);
  373. }
  374. /*****************************************************************************
  375. *
  376. * FUNCTION
  377. *
  378. * Translate_CSG
  379. *
  380. * INPUT
  381. *
  382. * OUTPUT
  383. *
  384. * RETURNS
  385. *
  386. * AUTHOR
  387. *
  388. * POV-Ray Team
  389. *
  390. * DESCRIPTION
  391. *
  392. * -
  393. *
  394. * CHANGES
  395. *
  396. * -
  397. *
  398. ******************************************************************************/
  399. static void Translate_CSG (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
  400. {
  401. OBJECT *Sib;
  402. for (Sib = ((CSG *) Object)->Children; Sib != NULL; Sib = Sib->Sibling)
  403. {
  404. Translate_Object(Sib, Vector, Trans);
  405. }
  406. Recompute_BBox(&Object->BBox, Trans);
  407. }
  408. /*****************************************************************************
  409. *
  410. * FUNCTION
  411. *
  412. * Rotate_CSG
  413. *
  414. * INPUT
  415. *
  416. * OUTPUT
  417. *
  418. * RETURNS
  419. *
  420. * AUTHOR
  421. *
  422. * POV-Ray Team
  423. *
  424. * DESCRIPTION
  425. *
  426. * -
  427. *
  428. * CHANGES
  429. *
  430. * -
  431. *
  432. ******************************************************************************/
  433. static void Rotate_CSG (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
  434. {
  435. OBJECT *Sib;
  436. for (Sib = ((CSG *) Object)->Children; Sib != NULL; Sib = Sib->Sibling)
  437. {
  438. Rotate_Object(Sib, Vector, Trans);
  439. }
  440. Recompute_BBox(&Object->BBox, Trans);
  441. }
  442. /*****************************************************************************
  443. *
  444. * FUNCTION
  445. *
  446. * Scale_CSG
  447. *
  448. * INPUT
  449. *
  450. * OUTPUT
  451. *
  452. * RETURNS
  453. *
  454. * AUTHOR
  455. *
  456. * POV-Ray Team
  457. *
  458. * DESCRIPTION
  459. *
  460. * -
  461. *
  462. * CHANGES
  463. *
  464. * -
  465. *
  466. ******************************************************************************/
  467. static void Scale_CSG (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
  468. {
  469. OBJECT *Sib;
  470. for (Sib = ((CSG *) Object)->Children; Sib != NULL; Sib = Sib->Sibling)
  471. {
  472. Scale_Object(Sib, Vector, Trans);
  473. }
  474. Recompute_BBox(&Object->BBox, Trans);
  475. }
  476. /*****************************************************************************
  477. *
  478. * FUNCTION
  479. *
  480. * Transform_CSG
  481. *
  482. * INPUT
  483. *
  484. * OUTPUT
  485. *
  486. * RETURNS
  487. *
  488. * AUTHOR
  489. *
  490. * POV-Ray Team
  491. *
  492. * DESCRIPTION
  493. *
  494. * -
  495. *
  496. * CHANGES
  497. *
  498. * -
  499. *
  500. ******************************************************************************/
  501. static void Transform_CSG (OBJECT *Object, TRANSFORM *Trans)
  502. {
  503. OBJECT *Sib;
  504. for (Sib = ((CSG *) Object)->Children; Sib != NULL; Sib = Sib->Sibling)
  505. {
  506. Transform_Object (Sib, Trans);
  507. }
  508. Recompute_BBox(&Object->BBox, Trans);
  509. }
  510. /*****************************************************************************
  511. *
  512. * FUNCTION
  513. *
  514. * Invert_CSG_Union
  515. *
  516. * INPUT
  517. *
  518. * OUTPUT
  519. *
  520. * RETURNS
  521. *
  522. * AUTHOR
  523. *
  524. * POV-Ray Team
  525. *
  526. * DESCRIPTION
  527. *
  528. * -
  529. *
  530. * CHANGES
  531. *
  532. * -
  533. *
  534. ******************************************************************************/
  535. static void Invert_CSG_Union (OBJECT *Object)
  536. {
  537. OBJECT *Sib;
  538. Object->Methods = &CSG_Intersection_Methods;
  539. for (Sib = ((CSG *)Object)->Children; Sib != NULL; Sib = Sib->Sibling)
  540. {
  541. Invert_Object (Sib);
  542. }
  543. Invert_Flag(Object, INVERTED_FLAG);
  544. }
  545. /*****************************************************************************
  546. *
  547. * FUNCTION
  548. *
  549. * Invert_CSG_Intersection
  550. *
  551. * INPUT
  552. *
  553. * OUTPUT
  554. *
  555. * RETURNS
  556. *
  557. * AUTHOR
  558. *
  559. * POV-Ray Team
  560. *
  561. * DESCRIPTION
  562. *
  563. * -
  564. *
  565. * CHANGES
  566. *
  567. * -
  568. *
  569. ******************************************************************************/
  570. static void Invert_CSG_Intersection (OBJECT *Object)
  571. {
  572. OBJECT *Sib;
  573. Object->Methods = &CSG_Merge_Methods;
  574. for (Sib = ((CSG *)Object)->Children; Sib != NULL; Sib = Sib->Sibling)
  575. {
  576. Invert_Object (Sib);
  577. }
  578. Invert_Flag(Object, INVERTED_FLAG);
  579. }
  580. /*****************************************************************************
  581. *
  582. * FUNCTION
  583. *
  584. * Create_CSG_Union
  585. *
  586. * INPUT
  587. *
  588. * OUTPUT
  589. *
  590. * RETURNS
  591. *
  592. * AUTHOR
  593. *
  594. * POV-Ray Team
  595. *
  596. * DESCRIPTION
  597. *
  598. * -
  599. *
  600. * CHANGES
  601. *
  602. * -
  603. *
  604. ******************************************************************************/
  605. CSG *Create_CSG_Union ()
  606. {
  607. CSG *New;
  608. New = (CSG *)POV_MALLOC(sizeof (CSG), "union");
  609. INIT_OBJECT_FIELDS(New, UNION_OBJECT, &CSG_Union_Methods)
  610. New->Children = NULL;
  611. return (New);
  612. }
  613. /*****************************************************************************
  614. *
  615. * FUNCTION
  616. *
  617. * Create_CSG_Merge
  618. *
  619. * INPUT
  620. *
  621. * OUTPUT
  622. *
  623. * RETURNS
  624. *
  625. * AUTHOR
  626. *
  627. * POV-Ray Team
  628. *
  629. * DESCRIPTION
  630. *
  631. * -
  632. *
  633. * CHANGES
  634. *
  635. * -
  636. *
  637. ******************************************************************************/
  638. CSG *Create_CSG_Merge ()
  639. {
  640. CSG *New;
  641. New = (CSG *)POV_MALLOC(sizeof (CSG), "merge");
  642. INIT_OBJECT_FIELDS(New, MERGE_OBJECT, &CSG_Merge_Methods)
  643. New->Children = NULL;
  644. return (New);
  645. }
  646. /*****************************************************************************
  647. *
  648. * FUNCTION
  649. *
  650. * Create_CSG_Intersection
  651. *
  652. * INPUT
  653. *
  654. * OUTPUT
  655. *
  656. * RETURNS
  657. *
  658. * AUTHOR
  659. *
  660. * POV-Ray Team
  661. *
  662. * DESCRIPTION
  663. *
  664. * -
  665. *
  666. * CHANGES
  667. *
  668. * -
  669. *
  670. ******************************************************************************/
  671. CSG *Create_CSG_Intersection ()
  672. {
  673. CSG *New;
  674. New = (CSG *)POV_MALLOC(sizeof (CSG), "intersection");
  675. INIT_OBJECT_FIELDS(New, INTERSECTION_OBJECT, &CSG_Intersection_Methods)
  676. New->Children = NULL;
  677. return (New);
  678. }
  679. /*****************************************************************************
  680. *
  681. * FUNCTION
  682. *
  683. * Copy_CSG
  684. *
  685. * INPUT
  686. *
  687. * OUTPUT
  688. *
  689. * RETURNS
  690. *
  691. * AUTHOR
  692. *
  693. * POV-Ray Team
  694. *
  695. * DESCRIPTION
  696. *
  697. * -
  698. *
  699. * CHANGES
  700. *
  701. * -
  702. *
  703. ******************************************************************************/
  704. static CSG *Copy_CSG (OBJECT *Object)
  705. {
  706. CSG *New;
  707. OBJECT *Old_Sib, *New_Sib, *Prev_Sib;
  708. New = (CSG *)POV_MALLOC(sizeof (CSG), "csg");
  709. *New = *(CSG *)Object;
  710. New->Children = Prev_Sib = NULL;
  711. for (Old_Sib = ((CSG *)Object)->Children; Old_Sib != NULL; Old_Sib = Old_Sib->Sibling)
  712. {
  713. New_Sib = Copy_Object (Old_Sib);
  714. if (New->Children == NULL)
  715. {
  716. New->Children = New_Sib;
  717. }
  718. if (Prev_Sib != NULL)
  719. {
  720. Prev_Sib->Sibling = New_Sib;
  721. }
  722. Prev_Sib = New_Sib;
  723. }
  724. return (New);
  725. }
  726. /*****************************************************************************
  727. *
  728. * FUNCTION
  729. *
  730. * Destroy_CSG
  731. *
  732. * INPUT
  733. *
  734. * OUTPUT
  735. *
  736. * RETURNS
  737. *
  738. * AUTHOR
  739. *
  740. * POV-Ray Team
  741. *
  742. * DESCRIPTION
  743. *
  744. * -
  745. *
  746. * CHANGES
  747. *
  748. * -
  749. *
  750. ******************************************************************************/
  751. static void Destroy_CSG (OBJECT *Object)
  752. {
  753. Destroy_Object (((CSG *) Object)->Children);
  754. POV_FREE (Object);
  755. }
  756. /*****************************************************************************
  757. *
  758. * FUNCTION
  759. *
  760. * Compute_CSG_BBox
  761. *
  762. * INPUT
  763. *
  764. * OUTPUT
  765. *
  766. * RETURNS
  767. *
  768. * AUTHOR
  769. *
  770. * POV-Ray Team
  771. *
  772. * DESCRIPTION
  773. *
  774. * -
  775. *
  776. * CHANGES
  777. *
  778. * Sep 1994 : Improved bounding of quadrics used in CSG intersections. [DB]
  779. *
  780. ******************************************************************************/
  781. void Compute_CSG_BBox (OBJECT *Object)
  782. {
  783. int i, count;
  784. DBL Old_Volume, New_Volume;
  785. VECTOR NewMin, NewMax, TmpMin, TmpMax, Min, Max;
  786. OBJECT *Sib;
  787. QUADRIC **Quadrics;
  788. if (Object->Methods == &CSG_Intersection_Methods)
  789. {
  790. /*
  791. * Calculate the bounding box of a CSG intersection
  792. * by intersecting the bounding boxes of all children.
  793. */
  794. Make_Vector(NewMin, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE);
  795. Make_Vector(NewMax, BOUND_HUGE, BOUND_HUGE, BOUND_HUGE);
  796. count = 0;
  797. Quadrics = NULL;
  798. /* Process all children. */
  799. for (Sib = ((CSG *)Object)->Children; Sib != NULL; Sib = Sib->Sibling)
  800. {
  801. /* Inverted objects and height fields mustn't be considered */
  802. if (!Test_Flag(Sib, INVERTED_FLAG) && (Sib->Methods != &HField_Methods))
  803. {
  804. /* Store quadrics since they'll be processed last. */
  805. if (Sib->Methods == &Quadric_Methods)
  806. {
  807. Quadrics = (QUADRIC **)POV_REALLOC(Quadrics, (count+1)*sizeof(QUADRIC *), "temporary quadric list");
  808. Quadrics[count++] = (QUADRIC *)Sib;
  809. }
  810. else
  811. {
  812. if (Sib->Methods == &Plane_Methods)
  813. {
  814. Compute_Plane_Min_Max((PLANE *)Sib, TmpMin, TmpMax);
  815. }
  816. else
  817. {
  818. Make_min_max_from_BBox(TmpMin, TmpMax, Sib->BBox);
  819. }
  820. NewMin[X] = max(NewMin[X], TmpMin[X]);
  821. NewMin[Y] = max(NewMin[Y], TmpMin[Y]);
  822. NewMin[Z] = max(NewMin[Z], TmpMin[Z]);
  823. NewMax[X] = min(NewMax[X], TmpMax[X]);
  824. NewMax[Y] = min(NewMax[Y], TmpMax[Y]);
  825. NewMax[Z] = min(NewMax[Z], TmpMax[Z]);
  826. }
  827. }
  828. }
  829. /* Process any quadrics. */
  830. for (i = 0; i < count; i++)
  831. {
  832. Assign_Vector(Min, NewMin);
  833. Assign_Vector(Max, NewMax);
  834. Compute_Quadric_BBox(Quadrics[i], Min, Max);
  835. Make_min_max_from_BBox(TmpMin, TmpMax, Quadrics[i]->BBox);
  836. NewMin[X] = max(NewMin[X], TmpMin[X]);
  837. NewMin[Y] = max(NewMin[Y], TmpMin[Y]);
  838. NewMin[Z] = max(NewMin[Z], TmpMin[Z]);
  839. NewMax[X] = min(NewMax[X], TmpMax[X]);
  840. NewMax[Y] = min(NewMax[Y], TmpMax[Y]);
  841. NewMax[Z] = min(NewMax[Z], TmpMax[Z]);
  842. }
  843. if (Quadrics != NULL)
  844. {
  845. POV_FREE(Quadrics);
  846. }
  847. }
  848. else
  849. {
  850. /* Calculate the bounding box of a CSG merge/union object. */
  851. Make_Vector(NewMin, BOUND_HUGE, BOUND_HUGE, BOUND_HUGE);
  852. Make_Vector(NewMax, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE);
  853. for (Sib = ((CSG *)Object)->Children; Sib != NULL; Sib = Sib->Sibling)
  854. {
  855. Make_min_max_from_BBox(TmpMin, TmpMax, Sib->BBox);
  856. NewMin[X] = min(NewMin[X], TmpMin[X]);
  857. NewMin[Y] = min(NewMin[Y], TmpMin[Y]);
  858. NewMin[Z] = min(NewMin[Z], TmpMin[Z]);
  859. NewMax[X] = max(NewMax[X], TmpMax[X]);
  860. NewMax[Y] = max(NewMax[Y], TmpMax[Y]);
  861. NewMax[Z] = max(NewMax[Z], TmpMax[Z]);
  862. }
  863. }
  864. if ((NewMin[X] > NewMax[X]) || (NewMin[Y] > NewMax[Y]) || (NewMin[Z] > NewMax[Z]))
  865. {
  866. Warning(0.0, "Degenerate CSG bounding box (not used!).\n");
  867. }
  868. else
  869. {
  870. New_Volume = (NewMax[X] - NewMin[X]) * (NewMax[Y] - NewMin[Y]) * (NewMax[Z] - NewMin[Z]);
  871. BOUNDS_VOLUME(Old_Volume, Object->BBox);
  872. if (New_Volume < Old_Volume)
  873. {
  874. Make_BBox_from_min_max(Object->BBox, NewMin, NewMax);
  875. /* Beware of bounding boxes to large. */
  876. if ((Object->BBox.Lengths[X] > CRITICAL_LENGTH) ||
  877. (Object->BBox.Lengths[Y] > CRITICAL_LENGTH) ||
  878. (Object->BBox.Lengths[Z] > CRITICAL_LENGTH))
  879. {
  880. Make_BBox(Object->BBox, -BOUND_HUGE/2, -BOUND_HUGE/2, -BOUND_HUGE/2,
  881. BOUND_HUGE, BOUND_HUGE, BOUND_HUGE);
  882. }
  883. }
  884. }
  885. }