/**************************************************************************** * triangle.c * * This module implements primitives for triangles and smooth triangles. * * from Persistence of Vision(tm) Ray Tracer * Copyright 1996 Persistence of Vision Team *--------------------------------------------------------------------------- * NOTICE: This source code file is provided so that users may experiment * with enhancements to POV-Ray and to port the software to platforms other * than those supported by the POV-Ray Team. There are strict rules under * which you are permitted to use this file. The rules are in the file * named POVLEGAL.DOC which should be distributed with this file. If * POVLEGAL.DOC is not available or for more info please contact the POV-Ray * Team Coordinator by leaving a message in CompuServe's Graphics Developer's * Forum. The latest version of POV-Ray may be found there as well. * * This program is based on the popular DKB raytracer version 2.12. * DKBTrace was originally written by David K. Buck. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins. * *****************************************************************************/ #include "frame.h" #include "povray.h" #include "vector.h" #include "povproto.h" #include "matrices.h" #include "objects.h" #include "triangle.h" /***************************************************************************** * Local preprocessor defines ******************************************************************************/ #define DEPTH_TOLERANCE 1e-6 #define max3_coordinate(x,y,z) \ ((x > y) ? ((x > z) ? X : Z) : ((y > z) ? Y : Z)) /***************************************************************************** * Static functions ******************************************************************************/ static void find_triangle_dominant_axis PARAMS((TRIANGLE *Triangle)); static void compute_smooth_triangle PARAMS((SMOOTH_TRIANGLE *Triangle)); static int Intersect_Triangle PARAMS((RAY *Ray, TRIANGLE *Triangle, DBL *Depth)); static int All_Triangle_Intersections PARAMS((OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack)); static int Inside_Triangle PARAMS((VECTOR IPoint, OBJECT *Object)); static void Triangle_Normal PARAMS((VECTOR Result, OBJECT *Object, INTERSECTION *Inter)); static void *Copy_Triangle PARAMS((OBJECT *Object)); static void Translate_Triangle PARAMS((OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)); static void Rotate_Triangle PARAMS((OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)); static void Scale_Triangle PARAMS((OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)); static void Transform_Triangle PARAMS((OBJECT *Object, TRANSFORM *Trans)); static void Invert_Triangle PARAMS((OBJECT *Object)); static void Smooth_Triangle_Normal PARAMS((VECTOR Result, OBJECT *Object, INTERSECTION *Inter)); static void *Copy_Smooth_Triangle PARAMS((OBJECT *Object)); static void Translate_Smooth_Triangle PARAMS((OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)); static void Rotate_Smooth_Triangle PARAMS((OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)); static void Scale_Smooth_Triangle PARAMS((OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)); static void Transform_Smooth_Triangle PARAMS((OBJECT *Object, TRANSFORM *Trans)); static void Invert_Smooth_Triangle PARAMS((OBJECT *Object)); static void Destroy_Triangle PARAMS((OBJECT *Object)); /***************************************************************************** * Local variables ******************************************************************************/ METHODS Triangle_Methods = { All_Triangle_Intersections, Inside_Triangle, Triangle_Normal, Copy_Triangle, Translate_Triangle, Rotate_Triangle, Scale_Triangle, Transform_Triangle, Invert_Triangle, Destroy_Triangle }; METHODS Smooth_Triangle_Methods = { All_Triangle_Intersections, Inside_Triangle, Smooth_Triangle_Normal, Copy_Smooth_Triangle, Translate_Smooth_Triangle, Rotate_Smooth_Triangle, Scale_Smooth_Triangle, Transform_Smooth_Triangle, Invert_Smooth_Triangle, Destroy_Triangle }; /***************************************************************************** * * FUNCTION * * find_triangle_dominant_axis * * INPUT * * OUTPUT * * RETURNS * * AUTHOR * * POV-Ray Team * * DESCRIPTION * * - * * CHANGES * * - * ******************************************************************************/ static void find_triangle_dominant_axis(Triangle) TRIANGLE *Triangle; { DBL x, y, z; x = fabs(Triangle->Normal_Vector[X]); y = fabs(Triangle->Normal_Vector[Y]); z = fabs(Triangle->Normal_Vector[Z]); Triangle->Dominant_Axis = max3_coordinate(x, y, z); } /***************************************************************************** * * FUNCTION * * compute_smooth_triangle * * INPUT * * OUTPUT * * RETURNS * * AUTHOR * * POV-Ray Team * * DESCRIPTION * * - * * CHANGES * * - * ******************************************************************************/ static void compute_smooth_triangle(Triangle) SMOOTH_TRIANGLE *Triangle; { VECTOR P3MinusP2, VTemp1, VTemp2; DBL x, y, z, uDenominator, Proj; VSub(P3MinusP2, Triangle->P3, Triangle->P2); x = fabs(P3MinusP2[X]); y = fabs(P3MinusP2[Y]); z = fabs(P3MinusP2[Z]); Triangle->vAxis = max3_coordinate(x, y, z); VSub(VTemp1, Triangle->P2, Triangle->P3); VNormalize(VTemp1, VTemp1); VSub(VTemp2, Triangle->P1, Triangle->P3); VDot(Proj, VTemp2, VTemp1); VScaleEq(VTemp1, Proj); VSub(Triangle->Perp, VTemp1, VTemp2); VNormalize(Triangle->Perp, Triangle->Perp); VDot(uDenominator, VTemp2, Triangle->Perp); VInverseScaleEq(Triangle->Perp, -uDenominator); } /***************************************************************************** * * FUNCTION * * Compute_Triangle * * INPUT * * OUTPUT * * RETURNS * * AUTHOR * * POV-Ray Team * * DESCRIPTION * * - * * CHANGES * * - * ******************************************************************************/ int Compute_Triangle(Triangle,Smooth) TRIANGLE *Triangle; int Smooth; { int swap; VECTOR V1, V2, Temp; DBL Length; VSub(V1, Triangle->P1, Triangle->P2); VSub(V2, Triangle->P3, Triangle->P2); VCross(Triangle->Normal_Vector, V1, V2); VLength(Length, Triangle->Normal_Vector); /* Set up a flag so we can ignore degenerate triangles */ if (Length == 0.0) { Set_Flag(Triangle, DEGENERATE_FLAG); return(FALSE); } /* Normalize the normal vector. */ VInverseScaleEq(Triangle->Normal_Vector, Length); VDot(Triangle->Distance, Triangle->Normal_Vector, Triangle->P1); Triangle->Distance *= -1.0; find_triangle_dominant_axis(Triangle); swap = FALSE; switch (Triangle->Dominant_Axis) { case X: if ((Triangle->P2[Y] - Triangle->P3[Y])*(Triangle->P2[Z] - Triangle->P1[Z]) < (Triangle->P2[Z] - Triangle->P3[Z])*(Triangle->P2[Y] - Triangle->P1[Y])) { swap = TRUE; } break; case Y: if ((Triangle->P2[X] - Triangle->P3[X])*(Triangle->P2[Z] - Triangle->P1[Z]) < (Triangle->P2[Z] - Triangle->P3[Z])*(Triangle->P2[X] - Triangle->P1[X])) { swap = TRUE; } break; case Z: if ((Triangle->P2[X] - Triangle->P3[X])*(Triangle->P2[Y] - Triangle->P1[Y]) < (Triangle->P2[Y] - Triangle->P3[Y])*(Triangle->P2[X] - Triangle->P1[X])) { swap = TRUE; } break; } if (swap) { Assign_Vector(Temp, Triangle->P2); Assign_Vector(Triangle->P2, Triangle->P1); Assign_Vector(Triangle->P1, Temp); if (Smooth) { Assign_Vector(Temp, ((SMOOTH_TRIANGLE *)Triangle)->N2); Assign_Vector(((SMOOTH_TRIANGLE *)Triangle)->N2, ((SMOOTH_TRIANGLE *)Triangle)->N1); Assign_Vector(((SMOOTH_TRIANGLE *)Triangle)->N1, Temp); } } if (Smooth) { compute_smooth_triangle((SMOOTH_TRIANGLE *)Triangle); } /* Build the bounding information from the vertices. */ Compute_Triangle_BBox(Triangle); return(TRUE); } /***************************************************************************** * * FUNCTION * * All_Triangle_Intersections * * INPUT * * OUTPUT * * RETURNS * * AUTHOR * * POV-Ray Team * * DESCRIPTION * * - * * CHANGES * * - * ******************************************************************************/ static int All_Triangle_Intersections(Object, Ray, Depth_Stack) OBJECT *Object; RAY *Ray; ISTACK *Depth_Stack; { DBL Depth; VECTOR IPoint; if (Intersect_Triangle(Ray, (TRIANGLE *)Object, &Depth)) { VEvaluateRay(IPoint, Ray->Initial, Depth, Ray->Direction); if (Point_In_Clip(IPoint,Object->Clip)) { push_entry(Depth,IPoint,Object,Depth_Stack); return(TRUE); } } return(FALSE); } /***************************************************************************** * * FUNCTION * * Intersect_Triangle * * INPUT * * OUTPUT * * RETURNS * * AUTHOR * * POV-Ray Team * * DESCRIPTION * * - * * CHANGES * * - * ******************************************************************************/ static int Intersect_Triangle(Ray, Triangle, Depth) RAY *Ray; TRIANGLE *Triangle; DBL *Depth; { DBL NormalDotOrigin, NormalDotDirection; DBL s, t; Increase_Counter(stats[Ray_Triangle_Tests]); if (Test_Flag(Triangle, DEGENERATE_FLAG)) { return(FALSE); } VDot(NormalDotDirection, Triangle->Normal_Vector, Ray->Direction); if (fabs(NormalDotDirection) < EPSILON) { return(FALSE); } VDot(NormalDotOrigin, Triangle->Normal_Vector, Ray->Initial); *Depth = -(Triangle->Distance + NormalDotOrigin) / NormalDotDirection; if ((*Depth < DEPTH_TOLERANCE) || (*Depth > Max_Distance)) { return(FALSE); } switch (Triangle->Dominant_Axis) { case X: s = Ray->Initial[Y] + *Depth * Ray->Direction[Y]; t = Ray->Initial[Z] + *Depth * Ray->Direction[Z]; if ((Triangle->P2[Y] - s) * (Triangle->P2[Z] - Triangle->P1[Z]) < (Triangle->P2[Z] - t) * (Triangle->P2[Y] - Triangle->P1[Y])) { return(FALSE); } if ((Triangle->P3[Y] - s) * (Triangle->P3[Z] - Triangle->P2[Z]) < (Triangle->P3[Z] - t) * (Triangle->P3[Y] - Triangle->P2[Y])) { return(FALSE); } if ((Triangle->P1[Y] - s) * (Triangle->P1[Z] - Triangle->P3[Z]) < (Triangle->P1[Z] - t) * (Triangle->P1[Y] - Triangle->P3[Y])) { return(FALSE); } Increase_Counter(stats[Ray_Triangle_Tests_Succeeded]); return(TRUE); case Y: s = Ray->Initial[X] + *Depth * Ray->Direction[X]; t = Ray->Initial[Z] + *Depth * Ray->Direction[Z]; if ((Triangle->P2[X] - s) * (Triangle->P2[Z] - Triangle->P1[Z]) < (Triangle->P2[Z] - t) * (Triangle->P2[X] - Triangle->P1[X])) { return(FALSE); } if ((Triangle->P3[X] - s) * (Triangle->P3[Z] - Triangle->P2[Z]) < (Triangle->P3[Z] - t) * (Triangle->P3[X] - Triangle->P2[X])) { return(FALSE); } if ((Triangle->P1[X] - s) * (Triangle->P1[Z] - Triangle->P3[Z]) < (Triangle->P1[Z] - t) * (Triangle->P1[X] - Triangle->P3[X])) { return(FALSE); } Increase_Counter(stats[Ray_Triangle_Tests_Succeeded]); return(TRUE); case Z: s = Ray->Initial[X] + *Depth * Ray->Direction[X]; t = Ray->Initial[Y] + *Depth * Ray->Direction[Y]; if ((Triangle->P2[X] - s) * (Triangle->P2[Y] - Triangle->P1[Y]) < (Triangle->P2[Y] - t) * (Triangle->P2[X] - Triangle->P1[X])) { return(FALSE); } if ((Triangle->P3[X] - s) * (Triangle->P3[Y] - Triangle->P2[Y]) < (Triangle->P3[Y] - t) * (Triangle->P3[X] - Triangle->P2[X])) { return(FALSE); } if ((Triangle->P1[X] - s) * (Triangle->P1[Y] - Triangle->P3[Y]) < (Triangle->P1[Y] - t) * (Triangle->P1[X] - Triangle->P3[X])) { return(FALSE); } Increase_Counter(stats[Ray_Triangle_Tests_Succeeded]); return(TRUE); } return(FALSE); } /***************************************************************************** * * FUNCTION * * Inside_Triangle * * INPUT * * OUTPUT * * RETURNS * * AUTHOR * * POV-Ray Team * * DESCRIPTION * * - * * CHANGES * * - * ******************************************************************************/ static int Inside_Triangle(IPoint, Object) VECTOR IPoint; OBJECT *Object; { return(FALSE); } /***************************************************************************** * * FUNCTION * * Triangle_Normal * * INPUT * * OUTPUT * * RETURNS * * AUTHOR * * POV-Ray Team * * DESCRIPTION * * - * * CHANGES * * - * ******************************************************************************/ static void Triangle_Normal(Result, Object, Inter) OBJECT *Object; VECTOR Result; INTERSECTION *Inter; { Assign_Vector(Result, ((TRIANGLE *)Object)->Normal_Vector); } /***************************************************************************** * * FUNCTION * * Smooth_Triangle_Normal * * INPUT * * OUTPUT * * RETURNS * * AUTHOR * * POV-Ray Team * * DESCRIPTION * * Calculate the Phong-interpolated vector within the triangle * at the given intersection point. The math for this is a bit * bizarre: * * - P1 * | /|\ \ * | / |Perp\ * | / V \ \ * | / | \ \ * u | /____|_____PI___\ * | / | \ \ * - P2-----|--------|----P3 * Pbase PIntersect * |-------------------| * v * * Triangle->Perp is a unit vector from P1 to Pbase. We calculate * * u = (PI - P1) DOT Perp / ((P3 - P1) DOT Perp). * * We then calculate where the line from P1 to PI intersects the line P2 to P3: * PIntersect = (PI - P1)/u. * * We really only need one coordinate of PIntersect. We then calculate v as: * * v = PIntersect[X] / (P3[X] - P2[X]) * or v = PIntersect[Y] / (P3[Y] - P2[Y]) * or v = PIntersect[Z] / (P3[Z] - P2[Z]) * * depending on which calculation will give us the best answers. * * Once we have u and v, we can perform the normal interpolation as: * * NTemp1 = N1 + u(N2 - N1); * NTemp2 = N1 + u(N3 - N1); * Result = normalize (NTemp1 + v(NTemp2 - NTemp1)) * * As always, any values which are constant for the triangle are cached * in the triangle. * * CHANGES * * - * ******************************************************************************/ static void Smooth_Triangle_Normal(Result, Object, Inter) OBJECT *Object; VECTOR Result; INTERSECTION *Inter; { int Axis; DBL u, v; VECTOR PIMinusP1; SMOOTH_TRIANGLE *Triangle = (SMOOTH_TRIANGLE *)Object; VSub(PIMinusP1, Inter->IPoint, Triangle->P1); VDot(u, PIMinusP1, Triangle->Perp); if (u < EPSILON) { Assign_Vector(Result, Triangle->N1); return; } Axis = Triangle->vAxis; v = (PIMinusP1[Axis] / u + Triangle->P1[Axis] - Triangle->P2[Axis]) / (Triangle->P3[Axis] - Triangle->P2[Axis]); /* This is faster. [DB 8/94] */ Result[X] = Triangle->N1[X] + u * (Triangle->N2[X] - Triangle->N1[X] + v * (Triangle->N3[X] - Triangle->N2[X])); Result[Y] = Triangle->N1[Y] + u * (Triangle->N2[Y] - Triangle->N1[Y] + v * (Triangle->N3[Y] - Triangle->N2[Y])); Result[Z] = Triangle->N1[Z] + u * (Triangle->N2[Z] - Triangle->N1[Z] + v * (Triangle->N3[Z] - Triangle->N2[Z])); VNormalize(Result, Result); } /***************************************************************************** * * FUNCTION * * Translate_Triangle * * INPUT * * OUTPUT * * RETURNS * * AUTHOR * * POV-Ray Team * * DESCRIPTION * * - * * CHANGES * * - * ******************************************************************************/ static void Translate_Triangle(Object, Vector, Trans) OBJECT *Object; VECTOR Vector; TRANSFORM *Trans; { TRIANGLE *Triangle = (TRIANGLE *)Object; VECTOR Translation; if (!Test_Flag(Triangle, DEGENERATE_FLAG)) { VEvaluate(Translation, Triangle->Normal_Vector, Vector); Triangle->Distance -= Translation[X] + Translation[Y] + Translation[Z]; VAddEq(Triangle->P1, Vector); VAddEq(Triangle->P2, Vector); VAddEq(Triangle->P3, Vector); Compute_Triangle(Triangle, FALSE); } } /***************************************************************************** * * FUNCTION * * Rotate_Triangle * * INPUT * * OUTPUT * * RETURNS * * AUTHOR * * POV-Ray Team * * DESCRIPTION * * - * * CHANGES * * - * ******************************************************************************/ static void Rotate_Triangle(Object, Vector, Trans) OBJECT *Object; VECTOR Vector; TRANSFORM *Trans; { if (!Test_Flag(Object, DEGENERATE_FLAG)) { Transform_Triangle(Object, Trans); } } /***************************************************************************** * * FUNCTION * * Scale_Triangle * * INPUT * * OUTPUT * * RETURNS * * AUTHOR * * POV-Ray Team * * DESCRIPTION * * - * * CHANGES * * - * ******************************************************************************/ static void Scale_Triangle(Object, Vector, Trans) OBJECT *Object; VECTOR Vector; TRANSFORM *Trans; { DBL Length; TRIANGLE *Triangle = (TRIANGLE *)Object; if (!Test_Flag(Object, DEGENERATE_FLAG)) { Triangle->Normal_Vector[X] = Triangle->Normal_Vector[X] / Vector[X]; Triangle->Normal_Vector[Y] = Triangle->Normal_Vector[Y] / Vector[Y]; Triangle->Normal_Vector[Z] = Triangle->Normal_Vector[Z] / Vector[Z]; VLength(Length, Triangle->Normal_Vector); VInverseScaleEq(Triangle->Normal_Vector, Length); Triangle->Distance /= Length; VEvaluateEq(Triangle->P1, Vector); VEvaluateEq(Triangle->P2, Vector); VEvaluateEq(Triangle->P3, Vector); Compute_Triangle(Triangle, FALSE); } } /***************************************************************************** * * FUNCTION * * Transfrom_Triangle * * INPUT * * OUTPUT * * RETURNS * * AUTHOR * * POV-Ray Team * * DESCRIPTION * * - * * CHANGES * * - * ******************************************************************************/ static void Transform_Triangle(Object, Trans) OBJECT *Object; TRANSFORM *Trans; { TRIANGLE *Triangle = (TRIANGLE *)Object; if (!Test_Flag(Object, DEGENERATE_FLAG)) { MTransPoint(Triangle->Normal_Vector,Triangle->Normal_Vector, Trans); MTransPoint(Triangle->P1, Triangle->P1, Trans); MTransPoint(Triangle->P2, Triangle->P2, Trans); MTransPoint(Triangle->P3, Triangle->P3, Trans); Compute_Triangle(Triangle, FALSE); } } /***************************************************************************** * * FUNCTION * * Invert_Triangle * * INPUT * * OUTPUT * * RETURNS * * AUTHOR * * POV-Ray Team * * DESCRIPTION * * - * * CHANGES * * - * ******************************************************************************/ static void Invert_Triangle(Object) OBJECT *Object; { } /***************************************************************************** * * FUNCTION * * Create_Triangle * * INPUT * * OUTPUT * * RETURNS * * AUTHOR * * POV-Ray Team * * DESCRIPTION * * - * * CHANGES * * - * ******************************************************************************/ TRIANGLE *Create_Triangle() { TRIANGLE *New; New = (TRIANGLE *)POV_MALLOC(sizeof(TRIANGLE), "triangle"); INIT_OBJECT_FIELDS(New,TRIANGLE_OBJECT,&Triangle_Methods) Make_Vector(New->Normal_Vector, 0.0, 1.0, 0.0); New->Distance = 0.0; Make_Vector(New->P1, 0.0, 0.0, 0.0); Make_Vector(New->P2, 1.0, 0.0, 0.0); Make_Vector(New->P3, 0.0, 1.0, 0.0); /* * NOTE: Dominant_Axis is computed when Parse_Triangle calls * Compute_Triangle. vAxis is used only for smooth triangles. */ return(New); } /***************************************************************************** * * FUNCTION * * Copy_Triangle * * INPUT * * OUTPUT * * RETURNS * * AUTHOR * * POV-Ray Team * * DESCRIPTION * * - * * CHANGES * * - * ******************************************************************************/ static void *Copy_Triangle(Object) OBJECT *Object; { TRIANGLE *New; New = Create_Triangle(); *New = *((TRIANGLE *)Object); return(New); } /***************************************************************************** * * FUNCTION * * Destroy_Triangle * * INPUT * * OUTPUT * * RETURNS * * AUTHOR * * POV-Ray Team * * DESCRIPTION * * - * * CHANGES * * - * ******************************************************************************/ static void Destroy_Triangle(Object) OBJECT *Object; { POV_FREE (Object); } /***************************************************************************** * * FUNCTION * * Translate_Smooth_Triangle * * INPUT * * OUTPUT * * RETURNS * * AUTHOR * * POV-Ray Team * * DESCRIPTION * * - * * CHANGES * * - * ******************************************************************************/ static void Translate_Smooth_Triangle(Object, Vector, Trans) OBJECT *Object; VECTOR Vector; TRANSFORM *Trans; { SMOOTH_TRIANGLE *Triangle = (SMOOTH_TRIANGLE *)Object; VECTOR Translation; if (!Test_Flag(Object, DEGENERATE_FLAG)) { VEvaluate(Translation, Triangle->Normal_Vector, Vector); Triangle->Distance -= Translation[X] + Translation[Y] + Translation[Z]; VAddEq(Triangle->P1, Vector); VAddEq(Triangle->P2, Vector); VAddEq(Triangle->P3, Vector); Compute_Triangle((TRIANGLE *)Triangle, TRUE); } } /***************************************************************************** * * FUNCTION * * Rotate_Smooth_Triangle * * INPUT * * OUTPUT * * RETURNS * * AUTHOR * * POV-Ray Team * * DESCRIPTION * * - * * CHANGES * * - * ******************************************************************************/ static void Rotate_Smooth_Triangle(Object, Vector, Trans) OBJECT *Object; VECTOR Vector; TRANSFORM *Trans; { if (!Test_Flag(Object, DEGENERATE_FLAG)) { Transform_Smooth_Triangle(Object, Trans); } } /***************************************************************************** * * FUNCTION * * Scale_Smooth_Triangle * * INPUT * * OUTPUT * * RETURNS * * AUTHOR * * POV-Ray Team * * DESCRIPTION * * - * * CHANGES * * - * ******************************************************************************/ static void Scale_Smooth_Triangle(Object, Vector, Trans) OBJECT *Object; VECTOR Vector; TRANSFORM *Trans; { DBL Length; SMOOTH_TRIANGLE *Triangle = (SMOOTH_TRIANGLE *)Object; if (!Test_Flag(Object, DEGENERATE_FLAG)) { Triangle->Normal_Vector[X] = Triangle->Normal_Vector[X] / Vector[X]; Triangle->Normal_Vector[Y] = Triangle->Normal_Vector[Y] / Vector[Y]; Triangle->Normal_Vector[Z] = Triangle->Normal_Vector[Z] / Vector[Z]; VLength(Length, Triangle->Normal_Vector); VScaleEq(Triangle->Normal_Vector, 1.0 / Length); Triangle->Distance /= Length; VEvaluateEq(Triangle->P1, Vector); VEvaluateEq(Triangle->P2, Vector); VEvaluateEq(Triangle->P3, Vector); Compute_Triangle((TRIANGLE *)Triangle,TRUE); } } /***************************************************************************** * * FUNCTION * * Transform_Smooth_Triangle * * INPUT * * OUTPUT * * RETURNS * * AUTHOR * * POV-Ray Team * * DESCRIPTION * * - * * CHANGES * * - * ******************************************************************************/ static void Transform_Smooth_Triangle(Object, Trans) OBJECT *Object; TRANSFORM *Trans; { SMOOTH_TRIANGLE *Triangle = (SMOOTH_TRIANGLE *)Object; if (!Test_Flag(Object, DEGENERATE_FLAG)) { MTransPoint(Triangle->Normal_Vector,Triangle->Normal_Vector, Trans); MTransPoint(Triangle->P1, Triangle->P1, Trans); MTransPoint(Triangle->P2, Triangle->P2, Trans); MTransPoint(Triangle->P3, Triangle->P3, Trans); MTransPoint(Triangle->N1, Triangle->N1, Trans); MTransPoint(Triangle->N2, Triangle->N2, Trans); MTransPoint(Triangle->N3, Triangle->N3, Trans); Compute_Triangle((TRIANGLE *)Triangle, TRUE); } } /***************************************************************************** * * FUNCTION * * Invert_Smooth_Triangle * * INPUT * * OUTPUT * * RETURNS * * AUTHOR * * POV-Ray Team * * DESCRIPTION * * - * * CHANGES * * - * ******************************************************************************/ static void Invert_Smooth_Triangle(Object) OBJECT *Object; { } /***************************************************************************** * * FUNCTION * * Create_Smooth_Triangle * * INPUT * * OUTPUT * * RETURNS * * AUTHOR * * POV-Ray Team * * DESCRIPTION * * - * * CHANGES * * - * ******************************************************************************/ SMOOTH_TRIANGLE *Create_Smooth_Triangle() { SMOOTH_TRIANGLE *New; New = (SMOOTH_TRIANGLE *)POV_MALLOC(sizeof(SMOOTH_TRIANGLE), "smooth triangle"); INIT_OBJECT_FIELDS(New,SMOOTH_TRIANGLE_OBJECT,&Smooth_Triangle_Methods) Make_Vector(New->Normal_Vector, 0.0, 1.0, 0.0); New->Distance = 0.0; Make_Vector(New->P1, 0.0, 0.0, 0.0); Make_Vector(New->P2, 1.0, 0.0, 0.0); Make_Vector(New->P3, 0.0, 1.0, 0.0); Make_Vector(New->N1, 0.0, 1.0, 0.0); Make_Vector(New->N2, 0.0, 1.0, 0.0); Make_Vector(New->N3, 0.0, 1.0, 0.0); /* * NOTE: Dominant_Axis and vAxis are computed when * Parse_Triangle calls Compute_Triangle. */ return(New); } /***************************************************************************** * * FUNCTION * * Copy_Smooth_Triangle * * INPUT * * OUTPUT * * RETURNS * * AUTHOR * * POV-Ray Team * * DESCRIPTION * * - * * CHANGES * * - * ******************************************************************************/ static void *Copy_Smooth_Triangle(Object) OBJECT *Object; { SMOOTH_TRIANGLE *New; New = Create_Smooth_Triangle(); *New = *((SMOOTH_TRIANGLE *)Object); return(New); } /***************************************************************************** * * FUNCTION * * Compute_Triangle_BBox * * INPUT * * Triangle - Triangle * * OUTPUT * * Triangle * * RETURNS * * AUTHOR * * Dieter Bayer * * DESCRIPTION * * Calculate the bounding box of a triangle. * * CHANGES * * Aug 1994 : Creation. * ******************************************************************************/ void Compute_Triangle_BBox(Triangle) TRIANGLE *Triangle; { VECTOR Min, Max, Epsilon; Make_Vector(Epsilon, EPSILON, EPSILON, EPSILON); Min[X] = min3(Triangle->P1[X], Triangle->P2[X], Triangle->P3[X]); Min[Y] = min3(Triangle->P1[Y], Triangle->P2[Y], Triangle->P3[Y]); Min[Z] = min3(Triangle->P1[Z], Triangle->P2[Z], Triangle->P3[Z]); Max[X] = max3(Triangle->P1[X], Triangle->P2[X], Triangle->P3[X]); Max[Y] = max3(Triangle->P1[Y], Triangle->P2[Y], Triangle->P3[Y]); Max[Z] = max3(Triangle->P1[Z], Triangle->P2[Z], Triangle->P3[Z]); VSubEq(Min, Epsilon); VAddEq(Max, Epsilon); Make_BBox_from_min_max(Triangle->BBox, Min, Max); }