/***************************************************************************** * "Irit" - the 3d polygonal solid modeller. * * * * Written by: Gershon Elber Ver 0.2, Aug. 1990 * ****************************************************************************** * Module to interplate internal vertices using vertices on the given * * convex boundary OriginalVList. All internal vertices are assumed to be in * * the interior of the convex region defined by OriginalVList or on its * * boundary. * *****************************************************************************/ #include #include "program.h" #include "geomat3d.h" #include "intrnrml.h" /* #define DEBUG To define polygon (with normals printing routine. */ static void UpdateOneVertexNormal(VertexStruct *VUpdate, PolygonStruct *OriginalPl); #ifdef DEBUG static void PrintPolygon(PolygonStruct *Pl); #endif /* DEBUG */ /***************************************************************************** * For each polygon in PlList update any vertex normal which is zero to an * *interpolated value using the Original polygon vertex list OriginalVList. * * All the new vertices are enclosed within the original polygon which * * must be convex as well. * *****************************************************************************/ void UpdateVerticesNormals(PolygonStruct *PlList, PolygonStruct *OriginalPl) { VertexStruct *V, *VHead; while (PlList) { V = VHead = PlList -> V; do { if (APX_EQ(V -> Normal[0], 0.0) && APX_EQ(V -> Normal[1], 0.0) && APX_EQ(V -> Normal[2], 0.0)) { /* This vertex need to be updated. */ UpdateOneVertexNormal(V, OriginalPl); } V = V -> Pnext; } while (V != NULL && V != VHead); PlList = PlList -> Pnext; } } /***************************************************************************** * Update one vertex normal be a convex blend of boundary vertices normals * *****************************************************************************/ static void UpdateOneVertexNormal(VertexStruct *VUpdate, PolygonStruct *OriginalPl) { VertexStruct *V, *OriginalVList = OriginalPl -> V; V = OriginalVList; do { if (Colinear3Vertices(V, VUpdate, V -> Pnext)) { /* Interpolate the normal according to the edge vertices VUpdate */ /* is on and according to the distance of VUpdate to edge ends. */ InterpNrmlBetweenTwo(VUpdate, V, V -> Pnext); return; } V = V -> Pnext; } while (V != NULL && V != OriginalVList); /* If we are here then the point is not on the polygon boundary and in */ /* that case we simply use the polygon normal as an approximation. */ PT_COPY(VUpdate -> Normal, OriginalPl -> Plane); } /***************************************************************************** * Returns TRUE iff the 3 vertices are colinear. * *****************************************************************************/ int Colinear3Vertices(VertexStruct *V1, VertexStruct *V2, VertexStruct *V3) { RealType l; VectorType V12, V23, V; if (PT_EQ(V1 -> Pt, V2 -> Pt) || PT_EQ(V2 -> Pt, V3 -> Pt)) return TRUE; PT_SUB(V12, V1 -> Pt, V2 -> Pt); PT_SUB(V23, V2 -> Pt, V3 -> Pt); /* Make sure the middle point is in fact in the middle. */ if (V12[0] * V23[0] < -EPSILON || V12[1] * V23[1] < -EPSILON || V12[2] * V23[2] < -EPSILON) return FALSE; VecCrossProd(V, V12, V23); l = PT_LENGTH(V); return APX_EQ(l, 0.0); } /***************************************************************************** * Returns TRUE iff the 3 vertices are colinear. * *****************************************************************************/ void InterpNrmlBetweenTwo(VertexStruct *V, VertexStruct *V1, VertexStruct *V2) { RealType t1, t2; VectorType Vec1, Vec2; PT_SUB(Vec1, V -> Pt, V1 -> Pt); PT_SUB(Vec2, V -> Pt, V2 -> Pt); t1 = PT_LENGTH(Vec1); t2 = PT_LENGTH(Vec2); PT_COPY(Vec1, V1 -> Normal); PT_COPY(Vec2, V2 -> Normal); PT_SCALE(Vec1, t2); PT_SCALE(Vec2, t1); PT_ADD(V -> Normal, Vec1, Vec2); PT_NORMALIZE(V -> Normal); } #ifdef DEBUG /***************************************************************************** * Print the content of the given polygon, to standard output. * *****************************************************************************/ static void PrintPolygon(PolygonStruct *Pl) { VertexStruct *V = Pl -> V, *VHead = V; do { printf(" %10lg %10lg %10lg (%10lg %10lg %10lg)", V -> Pt[0], V -> Pt[1], V -> Pt[2], V -> Normal[0], V -> Normal[1], V -> Normal[2]); if (IS_INTERNAL_EDGE(V)) printf(" (Internal)\n"); else printf("\n"); V = V -> Pnext; } while (V!= NULL && V != VHead); } #endif /* DEBUG */