home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / dirs / dkbtrace_397.lzh / DKBTrace / DKBSource.LZH / triangle.c < prev    next >
C/C++ Source or Header  |  1990-08-26  |  18KB  |  567 lines

  1. /*****************************************************************************
  2. *
  3. *                                      triangle.c
  4. *
  5. *   from DKBTrace (c) 1990  David Buck
  6. *
  7. *  This module implements primitives for triangles and smooth triangles.
  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. *     ATX              (613) 526-4141
  37. *     OMX              (613) 731-3419
  38. *     Mystic           (613) 731-0088 or (613) 731-6698
  39. *
  40. *  Fidonet:   1:163/109.9
  41. *  Internet:  David_Buck@Carleton.CA
  42. *
  43. *  IBM Port by Aaron A. Collins. Aaron may be reached on the following BBS'es:
  44. *
  45. *     Lattice BBS                      (708) 916-1200
  46. *     The Information Exchange BBS     (708) 945-5575
  47. *     Stillwaters BBS                  (708) 403-2826
  48. *
  49. *****************************************************************************/
  50.  
  51. #include "frame.h"
  52. #include "vector.h"
  53. #include "dkbproto.h"
  54.  
  55. METHODS Triangle_Methods = {
  56.      Object_Intersect, All_Triangle_Intersections,
  57.      Inside_Triangle, Triangle_Normal,
  58.      Copy_Triangle,
  59.      Translate_Triangle, Rotate_Triangle,
  60.      Scale_Triangle, Invert_Triangle};
  61.  
  62. METHODS Smooth_Triangle_Methods = {
  63.      Object_Intersect, All_Triangle_Intersections,
  64.      Inside_Triangle, Smooth_Triangle_Normal,
  65.      Copy_Smooth_Triangle,
  66.      Translate_Triangle, Rotate_Smooth_Triangle,
  67.      Scale_Triangle, Invert_Triangle};
  68.  
  69. extern TRIANGLE *Get_Triangle_Shape();
  70.  
  71. extern RAY *VP_Ray;
  72. extern long Ray_Triangle_Tests, Ray_Triangle_Tests_Succeeded;
  73.  
  74. #define max3(x,y,z) ((x>y)?((x>z)?1:3):((y>z)?2:3))
  75.  
  76. void Find_Triangle_Dominant_Axis(Triangle)
  77.    TRIANGLE *Triangle;
  78.    {
  79.    DBL x, y, z;
  80.  
  81.    x = fabs(Triangle->Normal_Vector.x);
  82.    y = fabs (Triangle->Normal_Vector.y);
  83.    z = fabs (Triangle->Normal_Vector.z);
  84.    switch (max3(x, y, z)) {
  85.       case 1: Triangle->Dominant_Axis = X_AXIS;
  86.               break;
  87.       case 2: Triangle->Dominant_Axis = Y_AXIS;
  88.               break;
  89.       case 3: Triangle->Dominant_Axis = Z_AXIS;
  90.               break;
  91.       }
  92.    }
  93.  
  94. void Compute_Smooth_Triangle (Triangle)
  95.    SMOOTH_TRIANGLE *Triangle;
  96.    {
  97.    VECTOR P3MinusP2, VTemp1, VTemp2;
  98.    DBL x, y, z, uDenominator, Proj;
  99.  
  100.    VSub (P3MinusP2, Triangle->P3, Triangle->P2);
  101.    x = fabs (P3MinusP2.x);
  102.    y = fabs (P3MinusP2.y);
  103.    z = fabs (P3MinusP2.z);
  104.  
  105.    switch (max3 (x, y, z)) {
  106.       case 1:  Triangle->vAxis = X_AXIS;
  107.                Triangle->BaseDelta = P3MinusP2.x;
  108.                break;
  109.  
  110.       case 2:  Triangle->vAxis = Y_AXIS;
  111.                Triangle->BaseDelta = P3MinusP2.y;
  112.                break;
  113.  
  114.       case 3:  Triangle->vAxis = Z_AXIS;
  115.                Triangle->BaseDelta = P3MinusP2.z;
  116.                break;
  117.       }   
  118.  
  119.    VSub (VTemp1, Triangle->P2, Triangle->P3);
  120.    VNormalize (VTemp1, VTemp1);
  121.    VSub (VTemp2, Triangle->P1, Triangle->P3);
  122.    VDot (Proj, VTemp2, VTemp1);
  123.    VScale (VTemp1, VTemp1, Proj);
  124.    VSub (Triangle->Perp, VTemp1, VTemp2);
  125.    VNormalize (Triangle->Perp, Triangle->Perp);
  126.    VDot (uDenominator, VTemp2, Triangle->Perp);
  127.    uDenominator = -1.0 / uDenominator;
  128.    VScale (Triangle->Perp, Triangle->Perp, uDenominator);
  129.    }
  130.  
  131. int Compute_Triangle (Triangle)
  132.    TRIANGLE *Triangle;
  133.    {
  134.    VECTOR V1, V2, Temp;
  135.    DBL Length;
  136.  
  137.    VSub (V1, Triangle->P1, Triangle->P2);
  138.    VSub (V2, Triangle->P3, Triangle->P2);
  139.    VCross (Triangle->Normal_Vector, V1, V2);
  140.    VLength (Length, Triangle->Normal_Vector);
  141.    if (Length < 1.0e-9)
  142.       return (0);
  143.  
  144.    VDot (Triangle->Distance, Triangle->Normal_Vector, Triangle->P1);
  145.    Triangle->Distance *= -1.0;
  146.    Find_Triangle_Dominant_Axis(Triangle);
  147.  
  148.    switch (Triangle->Dominant_Axis) {
  149.       case X_AXIS:
  150.          if ((Triangle->P2.y - Triangle->P3.y)*(Triangle->P2.z - Triangle->P1.z) <
  151.              (Triangle->P2.z - Triangle->P3.z)*(Triangle->P2.y - Triangle->P1.y)) {
  152.  
  153.              Temp = Triangle->P2;
  154.              Triangle->P2 = Triangle->P1;
  155.              Triangle->P1 = Temp;
  156.              }
  157.           break;
  158.  
  159.       case Y_AXIS:
  160.          if ((Triangle->P2.x - Triangle->P3.x)*(Triangle->P2.z - Triangle->P1.z) <
  161.              (Triangle->P2.z - Triangle->P3.z)*(Triangle->P2.x - Triangle->P1.x)) {
  162.  
  163.              Temp = Triangle->P2;
  164.              Triangle->P2 = Triangle->P1;
  165.              Triangle->P1 = Temp;
  166.              }
  167.           break;
  168.  
  169.       case Z_AXIS:
  170.          if ((Triangle->P2.x - Triangle->P3.x)*(Triangle->P2.y - Triangle->P1.y) <
  171.              (Triangle->P2.y - Triangle->P3.y)*(Triangle->P2.x - Triangle->P1.x)) {
  172.  
  173.              Temp = Triangle->P2;
  174.              Triangle->P2 = Triangle->P1;
  175.              Triangle->P1 = Temp;
  176.              }
  177.           break;
  178.       }
  179.  
  180.    if (Triangle->Type == SMOOTH_TRIANGLE_TYPE)
  181.       Compute_Smooth_Triangle((SMOOTH_TRIANGLE *) Triangle);
  182.    return (1);
  183.    }
  184.  
  185. int All_Triangle_Intersections (Object, Ray, Depth_Queue)
  186.   OBJECT *Object;
  187.   RAY *Ray;
  188.   PRIOQ *Depth_Queue;
  189.   {
  190.   TRIANGLE *Shape = (TRIANGLE *) Object;
  191.   DBL Depth;
  192.   VECTOR Intersection_Point;
  193.   INTERSECTION Local_Element;
  194.  
  195.   if (Intersect_Triangle (Ray, Shape, &Depth))
  196.     {
  197.     Local_Element.Depth = Depth;
  198.     Local_Element.Object = Shape -> Parent_Object;
  199.     VScale (Intersection_Point, Ray -> Direction, Depth);
  200.     VAdd (Intersection_Point, Intersection_Point, Ray -> Initial);
  201.     Local_Element.Point = Intersection_Point;
  202.     Local_Element.Shape = (SHAPE *)Shape;
  203.     pq_add (Depth_Queue, &Local_Element);
  204.     return (TRUE);
  205.     }
  206.   return (FALSE);
  207.   }
  208.  
  209. int Intersect_Triangle (Ray, Triangle, Depth)
  210.    RAY *Ray;
  211.    TRIANGLE *Triangle;
  212.    DBL *Depth;
  213.    {
  214.    DBL NormalDotOrigin, NormalDotDirection;
  215.    DBL s, t;
  216.  
  217.    Ray_Triangle_Tests++;
  218.    if (Ray == VP_Ray) {
  219.       if (!Triangle->VPCached) {
  220.          VDot (Triangle->VPNormDotOrigin, Triangle->Normal_Vector, Ray->Initial);
  221.          Triangle->VPNormDotOrigin += Triangle->Distance;
  222.          Triangle->VPNormDotOrigin *= -1.0;
  223.          Triangle->VPCached = TRUE;
  224.          }
  225.  
  226.       VDot (NormalDotDirection, Triangle->Normal_Vector, Ray->Direction);
  227.       if ((NormalDotDirection < Small_Tolerance) &&
  228.           (NormalDotDirection > -Small_Tolerance))
  229.          return (FALSE);
  230.  
  231.       *Depth = Triangle->VPNormDotOrigin / NormalDotDirection;
  232.       }
  233.    else {
  234.       VDot (NormalDotOrigin, Triangle->Normal_Vector, Ray->Initial);
  235.       NormalDotOrigin += Triangle->Distance;
  236.       NormalDotOrigin *= -1.0;
  237.  
  238.       VDot (NormalDotDirection, Triangle->Normal_Vector, Ray->Direction);
  239.       if ((NormalDotDirection < Small_Tolerance) &&
  240.           (NormalDotDirection > -Small_Tolerance))
  241.             return (FALSE);
  242.  
  243.       *Depth = NormalDotOrigin / NormalDotDirection;
  244.       }
  245.  
  246.    if ((*Depth < Small_Tolerance) || (*Depth > Max_Distance))
  247.       return (FALSE);
  248.  
  249.    switch (Triangle->Dominant_Axis) {
  250.       case X_AXIS:
  251.          s = Ray->Initial.y + *Depth * Ray->Direction.y;
  252.          t = Ray->Initial.z + *Depth * Ray->Direction.z;
  253.  
  254.          if ((Triangle->P2.y - s)*(Triangle->P2.z - Triangle->P1.z) <
  255.              (Triangle->P2.z - t)*(Triangle->P2.y - Triangle->P1.y))
  256.             if ((int) Triangle->Inverted) {
  257.                Ray_Triangle_Tests_Succeeded++;
  258.                return (TRUE);
  259.                }
  260.             else
  261.                return (FALSE);
  262.  
  263.          if ((Triangle->P3.y - s)*(Triangle->P3.z - Triangle->P2.z) <
  264.              (Triangle->P3.z - t)*(Triangle->P3.y - Triangle->P2.y))
  265.             if ((int) Triangle->Inverted) {
  266.                Ray_Triangle_Tests_Succeeded++;
  267.                return (TRUE);
  268.                }
  269.             else
  270.                return (FALSE);
  271.  
  272.          if ((Triangle->P1.y - s)*(Triangle->P1.z - Triangle->P3.z) <
  273.              (Triangle->P1.z - t)*(Triangle->P1.y - Triangle->P3.y))
  274.             if ((int) Triangle->Inverted) {
  275.                Ray_Triangle_Tests_Succeeded++;
  276.                return (TRUE);
  277.                }
  278.             else
  279.                return (FALSE);
  280.  
  281.          if (!(int) Triangle->Inverted) {
  282.                Ray_Triangle_Tests_Succeeded++;
  283.                return (TRUE);
  284.                }
  285.             else
  286.                return (FALSE);
  287.  
  288.       case Y_AXIS:
  289.          s = Ray->Initial.x + *Depth * Ray->Direction.x;
  290.          t = Ray->Initial.z + *Depth * Ray->Direction.z;
  291.  
  292.          if ((Triangle->P2.x - s)*(Triangle->P2.z - Triangle->P1.z) <
  293.              (Triangle->P2.z - t)*(Triangle->P2.x - Triangle->P1.x))
  294.             if ((int) Triangle->Inverted) {
  295.                Ray_Triangle_Tests_Succeeded++;
  296.                return (TRUE);
  297.                }
  298.             else
  299.                return (FALSE);
  300.  
  301.          if ((Triangle->P3.x - s)*(Triangle->P3.z - Triangle->P2.z) <
  302.              (Triangle->P3.z - t)*(Triangle->P3.x - Triangle->P2.x))
  303.             if ((int) Triangle->Inverted) {
  304.                Ray_Triangle_Tests_Succeeded++;
  305.                return (TRUE);
  306.                }
  307.             else
  308.                return (FALSE);
  309.  
  310.          if ((Triangle->P1.x - s)*(Triangle->P1.z - Triangle->P3.z) <
  311.              (Triangle->P1.z - t)*(Triangle->P1.x - Triangle->P3.x))
  312.             if ((int) Triangle->Inverted) {
  313.                Ray_Triangle_Tests_Succeeded++;
  314.                return (TRUE);
  315.                }
  316.             else
  317.                return (FALSE);
  318.  
  319.          if (!(int) Triangle->Inverted) {
  320.                Ray_Triangle_Tests_Succeeded++;
  321.                return (TRUE);
  322.                }
  323.             else
  324.                return (FALSE);
  325.  
  326.       case Z_AXIS:
  327.          s = Ray->Initial.x + *Depth * Ray->Direction.x;
  328.          t = Ray->Initial.y + *Depth * Ray->Direction.y;
  329.  
  330.          if ((Triangle->P2.x - s)*(Triangle->P2.y - Triangle->P1.y) <
  331.              (Triangle->P2.y - t)*(Triangle->P2.x - Triangle->P1.x))
  332.             if ((int) Triangle->Inverted) {
  333.                Ray_Triangle_Tests_Succeeded++;
  334.                return (TRUE);
  335.                }
  336.             else
  337.                return (FALSE);
  338.  
  339.          if ((Triangle->P3.x - s)*(Triangle->P3.y - Triangle->P2.y) <
  340.              (Triangle->P3.y - t)*(Triangle->P3.x - Triangle->P2.x))
  341.             if ((int) Triangle->Inverted) {
  342.                Ray_Triangle_Tests_Succeeded++;
  343.                return (TRUE);
  344.                }
  345.             else
  346.                return (FALSE);
  347.  
  348.          if ((Triangle->P1.x - s)*(Triangle->P1.y - Triangle->P3.y) <
  349.              (Triangle->P1.y - t)*(Triangle->P1.x - Triangle->P3.x))
  350.             if ((int) Triangle->Inverted) {
  351.                Ray_Triangle_Tests_Succeeded++;
  352.                return (TRUE);
  353.                }
  354.             else
  355.                return (FALSE);
  356.  
  357.          if (!(int) Triangle->Inverted) {
  358.                Ray_Triangle_Tests_Succeeded++;
  359.                return (TRUE);
  360.                }
  361.             else
  362.                return (FALSE);
  363.  
  364.       }
  365.    return (FALSE);
  366.    }
  367.  
  368. int Inside_Triangle (Point, Object)
  369.    VECTOR *Point;
  370.    OBJECT *Object;
  371.    {
  372.    return (FALSE);
  373.    }
  374.  
  375. void Triangle_Normal (Result, Object, Intersection_Point)
  376.    OBJECT *Object;
  377.    VECTOR *Result, *Intersection_Point;
  378.    {
  379.    TRIANGLE *Triangle = (TRIANGLE *) Object;
  380.  
  381.    *Result = Triangle->Normal_Vector;
  382.    Perturb_Normal (Result, Triangle->Parent_Object,
  383.                    Intersection_Point, Result);
  384.    }
  385.  
  386. void *Copy_Triangle (Object)
  387.    OBJECT *Object;
  388.    {
  389.    TRIANGLE *New_Shape;
  390.  
  391.    New_Shape = Get_Triangle_Shape ();
  392.    *New_Shape = * ((TRIANGLE *)Object);
  393.    New_Shape -> Next_Object = NULL;
  394.    return (New_Shape);
  395.    }
  396.  
  397. void Translate_Triangle (Object, Vector)
  398.    OBJECT *Object;
  399.    VECTOR *Vector;
  400.    {
  401.    TRIANGLE *Triangle = (TRIANGLE *) Object;
  402.    VECTOR Translation;
  403.  
  404.    VEvaluate (Translation, Triangle->Normal_Vector, *Vector);
  405.    Triangle->Distance -= Translation.x + Translation.y + Translation.z;
  406.    VAdd (Triangle->P1, Triangle->P1, *Vector)
  407.    VAdd (Triangle->P2, Triangle->P2, *Vector)
  408.    VAdd (Triangle->P3, Triangle->P3, *Vector)
  409.    }
  410.  
  411. void Rotate_Triangle (Object, Vector)
  412.    OBJECT *Object;
  413.    VECTOR *Vector;
  414.    {
  415.    TRANSFORMATION Transformation;
  416.    TRIANGLE *Triangle = (TRIANGLE *) Object;
  417.  
  418.    Get_Rotation_Transformation (&Transformation, Vector);
  419.    MTransformVector (&Triangle->Normal_Vector,
  420.                      &Triangle->Normal_Vector, &Transformation);
  421.    MTransformVector (&Triangle->P1, &Triangle->P1, &Transformation);
  422.    MTransformVector (&Triangle->P2, &Triangle->P2, &Transformation);
  423.    MTransformVector (&Triangle->P3, &Triangle->P3, &Transformation);
  424.    Compute_Triangle (Triangle);
  425.    }
  426.  
  427. void Scale_Triangle (Object, Vector)
  428.    OBJECT *Object;
  429.    VECTOR *Vector;
  430.    {
  431.    TRIANGLE *Triangle = (TRIANGLE *) Object;
  432.    DBL Length;
  433.  
  434.    Triangle->Normal_Vector.x = Triangle->Normal_Vector.x / Vector->x;
  435.    Triangle->Normal_Vector.y = Triangle->Normal_Vector.y / Vector->y;
  436.    Triangle->Normal_Vector.z = Triangle->Normal_Vector.z / Vector->z;
  437.  
  438.    VLength(Length, Triangle->Normal_Vector);
  439.    VScale (Triangle->Normal_Vector, Triangle->Normal_Vector, 1.0 / Length);
  440.    Triangle->Distance /= Length;
  441.  
  442.    VEvaluate (Triangle->P1, Triangle->P1, *Vector);
  443.    VEvaluate (Triangle->P2, Triangle->P2, *Vector);
  444.    VEvaluate (Triangle->P3, Triangle->P3, *Vector);
  445.    }
  446.  
  447.  
  448. void Invert_Triangle (Object)
  449.    OBJECT *Object;
  450.    {
  451.    TRIANGLE *Triangle = (TRIANGLE  *) Object;
  452.  
  453.    Triangle->Inverted ^= TRUE;
  454.    }
  455.  
  456. /* Calculate the Phong-interpolated vector within the triangle
  457.    at the given intersection point. The math for this is a bit
  458.    bizarre:
  459.  
  460.     -         P1
  461.     |        /|\ \
  462.     |       / |Perp\
  463.     |      /  V  \   \
  464.     |     /   |    \   \
  465.   u |    /____|_____PI___\
  466.     |   /     |       \    \
  467.     -  P2-----|--------|----P3
  468.               Pbase    PIntersect
  469.         |-------------------|
  470.                        v
  471.  
  472.    Triangle->Perp is a unit vector from P1 to Pbase. We calculate
  473.  
  474.    u = (PI - P1) DOT Perp / ((P3 - P1) DOT Perp).
  475.  
  476.    We then calculate where the line from P1 to PI intersects the line P2 to P3:
  477.    PIntersect = (PI - P1)/u.
  478.  
  479.    We really only need one coordinate of PIntersect.  We then calculate v as:
  480.  
  481.       v = PIntersect.x / (P3.x - P2.x)
  482.  or   v = PIntersect.y / (P3.y - P2.y)
  483.  or   v = PIntersect.z / (P3.z - P2.z)
  484.  
  485.    depending on which calculation will give us the best answers.
  486.  
  487.    Once we have u and v, we can perform the normal interpolation as:
  488.  
  489.      NTemp1 = N1 + u(N2 - N1);
  490.      NTemp2 = N1 + u(N3 - N1);
  491.      Result = normalize (NTemp1 + v(NTemp2 - NTemp1))
  492.  
  493.    As always, any values which are constant for the triangle are cached
  494.    in the triangle.
  495. */
  496.  
  497. void Smooth_Triangle_Normal (Result, Object, Intersection_Point)
  498.    OBJECT *Object;
  499.    VECTOR *Result, *Intersection_Point;
  500.    {
  501.    SMOOTH_TRIANGLE *Triangle = (SMOOTH_TRIANGLE *) Object;
  502.    VECTOR PIMinusP1, NTemp1, NTemp2;
  503.    DBL u, v;
  504.  
  505.    VSub (PIMinusP1, *Intersection_Point, Triangle->P1);
  506.    VDot (u, PIMinusP1, Triangle->Perp);
  507.    if (u < 1.0e-9) {
  508.       *Result = Triangle->N1;
  509.       return;
  510.       }
  511.  
  512.    /* BaseDelta contains P3.x-P2.x,  P3.y-P2.y, or P3.z-P2.z depending on the
  513.       value of vAxis. */
  514.  
  515.    switch (Triangle->vAxis) {
  516.       case X_AXIS:  v = (PIMinusP1.x/u + Triangle->P1.x - Triangle->P2.x) / Triangle->BaseDelta;
  517.                break;
  518.  
  519.       case Y_AXIS:  v = (PIMinusP1.y/u + Triangle->P1.y - Triangle->P2.y) / Triangle->BaseDelta;
  520.                break;
  521.  
  522.       case Z_AXIS:  v = (PIMinusP1.z/u + Triangle->P1.z - Triangle->P2.z)/ Triangle->BaseDelta;
  523.                break;
  524.       }
  525.  
  526.    VScale (NTemp1, Triangle->DN12, u);
  527.    VAdd (NTemp1, NTemp1, Triangle->N1);
  528.    VScale (NTemp2, Triangle->DN13, u);
  529.    VAdd (NTemp2, NTemp2, Triangle->N1);
  530.    VSub (*Result, NTemp2, NTemp1);
  531.    VScale (*Result, *Result, v);
  532.    VAdd (*Result, *Result, NTemp1); 
  533.    VNormalize (*Result, *Result);
  534.    Perturb_Normal (Result, Triangle->Parent_Object,
  535.                    Intersection_Point, Result);
  536.    }
  537.  
  538. void *Copy_Smooth_Triangle (Object)
  539.    OBJECT *Object;
  540.    {
  541.    SMOOTH_TRIANGLE *New_Shape;
  542.  
  543.    New_Shape = Get_Smooth_Triangle_Shape ();
  544.    *New_Shape = * ((SMOOTH_TRIANGLE *)Object);
  545.    New_Shape -> Next_Object = NULL;
  546.    return (New_Shape);
  547.    }
  548.  
  549. void Rotate_Smooth_Triangle (Object, Vector)
  550.    OBJECT *Object;
  551.    VECTOR *Vector;
  552.    {
  553.    TRANSFORMATION Transformation;
  554.    SMOOTH_TRIANGLE *Triangle = (SMOOTH_TRIANGLE *) Object;
  555.  
  556.    Get_Rotation_Transformation (&Transformation, Vector);
  557.    MTransformVector (&Triangle->Normal_Vector,
  558.                      &Triangle->Normal_Vector, &Transformation);
  559.    MTransformVector (&Triangle->P1, &Triangle->P1, &Transformation);
  560.    MTransformVector (&Triangle->P2, &Triangle->P2, &Transformation);
  561.    MTransformVector (&Triangle->P3, &Triangle->P3, &Transformation);
  562.    MTransformVector (&Triangle->N1, &Triangle->N1, &Transformation);
  563.    MTransformVector (&Triangle->DN12, &Triangle->DN12, &Transformation);
  564.    MTransformVector (&Triangle->DN13, &Triangle->DN13, &Transformation);
  565.    Compute_Triangle ((TRIANGLE *) Triangle);
  566.    }
  567.