home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / source / povsrc.sit / SOURCE / QUADRICS.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-03  |  10.5 KB  |  336 lines

  1. /****************************************************************************
  2. *                quadrics.c
  3. *
  4. *  This module implements the code for the quadric shape primitive.
  5. *
  6. *  from Persistence of Vision Raytracer 
  7. *  Copyright 1992 Persistence of Vision Team
  8. *---------------------------------------------------------------------------
  9. *  Copying, distribution and legal info is in the file povlegal.doc which
  10. *  should be distributed with this file. If povlegal.doc is not available
  11. *  or for more info please contact:
  12. *
  13. *       Drew Wells [POV-Team Leader] 
  14. *       CIS: 73767,1244  Internet: 73767.1244@compuserve.com
  15. *       Phone: (213) 254-4041
  16. * This program is based on the popular DKB raytracer version 2.12.
  17. * DKBTrace was originally written by David K. Buck.
  18. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  19. *
  20. *****************************************************************************/
  21.  
  22.  
  23. #include "frame.h"
  24. #include "vector.h"
  25. #include "povproto.h"
  26.  
  27. METHODS Quadric_Methods =
  28. { Object_Intersect, All_Quadric_Intersections,
  29.    Inside_Quadric, Quadric_Normal,
  30.    Copy_Quadric,
  31.    Translate_Quadric, Rotate_Quadric,
  32.    Scale_Quadric, Invert_Quadric};
  33.  
  34. extern RAY *VP_Ray;
  35. extern long Ray_Quadric_Tests, Ray_Quadric_Tests_Succeeded;
  36.  
  37. int All_Quadric_Intersections (Object, Ray, Depth_Queue)
  38. OBJECT *Object;
  39. RAY *Ray;
  40. PRIOQ *Depth_Queue;
  41. {
  42.    QUADRIC *Shape = (QUADRIC *) Object;
  43.    DBL Depth1, Depth2;
  44.    VECTOR Intersection_Point;
  45.    INTERSECTION Local_Element;
  46.    register int Intersection_Found;
  47.  
  48.    Intersection_Found = FALSE;
  49.    if (Intersect_Quadric (Ray, Shape, &Depth1, &Depth2))
  50.    {
  51.       Local_Element.Depth = Depth1;
  52.       Local_Element.Object = Shape -> Parent_Object;
  53.       VScale (Intersection_Point, Ray -> Direction, Depth1);
  54.       VAdd (Intersection_Point, Intersection_Point, Ray -> Initial);
  55.       Local_Element.Point = Intersection_Point;
  56.       Local_Element.Shape = (SHAPE *)Shape;
  57.       pq_add (Depth_Queue, &Local_Element);
  58.       Intersection_Found = TRUE;
  59.  
  60.       if (Depth2 != Depth1)
  61.       {
  62.          Local_Element.Depth = Depth2;
  63.          Local_Element.Object = Shape -> Parent_Object;
  64.          VScale (Intersection_Point, Ray -> Direction, Depth2);
  65.          VAdd (Intersection_Point, Intersection_Point, Ray -> Initial);
  66.          Local_Element.Point = Intersection_Point;
  67.          Local_Element.Shape = (SHAPE *) Shape;
  68.          pq_add (Depth_Queue, &Local_Element);
  69.          Intersection_Found = TRUE;
  70.       }
  71.    }
  72.    return (Intersection_Found);
  73. }
  74.  
  75. int Intersect_Quadric (Ray, Shape, Depth1, Depth2)
  76. RAY *Ray;
  77. QUADRIC *Shape;
  78. DBL *Depth1, *Depth2;
  79. {
  80.    register DBL Square_Term, Linear_Term, Constant_Term, Temp_Term;
  81.    register DBL Determinant, Determinant_2, A2, BMinus;
  82.  
  83.    Ray_Quadric_Tests++;
  84.    if (!Ray->Quadric_Constants_Cached)
  85.       Make_Ray(Ray);
  86.  
  87.    if (Shape -> Non_Zero_Square_Term)
  88.    {
  89.       VDot (Square_Term, Shape -> Object_2_Terms, Ray -> Direction_2);
  90.       VDot (Temp_Term, Shape -> Object_Mixed_Terms, Ray -> Mixed_Dir_Dir);
  91.       Square_Term += Temp_Term;
  92.    }
  93.    else
  94.       Square_Term = 0.0;
  95.  
  96.    VDot (Linear_Term, Shape -> Object_2_Terms, Ray -> Initial_Direction);
  97.    Linear_Term *= 2.0;
  98.    VDot (Temp_Term, Shape -> Object_Terms, Ray -> Direction);
  99.    Linear_Term += Temp_Term;
  100.    VDot (Temp_Term, Shape -> Object_Mixed_Terms, Ray -> Mixed_Init_Dir);
  101.    Linear_Term += Temp_Term;
  102.  
  103.    if (Ray == VP_Ray)
  104.       if (!Shape -> Constant_Cached)
  105.       {
  106.          VDot (Constant_Term, Shape -> Object_2_Terms, Ray -> Initial_2);
  107.          VDot (Temp_Term, Shape -> Object_Terms, Ray -> Initial);
  108.          Constant_Term +=  Temp_Term + Shape -> Object_Constant;
  109.          Shape -> Object_VP_Constant = Constant_Term;
  110.          Shape -> Constant_Cached = TRUE;
  111.       }
  112.       else
  113.          Constant_Term = Shape -> Object_VP_Constant;
  114.    else
  115.    {
  116.       VDot (Constant_Term, Shape -> Object_2_Terms, Ray -> Initial_2);
  117.       VDot (Temp_Term, Shape -> Object_Terms, Ray -> Initial);
  118.       Constant_Term += Temp_Term + Shape -> Object_Constant;
  119.    }
  120.  
  121.    VDot (Temp_Term, Shape -> Object_Mixed_Terms, 
  122.       Ray -> Mixed_Initial_Initial);
  123.    Constant_Term += Temp_Term;
  124.  
  125.    if (Square_Term != 0.0)
  126.    {
  127.       /* The equation is quadratic - find its roots */
  128.  
  129.       Determinant_2 = Linear_Term * Linear_Term - 4.0 * Square_Term * Constant_Term;
  130.  
  131.       if (Determinant_2 < 0.0)
  132.          return (FALSE);
  133.  
  134.       Determinant = sqrt (Determinant_2);
  135.       A2 = Square_Term * 2.0;
  136.       BMinus = Linear_Term * -1.0;
  137.  
  138.       *Depth1 = (BMinus + Determinant) / A2;
  139.       *Depth2 = (BMinus - Determinant) / A2;
  140.    }
  141.    else
  142.    {
  143.       /* There are no quadratic terms.  Solve the linear equation instead. */
  144.       if (Linear_Term == 0.0)
  145.          return (FALSE);
  146.  
  147.       *Depth1 = Constant_Term * -1.0 / Linear_Term;
  148.       *Depth2 = *Depth1;
  149.    }
  150.  
  151.    if ((*Depth1 < Small_Tolerance) || (*Depth1 > Max_Distance))
  152.       if ((*Depth2 < Small_Tolerance) || (*Depth2 > Max_Distance))
  153.          return (FALSE);
  154.       else
  155.          *Depth1 = *Depth2;
  156.    else
  157.       if ((*Depth2 < Small_Tolerance) || (*Depth2 > Max_Distance))
  158.          *Depth2 = *Depth1;
  159.  
  160.    Ray_Quadric_Tests_Succeeded++;
  161.    return (TRUE);
  162. }
  163.  
  164. int Inside_Quadric (Test_Point, Object)
  165. VECTOR *Test_Point;
  166. OBJECT *Object;
  167. {
  168.    QUADRIC *Shape = (QUADRIC *) Object;
  169.    VECTOR New_Point;
  170.    register DBL Result, Linear_Term, Square_Term;
  171.  
  172.    VDot (Linear_Term, *Test_Point, Shape -> Object_Terms);
  173.    Result = Linear_Term + Shape -> Object_Constant;
  174.    VSquareTerms (New_Point, *Test_Point);
  175.    VDot (Square_Term, New_Point, Shape -> Object_2_Terms);
  176.    Result += Square_Term;
  177.    Result += Shape -> Object_Mixed_Terms.x * (Test_Point -> x) * (Test_Point -> y)
  178.       + Shape -> Object_Mixed_Terms.y * (Test_Point -> x) * (Test_Point -> z)
  179.          + Shape -> Object_Mixed_Terms.z * (Test_Point -> y) * (Test_Point -> z);
  180.  
  181.    if (Result < Small_Tolerance)
  182.       return (TRUE);
  183.  
  184.    return (FALSE);
  185. }
  186.  
  187. void Quadric_Normal (Result, Object, Intersection_Point)
  188. VECTOR *Result, *Intersection_Point;
  189. OBJECT *Object;
  190. {
  191.    QUADRIC *Intersection_Shape = (QUADRIC *) Object;
  192.    VECTOR Derivative_Linear;
  193.    DBL Len;
  194.  
  195.    VScale (Derivative_Linear, Intersection_Shape -> Object_2_Terms, 2.0);
  196.    VEvaluate (*Result, Derivative_Linear, *Intersection_Point);
  197.    VAdd (*Result, *Result, Intersection_Shape -> Object_Terms);
  198.  
  199.    Result -> x += 
  200.    Intersection_Shape->Object_Mixed_Terms.x * Intersection_Point->y +
  201.    Intersection_Shape->Object_Mixed_Terms.y * Intersection_Point->z;
  202.  
  203.  
  204.    Result -> y +=
  205.    Intersection_Shape->Object_Mixed_Terms.x * Intersection_Point->x +
  206.    Intersection_Shape->Object_Mixed_Terms.z * Intersection_Point->z;
  207.  
  208.    Result -> z +=
  209.    Intersection_Shape->Object_Mixed_Terms.y * Intersection_Point->x +
  210.    Intersection_Shape->Object_Mixed_Terms.z * Intersection_Point->y;
  211.  
  212.    Len = Result->x * Result->x + Result->y * Result->y + Result->z * Result->z;
  213.    Len = sqrt(Len);
  214.    if (Len == 0.0) {
  215.       /* The normal is not defined at this point of the surface.  Set it
  216.          to any arbitrary direction. */
  217.       Result->x = 1.0;
  218.       Result->y = 0.0;
  219.       Result->z = 0.0;
  220.    }
  221.    else {
  222.       Result->x /= Len;        /* normalize the normal */
  223.       Result->y /= Len;
  224.       Result->z /= Len;
  225.    }
  226. }
  227.  
  228.    void *Copy_Quadric (Object)
  229.       OBJECT *Object;
  230. {
  231.    QUADRIC *New_Shape;
  232.  
  233.    New_Shape = Get_Quadric_Shape ();
  234.    *New_Shape = *((QUADRIC *) Object);
  235.    New_Shape -> Next_Object = NULL;
  236.  
  237.    if (New_Shape->Shape_Texture != NULL)
  238.       New_Shape->Shape_Texture = Copy_Texture (New_Shape->Shape_Texture);
  239.  
  240.    return (New_Shape);
  241. }
  242.  
  243. void Transform_Quadric (Shape, Transformation)
  244. QUADRIC *Shape;
  245. TRANSFORMATION *Transformation;
  246. {
  247.    MATRIX Quadric_Matrix, Transform_Transposed;
  248.  
  249.    Quadric_To_Matrix (Shape, (MATRIX *) &Quadric_Matrix[0][0]);
  250.    MTimes ((MATRIX *) &Quadric_Matrix[0][0], (MATRIX *) &(Transformation -> inverse[0][0]), (MATRIX *) &Quadric_Matrix[0][0]);
  251.    MTranspose ((MATRIX *) &Transform_Transposed[0][0], (MATRIX *) &(Transformation -> inverse[0][0]));
  252.    MTimes ((MATRIX *) &Quadric_Matrix[0][0], (MATRIX *) &Quadric_Matrix[0][0], (MATRIX *) &Transform_Transposed[0][0]);
  253.    Matrix_To_Quadric ((MATRIX *) &Quadric_Matrix[0][0], Shape);
  254. }
  255.  
  256. void Quadric_To_Matrix (Quadric, Matrix)
  257. QUADRIC *Quadric;
  258. MATRIX *Matrix;
  259. {
  260.    MZero (Matrix);
  261.    (*Matrix)[0][0] = Quadric -> Object_2_Terms.x;
  262.    (*Matrix)[1][1] = Quadric -> Object_2_Terms.y;
  263.    (*Matrix)[2][2] = Quadric -> Object_2_Terms.z;
  264.    (*Matrix)[0][1] = Quadric -> Object_Mixed_Terms.x;
  265.    (*Matrix)[0][2] = Quadric -> Object_Mixed_Terms.y;
  266.    (*Matrix)[0][3] = Quadric -> Object_Terms.x;
  267.    (*Matrix)[1][2] = Quadric -> Object_Mixed_Terms.z;
  268.    (*Matrix)[1][3] = Quadric -> Object_Terms.y;
  269.    (*Matrix)[2][3] = Quadric -> Object_Terms.z;
  270.    (*Matrix)[3][3] = Quadric -> Object_Constant;
  271. }
  272.  
  273. void Matrix_To_Quadric (Matrix, Quadric)
  274. MATRIX *Matrix;
  275. QUADRIC *Quadric;
  276. {
  277.    Quadric -> Object_2_Terms.x = (*Matrix)[0][0];
  278.    Quadric -> Object_2_Terms.y = (*Matrix)[1][1];
  279.    Quadric -> Object_2_Terms.z = (*Matrix)[2][2];
  280.    Quadric -> Object_Mixed_Terms.x = (*Matrix)[0][1] + (*Matrix)[1][0];
  281.    Quadric -> Object_Mixed_Terms.y = (*Matrix)[0][2] + (*Matrix)[2][0];
  282.    Quadric -> Object_Terms.x = (*Matrix)[0][3] + (*Matrix)[3][0];
  283.    Quadric -> Object_Mixed_Terms.z = (*Matrix)[1][2] + (*Matrix)[2][1];
  284.    Quadric -> Object_Terms.y = (*Matrix)[1][3] + (*Matrix)[3][1];
  285.    Quadric -> Object_Terms.z = (*Matrix)[2][3] + (*Matrix)[3][2];
  286.    Quadric -> Object_Constant = (*Matrix)[3][3];
  287. }
  288.  
  289. void Translate_Quadric (Object, Vector)
  290. OBJECT *Object;
  291. VECTOR *Vector;
  292. {
  293.    TRANSFORMATION Transformation;
  294.  
  295.    Get_Translation_Transformation (&Transformation, Vector);
  296.    Transform_Quadric ((QUADRIC *) Object, &Transformation);
  297.  
  298.    Translate_Texture (&((QUADRIC *) Object)->Shape_Texture, Vector);
  299. }
  300.  
  301. void Rotate_Quadric (Object, Vector)
  302. OBJECT *Object;
  303. VECTOR *Vector;
  304. {
  305.    TRANSFORMATION Transformation;
  306.  
  307.    Get_Rotation_Transformation (&Transformation, Vector);
  308.    Transform_Quadric ((QUADRIC *) Object, &Transformation);
  309.  
  310.    Rotate_Texture (&((QUADRIC *) Object)->Shape_Texture, Vector);
  311. }
  312.  
  313. void Scale_Quadric (Object, Vector)
  314. OBJECT *Object;
  315. VECTOR *Vector;
  316. {
  317.    TRANSFORMATION Transformation;
  318.  
  319.    Get_Scaling_Transformation (&Transformation, Vector);
  320.    Transform_Quadric ((QUADRIC *) Object, &Transformation);
  321.  
  322.    Scale_Texture (&((QUADRIC *) Object)->Shape_Texture, Vector);
  323. }
  324.  
  325. void Invert_Quadric (Object)
  326. OBJECT *Object;
  327. {
  328.    QUADRIC *Shape = (QUADRIC *) Object;
  329.  
  330.    VScale (Shape -> Object_2_Terms, Shape -> Object_2_Terms, -1.0);
  331.    VScale (Shape -> Object_Mixed_Terms, Shape -> Object_Mixed_Terms, -1.0);
  332.    VScale (Shape -> Object_Terms, Shape -> Object_Terms, -1.0);
  333.    Shape -> Object_Constant *= -1.0;
  334. }
  335.