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

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