SPHERES.C 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860
  1. /****************************************************************************
  2. * spheres.c
  3. *
  4. * This module implements the sphere primitive.
  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 "matrices.h"
  29. #include "objects.h"
  30. #include "spheres.h"
  31. /*****************************************************************************
  32. * Local preprocessor defines
  33. ******************************************************************************/
  34. #define DEPTH_TOLERANCE 1.0e-6
  35. /*****************************************************************************
  36. * Static functions
  37. ******************************************************************************/
  38. static int All_Sphere_Intersections (OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack);
  39. static int All_Ellipsoid_Intersections (OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack);
  40. static int Inside_Sphere (VECTOR IPoint, OBJECT *Object);
  41. static int Inside_Ellipsoid (VECTOR IPoint, OBJECT *Object);
  42. static void Sphere_Normal (VECTOR Result, OBJECT *Object, INTERSECTION *Inter);
  43. static void Ellipsoid_Normal (VECTOR Result, OBJECT *Object, INTERSECTION *Inter);
  44. static void Translate_Sphere (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
  45. static void Rotate_Sphere (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
  46. static void Scale_Sphere (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
  47. static void Invert_Sphere (OBJECT *Object);
  48. /*****************************************************************************
  49. * Local variables
  50. ******************************************************************************/
  51. static METHODS Sphere_Methods =
  52. {
  53. All_Sphere_Intersections,
  54. Inside_Sphere, Sphere_Normal,
  55. (COPY_METHOD)Copy_Sphere,
  56. Translate_Sphere, Rotate_Sphere,
  57. Scale_Sphere, Transform_Sphere, Invert_Sphere,
  58. Destroy_Sphere
  59. };
  60. static METHODS Ellipsoid_Methods =
  61. {
  62. All_Ellipsoid_Intersections,
  63. Inside_Ellipsoid, Ellipsoid_Normal,
  64. (COPY_METHOD)Copy_Sphere,
  65. Translate_Sphere, Rotate_Sphere,
  66. Scale_Sphere, Transform_Sphere, Invert_Sphere,
  67. Destroy_Sphere
  68. };
  69. /*****************************************************************************
  70. *
  71. * FUNCTION
  72. *
  73. * All_Sphere_Intersection
  74. *
  75. * INPUT
  76. *
  77. * OUTPUT
  78. *
  79. * RETURNS
  80. *
  81. * AUTHOR
  82. *
  83. * ?
  84. *
  85. * DESCRIPTION
  86. *
  87. * -
  88. *
  89. * CHANGES
  90. *
  91. * -
  92. *
  93. ******************************************************************************/
  94. static int All_Sphere_Intersections(OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack)
  95. {
  96. register int Intersection_Found;
  97. DBL Depth1, Depth2;
  98. VECTOR IPoint;
  99. SPHERE *Sphere = (SPHERE *)Object;
  100. Intersection_Found = FALSE;
  101. if (Intersect_Sphere(Ray, Sphere->Center, Sqr(Sphere->Radius), &Depth1, &Depth2))
  102. {
  103. if ((Depth1 > DEPTH_TOLERANCE) && (Depth1 < Max_Distance))
  104. {
  105. VEvaluateRay(IPoint, Ray->Initial, Depth1, Ray->Direction);
  106. if (Point_In_Clip(IPoint, Object->Clip))
  107. {
  108. push_entry(Depth1, IPoint, Object, Depth_Stack);
  109. Intersection_Found = TRUE;
  110. }
  111. }
  112. if ((Depth2 > DEPTH_TOLERANCE) && (Depth2 < Max_Distance))
  113. {
  114. VEvaluateRay(IPoint, Ray->Initial, Depth2, Ray->Direction);
  115. if (Point_In_Clip(IPoint, Object->Clip))
  116. {
  117. push_entry(Depth2, IPoint, Object, Depth_Stack);
  118. Intersection_Found = TRUE;
  119. }
  120. }
  121. }
  122. return(Intersection_Found);
  123. }
  124. /*****************************************************************************
  125. *
  126. * FUNCTION
  127. *
  128. * All_Ellipsoid_Intersection
  129. *
  130. * INPUT
  131. *
  132. * OUTPUT
  133. *
  134. * RETURNS
  135. *
  136. * AUTHOR
  137. *
  138. * ?
  139. *
  140. * DESCRIPTION
  141. *
  142. * -
  143. *
  144. * CHANGES
  145. *
  146. * -
  147. *
  148. ******************************************************************************/
  149. static int All_Ellipsoid_Intersections(OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack)
  150. {
  151. register int Intersection_Found;
  152. DBL Depth1, Depth2, len;
  153. VECTOR IPoint;
  154. RAY New_Ray;
  155. SPHERE *Sphere = (SPHERE *)Object;
  156. /* Transform the ray into the ellipsoid's space */
  157. MInvTransPoint(New_Ray.Initial, Ray->Initial, ((SPHERE *)Object)->Trans);
  158. MInvTransDirection(New_Ray.Direction, Ray->Direction, ((SPHERE *)Object)->Trans);
  159. VLength(len, New_Ray.Direction);
  160. VInverseScaleEq(New_Ray.Direction, len);
  161. Intersection_Found = FALSE;
  162. if (Intersect_Sphere(&New_Ray, Sphere->Center, Sqr(Sphere->Radius), &Depth1, &Depth2))
  163. {
  164. if ((Depth1 > DEPTH_TOLERANCE) && (Depth1 < Max_Distance))
  165. {
  166. VEvaluateRay(IPoint, New_Ray.Initial, Depth1, New_Ray.Direction);
  167. MTransPoint(IPoint, IPoint, ((SPHERE *)Object)->Trans);
  168. if (Point_In_Clip(IPoint, Object->Clip))
  169. {
  170. push_entry(Depth1 / len, IPoint, Object, Depth_Stack);
  171. Intersection_Found = TRUE;
  172. }
  173. }
  174. if ((Depth2 > DEPTH_TOLERANCE) && (Depth2 < Max_Distance))
  175. {
  176. VEvaluateRay(IPoint, New_Ray.Initial, Depth2, New_Ray.Direction);
  177. MTransPoint(IPoint, IPoint, ((SPHERE *)Object)->Trans);
  178. if (Point_In_Clip(IPoint, Object->Clip))
  179. {
  180. push_entry(Depth2 / len, IPoint, Object, Depth_Stack);
  181. Intersection_Found = TRUE;
  182. }
  183. }
  184. }
  185. return(Intersection_Found);
  186. }
  187. /*****************************************************************************
  188. *
  189. * FUNCTION
  190. *
  191. * Intersect_Sphere
  192. *
  193. * INPUT
  194. *
  195. * Ray - Ray to test intersection with
  196. * Center - Center of the sphere
  197. * Radius2 - Squared radius of the sphere
  198. * Depth1 - Lower intersection distance
  199. * Depth2 - Upper intersection distance
  200. *
  201. * OUTPUT
  202. *
  203. * RETURNS
  204. *
  205. * AUTHOR
  206. *
  207. * ?
  208. *
  209. * DESCRIPTION
  210. *
  211. * -
  212. *
  213. * CHANGES
  214. *
  215. * -
  216. *
  217. ******************************************************************************/
  218. int Intersect_Sphere(RAY *Ray, VECTOR Center, DBL Radius2, DBL *Depth1, DBL *Depth2)
  219. {
  220. DBL OCSquared, t_Closest_Approach, Half_Chord, t_Half_Chord_Squared;
  221. VECTOR Origin_To_Center;
  222. Increase_Counter(stats[Ray_Sphere_Tests]);
  223. VSub(Origin_To_Center, Center, Ray->Initial);
  224. VDot(OCSquared, Origin_To_Center, Origin_To_Center);
  225. VDot(t_Closest_Approach, Origin_To_Center, Ray->Direction);
  226. if ((OCSquared >= Radius2) && (t_Closest_Approach < EPSILON))
  227. {
  228. return(FALSE);
  229. }
  230. t_Half_Chord_Squared = Radius2 - OCSquared + Sqr(t_Closest_Approach);
  231. if (t_Half_Chord_Squared > EPSILON)
  232. {
  233. Half_Chord = sqrt(t_Half_Chord_Squared);
  234. *Depth1 = t_Closest_Approach - Half_Chord;
  235. *Depth2 = t_Closest_Approach + Half_Chord;
  236. Increase_Counter(stats[Ray_Sphere_Tests_Succeeded]);
  237. return(TRUE);
  238. }
  239. return(FALSE);
  240. }
  241. /*****************************************************************************
  242. *
  243. * FUNCTION
  244. *
  245. * Inside_Sphere
  246. *
  247. * INPUT
  248. *
  249. * OUTPUT
  250. *
  251. * RETURNS
  252. *
  253. * AUTHOR
  254. *
  255. * ?
  256. *
  257. * DESCRIPTION
  258. *
  259. * -
  260. *
  261. * CHANGES
  262. *
  263. * -
  264. *
  265. ******************************************************************************/
  266. static int Inside_Sphere(VECTOR IPoint, OBJECT *Object)
  267. {
  268. DBL OCSquared;
  269. VECTOR Origin_To_Center;
  270. VSub(Origin_To_Center, ((SPHERE *)Object)->Center, IPoint);
  271. VDot(OCSquared, Origin_To_Center, Origin_To_Center);
  272. if (Test_Flag(Object, INVERTED_FLAG))
  273. {
  274. return(OCSquared > Sqr(((SPHERE *)Object)->Radius));
  275. }
  276. else
  277. {
  278. return(OCSquared < Sqr(((SPHERE *)Object)->Radius));
  279. }
  280. }
  281. /*****************************************************************************
  282. *
  283. * FUNCTION
  284. *
  285. * Inside_Ellipsoid
  286. *
  287. * INPUT
  288. *
  289. * OUTPUT
  290. *
  291. * RETURNS
  292. *
  293. * AUTHOR
  294. *
  295. * ?
  296. *
  297. * DESCRIPTION
  298. *
  299. * -
  300. *
  301. * CHANGES
  302. *
  303. * -
  304. *
  305. ******************************************************************************/
  306. static int Inside_Ellipsoid(VECTOR IPoint, OBJECT *Object)
  307. {
  308. DBL OCSquared;
  309. VECTOR Origin_To_Center, New_Point;
  310. /* Transform the point into the sphere's space */
  311. MInvTransPoint(New_Point, IPoint, ((SPHERE *)Object)->Trans);
  312. VSub(Origin_To_Center, ((SPHERE *)Object)->Center, New_Point);
  313. VDot(OCSquared, Origin_To_Center, Origin_To_Center);
  314. if (Test_Flag(Object, INVERTED_FLAG))
  315. {
  316. return(OCSquared > Sqr(((SPHERE *)Object)->Radius));
  317. }
  318. else
  319. {
  320. return(OCSquared < Sqr(((SPHERE *)Object)->Radius));
  321. }
  322. }
  323. /*****************************************************************************
  324. *
  325. * FUNCTION
  326. *
  327. * Sphere_Normal
  328. *
  329. * INPUT
  330. *
  331. * OUTPUT
  332. *
  333. * RETURNS
  334. *
  335. * AUTHOR
  336. *
  337. * ?
  338. *
  339. * DESCRIPTION
  340. *
  341. * -
  342. *
  343. * CHANGES
  344. *
  345. * -
  346. *
  347. ******************************************************************************/
  348. static void Sphere_Normal(VECTOR Result, OBJECT *Object, INTERSECTION *Inter)
  349. {
  350. VSub(Result, Inter->IPoint, ((SPHERE *)Object)->Center);
  351. VInverseScaleEq(Result, ((SPHERE *)Object)->Radius);
  352. }
  353. /*****************************************************************************
  354. *
  355. * FUNCTION
  356. *
  357. * Ellipsoid_Normal
  358. *
  359. * INPUT
  360. *
  361. * OUTPUT
  362. *
  363. * RETURNS
  364. *
  365. * AUTHOR
  366. *
  367. * ?
  368. *
  369. * DESCRIPTION
  370. *
  371. * -
  372. *
  373. * CHANGES
  374. *
  375. * -
  376. *
  377. ******************************************************************************/
  378. static void Ellipsoid_Normal(VECTOR Result, OBJECT *Object, INTERSECTION *Inter)
  379. {
  380. VECTOR New_Point;
  381. /* Transform the point into the sphere's space */
  382. MInvTransPoint(New_Point, Inter->IPoint, ((SPHERE *)Object)->Trans);
  383. VSub(Result, New_Point, ((SPHERE *)Object)->Center);
  384. MTransNormal(Result, Result, ((SPHERE *)Object)->Trans);
  385. VNormalize(Result, Result);
  386. }
  387. /*****************************************************************************
  388. *
  389. * FUNCTION
  390. *
  391. * Copy_Shere
  392. *
  393. * INPUT
  394. *
  395. * OUTPUT
  396. *
  397. * RETURNS
  398. *
  399. * AUTHOR
  400. *
  401. * ?
  402. *
  403. * DESCRIPTION
  404. *
  405. * -
  406. *
  407. * CHANGES
  408. *
  409. * -
  410. *
  411. ******************************************************************************/
  412. SPHERE *Copy_Sphere(OBJECT *Object)
  413. {
  414. SPHERE *New;
  415. New = Create_Sphere();
  416. *New = *((SPHERE *)Object);
  417. New->Trans = Copy_Transform(((SPHERE *)Object)->Trans);
  418. return(New);
  419. }
  420. /*****************************************************************************
  421. *
  422. * FUNCTION
  423. *
  424. * Translate_Sphere
  425. *
  426. * INPUT
  427. *
  428. * OUTPUT
  429. *
  430. * RETURNS
  431. *
  432. * AUTHOR
  433. *
  434. * ?
  435. *
  436. * DESCRIPTION
  437. *
  438. * -
  439. *
  440. * CHANGES
  441. *
  442. * -
  443. *
  444. ******************************************************************************/
  445. static void Translate_Sphere(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
  446. {
  447. SPHERE *Sphere = (SPHERE *) Object;
  448. if (Sphere->Trans == NULL)
  449. {
  450. VAddEq(Sphere->Center, Vector);
  451. Compute_Sphere_BBox(Sphere);
  452. }
  453. else
  454. {
  455. Transform_Sphere(Object, Trans);
  456. }
  457. }
  458. /*****************************************************************************
  459. *
  460. * FUNCTION
  461. *
  462. * Rotate_Sphere
  463. *
  464. * INPUT
  465. *
  466. * OUTPUT
  467. *
  468. * RETURNS
  469. *
  470. * AUTHOR
  471. *
  472. * ?
  473. *
  474. * DESCRIPTION
  475. *
  476. * -
  477. *
  478. * CHANGES
  479. *
  480. * -
  481. *
  482. ******************************************************************************/
  483. static void Rotate_Sphere(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
  484. {
  485. SPHERE *Sphere = (SPHERE *) Object;
  486. if (Sphere->Trans == NULL)
  487. {
  488. MTransPoint(Sphere->Center, Sphere->Center, Trans);
  489. Compute_Sphere_BBox(Sphere);
  490. }
  491. else
  492. {
  493. Transform_Sphere(Object, Trans);
  494. }
  495. }
  496. /*****************************************************************************
  497. *
  498. * FUNCTION
  499. *
  500. * Scale_Sphere
  501. *
  502. * INPUT
  503. *
  504. * OUTPUT
  505. *
  506. * RETURNS
  507. *
  508. * AUTHOR
  509. *
  510. * ?
  511. *
  512. * DESCRIPTION
  513. *
  514. * -
  515. *
  516. * CHANGES
  517. *
  518. * -
  519. *
  520. ******************************************************************************/
  521. static void Scale_Sphere(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
  522. {
  523. SPHERE *Sphere = (SPHERE *) Object;
  524. if ((Vector[X] != Vector[Y]) || (Vector[X] != Vector[Z]))
  525. {
  526. if (Sphere->Trans == NULL)
  527. {
  528. Sphere->Methods = &Ellipsoid_Methods;
  529. Sphere->Trans = Create_Transform();
  530. }
  531. }
  532. if (Sphere->Trans == NULL)
  533. {
  534. VScaleEq(Sphere->Center, Vector[X]);
  535. Sphere->Radius *= Vector[X];
  536. Compute_Sphere_BBox(Sphere);
  537. }
  538. else
  539. {
  540. Transform_Sphere(Object, Trans);
  541. }
  542. }
  543. /*****************************************************************************
  544. *
  545. * FUNCTION
  546. *
  547. * Invert_Sphere
  548. *
  549. * INPUT
  550. *
  551. * OUTPUT
  552. *
  553. * RETURNS
  554. *
  555. * AUTHOR
  556. *
  557. * ?
  558. *
  559. * DESCRIPTION
  560. *
  561. * -
  562. *
  563. * CHANGES
  564. *
  565. * -
  566. *
  567. ******************************************************************************/
  568. static void Invert_Sphere(OBJECT *Object)
  569. {
  570. Invert_Flag(Object, INVERTED_FLAG);
  571. }
  572. /*****************************************************************************
  573. *
  574. * FUNCTION
  575. *
  576. * Create_Sphere
  577. *
  578. * INPUT
  579. *
  580. * OUTPUT
  581. *
  582. * RETURNS
  583. *
  584. * AUTHOR
  585. *
  586. * ?
  587. *
  588. * DESCRIPTION
  589. *
  590. * -
  591. *
  592. * CHANGES
  593. *
  594. * -
  595. *
  596. ******************************************************************************/
  597. SPHERE *Create_Sphere()
  598. {
  599. SPHERE *New;
  600. New = (SPHERE *)POV_MALLOC(sizeof(SPHERE), "sphere");
  601. INIT_OBJECT_FIELDS(New, SPHERE_OBJECT, &Sphere_Methods)
  602. Make_Vector(New->Center, 0.0, 0.0, 0.0);
  603. New->Radius = 1.0;
  604. New->Trans = NULL;
  605. return(New);
  606. }
  607. /*****************************************************************************
  608. *
  609. * FUNCTION
  610. *
  611. * Transform_Sphere
  612. *
  613. * INPUT
  614. *
  615. * OUTPUT
  616. *
  617. * RETURNS
  618. *
  619. * AUTHOR
  620. *
  621. * ?
  622. *
  623. * DESCRIPTION
  624. *
  625. * -
  626. *
  627. * CHANGES
  628. *
  629. * -
  630. *
  631. ******************************************************************************/
  632. void Transform_Sphere(OBJECT *Object, TRANSFORM *Trans)
  633. {
  634. SPHERE *Sphere = (SPHERE *)Object;
  635. if (Sphere->Trans == NULL)
  636. {
  637. Sphere->Methods = &Ellipsoid_Methods;
  638. Sphere->Trans = Create_Transform();
  639. }
  640. Compose_Transforms(Sphere->Trans, Trans);
  641. Compute_Sphere_BBox(Sphere);
  642. }
  643. /*****************************************************************************
  644. *
  645. * FUNCTION
  646. *
  647. * Destroy_Sphere
  648. *
  649. * INPUT
  650. *
  651. * OUTPUT
  652. *
  653. * RETURNS
  654. *
  655. * AUTHOR
  656. *
  657. * ?
  658. *
  659. * DESCRIPTION
  660. *
  661. * -
  662. *
  663. * CHANGES
  664. *
  665. * -
  666. *
  667. ******************************************************************************/
  668. void Destroy_Sphere(OBJECT *Object)
  669. {
  670. Destroy_Transform(((SPHERE *)Object)->Trans);
  671. POV_FREE (Object);
  672. }
  673. /*****************************************************************************
  674. *
  675. * FUNCTION
  676. *
  677. * Compute_Sphere_BBox
  678. *
  679. * INPUT
  680. *
  681. * Sphere - Sphere
  682. *
  683. * OUTPUT
  684. *
  685. * Sphere
  686. *
  687. * RETURNS
  688. *
  689. * AUTHOR
  690. *
  691. * Dieter Bayer
  692. *
  693. * DESCRIPTION
  694. *
  695. * Calculate the bounding box of a sphere.
  696. *
  697. * CHANGES
  698. *
  699. * Aug 1994 : Creation.
  700. *
  701. ******************************************************************************/
  702. void Compute_Sphere_BBox(SPHERE *Sphere)
  703. {
  704. Make_BBox(Sphere->BBox, Sphere->Center[X] - Sphere->Radius, Sphere->Center[Y] - Sphere->Radius, Sphere->Center[Z] - Sphere->Radius,
  705. 2.0 * Sphere->Radius, 2.0 * Sphere->Radius, 2.0 * Sphere->Radius);
  706. if (Sphere->Trans != NULL)
  707. {
  708. Recompute_BBox(&Sphere->BBox, Sphere->Trans);
  709. }
  710. }