home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: Graphics / Graphics.zip / povsrc31.zip / Spheres.c < prev    next >
C/C++ Source or Header  |  2000-11-26  |  19KB  |  984 lines

  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.  
  24. #include "frame.h"
  25. #include "povray.h"
  26. #include "vector.h"
  27. #include "povproto.h"
  28. #include "bbox.h"
  29. #include "matrices.h"
  30. #include "objects.h"
  31. #include "spheres.h"
  32.  
  33.  
  34.  
  35. /*****************************************************************************
  36. * Local preprocessor defines
  37. ******************************************************************************/
  38.  
  39. #define DEPTH_TOLERANCE 1.0e-6
  40.  
  41.  
  42.  
  43. /*****************************************************************************
  44. * Static functions
  45. ******************************************************************************/
  46. static int All_Sphere_Intersections (OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack);
  47. static int All_Ellipsoid_Intersections (OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack);
  48. static int Inside_Sphere (VECTOR IPoint, OBJECT *Object);
  49. static int Inside_Ellipsoid (VECTOR IPoint, OBJECT *Object);
  50. static void Sphere_Normal (VECTOR Result, OBJECT *Object, INTERSECTION *Inter);
  51. static void Sphere_UVCoord (UV_VECT Result, OBJECT *Object, INTERSECTION *Inter);
  52. static void Ellipsoid_Normal (VECTOR Result, OBJECT *Object, INTERSECTION *Inter);
  53. static void Translate_Sphere (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
  54. static void Rotate_Sphere (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
  55. static void Scale_Sphere (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
  56. static void Invert_Sphere (OBJECT *Object);
  57.  
  58.  
  59.  
  60. /*****************************************************************************
  61. * Local variables
  62. ******************************************************************************/
  63.  
  64. static METHODS Sphere_Methods =
  65. {
  66.   All_Sphere_Intersections,
  67.   Inside_Sphere, Sphere_Normal, Sphere_UVCoord,
  68.   (COPY_METHOD)Copy_Sphere,
  69.   Translate_Sphere, Rotate_Sphere,
  70.   Scale_Sphere, Transform_Sphere, Invert_Sphere,
  71.   Destroy_Sphere
  72. };
  73.  
  74.  
  75.  
  76. static METHODS Ellipsoid_Methods =
  77. {
  78.   All_Ellipsoid_Intersections,
  79.   Inside_Ellipsoid, Ellipsoid_Normal, Sphere_UVCoord,
  80.   (COPY_METHOD)Copy_Sphere,
  81.   Translate_Sphere, Rotate_Sphere,
  82.   Scale_Sphere, Transform_Sphere, Invert_Sphere,
  83.   Destroy_Sphere
  84. };
  85.  
  86.  
  87.  
  88. /*****************************************************************************
  89. *
  90. * FUNCTION
  91. *
  92. *   All_Sphere_Intersection
  93. *
  94. * INPUT
  95. *   
  96. * OUTPUT
  97. *   
  98. * RETURNS
  99. *   
  100. * AUTHOR
  101. *
  102. *   ?
  103. *   
  104. * DESCRIPTION
  105. *
  106. *   -
  107. *
  108. * CHANGES
  109. *
  110. *   -
  111. *
  112. ******************************************************************************/
  113.  
  114. static int All_Sphere_Intersections(OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack)
  115. {
  116.   register int Intersection_Found;
  117.   DBL Depth1, Depth2;
  118.   VECTOR IPoint;
  119.   SPHERE *Sphere = (SPHERE *)Object;
  120.  
  121.   Intersection_Found = FALSE;
  122.  
  123.   if (Intersect_Sphere(Ray, Sphere->Center, Sqr(Sphere->Radius), &Depth1, &Depth2))
  124.   {
  125.     if ((Depth1 > DEPTH_TOLERANCE) && (Depth1 < Max_Distance))
  126.     {
  127.       VEvaluateRay(IPoint, Ray->Initial, Depth1, Ray->Direction);
  128.  
  129.       if (Point_In_Clip(IPoint, Object->Clip))
  130.       {
  131.         push_entry(Depth1, IPoint, Object, Depth_Stack);
  132.  
  133.         Intersection_Found = TRUE;
  134.       }
  135.     }
  136.  
  137.     if ((Depth2 > DEPTH_TOLERANCE) && (Depth2 < Max_Distance))
  138.     {
  139.       VEvaluateRay(IPoint, Ray->Initial, Depth2, Ray->Direction);
  140.  
  141.       if (Point_In_Clip(IPoint, Object->Clip))
  142.       {
  143.         push_entry(Depth2, IPoint, Object, Depth_Stack);
  144.  
  145.         Intersection_Found = TRUE;
  146.       }
  147.     }
  148.   }
  149.  
  150.   return(Intersection_Found);
  151. }
  152.  
  153.  
  154.  
  155. /*****************************************************************************
  156. *
  157. * FUNCTION
  158. *
  159. *   All_Ellipsoid_Intersection
  160. *
  161. * INPUT
  162. *   
  163. * OUTPUT
  164. *   
  165. * RETURNS
  166. *   
  167. * AUTHOR
  168. *
  169. *   ?
  170. *   
  171. * DESCRIPTION
  172. *
  173. *   -
  174. *
  175. * CHANGES
  176. *
  177. *   -
  178. *
  179. ******************************************************************************/
  180.  
  181. static int All_Ellipsoid_Intersections(OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack)
  182. {
  183.   register int Intersection_Found;
  184.   DBL Depth1, Depth2, len;
  185.   VECTOR IPoint;
  186.   RAY New_Ray;
  187.   SPHERE *Sphere = (SPHERE *)Object;
  188.  
  189.   /* Transform the ray into the ellipsoid's space */
  190.  
  191.   MInvTransPoint(New_Ray.Initial, Ray->Initial, ((SPHERE *)Object)->Trans);
  192.   MInvTransDirection(New_Ray.Direction, Ray->Direction, ((SPHERE *)Object)->Trans);
  193.  
  194.   VLength(len, New_Ray.Direction);
  195.   VInverseScaleEq(New_Ray.Direction, len);
  196.  
  197.   Intersection_Found = FALSE;
  198.  
  199.   if (Intersect_Sphere(&New_Ray, Sphere->Center, Sqr(Sphere->Radius), &Depth1, &Depth2))
  200.   {
  201.     if ((Depth1 > DEPTH_TOLERANCE) && (Depth1 < Max_Distance))
  202.     {
  203. #ifdef FastSpherePatch
  204.       Depth1 /= len;
  205.  
  206.       VEvaluateRay(IPoint, Ray->Initial, Depth1, Ray->Direction);
  207.  
  208.       if (Point_In_Clip(IPoint, Object->Clip))
  209.       {
  210.         push_entry(Depth1, IPoint, Object, Depth_Stack);
  211.  
  212.         Intersection_Found = TRUE;
  213.       }
  214. #else
  215.       VEvaluateRay(IPoint, New_Ray.Initial, Depth1, New_Ray.Direction);
  216.  
  217.       MTransPoint(IPoint, IPoint, ((SPHERE *)Object)->Trans);
  218.       if (Point_In_Clip(IPoint, Object->Clip))
  219.       {
  220.         push_entry(Depth1 / len, IPoint, Object, Depth_Stack);
  221.  
  222.         Intersection_Found = TRUE;
  223.       }
  224. #endif
  225.     }
  226.  
  227.     if ((Depth2 > DEPTH_TOLERANCE) && (Depth2 < Max_Distance))
  228.     {
  229. #ifdef FastSpherePatch
  230.       Depth2/=len;
  231.       VEvaluateRay(IPoint, Ray->Initial, Depth2, Ray->Direction);
  232.  
  233.       if (Point_In_Clip(IPoint, Object->Clip))
  234.       {
  235.         push_entry(Depth2, IPoint, Object, Depth_Stack);
  236.  
  237.         Intersection_Found = TRUE;
  238.       }
  239. #else
  240.       VEvaluateRay(IPoint, New_Ray.Initial, Depth2, New_Ray.Direction);
  241.  
  242.       MTransPoint(IPoint, IPoint, ((SPHERE *)Object)->Trans);
  243.  
  244.       if (Point_In_Clip(IPoint, Object->Clip))
  245.       {
  246.         push_entry(Depth2 / len, IPoint, Object, Depth_Stack);
  247.  
  248.         Intersection_Found = TRUE;
  249.       }
  250. #endif
  251.  
  252.     }
  253.   }
  254.  
  255.   return(Intersection_Found);
  256. }
  257.  
  258.  
  259.  
  260. /*****************************************************************************
  261. *
  262. * FUNCTION
  263. *
  264. *   Intersect_Sphere
  265. *
  266. * INPUT
  267. *
  268. *   Ray     - Ray to test intersection with
  269. *   Center  - Center of the sphere
  270. *   Radius2 - Squared radius of the sphere
  271. *   Depth1  - Lower intersection distance
  272. *   Depth2  - Upper intersection distance
  273. *   
  274. * OUTPUT
  275. *   
  276. * RETURNS
  277. *   
  278. * AUTHOR
  279. *
  280. *   ?
  281. *   
  282. * DESCRIPTION
  283. *
  284. *   -
  285. *
  286. * CHANGES
  287. *
  288. *   -
  289. *
  290. ******************************************************************************/
  291.  
  292. int Intersect_Sphere(RAY *Ray, VECTOR Center, DBL Radius2, DBL *Depth1, DBL  *Depth2)
  293. {
  294.   DBL OCSquared, t_Closest_Approach, Half_Chord, t_Half_Chord_Squared;
  295.   VECTOR Origin_To_Center;
  296.  
  297.   Increase_Counter(stats[Ray_Sphere_Tests]);
  298.  
  299.   VSub(Origin_To_Center, Center, Ray->Initial);
  300.  
  301.   VDot(OCSquared, Origin_To_Center, Origin_To_Center);
  302.  
  303.   VDot(t_Closest_Approach, Origin_To_Center, Ray->Direction);
  304.  
  305.   if ((OCSquared >= Radius2) && (t_Closest_Approach < EPSILON))
  306.   {
  307.     return(FALSE);
  308.   }
  309.  
  310.   t_Half_Chord_Squared = Radius2 - OCSquared + Sqr(t_Closest_Approach);
  311.  
  312.   if (t_Half_Chord_Squared > EPSILON)
  313.   {
  314.     Half_Chord = sqrt(t_Half_Chord_Squared);
  315.  
  316.     *Depth1 = t_Closest_Approach - Half_Chord;
  317.     *Depth2 = t_Closest_Approach + Half_Chord;
  318.  
  319.     Increase_Counter(stats[Ray_Sphere_Tests_Succeeded]);
  320.  
  321.     return(TRUE);
  322.   }
  323.  
  324.   return(FALSE);
  325. }
  326.  
  327.  
  328.  
  329. /*****************************************************************************
  330. *
  331. * FUNCTION
  332. *
  333. *   Inside_Sphere
  334. *
  335. * INPUT
  336. *   
  337. * OUTPUT
  338. *   
  339. * RETURNS
  340. *   
  341. * AUTHOR
  342. *
  343. *   ?
  344. *   
  345. * DESCRIPTION
  346. *
  347. *   -
  348. *
  349. * CHANGES
  350. *
  351. *   -
  352. *
  353. ******************************************************************************/
  354.  
  355. static int Inside_Sphere(VECTOR IPoint, OBJECT *Object)
  356. {
  357.   DBL OCSquared;
  358.   VECTOR Origin_To_Center;
  359.  
  360.   VSub(Origin_To_Center, ((SPHERE *)Object)->Center, IPoint);
  361.  
  362.   VDot(OCSquared, Origin_To_Center, Origin_To_Center);
  363.  
  364.   if (Test_Flag(Object, INVERTED_FLAG))
  365.   {
  366.     return(OCSquared > Sqr(((SPHERE *)Object)->Radius));
  367.   }
  368.   else
  369.   {
  370.     return(OCSquared < Sqr(((SPHERE *)Object)->Radius));
  371.   }
  372. }
  373.  
  374.  
  375.  
  376. /*****************************************************************************
  377. *
  378. * FUNCTION
  379. *
  380. *   Inside_Ellipsoid
  381. *
  382. * INPUT
  383. *
  384. * OUTPUT
  385. *   
  386. * RETURNS
  387. *   
  388. * AUTHOR
  389. *
  390. *   ?
  391. *   
  392. * DESCRIPTION
  393. *
  394. *   -
  395. *
  396. * CHANGES
  397. *
  398. *   -
  399. *
  400. ******************************************************************************/
  401.  
  402. static int Inside_Ellipsoid(VECTOR IPoint, OBJECT *Object)
  403. {
  404.   DBL OCSquared;
  405.   VECTOR Origin_To_Center, New_Point;
  406.  
  407.   /* Transform the point into the sphere's space */
  408.  
  409.   MInvTransPoint(New_Point, IPoint, ((SPHERE *)Object)->Trans);
  410.  
  411.   VSub(Origin_To_Center, ((SPHERE *)Object)->Center, New_Point);
  412.  
  413.   VDot(OCSquared, Origin_To_Center, Origin_To_Center);
  414.  
  415.   if (Test_Flag(Object, INVERTED_FLAG))
  416.   {
  417.     return(OCSquared > Sqr(((SPHERE *)Object)->Radius));
  418.   }
  419.   else
  420.   {
  421.     return(OCSquared < Sqr(((SPHERE *)Object)->Radius));
  422.   }
  423. }
  424.  
  425.  
  426.  
  427. /*****************************************************************************
  428. *
  429. * FUNCTION
  430. *
  431. *   Sphere_Normal
  432. *
  433. * INPUT
  434. *   
  435. * OUTPUT
  436. *   
  437. * RETURNS
  438. *   
  439. * AUTHOR
  440. *
  441. *   ?
  442. *   
  443. * DESCRIPTION
  444. *
  445. *   -
  446. *
  447. * CHANGES
  448. *
  449. *   -
  450. *
  451. ******************************************************************************/
  452.  
  453. static void Sphere_Normal(VECTOR Result, OBJECT *Object, INTERSECTION *Inter)
  454. {
  455.   VSub(Result, Inter->IPoint, ((SPHERE *)Object)->Center);
  456.  
  457.   VInverseScaleEq(Result, ((SPHERE *)Object)->Radius);
  458. }
  459.  
  460.  
  461.  
  462. /*****************************************************************************
  463. *
  464. * FUNCTION
  465. *
  466. *   Ellipsoid_Normal
  467. *
  468. * INPUT
  469. *   
  470. * OUTPUT
  471. *   
  472. * RETURNS
  473. *   
  474. * AUTHOR
  475. *
  476. *   ?
  477. *   
  478. * DESCRIPTION
  479. *
  480. *   -
  481. *
  482. * CHANGES
  483. *
  484. *   -
  485. *
  486. ******************************************************************************/
  487.  
  488. static void Ellipsoid_Normal(VECTOR Result, OBJECT *Object, INTERSECTION *Inter)
  489. {
  490.   VECTOR New_Point;
  491.  
  492.   /* Transform the point into the sphere's space */
  493.  
  494.   MInvTransPoint(New_Point, Inter->IPoint, ((SPHERE *)Object)->Trans);
  495.  
  496.   VSub(Result, New_Point, ((SPHERE *)Object)->Center);
  497.  
  498.   MTransNormal(Result, Result, ((SPHERE *)Object)->Trans);
  499.  
  500.   VNormalize(Result, Result);
  501. }
  502.  
  503.  
  504.  
  505. /*****************************************************************************
  506. *
  507. * FUNCTION
  508. *
  509. *   Copy_Shere
  510. *
  511. * INPUT
  512. *   
  513. * OUTPUT
  514. *   
  515. * RETURNS
  516. *   
  517. * AUTHOR
  518. *
  519. *   ?
  520. *   
  521. * DESCRIPTION
  522. *
  523. *   -
  524. *
  525. * CHANGES
  526. *
  527. *   -
  528. *
  529. ******************************************************************************/
  530.  
  531. SPHERE *Copy_Sphere(OBJECT *Object)
  532. {
  533.   SPHERE *New;
  534.  
  535.   New = Create_Sphere();
  536.  
  537.   *New = *((SPHERE *)Object);
  538.  
  539.   New->Trans = Copy_Transform(((SPHERE *)Object)->Trans);
  540.  
  541.   return(New);
  542. }
  543.  
  544.  
  545.  
  546. /*****************************************************************************
  547. *
  548. * FUNCTION
  549. *
  550. *   Translate_Sphere
  551. *
  552. * INPUT
  553. *
  554. * OUTPUT
  555. *
  556. * RETURNS
  557. *
  558. * AUTHOR
  559. *
  560. *   ?
  561. *
  562. * DESCRIPTION
  563. *
  564. *   -
  565. *
  566. * CHANGES
  567. *
  568. *   -
  569. *
  570. ******************************************************************************/
  571.  
  572. static void Translate_Sphere(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
  573. {
  574.   SPHERE *Sphere = (SPHERE *) Object;
  575.  
  576.   if (Sphere->Trans == NULL)
  577.   {
  578.     VAddEq(Sphere->Center, Vector);
  579.  
  580.     Compute_Sphere_BBox(Sphere);
  581.   }
  582.   else
  583.   {
  584.     Transform_Sphere(Object, Trans);
  585.   }
  586. }
  587.  
  588.  
  589.  
  590. /*****************************************************************************
  591. *
  592. * FUNCTION
  593. *
  594. *   Rotate_Sphere
  595. *
  596. * INPUT
  597. *
  598. * OUTPUT
  599. *   
  600. * RETURNS
  601. *   
  602. * AUTHOR
  603. *
  604. *   ?
  605. *   
  606. * DESCRIPTION
  607. *
  608. *   -
  609. *
  610. * CHANGES
  611. *
  612. *   -
  613. *
  614. ******************************************************************************/
  615.  
  616. static void Rotate_Sphere(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
  617. {
  618.   SPHERE *Sphere = (SPHERE *) Object;
  619.  
  620.   if (Sphere->Trans == NULL)
  621.   {
  622.     MTransPoint(Sphere->Center, Sphere->Center, Trans);
  623.  
  624.     Compute_Sphere_BBox(Sphere);
  625.   }
  626.   else
  627.   {
  628.     Transform_Sphere(Object, Trans);
  629.   }
  630. }
  631.  
  632.  
  633.  
  634. /*****************************************************************************
  635. *
  636. * FUNCTION
  637. *
  638. *   Scale_Sphere
  639. *
  640. * INPUT
  641. *   
  642. * OUTPUT
  643. *   
  644. * RETURNS
  645. *   
  646. * AUTHOR
  647. *
  648. *   ?
  649. *   
  650. * DESCRIPTION
  651. *
  652. *   -
  653. *
  654. * CHANGES
  655. *
  656. *   -
  657. *
  658. ******************************************************************************/
  659.  
  660. static void Scale_Sphere(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
  661. {
  662.   SPHERE *Sphere = (SPHERE *) Object;
  663.  
  664.   if ((Vector[X] != Vector[Y]) || (Vector[X] != Vector[Z]))
  665.   {
  666.     if (Sphere->Trans == NULL)
  667.     {
  668.       Sphere->Methods = &Ellipsoid_Methods;
  669.  
  670.       Sphere->Trans = Create_Transform();
  671.     }
  672.   }
  673.  
  674.   if (Sphere->Trans == NULL)
  675.   {
  676.     VScaleEq(Sphere->Center, Vector[X]);
  677.  
  678.     Sphere->Radius *= fabs(Vector[X]);
  679.  
  680.     Compute_Sphere_BBox(Sphere);
  681.   }
  682.   else
  683.   {
  684.     Transform_Sphere(Object, Trans);
  685.   }
  686. }
  687.  
  688.  
  689.  
  690. /*****************************************************************************
  691. *
  692. * FUNCTION
  693. *
  694. *   Invert_Sphere
  695. *
  696. * INPUT
  697. *   
  698. * OUTPUT
  699. *   
  700. * RETURNS
  701. *   
  702. * AUTHOR
  703. *
  704. *   ?
  705. *   
  706. * DESCRIPTION
  707. *
  708. *   -
  709. *
  710. * CHANGES
  711. *
  712. *   -
  713. *
  714. ******************************************************************************/
  715.  
  716. static void Invert_Sphere(OBJECT *Object)
  717. {
  718.   Invert_Flag(Object, INVERTED_FLAG);
  719. }
  720.  
  721.  
  722.  
  723. /*****************************************************************************
  724. *
  725. * FUNCTION
  726. *
  727. *   Create_Sphere
  728. *
  729. * INPUT
  730. *   
  731. * OUTPUT
  732. *   
  733. * RETURNS
  734. *   
  735. * AUTHOR
  736. *
  737. *   ?
  738. *   
  739. * DESCRIPTION
  740. *
  741. *   -
  742. *
  743. * CHANGES
  744. *
  745. *   -
  746. *
  747. ******************************************************************************/
  748.  
  749. SPHERE *Create_Sphere()
  750. {
  751.   SPHERE *New;
  752.  
  753.   New = (SPHERE *)POV_MALLOC(sizeof(SPHERE), "sphere");
  754.  
  755.   INIT_OBJECT_FIELDS(New, SPHERE_OBJECT, &Sphere_Methods)
  756.  
  757.   Make_Vector(New->Center, 0.0, 0.0, 0.0);
  758.  
  759.   New->Radius = 1.0;
  760.  
  761.   New->Trans = NULL;
  762.  
  763.   return(New);
  764. }
  765.  
  766.  
  767.  
  768. /*****************************************************************************
  769. *
  770. * FUNCTION
  771. *
  772. *   Transform_Sphere
  773. *
  774. * INPUT
  775. *   
  776. * OUTPUT
  777. *   
  778. * RETURNS
  779. *   
  780. * AUTHOR
  781. *
  782. *   ?
  783. *   
  784. * DESCRIPTION
  785. *
  786. *   -
  787. *
  788. * CHANGES
  789. *
  790. *   -
  791. *
  792. ******************************************************************************/
  793.  
  794. void Transform_Sphere(OBJECT *Object, TRANSFORM *Trans)
  795. {
  796.   SPHERE *Sphere = (SPHERE *)Object;
  797.  
  798.   if (Sphere->Trans == NULL)
  799.   {
  800.     Sphere->Methods = &Ellipsoid_Methods;
  801.  
  802.     Sphere->Trans = Create_Transform();
  803.   }
  804.  
  805.   Compose_Transforms(Sphere->Trans, Trans);
  806.  
  807.   Compute_Sphere_BBox(Sphere);
  808. }
  809.  
  810.  
  811.  
  812. /*****************************************************************************
  813. *
  814. * FUNCTION
  815. *
  816. *   Destroy_Sphere
  817. *
  818. * INPUT
  819. *   
  820. * OUTPUT
  821. *   
  822. * RETURNS
  823. *   
  824. * AUTHOR
  825. *
  826. *   ?
  827. *   
  828. * DESCRIPTION
  829. *
  830. *   -
  831. *
  832. * CHANGES
  833. *
  834. *   -
  835. *
  836. ******************************************************************************/
  837.  
  838. void Destroy_Sphere(OBJECT *Object)
  839. {
  840.   Destroy_Transform(((SPHERE *)Object)->Trans);
  841.  
  842.   POV_FREE (Object);
  843. }
  844.  
  845.  
  846.  
  847. /*****************************************************************************
  848. *
  849. * FUNCTION
  850. *
  851. *   Compute_Sphere_BBox
  852. *
  853. * INPUT
  854. *
  855. *   Sphere - Sphere
  856. *   
  857. * OUTPUT
  858. *
  859. *   Sphere
  860. *   
  861. * RETURNS
  862. *   
  863. * AUTHOR
  864. *
  865. *   Dieter Bayer
  866. *   
  867. * DESCRIPTION
  868. *
  869. *   Calculate the bounding box of a sphere.
  870. *
  871. * CHANGES
  872. *
  873. *   Aug 1994 : Creation.
  874. *
  875. ******************************************************************************/
  876.  
  877. void Compute_Sphere_BBox(SPHERE *Sphere)
  878. {
  879.   Make_BBox(Sphere->BBox, Sphere->Center[X] - Sphere->Radius, Sphere->Center[Y] - Sphere->Radius,  Sphere->Center[Z] - Sphere->Radius,
  880.     2.0 * Sphere->Radius, 2.0 * Sphere->Radius, 2.0 * Sphere->Radius);
  881.  
  882.   if (Sphere->Trans != NULL)
  883.   {
  884.     Recompute_BBox(&Sphere->BBox, Sphere->Trans);
  885.   }
  886. }
  887.  
  888. /*****************************************************************************
  889. *
  890. * FUNCTION
  891. *
  892. *   Sphere_UVCoord
  893. *
  894. * INPUT
  895. *
  896. * OUTPUT
  897. *
  898. * RETURNS
  899. *
  900. * AUTHOR
  901. *
  902. *   Nathan Kopp   (adapted from spherical_image_map)
  903. *
  904. * DESCRIPTION
  905. *
  906. *   Find the UV coordinates of a sphere.
  907. *   Map a point (x, y, z) on a sphere of radius 1 to a 2-d image. (Or is it the
  908. *   other way around?)
  909. *
  910. * CHANGES
  911. *
  912. *   -
  913. *
  914. ******************************************************************************/
  915. static void Sphere_UVCoord(UV_VECT Result, OBJECT *Object, INTERSECTION *Inter)
  916. {
  917.   DBL len, phi, theta;
  918.   DBL x,y,z;
  919.   VECTOR New_Point, New_Center;
  920.   SPHERE *Sphere = (SPHERE *)Object;
  921.  
  922.   /* Transform the point into the sphere's space */
  923.   if (Object->UV_Trans != NULL)
  924.   {
  925.     MInvTransPoint(New_Point, Inter->IPoint, Object->UV_Trans);
  926.     MInvTransPoint(New_Center, Sphere->Center, Object->UV_Trans);
  927.     if (Sphere->Trans != NULL)
  928.       MTransPoint(New_Center, New_Center, Sphere->Trans);
  929.   }
  930.   else
  931.   {
  932.     Assign_Vector(New_Point, Inter->IPoint);
  933.     Assign_Vector(New_Center, Sphere->Center);
  934.   }
  935.   x = New_Point[X]-New_Center[X];
  936.   y = New_Point[Y]-New_Center[Y];
  937.   z = New_Point[Z]-New_Center[Z];
  938.  
  939.   len = sqrt(x * x + y * y + z * z);
  940.  
  941.   if (len == 0.0)
  942.     return;
  943.   else
  944.   {
  945.     x /= len;
  946.     y /= len;
  947.     z /= len;
  948.   }
  949.  
  950.   /* Determine its angle from the x-z plane. */
  951.   phi = 0.5 + asin(y) / M_PI; /* This will be from 0 to 1 */
  952.  
  953.  
  954.   /* Determine its angle from the point (1, 0, 0) in the x-z plane. */
  955.   len = x * x + z * z;
  956.  
  957.   if (len > EPSILON)
  958.   {
  959.     len = sqrt(len);
  960.     if (z == 0.0)
  961.     {
  962.       if (x > 0)
  963.         theta = 0.0;
  964.       else
  965.         theta = M_PI;
  966.     }
  967.     else
  968.     {
  969.       theta = acos(x / len);
  970.       if (z < 0.0)
  971.         theta = TWO_M_PI - theta;
  972.     }
  973.  
  974.     theta /= TWO_M_PI;  /* This will be from 0 to 1 */
  975.   }
  976.   else
  977.     /* This point is at one of the poles. Any value of xcoord will be ok... */
  978.     theta = 0;
  979.  
  980.   Result[U] = theta;
  981.   Result[V] = phi;
  982. }
  983.  
  984.