home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: Graphics / Graphics.zip / povsrc31.zip / cones.c < prev    next >
C/C++ Source or Header  |  2000-04-13  |  19KB  |  1,033 lines

  1. /****************************************************************************
  2. *                cones.c
  3. *
  4. *  This module implements the cone primitive.
  5. *  This file was written by Alexander Enzmann.    He wrote the code for
  6. *  cones 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 "cones.h"
  32. #include "matrices.h"
  33. #include "objects.h"
  34.  
  35.  
  36.  
  37. /*****************************************************************************
  38. * Local preprocessor defines
  39. ******************************************************************************/
  40.  
  41. #define Cone_Tolerance 1.0e-6
  42.  
  43. #define close(x, y) (fabs(x-y) < EPSILON ? 1 : 0)
  44.  
  45. /* Part of the cone/cylinder hit. [DB 9/94] */
  46.  
  47. #define BASE_HIT 1
  48. #define CAP_HIT  2
  49. #define SIDE_HIT 3
  50.  
  51.  
  52.  
  53. /*****************************************************************************
  54. * Local typedefs
  55. ******************************************************************************/
  56.  
  57. typedef struct Cone_Intersection_Structure CONE_INT;
  58.  
  59. struct Cone_Intersection_Structure
  60. {
  61.   DBL d;  /* Distance of intersection point               */
  62.   int t;  /* Type of intersection: base/cap plane or side */
  63. };
  64.  
  65.  
  66.  
  67. /*****************************************************************************
  68. * Static functions
  69. ******************************************************************************/
  70.  
  71. static int intersect_cone (RAY *Ray, CONE *Cone, CONE_INT *Depths);
  72. static void Destroy_Cone (OBJECT *Object);
  73. static int All_Cone_Intersections (OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack);
  74. static int Inside_Cone (VECTOR point, OBJECT *Object);
  75. static void Cone_Normal (VECTOR Result, OBJECT *Object, INTERSECTION *Inter);
  76. static CONE *Copy_Cone (OBJECT *Object);
  77. static void Translate_Cone (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
  78. static void Rotate_Cone (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
  79. static void Scale_Cone (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans);
  80. static void Transform_Cone (OBJECT *Object, TRANSFORM *Trans);
  81. static void Invert_Cone (OBJECT *Object);
  82.  
  83.  
  84. /*****************************************************************************
  85. * Local variables
  86. ******************************************************************************/
  87.  
  88. static METHODS Cone_Methods =
  89. {
  90.   All_Cone_Intersections,
  91.   Inside_Cone, Cone_Normal, Default_UVCoord,
  92.   (COPY_METHOD)Copy_Cone, Translate_Cone, Rotate_Cone, Scale_Cone, Transform_Cone,
  93.   Invert_Cone, Destroy_Cone
  94. };
  95.  
  96.  
  97.  
  98. /*****************************************************************************
  99. *
  100. * FUNCTION
  101. *
  102. *   All_Cone_Intersections
  103. *
  104. * INPUT
  105. *   
  106. * OUTPUT
  107. *   
  108. * RETURNS
  109. *   
  110. * AUTHOR
  111. *
  112. *   Alexander Enzmann
  113. *   
  114. * DESCRIPTION
  115. *
  116. *   -
  117. *
  118. * CHANGES
  119. *
  120. *   -
  121. *
  122. ******************************************************************************/
  123.  
  124. static int All_Cone_Intersections(OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack)
  125. {
  126.   int Intersection_Found, cnt, i;
  127.   VECTOR IPoint;
  128.   CONE_INT I[4];
  129.  
  130.   Intersection_Found = FALSE;
  131.  
  132.   if ((cnt = intersect_cone(Ray, (CONE *)Object, I)) != 0)
  133.   {
  134.     for (i = 0; i < cnt; i++)
  135.     {
  136.       VEvaluateRay(IPoint, Ray->Initial, I[i].d, Ray->Direction);
  137.  
  138.       if (Point_In_Clip(IPoint, Object->Clip))
  139.       {
  140.         push_entry_i1(I[i].d,IPoint,Object,I[i].t,Depth_Stack);
  141.  
  142.         Intersection_Found = TRUE;
  143.       }
  144.     }
  145.   }
  146.  
  147.   return (Intersection_Found);
  148. }
  149.  
  150.  
  151.  
  152. /*****************************************************************************
  153. *
  154. * FUNCTION
  155. *
  156. *   intersect_cone
  157. *
  158. * INPUT
  159. *   
  160. * OUTPUT
  161. *   
  162. * RETURNS
  163. *   
  164. * AUTHOR
  165. *
  166. *   Alexander Enzmann
  167. *   
  168. * DESCRIPTION
  169. *
  170. *   -
  171. *
  172. * CHANGES
  173. *
  174. *   -
  175. *
  176. ******************************************************************************/
  177.  
  178. static int intersect_cone(RAY *Ray, CONE *Cone, CONE_INT *Intersection)
  179. {
  180.   int i = 0;
  181.   DBL a, b, c, z, t1, t2, len;
  182.   DBL d;
  183.   VECTOR P, D;
  184.  
  185.   Increase_Counter(stats[Ray_Cone_Tests]);
  186.  
  187.   /* Transform the ray into the cones space */
  188.  
  189.   MInvTransPoint(P, Ray->Initial, Cone->Trans);
  190.   MInvTransDirection(D, Ray->Direction, Cone->Trans);
  191.  
  192.   VLength(len, D);
  193.   VInverseScaleEq(D, len);
  194.  
  195.   if (Test_Flag(Cone, CYLINDER_FLAG))
  196.   {
  197.     /* Solve intersections with a cylinder */
  198.  
  199.     a = D[X] * D[X] + D[Y] * D[Y];
  200.  
  201.     if (a > EPSILON)
  202.     {
  203.       b = P[X] * D[X] + P[Y] * D[Y];
  204.  
  205.       c = P[X] * P[X] + P[Y] * P[Y] - 1.0;
  206.  
  207.       d = b * b - a * c;
  208.  
  209.       if (d >= 0.0)
  210.       {
  211.         d = sqrt(d);
  212.  
  213.         t1 = (-b + d) / a;
  214.         t2 = (-b - d) / a;
  215.  
  216.         z = P[Z] + t1 * D[Z];
  217.  
  218.         if ((t1 > Cone_Tolerance) && (t1 < Max_Distance) && (z >= 0.0) && (z <= 1.0))
  219.         {
  220.           Intersection[i].d   = t1 / len;
  221.           Intersection[i++].t = SIDE_HIT;
  222.         }
  223.  
  224.         z = P[Z] + t2 * D[Z];
  225.  
  226.         if ((t2 > Cone_Tolerance) && (t1 < Max_Distance) && (z >= 0.0) && (z <= 1.0))
  227.         {
  228.           Intersection[i].d   = t2 / len;
  229.           Intersection[i++].t = SIDE_HIT;
  230.         }
  231.       }
  232.     }
  233.   }
  234.   else
  235.   {
  236.     /* Solve intersections with a cone */
  237.  
  238.     a = D[X] * D[X] + D[Y] * D[Y] - D[Z] * D[Z];
  239.  
  240.     b = D[X] * P[X] + D[Y] * P[Y] - D[Z] * P[Z];
  241.  
  242.     c = P[X] * P[X] + P[Y] * P[Y] - P[Z] * P[Z];
  243.  
  244.     if (fabs(a) < EPSILON)
  245.     {
  246.       if (fabs(b) > EPSILON)
  247.       {
  248.         /* One intersection */
  249.  
  250.         t1 = -0.5 * c / b;
  251.  
  252.         z = P[Z] + t1 * D[Z];
  253.  
  254.         if ((t1 > Cone_Tolerance) && (t1 < Max_Distance) && (z >= Cone->dist) && (z <= 1.0))
  255.         {
  256.           Intersection[i].d   = t1 / len;
  257.           Intersection[i++].t = SIDE_HIT;
  258.         }
  259.       }
  260.     }
  261.     else
  262.     {
  263.       /* Check hits against the side of the cone */
  264.  
  265.       d = b * b - a * c;
  266.  
  267.       if (d >= 0.0)
  268.       {
  269.         d = sqrt(d);
  270.  
  271.         t1 = (-b - d) / a;
  272.         t2 = (-b + d) / a;
  273.  
  274.         z = P[Z] + t1 * D[Z];
  275.  
  276.         if ((t1 > Cone_Tolerance) && (t1 < Max_Distance) && (z >= Cone->dist) && (z <= 1.0))
  277.         {
  278.           Intersection[i].d   = t1 / len;
  279.           Intersection[i++].t = SIDE_HIT;
  280.         }
  281.  
  282.         z = P[Z] + t2 * D[Z];
  283.  
  284.         if ((t2 > Cone_Tolerance) && (t1 < Max_Distance) && (z >= Cone->dist) && (z <= 1.0))
  285.         {
  286.           Intersection[i].d   = t2 / len;
  287.           Intersection[i++].t = SIDE_HIT;
  288.         }
  289.       }
  290.     }
  291.   }
  292.  
  293.   if (Test_Flag(Cone, CLOSED_FLAG) && (fabs(D[Z]) > EPSILON))
  294.   {
  295.     d = (1.0 - P[Z]) / D[Z];
  296.  
  297.     a = (P[X] + d * D[X]);
  298.  
  299.     b = (P[Y] + d * D[Y]);
  300.  
  301.     if (((Sqr(a) + Sqr(b)) <= 1.0) && (d > Cone_Tolerance) && (d < Max_Distance))
  302.     {
  303.       Intersection[i].d   = d / len;
  304.       Intersection[i++].t = CAP_HIT;
  305.     }
  306.  
  307.     d = (Cone->dist - P[Z]) / D[Z];
  308.  
  309.     a = (P[X] + d * D[X]);
  310.  
  311.     b = (P[Y] + d * D[Y]);
  312.  
  313.     if ((Sqr(a) + Sqr(b)) <= (Test_Flag(Cone, CYLINDER_FLAG) ? 1.0 : Sqr(Cone->dist))
  314.       && (d > Cone_Tolerance) && (d < Max_Distance))
  315.     {
  316.       Intersection[i].d   = d / len;
  317.       Intersection[i++].t = BASE_HIT;
  318.     }
  319.   }
  320.  
  321.   if (i)
  322.   {
  323.     Increase_Counter(stats[Ray_Cone_Tests_Succeeded]);
  324.   }
  325.  
  326.   return (i);
  327. }
  328.  
  329.  
  330.  
  331. /*****************************************************************************
  332. *
  333. * FUNCTION
  334. *
  335. *   Inside_Cone
  336. *
  337. * INPUT
  338. *   
  339. * OUTPUT
  340. *   
  341. * RETURNS
  342. *   
  343. * AUTHOR
  344. *
  345. *   Alexander Enzmann
  346. *   
  347. * DESCRIPTION
  348. *
  349. *   -
  350. *
  351. * CHANGES
  352. *
  353. *   -
  354. *
  355. ******************************************************************************/
  356.  
  357. static int Inside_Cone(VECTOR IPoint, OBJECT *Object)
  358. {
  359.   CONE *Cone = (CONE *)Object;
  360.   DBL w2, z2, offset = (Test_Flag(Cone, CLOSED_FLAG) ? -EPSILON : EPSILON);
  361.   VECTOR New_Point;
  362.  
  363.   /* Transform the point into the cones space */
  364.  
  365.   MInvTransPoint(New_Point, IPoint, Cone->Trans);
  366.  
  367.   /* Test to see if we are inside the cone */
  368.  
  369.   w2 = New_Point[X] * New_Point[X] + New_Point[Y] * New_Point[Y];
  370.  
  371.   if (Test_Flag(Cone, CYLINDER_FLAG))
  372.   {
  373.     /* Check to see if we are inside a cylinder */
  374.  
  375.     if ((w2 > 1.0 + offset) ||
  376.         (New_Point[Z] < 0.0 - offset) ||
  377.         (New_Point[Z] > 1.0 + offset))
  378.     {
  379.       return (Test_Flag(Cone, INVERTED_FLAG));
  380.     }
  381.     else
  382.     {
  383.       return (!Test_Flag(Cone, INVERTED_FLAG));
  384.     }
  385.   }
  386.   else
  387.   {
  388.     /* Check to see if we are inside a cone */
  389.  
  390.     z2 = New_Point[Z] * New_Point[Z];
  391.  
  392.     if ((w2 > z2 + offset) ||
  393.         (New_Point[Z] < Cone->dist - offset) ||
  394.         (New_Point[Z] > 1.0+offset))
  395.     {
  396.       return (Test_Flag(Cone, INVERTED_FLAG));
  397.     }
  398.     else
  399.     {
  400.       return (!Test_Flag(Cone, INVERTED_FLAG));
  401.     }
  402.   }
  403. }
  404.  
  405.  
  406.  
  407. /*****************************************************************************
  408. *
  409. * FUNCTION
  410. *
  411. *   Cone_Normal
  412. *
  413. * INPUT
  414. *
  415. * OUTPUT
  416. *
  417. * RETURNS
  418. *
  419. * AUTHOR
  420. *
  421. *   Alexander Enzmann
  422. *
  423. * DESCRIPTION
  424. *
  425. *   -
  426. *
  427. * CHANGES
  428. *
  429. *   -
  430. *
  431. ******************************************************************************/
  432.  
  433. static void Cone_Normal(VECTOR Result, OBJECT *Object, INTERSECTION *Inter)
  434. {
  435.   CONE *Cone = (CONE *)Object;
  436.  
  437.   /* Transform the point into the cones space */
  438.  
  439.   MInvTransPoint(Result, Inter->IPoint, Cone->Trans);
  440.  
  441.   /* Calculating the normal is real simple in canonical cone space */
  442.  
  443.   switch (Inter->i1)
  444.   {
  445.     case SIDE_HIT:
  446.  
  447.       if (Test_Flag(Cone, CYLINDER_FLAG))
  448.       {
  449.         Result[Z] = 0.0;
  450.       }
  451.       else
  452.       {
  453.         Result[Z] = -Result[Z];
  454.       }
  455.  
  456.       break;
  457.  
  458.     case BASE_HIT:
  459.  
  460.       Make_Vector(Result, 0.0, 0.0, -1.0)
  461.  
  462.       break;
  463.  
  464.     case CAP_HIT:
  465.  
  466.       Make_Vector(Result, 0.0, 0.0, 1.0)
  467.  
  468.       break;
  469.   }
  470.  
  471.   /* Transform the point out of the cones space */
  472.  
  473.   MTransNormal(Result, Result, Cone->Trans);
  474.  
  475.   VNormalize(Result, Result);
  476. }
  477.  
  478.  
  479.  
  480. /*****************************************************************************
  481. *
  482. * FUNCTION
  483. *
  484. *   Translate_Cone
  485. *
  486. * INPUT
  487. *
  488. * OUTPUT
  489. *
  490. * RETURNS
  491. *
  492. * AUTHOR
  493. *
  494. *   Alexander Enzmann
  495. *
  496. * DESCRIPTION
  497. *
  498. *   -
  499. *
  500. * CHANGES
  501. *
  502. *   -
  503. *
  504. ******************************************************************************/
  505.  
  506. static void Translate_Cone(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
  507. {
  508.   Transform_Cone(Object, Trans);
  509. }
  510.  
  511.  
  512.  
  513. /*****************************************************************************
  514. *
  515. * FUNCTION
  516. *
  517. *   Rotate_Cone
  518. *
  519. * INPUT
  520. *
  521. * OUTPUT
  522. *
  523. * RETURNS
  524. *
  525. * AUTHOR
  526. *
  527. *   Alexander Enzmann
  528. *
  529. * DESCRIPTION
  530. *
  531. *   -
  532. *
  533. * CHANGES
  534. *
  535. *   -
  536. *
  537. ******************************************************************************/
  538.  
  539. static void Rotate_Cone(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
  540. {
  541.   Transform_Cone(Object, Trans);
  542. }
  543.  
  544.  
  545.  
  546. /*****************************************************************************
  547. *
  548. * FUNCTION
  549. *
  550. *   Scale_Cone
  551. *
  552. * INPUT
  553. *
  554. * OUTPUT
  555. *
  556. * RETURNS
  557. *
  558. * AUTHOR
  559. *
  560. *   Alexander Enzmann
  561. *
  562. * DESCRIPTION
  563. *
  564. *   -
  565. *
  566. * CHANGES
  567. *
  568. *   -
  569. *
  570. ******************************************************************************/
  571.  
  572. static void Scale_Cone(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
  573. {
  574.   Transform_Cone(Object, Trans);
  575. }
  576.  
  577.  
  578.  
  579. /*****************************************************************************
  580. *
  581. * FUNCTION
  582. *
  583. *   Transform_Cone
  584. *
  585. * INPUT
  586. *
  587. * OUTPUT
  588. *
  589. * RETURNS
  590. *
  591. * AUTHOR
  592. *
  593. *   Alexander Enzmann
  594. *
  595. * DESCRIPTION
  596. *
  597. *   -
  598. *
  599. * CHANGES
  600. *
  601. *   -
  602. *
  603. ******************************************************************************/
  604.  
  605. static void Transform_Cone(OBJECT *Object, TRANSFORM *Trans)
  606. {
  607.   CONE *Cone = (CONE *)Object;
  608.  
  609.   Compose_Transforms(Cone->Trans, Trans);
  610.  
  611.   Compute_Cone_BBox(Cone);
  612. }
  613.  
  614.  
  615.  
  616. /*****************************************************************************
  617. *
  618. * FUNCTION
  619. *
  620. *   Invert_Cone
  621. *
  622. * INPUT
  623. *
  624. * OUTPUT
  625. *
  626. * RETURNS
  627. *
  628. * AUTHOR
  629. *
  630. *   Alexander Enzmann
  631. *
  632. * DESCRIPTION
  633. *
  634. *   -
  635. *
  636. * CHANGES
  637. *
  638. *   -
  639. *
  640. ******************************************************************************/
  641.  
  642. static void Invert_Cone(OBJECT *Object)
  643. {
  644.   Invert_Flag(Object, INVERTED_FLAG);
  645. }
  646.  
  647.  
  648.  
  649. /*****************************************************************************
  650. *
  651. * FUNCTION
  652. *
  653. *   Create_Cone
  654. *
  655. * INPUT
  656. *
  657. * OUTPUT
  658. *
  659. * RETURNS
  660. *
  661. * AUTHOR
  662. *
  663. *   Alexander Enzmann
  664. *
  665. * DESCRIPTION
  666. *
  667. *   -
  668. *
  669. * CHANGES
  670. *
  671. *   -
  672. *
  673. ******************************************************************************/
  674.  
  675. CONE *Create_Cone()
  676. {
  677.   CONE *New;
  678.  
  679.   New = (CONE *)POV_MALLOC(sizeof(CONE), "cone");
  680.  
  681.   INIT_OBJECT_FIELDS(New, CONE_OBJECT, &Cone_Methods)
  682.  
  683.   Make_Vector(New->apex, 0.0, 0.0, 1.0);
  684.   Make_Vector(New->base, 0.0, 0.0, 0.0);
  685.  
  686.   New->apex_radius = 1.0;
  687.   New->base_radius = 0.0;
  688.  
  689.   New->dist = 0.0;
  690.  
  691.   New->Trans = Create_Transform();
  692.  
  693.   /* Cone/Cylinder has capped ends by default. */
  694.  
  695.   Set_Flag(New, CLOSED_FLAG);
  696.  
  697.   /* Default bounds */
  698.  
  699.   Make_BBox(New->BBox, -1.0, -1.0, 0.0, 2.0, 2.0, 1.0);
  700.  
  701.   return (New);
  702. }
  703.  
  704.  
  705.  
  706. /*****************************************************************************
  707. *
  708. * FUNCTION
  709. *
  710. *   Copy_Cone
  711. *
  712. * INPUT
  713. *
  714. * OUTPUT
  715. *
  716. * RETURNS
  717. *
  718. * AUTHOR
  719. *
  720. *   Alexander Enzmann
  721. *
  722. * DESCRIPTION
  723. *
  724. *   -
  725. *
  726. * CHANGES
  727. *
  728. *   -
  729. *
  730. ******************************************************************************/
  731.  
  732. static CONE *Copy_Cone(OBJECT *Object)
  733. {
  734.   CONE *New;
  735.  
  736.   New = Create_Cone();
  737.  
  738.   /* Get rid of the transformation created in Create_Cone(). */
  739.  
  740.   Destroy_Transform(New->Trans);
  741.  
  742.   /* Copy cone. */
  743.  
  744.   *New = *((CONE *)Object);
  745.  
  746.   New->Trans = Copy_Transform(((CONE *)Object)->Trans);
  747.  
  748.   return (New);
  749. }
  750.  
  751.  
  752.  
  753. /*****************************************************************************
  754. *
  755. * FUNCTION
  756. *
  757. *   Create_Cylinder
  758. *
  759. * INPUT
  760. *
  761. * OUTPUT
  762. *
  763. * RETURNS
  764. *
  765. * AUTHOR
  766. *
  767. *   Alexander Enzmann
  768. *
  769. * DESCRIPTION
  770. *
  771. *   -
  772. *
  773. * CHANGES
  774. *
  775. *   -
  776. *
  777. ******************************************************************************/
  778.  
  779. CONE *Create_Cylinder()
  780. {
  781.   CONE *New;
  782.  
  783.   New = (CONE *)POV_MALLOC(sizeof(CONE), "cone");
  784.  
  785.   INIT_OBJECT_FIELDS(New, CONE_OBJECT, &Cone_Methods)
  786.  
  787.   Make_Vector(New->apex, 0.0, 0.0, 1.0);
  788.   Make_Vector(New->base, 0.0, 0.0, 0.0);
  789.  
  790.   New->apex_radius = 1.0;
  791.   New->base_radius = 1.0;
  792.   New->dist        = 0.0;
  793.  
  794.   New->Trans = Create_Transform();
  795.  
  796.   Set_Flag(New, CYLINDER_FLAG); /* This is a cylinder. */
  797.   Set_Flag(New, CLOSED_FLAG);   /* Has capped ends.    */
  798.  
  799.   /* Default bounds */
  800.  
  801.   Make_BBox(New->BBox, -1.0, -1.0, 0.0, 2.0, 2.0, 1.0);
  802.  
  803.   return (New);
  804. }
  805.  
  806.  
  807.  
  808. /*****************************************************************************
  809. *
  810. * FUNCTION
  811. *
  812. *   Compute_Cone_Data
  813. *
  814. * INPUT
  815. *
  816. * OUTPUT
  817. *
  818. * RETURNS
  819. *
  820. * AUTHOR
  821. *
  822. *   Alexander Enzmann
  823. *
  824. * DESCRIPTION
  825. *
  826. *   -
  827. *
  828. * CHANGES
  829. *
  830. *   Feb 1996: check for equal sized ends (cylinder) first [AED]
  831. *
  832. ******************************************************************************/
  833.  
  834. void Compute_Cone_Data(OBJECT *Object)
  835. {
  836.   DBL tlen, len, tmpf;
  837.   VECTOR tmpv, axis, origin;
  838.   CONE *Cone = (CONE *)Object;
  839.  
  840.   /* Process the primitive specific information */
  841.  
  842.   if (fabs(Cone->apex_radius - Cone->base_radius) < EPSILON)
  843.   {
  844.     /* What we are dealing with here is really a cylinder */
  845.  
  846.     Set_Flag(Cone, CYLINDER_FLAG);
  847.  
  848.     Compute_Cylinder_Data(Object);
  849.  
  850.     return;
  851.   }
  852.  
  853.   if (Cone->apex_radius < Cone->base_radius)
  854.   {
  855.     /* Want the bigger end at the top */
  856.  
  857.     Assign_Vector(tmpv,Cone->base);
  858.     Assign_Vector(Cone->base,Cone->apex);
  859.     Assign_Vector(Cone->apex,tmpv);
  860.  
  861.     tmpf = Cone->base_radius;
  862.     Cone->base_radius = Cone->apex_radius;
  863.     Cone->apex_radius = tmpf;
  864.   }
  865.  
  866.   /* Find the axis and axis length */
  867.  
  868.   VSub(axis, Cone->apex, Cone->base);
  869.  
  870.   VLength(len, axis);
  871.  
  872.   if (len < EPSILON)
  873.   {
  874.     Error("Degenerate cone/cylinder.\n");
  875.   }
  876.   else
  877.   {
  878.     VInverseScaleEq(axis, len)
  879.   }
  880.  
  881.   /* Determine alignment */
  882.  
  883.   tmpf = Cone->base_radius * len / (Cone->apex_radius - Cone->base_radius);
  884.  
  885.   VScale(origin, axis, tmpf);
  886.  
  887.   VSub(origin, Cone->base, origin);
  888.  
  889.   tlen = tmpf + len;
  890.  
  891.   Cone->dist = tmpf / tlen;
  892.  
  893.   Compute_Coordinate_Transform(Cone->Trans, origin, axis, Cone->apex_radius, tlen);
  894.  
  895.   /* Recalculate the bounds */
  896.  
  897.   Compute_Cone_BBox(Cone);
  898. }
  899.  
  900.  
  901.  
  902. /*****************************************************************************
  903. *
  904. * FUNCTION
  905. *
  906. *   Compute_Cylinder_Data
  907. *
  908. * INPUT
  909. *
  910. * OUTPUT
  911. *
  912. * RETURNS
  913. *
  914. * AUTHOR
  915. *
  916. *   Alexander Enzmann
  917. *
  918. * DESCRIPTION
  919. *
  920. *   -
  921. *
  922. * CHANGES
  923. *
  924. *   -
  925. *
  926. ******************************************************************************/
  927.  
  928. void Compute_Cylinder_Data(OBJECT *Object)
  929. {
  930.   DBL tmpf;
  931.   VECTOR axis;
  932.   CONE *Cone = (CONE *)Object;
  933.  
  934.   VSub(axis, Cone->apex, Cone->base);
  935.  
  936.   VLength(tmpf, axis);
  937.  
  938.   if (tmpf < EPSILON)
  939.   {
  940.     Error("Degenerate cylinder, base point = apex point.\n");
  941.   }
  942.   else
  943.   {
  944.     VInverseScaleEq(axis, tmpf)
  945.  
  946.     Compute_Coordinate_Transform(Cone->Trans, Cone->base, axis, Cone->apex_radius, tmpf);
  947.   }
  948.  
  949.   Cone->dist = 0.0;
  950.  
  951.   /* Recalculate the bounds */
  952.  
  953.   Compute_Cone_BBox(Cone);
  954. }
  955.  
  956.  
  957.  
  958.  
  959. /*****************************************************************************
  960. *
  961. * FUNCTION
  962. *
  963. *   Destroy_Cone
  964. *
  965. * INPUT
  966. *
  967. * OUTPUT
  968. *
  969. * RETURNS
  970. *
  971. * AUTHOR
  972. *
  973. *   Alexander Enzmann
  974. *
  975. * DESCRIPTION
  976. *
  977. *   -
  978. *
  979. * CHANGES
  980. *
  981. *   -
  982. *
  983. ******************************************************************************/
  984.  
  985. static void Destroy_Cone(OBJECT *Object)
  986. {
  987.   Destroy_Transform(((CONE *)Object)->Trans);
  988.  
  989.   POV_FREE (Object);
  990. }
  991.  
  992.  
  993.  
  994. /*****************************************************************************
  995. *
  996. * FUNCTION
  997. *
  998. *   Compute_Cone_BBox
  999. *
  1000. * INPUT
  1001. *
  1002. *   Cone - Cone/Cylinder
  1003. *
  1004. * OUTPUT
  1005. *
  1006. *   Cone
  1007. *
  1008. * RETURNS
  1009. *
  1010. * AUTHOR
  1011. *
  1012. *   Dieter Bayer
  1013. *
  1014. * DESCRIPTION
  1015. *
  1016. *   Calculate the bounding box of a cone or cylinder.
  1017. *
  1018. * CHANGES
  1019. *
  1020. *   Aug 1994 : Creation.
  1021. *
  1022. ******************************************************************************/
  1023.  
  1024. void Compute_Cone_BBox(CONE *Cone)
  1025. {
  1026.   /*cone  bounding fix*/
  1027.   Make_BBox(Cone->BBox, -1.0, -1.0, Cone->dist, 2.0, 2.0, 1.0-Cone->dist);
  1028.   /*Make_BBox(Cone->BBox, -1.0, -1.0, 0.0, 2.0, 2.0, 1.0);*/
  1029.  
  1030.   Recompute_BBox(&Cone->BBox, Cone->Trans);
  1031. }
  1032.  
  1033.