home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: Graphics / Graphics.zip / povsrc31.zip / discs.c < prev    next >
C/C++ Source or Header  |  2000-09-12  |  20KB  |  975 lines

  1. /****************************************************************************
  2. *                discs.c
  3. *
  4. *  This module implements the disc primitive.
  5. *  This file was written by Alexander Enzmann.  He wrote the code for
  6. *  discs and generously provided us these enhancements.
  7. *
  8. *  from Persistence of Vision(tm) Ray Tracer
  9. *  Copyright 1996,1999 Persistence of Vision Team
  10. *---------------------------------------------------------------------------
  11. *  NOTICE: This source code file is provided so that users may experiment
  12. *  with enhancements to POV-Ray and to port the software to platforms other 
  13. *  than those supported by the POV-Ray Team.  There are strict rules under
  14. *  which you are permitted to use this file.  The rules are in the file
  15. *  named POVLEGAL.DOC which should be distributed with this file.
  16. *  If POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  17. *  Team Coordinator by email to team-coord@povray.org or visit us on the web at
  18. *  http://www.povray.org. The latest version of POV-Ray may be found at this site.
  19. *
  20. * This program is based on the popular DKB raytracer version 2.12.
  21. * DKBTrace was originally written by David K. Buck.
  22. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  23. *
  24. *****************************************************************************/
  25.  
  26. #include "frame.h"
  27. #include "povray.h"
  28. #include "vector.h"
  29. #include "povproto.h"
  30. #include "bbox.h"
  31. #include "discs.h"
  32. #include "matrices.h"
  33. #include "objects.h"
  34.  
  35.  
  36.  
  37. /*****************************************************************************
  38. * Local preprocessor defines
  39. ******************************************************************************/
  40. #ifdef FastDiscPatch
  41. /* DISC.C is temporar place for next few defines*/
  42. #define UV_Dot(a,b,c)          { a=(b)[X]*(c)[X]+(b)[Y]*(c)[Y];}
  43. #define Make_UV_Vector(v,a,b ) { (v)[X]=(a); (v)[Y]=(b); }
  44. #define UV_ScaleEq(a,k)        { (a)[X]*=(k); (a)[Y]*=(k); }
  45. #define UV_LinComb2(V,k1,V1,k2,V2)              \
  46.   {                                             \
  47.     (V)[X] = (k1) * (V1)[X] + (k2) * (V2)[X];   \
  48.     (V)[Y] = (k1) * (V1)[Y] + (k2) * (V2)[Y];   \
  49.   }
  50.  
  51.  
  52.  
  53. #define max3_coordinate(x,y,z) \
  54.   (((x) > (y)) ? (((x) > (z)) ? X : Z) : (((y) > (z)) ? Y : Z))
  55.  
  56. #endif
  57.  
  58.  
  59. /*****************************************************************************
  60. * Static functions
  61. ******************************************************************************/
  62.  
  63. #ifdef FastDiscPatch
  64. static void ellipse_main_axis( UV_VECT x_axis, UV_VECT y_axis, UV_VECT ex, UV_VECT ey );
  65. #endif
  66. static int Intersect_Disc (RAY *Ray, DISC *Disc, DBL *Depth);
  67. static int All_Disc_Intersections (OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack);
  68. static int Inside_Disc (VECTOR point, OBJECT *Object);
  69. static void Disc_Normal (VECTOR Result, OBJECT *Object, INTERSECTION *Inter);
  70. static DISC *Copy_Disc (OBJECT *Object);
  71. static void Translate_Disc (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
  72. static void Rotate_Disc (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
  73. static void Scale_Disc (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
  74. static void Transform_Disc (OBJECT *Object, TRANSFORM *Trans);
  75. static void Invert_Disc (OBJECT *Object);
  76. static void Destroy_Disc (OBJECT *Object);
  77. static void Compute_Disc_BBox (DISC *Disc);
  78.  
  79. /*****************************************************************************
  80. * Local variables
  81. ******************************************************************************/
  82.  
  83. static METHODS Disc_Methods =
  84. {
  85.   All_Disc_Intersections,
  86.   Inside_Disc, Disc_Normal, Default_UVCoord,
  87.   (COPY_METHOD)Copy_Disc, Translate_Disc, Rotate_Disc, Scale_Disc, Transform_Disc,
  88.   Invert_Disc, Destroy_Disc
  89. };
  90.  
  91.  
  92. /*****************************************************************************
  93. *
  94. * FUNCTION
  95. *
  96. *   All_Disc_Intersections
  97. *
  98. * INPUT
  99. *   
  100. * OUTPUT
  101. *   
  102. * RETURNS
  103. *   
  104. * AUTHOR
  105. *
  106. *   Alexander Enzmann
  107. *   
  108. * DESCRIPTION
  109. *
  110. *   -
  111. *
  112. * CHANGES
  113. *
  114. *   -
  115. *
  116. ******************************************************************************/
  117.  
  118. static int All_Disc_Intersections (OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack)
  119. {
  120.   int Intersection_Found;
  121.   DBL Depth;
  122.   VECTOR IPoint;
  123.  
  124.   Intersection_Found = FALSE;
  125.  
  126.   if (Intersect_Disc (Ray, (DISC *)Object, &Depth))
  127.   {
  128.     VEvaluateRay(IPoint, Ray->Initial, Depth, Ray->Direction);
  129.  
  130.     if (Point_In_Clip (IPoint, Object->Clip))
  131.     {
  132.       push_entry(Depth,IPoint,Object,Depth_Stack);
  133.       Intersection_Found = TRUE;
  134.     }
  135.   }
  136.  
  137.   return (Intersection_Found);
  138. }
  139.  
  140.  
  141.  
  142. /*****************************************************************************
  143. *
  144. * FUNCTION
  145. *
  146. *   Intersect_Disc
  147. *
  148. * INPUT
  149. *
  150. * OUTPUT
  151. *
  152. * RETURNS
  153. *
  154. * AUTHOR
  155. *
  156. *   Alexander Enzmann
  157. *
  158. * DESCRIPTION
  159. *
  160. *   -
  161. *
  162. * CHANGES
  163. *
  164. *   -
  165. *
  166. ******************************************************************************/
  167.  
  168. static int Intersect_Disc (RAY *Ray, DISC *disc, DBL *Depth)
  169. {
  170. #ifndef FastDiscPatch
  171.   DBL t, u, v, r2, len;
  172.   VECTOR P, D;
  173.  Increase_Counter(stats[Ray_Disc_Tests]);
  174.  
  175.   /* Transform the point into the discs space */
  176.  
  177.   MInvTransPoint(P, Ray->Initial, disc->Trans);
  178.   MInvTransDirection(D, Ray->Direction, disc->Trans);
  179.  
  180.   VLength(len, D);
  181.   VInverseScaleEq(D, len);
  182.  
  183.   if (fabs(D[Z]) > EPSILON)
  184.   {
  185.     t = -P[Z] / D[Z];
  186.  
  187.     if (t >= 0.0)
  188.     {
  189.       u = P[X] + t * D[X];
  190.       v = P[Y] + t * D[Y];
  191.  
  192.       r2 = Sqr(u) + Sqr(v);
  193.  
  194.       if ((r2 >= disc->iradius2) && (r2 <= disc->oradius2))
  195.       {
  196.         *Depth = t / len;
  197.  
  198.         if ((*Depth > Small_Tolerance) && (*Depth < Max_Distance))
  199.         {
  200.           Increase_Counter(stats[Ray_Disc_Tests_Succeeded]);
  201.  
  202.           return (TRUE);
  203.         }
  204.       }
  205.     }
  206.   }
  207.     return (FALSE);
  208.  
  209. #else
  210.   DBL u, v, r2;
  211.   DBL NormalDotP, NormalDotDirection;
  212.   VECTOR P, IPoint;
  213.  
  214.   Increase_Counter(stats[Ray_Disc_Tests]);
  215.  
  216.  
  217.   VDot( NormalDotDirection, disc->normal, Ray->Direction );
  218.  
  219.   if(  fabs( NormalDotDirection ) < EPSILON ) return (FALSE);
  220.  
  221.  
  222.   VSub( P, Ray->Initial, disc->center );
  223.  
  224.   VDot( NormalDotP, disc->normal, P );
  225.  
  226.  
  227.   *Depth = - NormalDotP / NormalDotDirection;
  228.  
  229.   if ( *Depth <= Small_Tolerance ) return (FALSE);
  230.  
  231.  
  232.   switch( disc->Dominant_Axis )
  233.    {
  234.     case( X ):
  235.       IPoint[ Y ] = P[ Y ] + *Depth * Ray->Direction[ Y ];
  236.       IPoint[ Z ] = P[ Z ] + *Depth * Ray->Direction[ Z ];
  237.       u = IPoint[ Y ] * disc->u_axis[ X ]  +  IPoint[ Z ] * disc->u_axis[ Y ];
  238.       v = IPoint[ Y ] * disc->v_axis[ X ]  +  IPoint[ Z ] * disc->v_axis[ Y ];
  239.      break;
  240.     case( Y ):
  241.       IPoint[ X ] = P[ X ] + *Depth * Ray->Direction[ X ];
  242.       IPoint[ Z ] = P[ Z ] + *Depth * Ray->Direction[ Z ];
  243.       u = IPoint[ Z ] * disc->u_axis[ X ]  +  IPoint[ X ] * disc->u_axis[ Y ];
  244.       v = IPoint[ Z ] * disc->v_axis[ X ]  +  IPoint[ X ] * disc->v_axis[ Y ];
  245.      break;
  246.     case( Z ):
  247.       IPoint[ X ] = P[ X ] + *Depth * Ray->Direction[ X ];
  248.       IPoint[ Y ] = P[ Y ] + *Depth * Ray->Direction[ Y ];
  249.       u = IPoint[ X ] * disc->u_axis[ X ]  +  IPoint[ Y ] * disc->u_axis[ Y ];
  250.       v = IPoint[ X ] * disc->v_axis[ X ]  +  IPoint[ Y ] * disc->v_axis[ Y ];
  251.      break;
  252.    }
  253.  
  254.   r2 = Sqr(u) + Sqr(v);
  255.  
  256.   if ( ( disc->iradius2 <= r2 ) && ( r2 <= 1.0 ) )
  257.   {
  258.     if ( (*Depth < Max_Distance) )
  259.     {
  260.       Increase_Counter(stats[Ray_Disc_Tests_Succeeded]);
  261.  
  262.       return (TRUE);
  263.     }
  264.   }
  265.  
  266.   return (FALSE);
  267. #endif
  268. }
  269.  
  270.  
  271.  
  272. /*****************************************************************************
  273. *
  274. * FUNCTION
  275. *
  276. *   Inside_Disc
  277. *
  278. * INPUT
  279. *
  280. * OUTPUT
  281. *
  282. * RETURNS
  283. *
  284. * AUTHOR
  285. *
  286. *   Alexander Enzmann
  287. *
  288. * DESCRIPTION
  289. *
  290. *   -
  291. *
  292. * CHANGES
  293. *
  294. *   -
  295. *
  296. ******************************************************************************/
  297.  
  298. static int Inside_Disc (VECTOR IPoint, OBJECT *Object)
  299. {
  300.  #ifndef FastDiscPatch
  301.  VECTOR New_Point;
  302.   DISC *disc = (DISC *) Object;
  303.  
  304.   /* Transform the point into the discs space */
  305.  
  306.   MInvTransPoint(New_Point, IPoint, disc->Trans);
  307.  
  308.   if (New_Point[Z] >= 0.0)
  309.   {
  310.     /* We are outside. */
  311.  
  312.     return (Test_Flag(disc, INVERTED_FLAG));
  313.   }
  314.   else
  315.   {
  316.     /* We are inside. */
  317.  
  318.     return (!Test_Flag(disc, INVERTED_FLAG));
  319.   }
  320. #else
  321.   DBL Temp;
  322.   DISC *Disc = (DISC *) Object;
  323.  
  324.   VDot (Temp, IPoint, Disc->normal);
  325.  
  326.   return ( (Temp + Disc->d) < EPSILON );
  327.  
  328. #endif
  329. }
  330.  
  331.  
  332.  
  333. /*****************************************************************************
  334. *
  335. * FUNCTION
  336. *
  337. *   Disc_Normal
  338. *
  339. * INPUT
  340. *
  341. * OUTPUT
  342. *
  343. * RETURNS
  344. *
  345. * AUTHOR
  346. *
  347. *   Alexander Enzmann
  348. *
  349. * DESCRIPTION
  350. *
  351. *   -
  352. *
  353. * CHANGES
  354. *
  355. *   -
  356. *
  357. ******************************************************************************/
  358.  
  359. static void Disc_Normal (VECTOR Result, OBJECT *Object, INTERSECTION *Inter)
  360. {
  361.   Assign_Vector(Result, ((DISC *)Object)->normal);
  362. }
  363.  
  364.  
  365.  
  366. /*****************************************************************************
  367. *
  368. * FUNCTION
  369. *
  370. *   Translate_Disc
  371. *
  372. * INPUT
  373. *
  374. * OUTPUT
  375. *
  376. * RETURNS
  377. *
  378. * AUTHOR
  379. *
  380. *   Alexander Enzmann
  381. *
  382. * DESCRIPTION
  383. *
  384. *   -
  385. *
  386. * CHANGES
  387. *
  388. *   -
  389. *
  390. ******************************************************************************/
  391.  
  392. static void Translate_Disc (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
  393. {
  394.   Transform_Disc(Object, Trans);
  395. }
  396.  
  397.  
  398.  
  399. /*****************************************************************************
  400. *
  401. * FUNCTION
  402. *
  403. *   Rotate_Disc
  404. *
  405. * INPUT
  406. *
  407. * OUTPUT
  408. *
  409. * RETURNS
  410. *
  411. * AUTHOR
  412. *
  413. *   Alexander Enzmann
  414. *
  415. * DESCRIPTION
  416. *
  417. *   -
  418. *
  419. * CHANGES
  420. *
  421. *   -
  422. *
  423. ******************************************************************************/
  424.  
  425. static void Rotate_Disc(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
  426. {
  427.   Transform_Disc(Object, Trans);
  428. }
  429.  
  430.  
  431.  
  432. /*****************************************************************************
  433. *
  434. * FUNCTION
  435. *
  436. *   Scale_Disc
  437. *
  438. * INPUT
  439. *
  440. * OUTPUT
  441. *
  442. * RETURNS
  443. *
  444. * AUTHOR
  445. *
  446. *   Alexander Enzmann
  447. *
  448. * DESCRIPTION
  449. *
  450. *   -
  451. *
  452. * CHANGES
  453. *
  454. *   -
  455. *
  456. ******************************************************************************/
  457.  
  458. static void Scale_Disc(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
  459. {
  460.   Transform_Disc(Object, Trans);
  461. }
  462.  
  463.  
  464.  
  465. /*****************************************************************************
  466. *
  467. * FUNCTION
  468. *
  469. *   Invert_Disc
  470. *
  471. * INPUT
  472. *
  473. * OUTPUT
  474. *
  475. * RETURNS
  476. *
  477. * AUTHOR
  478. *
  479. *   Alexander Enzmann
  480. *
  481. * DESCRIPTION
  482. *
  483. *   -
  484. *
  485. * CHANGES
  486. *
  487. *   -
  488. *
  489. ******************************************************************************/
  490.  
  491. static void Invert_Disc (OBJECT *Object)
  492. {
  493.    #ifndef FastDiscPatch
  494. Invert_Flag(Object, INVERTED_FLAG);
  495. #else
  496.   VScaleEq(((DISC *)Object)->normal, -1.0);
  497.  
  498.   ((DISC *)Object)->d *= -1.0;
  499. #endif
  500. }
  501. #ifdef FastDiscPatch
  502. /*****************************************************************************
  503. *
  504. * FUNCTION
  505. *
  506. *   ellipse_main_axis
  507. *
  508. * INPUT
  509. *
  510. * OUTPUT
  511. *          ex, ey
  512. * RETURNS
  513. *     x_axis, y_axis
  514. * AUTHOR
  515. *
  516. *   Dejan D. M. Milosavljevic
  517. *
  518. * DESCRIPTION
  519. *
  520. *   Compute main axis of elipse given at form
  521. *    ex * cos( alpha ) + ey * sin( alpha );
  522. *     Where     0 <= alpha <= 2*M_PI.
  523. *
  524. * CHANGES
  525. *
  526. *   April 2000: Creation [DDMM]
  527. *
  528. ******************************************************************************/
  529.  
  530. static void ellipse_main_axis( UV_VECT x_axis, UV_VECT y_axis, UV_VECT ex, UV_VECT ey )
  531.  {
  532.   DBL b, c, alpha;
  533.   DBL t1, t2;
  534.  
  535.   UV_Dot( t1, ex, ex );
  536.   UV_Dot( t2, ey, ey );
  537.  
  538.   b = t2 - t1; if( fabs( b ) < EPSILON ) b = 0.0;
  539.   UV_Dot( c, ex, ey ); if( fabs( c ) < EPSILON ) c = 0.0;
  540.  
  541.   switch( ( ( b != 0.0 ) << 1 )  +  ( c != 0.0 ) )
  542.    {
  543.     case( 0 + 0 ):
  544.        Assign_UV_Vect( x_axis, ex );
  545.        Assign_UV_Vect( y_axis, ey );
  546.      break;
  547.     case( 0 + 1 ):
  548.       alpha = M_PI_2 / 2.0;
  549.        t1 = cos( alpha );  t2 = sin( alpha );
  550.       UV_LinComb2( x_axis, t1, ex, t2, ey );
  551.        t1 = cos( alpha + M_PI_2 );  t2 = sin( alpha + M_PI_2 );
  552.       UV_LinComb2( y_axis, t1, ex, t2, ey );
  553.     break;
  554.     case( 2 + 0 ):
  555.        Assign_UV_Vect( x_axis, ex );
  556.        Assign_UV_Vect( y_axis, ey );
  557.      break;
  558.     case( 2 + 1 ):
  559.        alpha = atan(  -2.0 * c / b )/2.0;
  560.         t1 = cos( alpha ); t2 = sin( alpha );
  561.        UV_LinComb2( x_axis, t1, ex, t2, ey );
  562.         t1 = cos( alpha + M_PI_2 );  t2 = sin( alpha + M_PI_2 );
  563.        UV_LinComb2( y_axis, t1, ex, t2, ey );
  564.      break;
  565.    }
  566.  
  567.  
  568.   UV_Dot( t1, x_axis, x_axis );  t1=1.0/t1;  UV_ScaleEq( x_axis, t1 );
  569.   UV_Dot( t1, y_axis, y_axis );  t1=1.0/t1;  UV_ScaleEq( y_axis, t1 );
  570.  }
  571.  
  572. #endif
  573. /*****************************************************************************
  574. *
  575. * FUNCTION
  576. *
  577. *   Transform_Disc
  578. *
  579. * INPUT
  580. *
  581. * OUTPUT
  582. *
  583. * RETURNS
  584. *
  585. * AUTHOR
  586. *
  587. *   Alexander Enzmann
  588. *
  589. * DESCRIPTION
  590. *
  591. *   -
  592. *
  593. * CHANGES
  594. *
  595. *   -
  596. *
  597. ******************************************************************************/
  598.  
  599. static void Transform_Disc (OBJECT *Object, TRANSFORM *Trans)
  600. {
  601. #ifndef FastDiscPatch
  602.   DISC *Disc = (DISC *)Object;
  603.  
  604.   MTransNormal(((DISC *)Object)->normal, ((DISC *)Object)->normal, Trans);
  605.  
  606.   VNormalize(((DISC *)Object)->normal, ((DISC *)Object)->normal);
  607.  
  608.   Compose_Transforms(Disc->Trans, Trans);
  609.  
  610.   /* Recalculate the bounds */
  611.  
  612.   Compute_Disc_BBox(Disc);
  613. #else
  614.   UV_VECT  u, v;
  615.   DISC *Disc = (DISC *)Object;
  616.  
  617.   /* Recalculate the normal */
  618.   MTransNormal( Disc->normal, Disc->normal, Trans);
  619.   VNormalizeEq( Disc->normal );
  620.  
  621.   /* Recalculate the center */
  622.   MTransPoint( Disc->center, Disc->center, Trans );
  623.  
  624.   /* Recalculate the d */
  625.   VDot( Disc->d, Disc->center, Disc->normal );
  626.   Disc->d = - Disc->d;
  627.  
  628.   /* Recalculate the x and y  axis */
  629.   MTransDirection( Disc->x_axis, Disc->x_axis, Trans );
  630.   MTransDirection( Disc->y_axis, Disc->y_axis, Trans );
  631.  
  632.   /* Recalculate the u and v axis */
  633.   Disc->Dominant_Axis
  634.     = max3_coordinate
  635.         (
  636.          fabs( Disc->normal[ X ] ),
  637.          fabs( Disc->normal[ Y ] ),
  638.          fabs( Disc->normal[ Z ] )
  639.         );
  640.  
  641.   switch( Disc->Dominant_Axis )
  642.    {
  643.     case( X ):
  644.       Make_UV_Vector( u, Disc->x_axis[ Y ], Disc->x_axis[ Z ] );
  645.       Make_UV_Vector( v, Disc->y_axis[ Y ], Disc->y_axis[ Z ] );
  646.       ellipse_main_axis( Disc->u_axis, Disc->v_axis, u, v );
  647.      break;
  648.     case( Y ):
  649.       Make_UV_Vector( u, Disc->x_axis[ Z ], Disc->x_axis[ X ] );
  650.       Make_UV_Vector( v, Disc->y_axis[ Z ], Disc->y_axis[ X ] );
  651.       ellipse_main_axis( Disc->u_axis, Disc->v_axis, u, v );
  652.      break;
  653.     case( Z ):
  654.       Make_UV_Vector( u, Disc->x_axis[ X ], Disc->x_axis[ Y ] );
  655.       Make_UV_Vector( v, Disc->y_axis[ X ], Disc->y_axis[ Y ] );
  656.       ellipse_main_axis( Disc->u_axis, Disc->v_axis, u, v );
  657.      break;
  658.    }
  659.  
  660.   /* Recalculate the bounds */
  661.   Compute_Disc_BBox(Disc);
  662. #endif
  663. }
  664.  
  665.  
  666.  
  667. /*****************************************************************************
  668. *
  669. * FUNCTION
  670. *
  671. *   Create_Disc
  672. *
  673. * INPUT
  674. *
  675. * OUTPUT
  676. *
  677. * RETURNS
  678. *
  679. * AUTHOR
  680. *
  681. *   Alexander Enzmann
  682. *
  683. * DESCRIPTION
  684. *
  685. *   -
  686. *
  687. * CHANGES
  688. *
  689. *   -
  690. *
  691. ******************************************************************************/
  692.  
  693. DISC *Create_Disc ()
  694. {
  695.  #ifndef FastDiscPatch
  696.  DISC *New;
  697.  
  698.   New = (DISC *)POV_MALLOC(sizeof (DISC), "disc");
  699.  
  700.   INIT_OBJECT_FIELDS(New, DISC_OBJECT, &Disc_Methods)
  701.  
  702.   Make_Vector (New->center, 0.0, 0.0, 0.0);
  703.   Make_Vector (New->normal, 0.0, 0.0, 1.0);
  704.  
  705.   New->iradius2 = 0.0;
  706.   New->oradius2 = 1.0;
  707.  
  708.   New->d = 0.0;
  709.  
  710.   New->Trans = Create_Transform();
  711.  
  712.   /* Default bounds */
  713.  
  714.   Make_BBox(New->BBox, -1.0, -1.0, -Small_Tolerance, 2.0,  2.0, 2.0 * Small_Tolerance);
  715.  
  716.   return (New);
  717.   #else
  718.     DISC *New;
  719.  
  720.   New = (DISC *)POV_MALLOC(sizeof (DISC), "disc");
  721.  
  722.   INIT_OBJECT_FIELDS(New, DISC_OBJECT, &Disc_Methods)
  723.  
  724.   Make_Vector( New->x_axis, 1.0, 0.0, 0.0 );
  725.   Make_Vector( New->y_axis, 0.0, 1.0, 0.0 );
  726.   Make_Vector( New->normal, 0.0, 0.0, 1.0 );
  727.  
  728.   Make_Vector( New->center, 0.0, 0.0, 0.0 );
  729.  
  730.   New->Dominant_Axis = Z;
  731.   Make_UV_Vector( New->u_axis, 1.0, 0.0 );
  732.   Make_UV_Vector( New->v_axis, 0.0, 1.0 );
  733.  
  734.   New->iradius2 = 0.0;
  735.  
  736.   New->d = 0.0;
  737.  
  738.  /* Default bounds */
  739.  
  740.   Make_BBox( New->BBox, -1.0,  -1.0,       -Small_Tolerance,
  741.                          2.0,   2.0,  2.0 * Small_Tolerance );
  742.  
  743.   return (New);
  744.   #endif
  745. }
  746.  
  747.  
  748.  
  749. /*****************************************************************************
  750. *
  751. * FUNCTION
  752. *
  753. *   Copy_Disc
  754. *
  755. * INPUT
  756. *
  757. * OUTPUT
  758. *
  759. * RETURNS
  760. *
  761. * AUTHOR
  762. *
  763. *   Alexander Enzmann
  764. *
  765. * DESCRIPTION
  766. *
  767. *   -
  768. *
  769. * CHANGES
  770. *
  771. *   Sep 1994 : Fixed memory leakage [DB]
  772. *
  773. ******************************************************************************/
  774.  
  775. static DISC *Copy_Disc (OBJECT *Object)
  776. {
  777. #ifndef FastDiscPatch
  778.   DISC *New;
  779.  
  780.   New  = Create_Disc();
  781.  
  782.   /* Get rid of the transformation created in Create_Disc(). */
  783.  
  784.   Destroy_Transform(New->Trans);
  785.  
  786.   /* Copy disc. */
  787.  
  788.   *New = *((DISC *) Object);
  789.  
  790.   New->Trans = Copy_Transform(((DISC *)Object)->Trans);
  791.  
  792.   return (New);
  793. #else
  794.   DISC *New;
  795.  
  796.   New  = Create_Disc();
  797.  
  798.   /* Copy disc. */
  799.  
  800.   *New = *((DISC *) Object);
  801.  
  802.   return (New);
  803.  
  804. #endif
  805. }
  806.  
  807.  
  808.  
  809. /*****************************************************************************
  810. *
  811. * FUNCTION
  812. *
  813. *   Destroy_Disc
  814. *
  815. * INPUT
  816. *
  817. * OUTPUT
  818. *
  819. * RETURNS
  820. *
  821. * AUTHOR
  822. *
  823. *   Alexander Enzmann
  824. *
  825. * DESCRIPTION
  826. *
  827. *   -
  828. *
  829. * CHANGES
  830. *
  831. *   -
  832. *
  833. ******************************************************************************/
  834.  
  835. static void Destroy_Disc (OBJECT *Object)
  836. {
  837. #ifndef FastDiscPatch
  838.   Destroy_Transform(((DISC *)Object)->Trans);
  839. #endif
  840.   POV_FREE (Object);
  841. }
  842.  
  843.  
  844.  
  845. /*****************************************************************************
  846. *
  847. * FUNCTION
  848. *
  849. *   Compute_Disc
  850. *
  851. * INPUT
  852. *
  853. *   Disc - Disc
  854. *
  855. * OUTPUT
  856. *
  857. *   Disc
  858. *
  859. * RETURNS
  860. *
  861. * AUTHOR
  862. *
  863. *   Dieter Bayer
  864. *
  865. * DESCRIPTION
  866. *
  867. *   Calculate the transformation that scales, rotates, and translates
  868. *   the disc to the desired location and orientation.
  869. *
  870. * CHANGES
  871. *
  872. *   Aug 1994 : Creation.
  873. *
  874. ******************************************************************************/
  875.  
  876. #ifndef FastDiscPatch
  877. void Compute_Disc(DISC *Disc)
  878. {
  879.   Compute_Coordinate_Transform(Disc->Trans, Disc->center, Disc->normal, 1.0, 1.0);
  880.  
  881.   Compute_Disc_BBox(Disc);
  882. #else
  883. void Compute_Disc(DISC *Disc, VECTOR center, VECTOR normal, DBL inner_radius, DBL outer_radius )
  884. {
  885.   DBL t;
  886.   VECTOR _normal;
  887.   TRANSFORM Trans;
  888.  
  889.   if( outer_radius < inner_radius  )
  890.    {
  891.     t = inner_radius; inner_radius = outer_radius; outer_radius = t;
  892.    }
  893.  
  894.   Disc->iradius2 = inner_radius / outer_radius;
  895.   Disc->iradius2 *= Disc->iradius2;
  896.  
  897.   VNormalize( _normal, normal );
  898.  
  899.   Compute_Coordinate_Transform( &Trans, center, _normal, outer_radius, 1.0 );
  900.  
  901.   Transform_Disc( (OBJECT *)Disc, &Trans );
  902.  
  903.   Compute_Disc_BBox(Disc);
  904. #endif
  905. }
  906.  
  907.  
  908.  
  909. /*****************************************************************************
  910. *
  911. * FUNCTION
  912. *
  913. *   Compute_Disc_BBox
  914. *
  915. * INPUT
  916. *
  917. *   Disc - Disc
  918. *
  919. * OUTPUT
  920. *
  921. *   Disc
  922. *
  923. * RETURNS
  924. *
  925. * AUTHOR
  926. *
  927. *   Dieter Bayer
  928. *
  929. * DESCRIPTION
  930. *
  931. *   Calculate the bounding box of a disc.
  932. *
  933. * CHANGES
  934. *
  935. *   Aug 1994 : Creation.
  936. *
  937. ******************************************************************************/
  938.  
  939. static void Compute_Disc_BBox(DISC *Disc)
  940. {
  941. #ifndef FastDiscPatch
  942.   DBL rad;
  943.  
  944.   rad = sqrt(Disc->oradius2);
  945.  
  946.   Make_BBox(Disc->BBox, -rad, -rad, -Small_Tolerance, 2.0*rad, 2.0*rad, 2.0*Small_Tolerance);
  947.  
  948.   Recompute_BBox(&Disc->BBox, Disc->Trans);
  949. #else
  950.   int i,j, k;
  951.   VECTOR lo, hi, v;
  952.   VECTOR  z_axis;
  953.  
  954.  
  955.   VScale( z_axis, Disc->normal, Small_Tolerance );
  956.  
  957.   Assign_Vector( lo, Disc->center );
  958.   Assign_Vector( hi, Disc->center );
  959.  
  960.   for( k = -1; k < 2; k += 2 )
  961.    for( j = -1; j < 2; j += 2 )
  962.     for( i = -1; i < 2; i += 2 )
  963.      {
  964.       VLinComb3( v, i, Disc->x_axis, j, Disc->y_axis, k, z_axis );
  965.       VAddEq( v, Disc->center );
  966.       lo[ X ] = min( lo[ X ], v[ X ] );  hi[ X ] = max( hi[ X ], v[ X ] );
  967.       lo[ Y ] = min( lo[ Y ], v[ Y ] );  hi[ Y ] = max( hi[ Y ], v[ Y ] );
  968.       lo[ Z ] = min( lo[ Z ], v[ Z ] );  hi[ Z ] = max( hi[ Z ], v[ Z ] );
  969.      }
  970.  
  971.   Make_BBox_from_min_max( Disc->BBox, lo, hi );
  972. #endif
  973. }
  974.  
  975.