/* Draws all visible faces in the specified polygon-based object. The object must have previously been transformed and projected, so that all vertex arrays are filled in. Ambient and diffuse shading are supported. */ #include "polygon.h" void DrawPObject(PObject * ObjectToXform) { int i, j, NumFaces = ObjectToXform->NumFaces, NumVertices; int * VertNumsPtr, Spot; Face * FacePtr = ObjectToXform->FaceList; Point * ScreenPoints = ObjectToXform->ScreenVertexList; PointListHeader Polygon; Fixedpoint Diffusion; ModelColor ColorTemp; ModelIntensity IntensityTemp; Point3 UnitNormal, *NormalStartpoint, *NormalEndpoint; long v1, v2, w1, w2; Point Vertices[MAX_POLY_LENGTH]; /* Draw each visible face (polygon) of the object in turn */ for (i=0; iVertNums; NormalEndpoint = &ObjectToXform->XformedVertexList[*VertNumsPtr++]; NormalStartpoint = &ObjectToXform->XformedVertexList[*VertNumsPtr]; /* Copy over the face's vertices from the vertex list */ NumVertices = FacePtr->NumVerts; for (j=0; j 0) { /* It is facing the screen, so draw */ /* Appropriately adjust the extent of the rectangle used to erase this object later */ for (j=0; j ObjectToXform->EraseRect[NonDisplayedPage].Right) if (Vertices[j].X < SCREEN_WIDTH) ObjectToXform->EraseRect[NonDisplayedPage].Right = Vertices[j].X; else ObjectToXform->EraseRect[NonDisplayedPage].Right = SCREEN_WIDTH; if (Vertices[j].Y > ObjectToXform->EraseRect[NonDisplayedPage].Bottom) if (Vertices[j].Y < SCREEN_HEIGHT) ObjectToXform->EraseRect[NonDisplayedPage].Bottom = Vertices[j].Y; else ObjectToXform->EraseRect[NonDisplayedPage].Bottom= SCREEN_HEIGHT; if (Vertices[j].X < ObjectToXform->EraseRect[NonDisplayedPage].Left) if (Vertices[j].X > 0) ObjectToXform->EraseRect[NonDisplayedPage].Left = Vertices[j].X; else ObjectToXform->EraseRect[NonDisplayedPage].Left=0; if (Vertices[j].Y < ObjectToXform->EraseRect[NonDisplayedPage].Top) if (Vertices[j].Y > 0) ObjectToXform->EraseRect[NonDisplayedPage].Top = Vertices[j].Y; else ObjectToXform->EraseRect[NonDisplayedPage].Top=0; } /* See if there's any shading */ if (FacePtr->ShadingType == NO_SHADING) { /* No shading in effect, so just draw */ DRAW_POLYGON(Vertices, NumVertices, FacePtr->ColorIndex, 0, 0); } else if (FacePtr->ShadingType & TEXTURE_MAPPED_SHADING) { /* Texture mapping in effect; this precludes illuminated shading */ DRAW_TEXTURED_POLYGON(Vertices, NumVertices, FacePtr->TexVerts, FacePtr->TexMap); } else { /* Handle shading */ /* Do ambient shading, if enabled */ if (AmbientOn && (FacePtr->ShadingType & AMBIENT_SHADING)) { /* Use the ambient shading component */ IntensityTemp = AmbientIntensity; } else { SET_INTENSITY(IntensityTemp, 0, 0, 0); } /* Do diffuse shading, if enabled */ if (FacePtr->ShadingType & DIFFUSE_SHADING) { /* Calculate the unit normal for this polygon, for use in dot products */ UnitNormal.X = NormalEndpoint->X - NormalStartpoint->X; UnitNormal.Y = NormalEndpoint->Y - NormalStartpoint->Y; UnitNormal.Z = NormalEndpoint->Z - NormalStartpoint->Z; /* Calculate the diffuse shading component for each active spotlight */ for (Spot=0; Spot 0) { IntensityTemp.Red += FixedMul(SpotIntensity[Spot].Red, Diffusion); IntensityTemp.Green += FixedMul(SpotIntensity[Spot].Green, Diffusion); IntensityTemp.Blue += FixedMul(SpotIntensity[Spot].Blue, Diffusion); } } } } /* Convert the drawing color to the desired fraction of the brightest possible color */ IntensityAdjustColor(&ColorTemp, &FacePtr->FullColor, &IntensityTemp); /* Draw with the cumulative shading, converting from the general color representation to the best-match color index */ DRAW_POLYGON(Vertices, NumVertices, ModelColorToColorIndex(&ColorTemp), 0, 0); } } } }