/***************************************************************************** * Routines to prepare objects for the scan conversion: * * At this stage, it is assumed all vertices normals has been evaluated, if * * is is required to interpolate them (i.e. Gouraud shading.) * * This module sort the polygons into hash table of GlblShadeInfo.ScrnYSize size, * * according to their lowest vertex, and update a pointer to it. * * * * Written by: Gershon Elber Ver 2.0, Mar. 1990 * *****************************************************************************/ #ifdef __MSDOS__ #include #endif /* __MSDOS__ */ #include #include #include #include "program.h" #include "genmat.h" #include "iritprsr.h" static void PrepareAllObjects(IPObjectStruct *PObjects); static void PrepareOneObject(IPObjectStruct *PObject); static void PrepareOnePolygon(IPPolygonStruct *PPolygon); static int UpdateBBoxPolygon(IPPolygonStruct *PPolygon); static void UpdateScanConvertData(int MinVertex, IPPolygonStruct *PPolygon); /***************************************************************************** * Routine to prepare NumOfObjects given in Objects from FileDescription FD * * according to view matrix Mat. If NumOfObjects == 0 then all the objects * * defined by the data sturcture are handled, and NumOfObjects is set to real * * number of objects exists. * *****************************************************************************/ void PrepareViewData(IPObjectStruct *PObjects) { long SaveTime = time(NULL); fprintf(stderr, "\nPass 2, Polys = "); PrepareAllObjects(PObjects); fprintf(stderr, ", %ld seconds.", time(NULL) - SaveTime); } /***************************************************************************** * Scan all objects. * *****************************************************************************/ static void PrepareAllObjects(IPObjectStruct *PObjects) { while (PObjects) { PrepareOneObject(PObjects); PObjects = PObjects -> Pnext; } } /***************************************************************************** * Routine to prepare one object PObject. * *****************************************************************************/ static void PrepareOneObject(IPObjectStruct *PObject) { struct IPPolygonStruct *PList = PObject -> U.PPolygon; while (PList) { PrepareOnePolygon(PList); PList = PList -> Pnext; } } /***************************************************************************** * Routine to prepare one polygon PPolygon. * *****************************************************************************/ static void PrepareOnePolygon(IPPolygonStruct *PPolygon) { static int PolyCount = 0; int i; RealType CpCoord[3]; IPVertexStruct *VList = PPolygon -> PVertex; fprintf(stderr, "\b\b\b\b\b%5d", ++PolyCount); GlblNumOfPolys++; for (; VList != NULL; VList = VList -> Pnext) { /* Convert the coordinate to screen space (pres.). */ MultVecby4by4(CpCoord, VList -> Coord, GlblViewMat); for (i = 0; i < 3; i++) VList -> Coord[i] = CpCoord[i]; } if (PPolygon -> Type != IP_POLYGON) return; /* Find X, Y extremum in screen space, and use the lowest vertex in Y to */ /* initialize the scan conversion structure of the polygon: */ i = UpdateBBoxPolygon(PPolygon); UpdateScanConvertData(i, PPolygon); /* Transform the polygon plane equation as well, and normalize it: */ UpdateEqnPolygon(PPolygon, FALSE); } /***************************************************************************** * Routine to update polygon boundary box in screen space: * * Note this routine is called after the polygons was checked for validity - * * all the list of objects was found to be vertices only. * *****************************************************************************/ static int UpdateBBoxPolygon(IPPolygonStruct *PPolygon) { int i, MinV = 0; RealType *Coord, Xmin, Xmax, Ymin, Ymax; struct IPVertexStruct *VList = PPolygon -> PVertex; Xmin = Xmax = VList -> Coord[0]; Ymin = Ymax = VList -> Coord[1]; for (VList = VList -> Pnext, i = 1; VList != NULL; VList = VList -> Pnext, i++) { Coord = VList -> Coord; if (Coord[0] > Xmax) Xmax = Coord[0]; if (Coord[0] < Xmin) Xmin = Coord[0]; if (Coord[1] > Ymax) Ymax = Coord[1]; if (Coord[1] < Ymin) { Ymin = Coord[1]; MinV = i; } } PPolygon -> Xmin = (int) Xmin; PPolygon -> Xmax = (int) Xmax; PPolygon -> Ymin = (int) Ymin; PPolygon -> Ymax = (int) Ymax; return MinV; } /***************************************************************************** * Routine to update polygon scan conversion information: * * Each polygon (Remember they must be convex), has two boundaries we cross * * by the scan lines if it is active. These are LeftBndry and RightBndry we * * update here. * *****************************************************************************/ static void UpdateScanConvertData(int MinVertex, IPPolygonStruct *PPolygon) { int i; struct IPVertexStruct *VMinY, *VBefore, *VAfter, *VList = PPolygon -> PVertex; struct PolygonScanConvertStruct *PScan; /* Find the minimum location again: */ if (MinVertex == 0) { /* Its the first vertex that has minimum Y value: */ VMinY = VList; for (VBefore = VList; VBefore -> Pnext != NULL; VBefore = VBefore -> Pnext); VAfter = VList -> Pnext; } else { for (i = 1, VBefore = VList; i < MinVertex; i++, VBefore = VBefore -> Pnext); VMinY = VBefore -> Pnext; VAfter = VMinY -> Pnext ? VMinY -> Pnext : VList; } PPolygon -> PAux = MyMalloc(sizeof(struct PolygonScanConvertStruct)); PScan = (PolygonScanConvertStruct *) PPolygon -> PAux; PScan -> Bndry1.VMinY = VMinY; PScan -> Bndry1.VMaxY = VBefore; PScan -> Bndry1.MaxEdgeY = (int) VBefore -> Coord[1]; PScan -> Bndry2.VMinY = VMinY; PScan -> Bndry2.VMaxY = VAfter; PScan -> Bndry2.MaxEdgeY = (int) VAfter -> Coord[1]; }