/* Affiche toutes les faces visibles d'un objet à base de polygones. L'objet doit avoir été préalablement transformé et projeté, afin que le tableau des points soit rempli. Les lumières ambiantes et diffuses sont supportées. */ #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]; /* Affiche l'une après l'autre chaque face visible(polygone) de l'objet */ for (i=0; iVertNums; NormalEndpoint = &ObjectToXform->XformedVertexList[*VertNumsPtr++]; NormalStartpoint = &ObjectToXform->XformedVertexList[*VertNumsPtr]; /* Copie les points des faces dans la liste des points */ NumVertices = FacePtr->NumVerts; for (j=0; j 0) { /* elle est face à l'écran, donc affichons */ /* Ajuste correctement la superficie du rectangle utilisé pour effacer cet objet ultérieurement */ 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; } /* Vérifie s'il n'y a pas d'illumination */ if (FacePtr->ShadingType == NO_SHADING) { /* En effet il n'y a pas d'illumination, affichons */ DRAW_POLYGON(Vertices, NumVertices, FacePtr->ColorIndex, 0, 0); } else if (FacePtr->ShadingType & TEXTURE_MAPPED_SHADING) { DRAW_TEXTURED_POLYGON(Vertices, NumVertices, FacePtr->TexVerts, FacePtr->TexMap); } else { /* Traite l'illumination */ /* Crée une lumière ambiante, si activée */ if (AmbientOn && (FacePtr->ShadingType & AMBIENT_SHADING)) { /* Utilise le composant de la lumière ambiante */ IntensityTemp = AmbientIntensity; } else { SET_INTENSITY(IntensityTemp, 0, 0, 0); } /* Crée une lumière diffuse, si activée*/ if (FacePtr->ShadingType & DIFFUSE_SHADING) { /* Calcule la normale unitaire de ce polygone, pour utiliser dans les produits scalaires */ UnitNormal.X = NormalEndpoint->X - NormalStartpoint->X; UnitNormal.Y = NormalEndpoint->Y - NormalStartpoint->Y; UnitNormal.Z = NormalEndpoint->Z - NormalStartpoint->Z; /* Calcule le composant de la lumière diffuse pour chaque spotlight actif */ 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); } } } } /* Convertit le couleur pour obtenir l'intensité souhaités de la couleur de référence */ IntensityAdjustColor(&ColorTemp, &FacePtr->FullColor, &IntensityTemp); /* Affiche avec l'illumination cumulée, en convertissant la représentation générale de la couleur en index de couleur correspondant le mieux */ DRAW_POLYGON(Vertices, NumVertices, ModelColorToColorIndex(&ColorTemp), 0, 0); } } } }