home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / gfx / dkb212sr.lzh / quadrics.c < prev    next >
C/C++ Source or Header  |  1991-04-30  |  12KB  |  363 lines

  1. /*****************************************************************************
  2. *
  3. *                                   quadrics.c
  4. *
  5. *   from DKBTrace (c) 1990  David Buck
  6. *
  7. *  This module implements the code for the quadric shape primitive.
  8. *
  9. * This software is freely distributable. The source and/or object code may be
  10. * copied or uploaded to communications services so long as this notice remains
  11. * at the top of each file.  If any changes are made to the program, you must
  12. * clearly indicate in the documentation and in the programs startup message
  13. * who it was who made the changes. The documentation should also describe what
  14. * those changes were. This software may not be included in whole or in
  15. * part into any commercial package without the express written consent of the
  16. * author.  It may, however, be included in other public domain or freely
  17. * distributed software so long as the proper credit for the software is given.
  18. *
  19. * This software is provided as is without any guarantees or warranty. Although
  20. * the author has attempted to find and correct any bugs in the software, he
  21. * is not responsible for any damage caused by the use of the software.  The
  22. * author is under no obligation to provide service, corrections, or upgrades
  23. * to this package.
  24. *
  25. * Despite all the legal stuff above, if you do find bugs, I would like to hear
  26. * about them.  Also, if you have any comments or questions, you may contact me
  27. * at the following address:
  28. *
  29. *     David Buck
  30. *     22C Sonnet Cres.
  31. *     Nepean Ontario
  32. *     Canada, K2H 8W7
  33. *
  34. *  I can also be reached on the following bulleton boards:
  35. *
  36. *     OMX              (613) 731-3419
  37. *     Mystic           (613) 596-4249  or  (613) 596-4772
  38. *
  39. *  Fidonet:   1:163/109.9
  40. *  Internet:  dbuck@ccs.carleton.ca
  41. *  The "You Can Call Me RAY" BBS    (708) 358-5611
  42. *
  43. *  IBM Port by Aaron A. Collins. Aaron may be reached on the following BBS'es:
  44. *
  45. *     The "You Can Call Me RAY" BBS (708) 358-5611
  46. *     The Information Exchange BBS  (708) 945-5575
  47. *
  48. *****************************************************************************/
  49.  
  50.  
  51. #include "frame.h"
  52. #include "vector.h"
  53. #include "dkbproto.h"
  54.  
  55. METHODS Quadric_Methods =
  56.    { Object_Intersect, All_Quadric_Intersections,
  57.      Inside_Quadric, Quadric_Normal,
  58.      Copy_Quadric,
  59.      Translate_Quadric, Rotate_Quadric,
  60.      Scale_Quadric, Invert_Quadric};
  61.  
  62. extern RAY *VP_Ray;
  63. extern long Ray_Quadric_Tests, Ray_Quadric_Tests_Succeeded;
  64.  
  65. int All_Quadric_Intersections (Object, Ray, Depth_Queue)
  66.    OBJECT *Object;
  67.    RAY *Ray;
  68.    PRIOQ *Depth_Queue;
  69.    {
  70.    QUADRIC *Shape = (QUADRIC *) Object;
  71.    DBL Depth1, Depth2;
  72.    VECTOR Intersection_Point;
  73.    INTERSECTION Local_Element;
  74.    register int Intersection_Found;
  75.  
  76.    Intersection_Found = FALSE;
  77.    if (Intersect_Quadric (Ray, Shape, &Depth1, &Depth2))
  78.       {
  79.       Local_Element.Depth = Depth1;
  80.       Local_Element.Object = Shape -> Parent_Object;
  81.       VScale (Intersection_Point, Ray -> Direction, Depth1);
  82.       VAdd (Intersection_Point, Intersection_Point, Ray -> Initial);
  83.       Local_Element.Point = Intersection_Point;
  84.       Local_Element.Shape = (SHAPE *)Shape;
  85.       pq_add (Depth_Queue, &Local_Element);
  86.       Intersection_Found = TRUE;
  87.  
  88.       if (Depth2 != Depth1)
  89.          {
  90.          Local_Element.Depth = Depth2;
  91.          Local_Element.Object = Shape -> Parent_Object;
  92.          VScale (Intersection_Point, Ray -> Direction, Depth2);
  93.          VAdd (Intersection_Point, Intersection_Point, Ray -> Initial);
  94.          Local_Element.Point = Intersection_Point;
  95.          Local_Element.Shape = (SHAPE *) Shape;
  96.          pq_add (Depth_Queue, &Local_Element);
  97.          Intersection_Found = TRUE;
  98.          }
  99.       }
  100.    return (Intersection_Found);
  101.    }
  102.  
  103. int Intersect_Quadric (Ray, Shape, Depth1, Depth2)
  104.    RAY *Ray;
  105.    QUADRIC *Shape;
  106.    DBL *Depth1, *Depth2;
  107.    {
  108.    register DBL Square_Term, Linear_Term, Constant_Term, Temp_Term;
  109.    register DBL Determinant, Determinant_2, A2, BMinus;
  110.  
  111.    Ray_Quadric_Tests++;
  112.    if (!Ray->Quadric_Constants_Cached)
  113.       Make_Ray(Ray);
  114.  
  115.    if (Shape -> Non_Zero_Square_Term)
  116.       {
  117.       VDot (Square_Term, Shape -> Object_2_Terms, Ray -> Direction_2);
  118.       VDot (Temp_Term, Shape -> Object_Mixed_Terms, Ray -> Mixed_Dir_Dir);
  119.       Square_Term += Temp_Term;
  120.       }
  121.    else
  122.       Square_Term = 0.0;
  123.  
  124.    VDot (Linear_Term, Shape -> Object_2_Terms, Ray -> Initial_Direction);
  125.    Linear_Term *= 2.0;
  126.    VDot (Temp_Term, Shape -> Object_Terms, Ray -> Direction);
  127.    Linear_Term += Temp_Term;
  128.    VDot (Temp_Term, Shape -> Object_Mixed_Terms, Ray -> Mixed_Init_Dir);
  129.    Linear_Term += Temp_Term;
  130.  
  131.    if (Ray == VP_Ray)
  132.       if (!Shape -> Constant_Cached)
  133.          {
  134.          VDot (Constant_Term, Shape -> Object_2_Terms, Ray -> Initial_2);
  135.          VDot (Temp_Term, Shape -> Object_Terms, Ray -> Initial);
  136.          Constant_Term +=  Temp_Term + Shape -> Object_Constant;
  137.          Shape -> Object_VP_Constant = Constant_Term;
  138.          Shape -> Constant_Cached = TRUE;
  139.          }
  140.       else
  141.          Constant_Term = Shape -> Object_VP_Constant;
  142.    else
  143.       {
  144.       VDot (Constant_Term, Shape -> Object_2_Terms, Ray -> Initial_2);
  145.       VDot (Temp_Term, Shape -> Object_Terms, Ray -> Initial);
  146.       Constant_Term += Temp_Term + Shape -> Object_Constant;
  147.       }
  148.  
  149.    VDot (Temp_Term, Shape -> Object_Mixed_Terms, 
  150.          Ray -> Mixed_Initial_Initial);
  151.    Constant_Term += Temp_Term;
  152.  
  153.    if (Square_Term != 0.0)
  154.       {
  155.   /* The equation is quadratic - find its roots */
  156.  
  157.       Determinant_2 = Linear_Term * Linear_Term - 4.0 * Square_Term * Constant_Term;
  158.  
  159.       if (Determinant_2 < 0.0)
  160.          return (FALSE);
  161.  
  162.       Determinant = sqrt (Determinant_2);
  163.       A2 = Square_Term * 2.0;
  164.       BMinus = Linear_Term * -1.0;
  165.  
  166.       *Depth1 = (BMinus + Determinant) / A2;
  167.       *Depth2 = (BMinus - Determinant) / A2;
  168.       }
  169.    else
  170.       {
  171.     /* There are no quadratic terms.  Solve the linear equation instead. */
  172.       if (Linear_Term == 0.0)
  173.          return (FALSE);
  174.  
  175.       *Depth1 = Constant_Term * -1.0 / Linear_Term;
  176.       *Depth2 = *Depth1;
  177.       }
  178.  
  179.    if ((*Depth1 < Small_Tolerance) || (*Depth1 > Max_Distance))
  180.       if ((*Depth2 < Small_Tolerance) || (*Depth2 > Max_Distance))
  181.          return (FALSE);
  182.       else
  183.          *Depth1 = *Depth2;
  184.    else
  185.       if ((*Depth2 < Small_Tolerance) || (*Depth2 > Max_Distance))
  186.         *Depth2 = *Depth1;
  187.  
  188.    Ray_Quadric_Tests_Succeeded++;
  189.    return (TRUE);
  190.    }
  191.  
  192. int Inside_Quadric (Test_Point, Object)
  193.    VECTOR *Test_Point;
  194.    OBJECT *Object;
  195.    {
  196.    QUADRIC *Shape = (QUADRIC *) Object;
  197.    VECTOR New_Point;
  198.    register DBL Result, Linear_Term, Square_Term;
  199.  
  200.    VDot (Linear_Term, *Test_Point, Shape -> Object_Terms);
  201.    Result = Linear_Term + Shape -> Object_Constant;
  202.    VSquareTerms (New_Point, *Test_Point);
  203.    VDot (Square_Term, New_Point, Shape -> Object_2_Terms);
  204.    Result += Square_Term;
  205.    Result += Shape -> Object_Mixed_Terms.x * (Test_Point -> x) * (Test_Point -> y)
  206.             + Shape -> Object_Mixed_Terms.y * (Test_Point -> x) * (Test_Point -> z)
  207.             + Shape -> Object_Mixed_Terms.z * (Test_Point -> y) * (Test_Point -> z);
  208.  
  209.    if (Result < Small_Tolerance)
  210.       return (TRUE);
  211.  
  212.    return (FALSE);
  213.    }
  214.  
  215. void Quadric_Normal (Result, Object, Intersection_Point)
  216.    VECTOR *Result, *Intersection_Point;
  217.    OBJECT *Object;
  218.    {
  219.    QUADRIC *Intersection_Shape = (QUADRIC *) Object;
  220.    VECTOR Derivative_Linear;
  221.    DBL Len;
  222.  
  223.    VScale (Derivative_Linear, Intersection_Shape -> Object_2_Terms, 2.0);
  224.    VEvaluate (*Result, Derivative_Linear, *Intersection_Point);
  225.    VAdd (*Result, *Result, Intersection_Shape -> Object_Terms);
  226.  
  227.    Result -> x += 
  228.          Intersection_Shape->Object_Mixed_Terms.x * Intersection_Point->y +
  229.          Intersection_Shape->Object_Mixed_Terms.y * Intersection_Point->z;
  230.  
  231.  
  232.    Result -> y +=
  233.          Intersection_Shape->Object_Mixed_Terms.x * Intersection_Point->x +
  234.          Intersection_Shape->Object_Mixed_Terms.z * Intersection_Point->z;
  235.  
  236.    Result -> z +=
  237.          Intersection_Shape->Object_Mixed_Terms.y * Intersection_Point->x +
  238.          Intersection_Shape->Object_Mixed_Terms.z * Intersection_Point->y;
  239.  
  240.    Len = Result->x * Result->x + Result->y * Result->y + Result->z * Result->z;
  241.    Len = sqrt(Len);
  242.    if (Len == 0.0) {
  243.       /* The normal is not defined at this point of the surface.  Set it
  244.          to any arbitrary direction. */
  245.       Result->x = 1.0;
  246.       Result->y = 0.0;
  247.       Result->z = 0.0;
  248.       }
  249.    else {
  250.       Result->x /= Len;        /* normalize the normal */
  251.       Result->y /= Len;
  252.       Result->z /= Len;
  253.       }
  254.    }
  255.  
  256. void *Copy_Quadric (Object)
  257.    OBJECT *Object;
  258.    {
  259.    QUADRIC *New_Shape;
  260.  
  261.    New_Shape = Get_Quadric_Shape ();
  262.    *New_Shape = *((QUADRIC *) Object);
  263.    New_Shape -> Next_Object = NULL;
  264.  
  265.    if (New_Shape->Shape_Texture != NULL)
  266.       New_Shape->Shape_Texture = Copy_Texture (New_Shape->Shape_Texture);
  267.  
  268.    return (New_Shape);
  269.    }
  270.  
  271. void Transform_Quadric (Shape, Transformation)
  272.    QUADRIC *Shape;
  273.    TRANSFORMATION *Transformation;
  274.    {
  275.    MATRIX Quadric_Matrix, Transform_Transposed;
  276.  
  277.    Quadric_To_Matrix (Shape, (MATRIX *) &Quadric_Matrix[0][0]);
  278.    MTimes ((MATRIX *) &Quadric_Matrix[0][0], (MATRIX *) &(Transformation -> inverse[0][0]), (MATRIX *) &Quadric_Matrix[0][0]);
  279.    MTranspose ((MATRIX *) &Transform_Transposed[0][0], (MATRIX *) &(Transformation -> inverse[0][0]));
  280.    MTimes ((MATRIX *) &Quadric_Matrix[0][0], (MATRIX *) &Quadric_Matrix[0][0], (MATRIX *) &Transform_Transposed[0][0]);
  281.    Matrix_To_Quadric ((MATRIX *) &Quadric_Matrix[0][0], Shape);
  282.    }
  283.  
  284. void Quadric_To_Matrix (Quadric, Matrix)
  285.    QUADRIC *Quadric;
  286.    MATRIX *Matrix;
  287.    {
  288.    MZero (Matrix);
  289.    (*Matrix)[0][0] = Quadric -> Object_2_Terms.x;
  290.    (*Matrix)[1][1] = Quadric -> Object_2_Terms.y;
  291.    (*Matrix)[2][2] = Quadric -> Object_2_Terms.z;
  292.    (*Matrix)[0][1] = Quadric -> Object_Mixed_Terms.x;
  293.    (*Matrix)[0][2] = Quadric -> Object_Mixed_Terms.y;
  294.    (*Matrix)[0][3] = Quadric -> Object_Terms.x;
  295.    (*Matrix)[1][2] = Quadric -> Object_Mixed_Terms.z;
  296.    (*Matrix)[1][3] = Quadric -> Object_Terms.y;
  297.    (*Matrix)[2][3] = Quadric -> Object_Terms.z;
  298.    (*Matrix)[3][3] = Quadric -> Object_Constant;
  299.    }
  300.  
  301. void Matrix_To_Quadric (Matrix, Quadric)
  302.    MATRIX *Matrix;
  303.    QUADRIC *Quadric;
  304.    {
  305.    Quadric -> Object_2_Terms.x = (*Matrix)[0][0];
  306.    Quadric -> Object_2_Terms.y = (*Matrix)[1][1];
  307.    Quadric -> Object_2_Terms.z = (*Matrix)[2][2];
  308.    Quadric -> Object_Mixed_Terms.x = (*Matrix)[0][1] + (*Matrix)[1][0];
  309.    Quadric -> Object_Mixed_Terms.y = (*Matrix)[0][2] + (*Matrix)[2][0];
  310.    Quadric -> Object_Terms.x = (*Matrix)[0][3] + (*Matrix)[3][0];
  311.    Quadric -> Object_Mixed_Terms.z = (*Matrix)[1][2] + (*Matrix)[2][1];
  312.    Quadric -> Object_Terms.y = (*Matrix)[1][3] + (*Matrix)[3][1];
  313.    Quadric -> Object_Terms.z = (*Matrix)[2][3] + (*Matrix)[3][2];
  314.    Quadric -> Object_Constant = (*Matrix)[3][3];
  315.    }
  316.  
  317. void Translate_Quadric (Object, Vector)
  318.    OBJECT *Object;
  319.    VECTOR *Vector;
  320.    {
  321.    TRANSFORMATION Transformation;
  322.  
  323.    Get_Translation_Transformation (&Transformation, Vector);
  324.    Transform_Quadric ((QUADRIC *) Object, &Transformation);
  325.  
  326.    Translate_Texture (&((QUADRIC *) Object)->Shape_Texture, Vector);
  327.    }
  328.  
  329. void Rotate_Quadric (Object, Vector)
  330.    OBJECT *Object;
  331.    VECTOR *Vector;
  332.    {
  333.    TRANSFORMATION Transformation;
  334.  
  335.    Get_Rotation_Transformation (&Transformation, Vector);
  336.    Transform_Quadric ((QUADRIC *) Object, &Transformation);
  337.  
  338.    Rotate_Texture (&((QUADRIC *) Object)->Shape_Texture, Vector);
  339.    }
  340.  
  341. void Scale_Quadric (Object, Vector)
  342.    OBJECT *Object;
  343.    VECTOR *Vector;
  344.    {
  345.    TRANSFORMATION Transformation;
  346.  
  347.    Get_Scaling_Transformation (&Transformation, Vector);
  348.    Transform_Quadric ((QUADRIC *) Object, &Transformation);
  349.  
  350.    Scale_Texture (&((QUADRIC *) Object)->Shape_Texture, Vector);
  351.    }
  352.  
  353. void Invert_Quadric (Object)
  354.    OBJECT *Object;
  355.    {
  356.    QUADRIC *Shape = (QUADRIC *) Object;
  357.  
  358.    VScale (Shape -> Object_2_Terms, Shape -> Object_2_Terms, -1.0);
  359.    VScale (Shape -> Object_Mixed_Terms, Shape -> Object_Mixed_Terms, -1.0);
  360.    VScale (Shape -> Object_Terms, Shape -> Object_Terms, -1.0);
  361.    Shape -> Object_Constant *= -1.0;
  362.    }
  363.