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