home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 2 / crawlyvol2.bin / graphics / ftpovstc / quadrics.c < prev    next >
C/C++ Source or Header  |  1994-05-25  |  18KB  |  603 lines

  1. /****************************************************************************
  2. *
  3. *  ATTENTION!!!
  4. *
  5. *  THIS FILE HAS BEEN MODIFIED!!! IT IS NOT PART OF THE OFFICAL
  6. *  POV-RAY 2.2 DISTRIBUTION!!!
  7. *
  8. *  THIS FILE IS PART OF "FASTER THAN POV-RAY" (VERSION 1.1),
  9. *  A SPED-UP VERSION OF POV-RAY 2.2. USE AT YOUR OWN RISK!!!!!!
  10. *
  11. *  New files: addon0.c, addon1.c, addon2.c, addon3.c, addon.h
  12. *
  13. *  The additional modules were written by Dieter Bayer.
  14. *
  15. *  Send comments, suggestions, bugs, ideas ... to:
  16. *
  17. *  dieter@cip.e-technik.uni-erlangen.de
  18. *
  19. *  All changed/added lines are enclosed in #ifdef DB_CODE ... #endif
  20. *
  21. *  The vista projection was taken from:
  22. *
  23. *    A. Hashimoto, T. Akimoto, K. Mase, and Y. Suenaga, 
  24. *    "Vista Ray-Tracing: High Speed Ray Tracing Using Perspective
  25. *    Projection Image", New Advances in Computer Graphics, Proceedings
  26. *    of CG International '89, R. A. Earnshaw, B. Wyvill (Eds.), 
  27. *    Springer, ..., pp. 549-560
  28. *
  29. *  The idea for the light buffer was taken from:
  30. *
  31. *    E. Haines and D. Greenberg, "The Light Buffer: A Shadow-Testing 
  32. *    Accelerator", IEEE CG&A, Vol. 6, No. 9, Sept. 1986, pp. 6-16
  33. *
  34. *****************************************************************************/
  35.  
  36. /****************************************************************************
  37. *                quadrics.c
  38. *
  39. *  This module implements the code for the quadric shape primitive.
  40. *
  41. *  from Persistence of Vision Raytracer
  42. *  Copyright 1993 Persistence of Vision Team
  43. *---------------------------------------------------------------------------
  44. *  NOTICE: This source code file is provided so that users may experiment
  45. *  with enhancements to POV-Ray and to port the software to platforms other 
  46. *  than those supported by the POV-Ray Team.  There are strict rules under
  47. *  which you are permitted to use this file.  The rules are in the file
  48. *  named POVLEGAL.DOC which should be distributed with this file. If 
  49. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  50. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  51. *  Forum.  The latest version of POV-Ray may be found there as well.
  52. *
  53. * This program is based on the popular DKB raytracer version 2.12.
  54. * DKBTrace was originally written by David K. Buck.
  55. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  56. *
  57. *****************************************************************************/
  58.  
  59. #include "frame.h"
  60. #include "vector.h"
  61. #include "povproto.h"
  62.  
  63. METHODS Quadric_Methods =
  64.   {
  65.   All_Quadric_Intersections,
  66.   Inside_Quadric, Quadric_Normal,
  67.   Copy_Quadric,
  68.   Translate_Quadric, Rotate_Quadric,
  69.   Scale_Quadric, Transform_Quadric, Invert_Quadric,
  70.   Destroy_Quadric
  71. };
  72.  
  73. extern RAY *CM_Ray;
  74. extern long Ray_Quadric_Tests, Ray_Quadric_Tests_Succeeded;
  75.  
  76. int All_Quadric_Intersections (Object, Ray, Depth_Stack)
  77. OBJECT *Object;
  78. RAY *Ray;
  79. ISTACK *Depth_Stack;
  80.   {
  81.   DBL Depth1, Depth2;
  82.   VECTOR IPoint;
  83.   register int Intersection_Found;
  84.  
  85.   Intersection_Found = FALSE;
  86.  
  87.   if (Intersect_Quadric (Ray, (QUADRIC *) Object, &Depth1, &Depth2))
  88.     {
  89.     VScale (IPoint, Ray->Direction, Depth1);
  90.     VAddEq (IPoint, Ray->Initial);
  91.  
  92.     if (Point_In_Clip (&IPoint, Object->Clip))
  93.       {
  94.       push_entry(Depth1,IPoint,Object,Depth_Stack);
  95.       Intersection_Found = TRUE;
  96.       }
  97.  
  98.     if (Depth2 != Depth1)
  99.       {
  100.       VScale (IPoint, Ray->Direction, Depth2);
  101.       VAddEq (IPoint, Ray->Initial);
  102.  
  103.       if (Point_In_Clip (&IPoint, Object->Clip))
  104.     {
  105.     push_entry(Depth2,IPoint,Object,Depth_Stack);
  106.     Intersection_Found = TRUE;
  107.     }
  108.       }
  109.     }
  110.   return (Intersection_Found);
  111.   }
  112.  
  113. #ifdef DB_CODE
  114. /* Some things have been optimized. */
  115. /*****************************************************************************
  116.    The term VDot(Quadric->Mixed_Terms, Ray->Mixed_Initial_Initial)
  117.    is added to the cached constant CM_Constant. Thus 3 MUL and 3 ADD
  118.    are saved for primary rays.
  119.    The calculation of the coefficients of the quadratic equation
  120.    is rewritten to save 3 MUL.
  121.  *****************************************************************************/
  122. int Intersect_Quadric (Ray, Quadric, Depth1, Depth2)
  123. RAY *Ray;
  124. QUADRIC *Quadric;
  125. DBL *Depth1, *Depth2;
  126. {
  127.   register DBL Square_Term, Linear_Term, Constant_Term;
  128.   register DBL Determinant;
  129.  
  130.   Ray_Quadric_Tests++;
  131.  
  132.   if (!Ray->Quadric_Constants_Cached)
  133.     Make_Ray(Ray);
  134.  
  135.   if (Quadric->Non_Zero_Square_Term)
  136.   {
  137.     Square_Term = Quadric->Square_Terms.x * Ray->Direction_2.x +
  138.           Quadric->Square_Terms.y * Ray->Direction_2.y +
  139.           Quadric->Square_Terms.z * Ray->Direction_2.z +
  140.           Quadric->Mixed_Terms.x * Ray->Mixed_Dir_Dir.x +
  141.           Quadric->Mixed_Terms.y * Ray->Mixed_Dir_Dir.y +
  142.           Quadric->Mixed_Terms.z * Ray->Mixed_Dir_Dir.z;
  143.   }
  144.   else
  145.   {
  146.     Square_Term = 0.0;
  147.   }
  148.  
  149.   Linear_Term = Quadric->Square_Terms.x * Ray->Initial_Direction.x +
  150.         Quadric->Square_Terms.y * Ray->Initial_Direction.y +
  151.         Quadric->Square_Terms.z * Ray->Initial_Direction.z +
  152.         0.5 * (Quadric->Terms.x * Ray->Direction.x +
  153.                Quadric->Terms.y * Ray->Direction.y +
  154.                Quadric->Terms.z * Ray->Direction.z +
  155.                Quadric->Mixed_Terms.x * Ray->Mixed_Init_Dir.x +
  156.                Quadric->Mixed_Terms.y * Ray->Mixed_Init_Dir.y +
  157.                Quadric->Mixed_Terms.z * Ray->Mixed_Init_Dir.z);
  158.  
  159.   if (Ray == CM_Ray)
  160.   {
  161.     if (!Quadric->Constant_Cached)
  162.     {
  163.       Constant_Term = Quadric->Square_Terms.x * Ray->Initial_2.x +
  164.               Quadric->Square_Terms.y * Ray->Initial_2.y +
  165.               Quadric->Square_Terms.z * Ray->Initial_2.z +
  166.               Quadric->Terms.x * Ray->Initial.x +
  167.               Quadric->Terms.y * Ray->Initial.y +
  168.               Quadric->Terms.z * Ray->Initial.z +
  169.               Quadric->Mixed_Terms.x * Ray->Mixed_Initial_Initial.x +
  170.               Quadric->Mixed_Terms.y * Ray->Mixed_Initial_Initial.y +
  171.               Quadric->Mixed_Terms.z * Ray->Mixed_Initial_Initial.z +
  172.               Quadric->Constant;
  173.       Quadric->CM_Constant = Constant_Term;
  174.       Quadric->Constant_Cached = TRUE;
  175.     }
  176.     else
  177.     {
  178.       Constant_Term = Quadric->CM_Constant;
  179.     }
  180.   }
  181.   else
  182.   {
  183.     Constant_Term = Quadric->Square_Terms.x * Ray->Initial_2.x +
  184.             Quadric->Square_Terms.y * Ray->Initial_2.y +
  185.             Quadric->Square_Terms.z * Ray->Initial_2.z +
  186.             Quadric->Terms.x * Ray->Initial.x +
  187.             Quadric->Terms.y * Ray->Initial.y +
  188.             Quadric->Terms.z * Ray->Initial.z +
  189.             Quadric->Mixed_Terms.x * Ray->Mixed_Initial_Initial.x +
  190.             Quadric->Mixed_Terms.y * Ray->Mixed_Initial_Initial.y +
  191.             Quadric->Mixed_Terms.z * Ray->Mixed_Initial_Initial.z +
  192.             Quadric->Constant;
  193.   }
  194.  
  195.   if (Square_Term != 0.0)
  196.   {
  197.     /* The equation is quadratic - find its roots */
  198.  
  199.     Determinant = Linear_Term * Linear_Term - Square_Term * Constant_Term;
  200.  
  201.     if (Determinant < 0.0)
  202.       return (FALSE);
  203.  
  204.     Determinant = sqrt (Determinant);
  205.  
  206.     *Depth1 = (-Linear_Term + Determinant) / Square_Term;
  207.     *Depth2 = (-Linear_Term - Determinant) / Square_Term;
  208.   }
  209.   else
  210.   {
  211.     /* There are no quadratic terms.  Solve the linear equation instead. */
  212.     if (Linear_Term == 0.0)
  213.       return (FALSE);
  214.  
  215.     *Depth1 = -2.0 * Constant_Term / Linear_Term;
  216.     *Depth2 = *Depth1;
  217.   }
  218.  
  219.   if ((*Depth1 < Small_Tolerance) || (*Depth1 > Max_Distance))
  220.     if ((*Depth2 < Small_Tolerance) || (*Depth2 > Max_Distance))
  221.       return (FALSE);
  222.     else
  223.       *Depth1 = *Depth2;
  224.   else
  225.     if ((*Depth2 < Small_Tolerance) || (*Depth2 > Max_Distance))
  226.       *Depth2 = *Depth1;
  227.  
  228.   Ray_Quadric_Tests_Succeeded++;
  229.   return (TRUE);
  230. }
  231. #else
  232. int Intersect_Quadric (Ray, Quadric, Depth1, Depth2)
  233. RAY *Ray;
  234. QUADRIC *Quadric;
  235. DBL *Depth1, *Depth2;
  236.   {
  237.   register DBL Square_Term, Linear_Term, Constant_Term, Temp_Term;
  238.   register DBL Determinant, Determinant_2, A2, BMinus;
  239.  
  240.   Ray_Quadric_Tests++;
  241.   if (!Ray->Quadric_Constants_Cached)
  242.     Make_Ray(Ray);
  243.  
  244.   if (Quadric->Non_Zero_Square_Term)
  245.     {
  246.     VDot (Square_Term, Quadric->Square_Terms, Ray->Direction_2);
  247.     VDot (Temp_Term, Quadric->Mixed_Terms, Ray->Mixed_Dir_Dir);
  248.     Square_Term += Temp_Term;
  249.     }
  250.   else
  251.     Square_Term = 0.0;
  252.  
  253.   VDot (Linear_Term, Quadric->Square_Terms, Ray->Initial_Direction);
  254.   Linear_Term *= 2.0;
  255.   VDot (Temp_Term, Quadric->Terms, Ray->Direction);
  256.   Linear_Term += Temp_Term;
  257.   VDot (Temp_Term, Quadric->Mixed_Terms, Ray->Mixed_Init_Dir);
  258.   Linear_Term += Temp_Term;
  259.  
  260.   if (Ray == CM_Ray)
  261.     if (!Quadric->Constant_Cached)
  262.       {
  263.       VDot (Constant_Term, Quadric->Square_Terms, Ray->Initial_2);
  264.       VDot (Temp_Term, Quadric->Terms, Ray->Initial);
  265.       Constant_Term +=  Temp_Term + Quadric->Constant;
  266.       Quadric->CM_Constant = Constant_Term;
  267.       Quadric->Constant_Cached = TRUE;
  268.       }
  269.     else
  270.       Constant_Term = Quadric->CM_Constant;
  271.   else
  272.     {
  273.     VDot (Constant_Term, Quadric->Square_Terms, Ray->Initial_2);
  274.     VDot (Temp_Term, Quadric->Terms, Ray->Initial);
  275.     Constant_Term += Temp_Term + Quadric->Constant;
  276.     }
  277.  
  278.   VDot (Temp_Term, Quadric->Mixed_Terms, 
  279.     Ray->Mixed_Initial_Initial);
  280.   Constant_Term += Temp_Term;
  281.  
  282.   if (Square_Term != 0.0)
  283.     {
  284.     /* The equation is quadratic - find its roots */
  285.  
  286.     Determinant_2 = Linear_Term * Linear_Term - 4.0 * Square_Term * Constant_Term;
  287.  
  288.     if (Determinant_2 < 0.0)
  289.       return (FALSE);
  290.  
  291.     Determinant = sqrt (Determinant_2);
  292.     A2 = Square_Term * 2.0;
  293.     BMinus = Linear_Term * -1.0;
  294.  
  295.     *Depth1 = (BMinus + Determinant) / A2;
  296.     *Depth2 = (BMinus - Determinant) / A2;
  297.     }
  298.   else
  299.     {
  300.     /* There are no quadratic terms.  Solve the linear equation instead. */
  301.     if (Linear_Term == 0.0)
  302.       return (FALSE);
  303.  
  304.     *Depth1 = Constant_Term * -1.0 / Linear_Term;
  305.     *Depth2 = *Depth1;
  306.     }
  307.  
  308.   if ((*Depth1 < Small_Tolerance) || (*Depth1 > Max_Distance))
  309.     if ((*Depth2 < Small_Tolerance) || (*Depth2 > Max_Distance))
  310.       return (FALSE);
  311.     else
  312.       *Depth1 = *Depth2;
  313.   else
  314.     if ((*Depth2 < Small_Tolerance) || (*Depth2 > Max_Distance))
  315.       *Depth2 = *Depth1;
  316.  
  317.   Ray_Quadric_Tests_Succeeded++;
  318.   return (TRUE);
  319.   }
  320. #endif
  321.  
  322. #ifdef DB_CODE
  323. /* Some things have been optimized. */
  324. /*****************************************************************************
  325.    Rewriting saves 6 MUL.
  326.  *****************************************************************************/
  327. int Inside_Quadric (IPoint, Object)
  328. VECTOR *IPoint;
  329. OBJECT *Object;
  330. {
  331.   QUADRIC *Quadric = (QUADRIC *) Object;
  332.   register DBL Result;
  333.  
  334.   Result =
  335.  
  336.     IPoint->x * (Quadric->Square_Terms.x * IPoint->x +
  337.          Quadric->Mixed_Terms.x * IPoint->y +
  338.          Quadric->Terms.x) +
  339.  
  340.     IPoint->y * (Quadric->Square_Terms.y * IPoint->y +
  341.          Quadric->Mixed_Terms.z * IPoint->z +
  342.          Quadric->Terms.y) +
  343.  
  344.     IPoint->z * (Quadric->Square_Terms.z * IPoint->z +
  345.          Quadric->Mixed_Terms.y * IPoint->x +
  346.          Quadric->Terms.z) +
  347.  
  348.     Quadric->Constant;
  349.  
  350.   return (Result < Small_Tolerance);
  351. }
  352. #else
  353. int Inside_Quadric (IPoint, Object)
  354. VECTOR *IPoint;
  355. OBJECT *Object;
  356.   {
  357.   QUADRIC *Quadric = (QUADRIC *) Object;
  358.   VECTOR New_Point;
  359.   register DBL Result, Linear_Term, Square_Term;
  360.  
  361.   VDot (Linear_Term, *IPoint, Quadric->Terms);
  362.   Result = Linear_Term + Quadric->Constant;
  363.   VSquareTerms (New_Point, *IPoint);
  364.   VDot (Square_Term, New_Point, Quadric->Square_Terms);
  365.   Result += Square_Term;
  366.   Result += Quadric->Mixed_Terms.x * (IPoint->x) * (IPoint->y)
  367.     + Quadric->Mixed_Terms.y * (IPoint->x) * (IPoint->z)
  368.       + Quadric->Mixed_Terms.z * (IPoint->y) * (IPoint->z);
  369.  
  370.   if (Result < Small_Tolerance)
  371.     return (TRUE);
  372.  
  373.   return (FALSE);
  374.   }
  375. #endif
  376.  
  377. #ifdef DB_CODE
  378. /* Some things have been optimized. */
  379. /*****************************************************************************
  380.    Rewriting saves some memory transfers.
  381.    Storing of 2.0 * Square_Terms would save 3 MUL.
  382.  *****************************************************************************/
  383. void Quadric_Normal (Result, Object, IPoint)
  384. VECTOR *Result, *IPoint;
  385. OBJECT *Object;
  386. {
  387.   QUADRIC *Quadric = (QUADRIC *) Object;
  388.   DBL Len;
  389.  
  390.   Result->x = 2.0 * Quadric->Square_Terms.x * IPoint->x +
  391.           Quadric->Mixed_Terms.x * IPoint->y +
  392.           Quadric->Mixed_Terms.y * IPoint->z +
  393.           Quadric->Terms.x;
  394.  
  395.   Result->y = 2.0 * Quadric->Square_Terms.y * IPoint->y +
  396.           Quadric->Mixed_Terms.x * IPoint->x +
  397.           Quadric->Mixed_Terms.z * IPoint->z +
  398.           Quadric->Terms.y;
  399.  
  400.   Result->z = 2.0 * Quadric->Square_Terms.z * IPoint->z +
  401.           Quadric->Mixed_Terms.y * IPoint->x +
  402.           Quadric->Mixed_Terms.z * IPoint->y +
  403.           Quadric->Terms.z;
  404.  
  405.   Len = sqrt(Result->x * Result->x + Result->y * Result->y + Result->z * Result->z);
  406.  
  407.   if (Len == 0.0)
  408.   {
  409.     /* The normal is not defined at this point of the surface. */
  410.     /* Set it to any arbitrary direction. */
  411.     Result->x = 1.0;
  412.     Result->y = 0.0;
  413.     Result->z = 0.0;
  414.   }
  415.   else
  416.   {
  417.     Result->x /= Len;        /* normalize the normal */
  418.     Result->y /= Len;
  419.     Result->z /= Len;
  420.   }
  421. }
  422. #else
  423. void Quadric_Normal (Result, Object, IPoint)
  424. VECTOR *Result, *IPoint;
  425. OBJECT *Object;
  426.   {
  427.   QUADRIC *Intersection_Quadric = (QUADRIC *) Object;
  428.   VECTOR Derivative_Linear;
  429.   DBL Len;
  430.  
  431.   VScale (Derivative_Linear, Intersection_Quadric->Square_Terms, 2.0);
  432.   VEvaluate (*Result, Derivative_Linear, *IPoint);
  433.   VAdd (*Result, *Result, Intersection_Quadric->Terms);
  434.  
  435.   Result->x +=
  436.   Intersection_Quadric->Mixed_Terms.x * IPoint->y +
  437.   Intersection_Quadric->Mixed_Terms.y * IPoint->z;
  438.  
  439.  
  440.   Result->y +=
  441.   Intersection_Quadric->Mixed_Terms.x * IPoint->x +
  442.   Intersection_Quadric->Mixed_Terms.z * IPoint->z;
  443.  
  444.   Result->z +=
  445.   Intersection_Quadric->Mixed_Terms.y * IPoint->x +
  446.   Intersection_Quadric->Mixed_Terms.z * IPoint->y;
  447.  
  448.   Len = Result->x * Result->x + Result->y * Result->y + Result->z * Result->z;
  449.   Len = sqrt(Len);
  450.   if (Len == 0.0) 
  451.     {
  452.     /* The normal is not defined at this point of the surface.  Set it
  453.          to any arbitrary direction. */
  454.     Result->x = 1.0;
  455.     Result->y = 0.0;
  456.     Result->z = 0.0;
  457.     }
  458.   else
  459.     {
  460.     Result->x /= Len;        /* normalize the normal */
  461.     Result->y /= Len;
  462.     Result->z /= Len;
  463.     }
  464.   }
  465. #endif
  466.  
  467.   void Transform_Quadric (Object, Trans)
  468.     OBJECT *Object;
  469. TRANSFORM *Trans;
  470.   {
  471.   QUADRIC *Quadric=(QUADRIC *)Object;
  472.   MATRIX Quadric_Matrix, Transform_Transposed;
  473.  
  474.   Quadric_To_Matrix (Quadric, (MATRIX *) &Quadric_Matrix[0][0]);
  475.   MTimes ((MATRIX *) &Quadric_Matrix[0][0], (MATRIX *) &(Trans->inverse[0][0]), (MATRIX *) &Quadric_Matrix[0][0]);
  476.   MTranspose ((MATRIX *) &Transform_Transposed[0][0], (MATRIX *) &(Trans->inverse[0][0]));
  477.   MTimes ((MATRIX *) &Quadric_Matrix[0][0], (MATRIX *) &Quadric_Matrix[0][0], (MATRIX *) &Transform_Transposed[0][0]);
  478.   Matrix_To_Quadric ((MATRIX *) &Quadric_Matrix[0][0], Quadric);
  479. #ifdef DB_CODE
  480.   /* this has been missing. */
  481.   recompute_bbox(&Object->Bounds, Trans);
  482. #endif
  483.   }
  484.  
  485. void Quadric_To_Matrix (Quadric, Matrix)
  486. QUADRIC *Quadric;
  487. MATRIX *Matrix;
  488.   {
  489.   MZero (Matrix);
  490.   (*Matrix)[0][0] = Quadric->Square_Terms.x;
  491.   (*Matrix)[1][1] = Quadric->Square_Terms.y;
  492.   (*Matrix)[2][2] = Quadric->Square_Terms.z;
  493.   (*Matrix)[0][1] = Quadric->Mixed_Terms.x;
  494.   (*Matrix)[0][2] = Quadric->Mixed_Terms.y;
  495.   (*Matrix)[0][3] = Quadric->Terms.x;
  496.   (*Matrix)[1][2] = Quadric->Mixed_Terms.z;
  497.   (*Matrix)[1][3] = Quadric->Terms.y;
  498.   (*Matrix)[2][3] = Quadric->Terms.z;
  499.   (*Matrix)[3][3] = Quadric->Constant;
  500.   }
  501.  
  502. void Matrix_To_Quadric (Matrix, Quadric)
  503. MATRIX *Matrix;
  504. QUADRIC *Quadric;
  505.   {
  506.   Quadric->Square_Terms.x = (*Matrix)[0][0];
  507.   Quadric->Square_Terms.y = (*Matrix)[1][1];
  508.   Quadric->Square_Terms.z = (*Matrix)[2][2];
  509.   Quadric->Mixed_Terms.x = (*Matrix)[0][1] + (*Matrix)[1][0];
  510.   Quadric->Mixed_Terms.y = (*Matrix)[0][2] + (*Matrix)[2][0];
  511.   Quadric->Terms.x = (*Matrix)[0][3] + (*Matrix)[3][0];
  512.   Quadric->Mixed_Terms.z = (*Matrix)[1][2] + (*Matrix)[2][1];
  513.   Quadric->Terms.y = (*Matrix)[1][3] + (*Matrix)[3][1];
  514.   Quadric->Terms.z = (*Matrix)[2][3] + (*Matrix)[3][2];
  515.   Quadric->Constant = (*Matrix)[3][3];
  516.   }
  517.  
  518. void Translate_Quadric (Object, Vector)
  519. OBJECT *Object;
  520. VECTOR *Vector;
  521.   {
  522.   TRANSFORM Trans;
  523.  
  524.   Compute_Translation_Transform (&Trans, Vector);
  525.   Transform_Quadric (Object, &Trans);
  526.  
  527.   }
  528.  
  529. void Rotate_Quadric (Object, Vector)
  530. OBJECT *Object;
  531. VECTOR *Vector;
  532.   {
  533.   TRANSFORM Trans;
  534.  
  535.   Compute_Rotation_Transform (&Trans, Vector);
  536.   Transform_Quadric (Object, &Trans);
  537.   }
  538.  
  539. void Scale_Quadric (Object, Vector)
  540. OBJECT *Object;
  541. VECTOR *Vector;
  542.   {
  543.   TRANSFORM Trans;
  544.  
  545.   Compute_Scaling_Transform (&Trans, Vector);
  546.   Transform_Quadric (Object, &Trans);
  547.   }
  548.  
  549. void Invert_Quadric (Object)
  550. OBJECT *Object;
  551.   {
  552.   QUADRIC *Quadric = (QUADRIC *) Object;
  553.  
  554.   VScaleEq (Quadric->Square_Terms, -1.0);
  555.   VScaleEq (Quadric->Mixed_Terms, -1.0);
  556.   VScaleEq (Quadric->Terms, -1.0);
  557.   Quadric->Constant *= -1.0;
  558. #ifdef DB_CODE
  559.   /* Necessary for new bounding box calculation of intersections. */
  560.   Quadric->Inverted ^= TRUE;
  561. #endif
  562.   }
  563.  
  564. QUADRIC *Create_Quadric()
  565.   {
  566.   QUADRIC *New;
  567.  
  568.   if ((New = (QUADRIC *) malloc (sizeof (QUADRIC))) == NULL)
  569.     MAError ("quadric");
  570.  
  571.   INIT_OBJECT_FIELDS(New, QUADRIC_OBJECT, &Quadric_Methods)
  572.     Make_Vector (&(New->Square_Terms), 1.0, 1.0, 1.0);
  573.   Make_Vector (&(New->Mixed_Terms), 0.0, 0.0, 0.0);
  574.   Make_Vector (&(New->Terms), 0.0, 0.0, 0.0);
  575.   New->Constant = 1.0;
  576.   New->CM_Constant = HUGE_VAL;
  577.   New->Constant_Cached = FALSE;
  578.   New->Non_Zero_Square_Term = FALSE;
  579. #ifdef DB_CODE
  580.   /* Necessary for new bounding box calculation of intersections. */
  581.   New->Inverted = FALSE;
  582. #endif
  583.  
  584.   return (New);
  585.   }
  586.  
  587. void *Copy_Quadric (Object)
  588. OBJECT *Object;
  589.   {
  590.   QUADRIC *New;
  591.  
  592.   New = Create_Quadric ();
  593.   *New = *((QUADRIC *) Object);
  594.  
  595.   return (New);
  596.   }
  597.  
  598. void Destroy_Quadric (Object)
  599. OBJECT *Object;
  600.   {
  601.   free (Object);
  602.   }
  603.