home *** CD-ROM | disk | FTP | other *** search
/ Graphics Programming Black Book (Special Edition) / BlackBook.bin / disk1 / xsharp22 / drawpobj.c < prev    next >
Text File  |  1997-06-18  |  7KB  |  142 lines

  1. /* Draws all visible faces in the specified polygon-based object.  The
  2.    object must have previously been transformed and projected, so that
  3.    all vertex arrays are filled in. Ambient and diffuse shading are
  4.    supported. */
  5.  
  6. #include "polygon.h"
  7.  
  8. void DrawPObject(PObject * ObjectToXform)
  9. {
  10.    int i, j, NumFaces = ObjectToXform->NumFaces, NumVertices;
  11.    int * VertNumsPtr, Spot;
  12.    Face * FacePtr = ObjectToXform->FaceList;
  13.    Point * ScreenPoints = ObjectToXform->ScreenVertexList;
  14.    PointListHeader Polygon;
  15.    Fixedpoint Diffusion;
  16.    ModelColor ColorTemp;
  17.    ModelIntensity IntensityTemp;
  18.    Point3 UnitNormal, *NormalStartpoint, *NormalEndpoint;
  19.    long v1, v2, w1, w2;
  20.    Point Vertices[MAX_POLY_LENGTH];
  21.  
  22.    /* Draw each visible face (polygon) of the object in turn */
  23.    for (i=0; i<NumFaces; i++, FacePtr++) {
  24.       /* Remember where we can find the start and end of the polygon's
  25.          unit normal in view space, and skip over the unit normal endpoint
  26.          entry. The end and start points of the unit normal to the polygon
  27.          must be the first and second entries in the polgyon's vertex list.
  28.          Note that the second point is also an active polygon vertex */
  29.       VertNumsPtr = FacePtr->VertNums;
  30.       NormalEndpoint = &ObjectToXform->XformedVertexList[*VertNumsPtr++];
  31.       NormalStartpoint = &ObjectToXform->XformedVertexList[*VertNumsPtr];
  32.  
  33.       /* Copy over the face's vertices from the vertex list */
  34.       NumVertices = FacePtr->NumVerts;
  35.       for (j=0; j<NumVertices; j++)
  36.          Vertices[j] = ScreenPoints[*VertNumsPtr++];
  37.  
  38.       /* Draw only if outside face showing (if the normal to the polygon
  39.          in screen coordinates points toward the viewer; that is, has a
  40.          positive Z component) */
  41.       v1 = Vertices[1].X - Vertices[0].X;
  42.       w1 = Vertices[NumVertices-1].X - Vertices[0].X;
  43.       v2 = Vertices[1].Y - Vertices[0].Y;
  44.       w2 = Vertices[NumVertices-1].Y - Vertices[0].Y;
  45.       if ((v1*w2 - v2*w1) > 0) {
  46.          /* It is facing the screen, so draw */
  47.          /* Appropriately adjust the extent of the rectangle used to
  48.             erase this object later */
  49.          for (j=0; j<NumVertices; j++) {
  50.             if (Vertices[j].X >
  51.                   ObjectToXform->EraseRect[NonDisplayedPage].Right)
  52.                if (Vertices[j].X < SCREEN_WIDTH)
  53.                   ObjectToXform->EraseRect[NonDisplayedPage].Right =
  54.                         Vertices[j].X;
  55.                else ObjectToXform->EraseRect[NonDisplayedPage].Right =
  56.                      SCREEN_WIDTH;
  57.             if (Vertices[j].Y >
  58.                   ObjectToXform->EraseRect[NonDisplayedPage].Bottom)
  59.                if (Vertices[j].Y < SCREEN_HEIGHT)
  60.                   ObjectToXform->EraseRect[NonDisplayedPage].Bottom =
  61.                         Vertices[j].Y;
  62.                else ObjectToXform->EraseRect[NonDisplayedPage].Bottom=
  63.                      SCREEN_HEIGHT;
  64.             if (Vertices[j].X <
  65.                   ObjectToXform->EraseRect[NonDisplayedPage].Left)
  66.                if (Vertices[j].X > 0)
  67.                   ObjectToXform->EraseRect[NonDisplayedPage].Left =
  68.                         Vertices[j].X;
  69.                else ObjectToXform->EraseRect[NonDisplayedPage].Left=0;
  70.             if (Vertices[j].Y <
  71.                   ObjectToXform->EraseRect[NonDisplayedPage].Top)
  72.                if (Vertices[j].Y > 0)
  73.                   ObjectToXform->EraseRect[NonDisplayedPage].Top =
  74.                         Vertices[j].Y;
  75.                else ObjectToXform->EraseRect[NonDisplayedPage].Top=0;
  76.          }
  77.  
  78.          /* See if there's any shading */
  79.          if (FacePtr->ShadingType == NO_SHADING) {
  80.             /* No shading in effect, so just draw */
  81.             DRAW_POLYGON(Vertices, NumVertices, FacePtr->ColorIndex, 0, 0);
  82.          } else if (FacePtr->ShadingType & TEXTURE_MAPPED_SHADING) {
  83.             /* Texture mapping in effect; this precludes illuminated
  84.                 shading */
  85.             DRAW_TEXTURED_POLYGON(Vertices, NumVertices, FacePtr->TexVerts,
  86.                   FacePtr->TexMap);
  87.          } else {
  88.             /* Handle shading */
  89.  
  90.             /* Do ambient shading, if enabled */
  91.             if (AmbientOn && (FacePtr->ShadingType & AMBIENT_SHADING)) {
  92.                /* Use the ambient shading component */
  93.                IntensityTemp = AmbientIntensity;
  94.             } else {
  95.                SET_INTENSITY(IntensityTemp, 0, 0, 0);
  96.             }
  97.  
  98.             /* Do diffuse shading, if enabled */
  99.             if (FacePtr->ShadingType & DIFFUSE_SHADING) {
  100.                /* Calculate the unit normal for this polygon, for use in dot
  101.                   products */
  102.                UnitNormal.X = NormalEndpoint->X - NormalStartpoint->X;
  103.                UnitNormal.Y = NormalEndpoint->Y - NormalStartpoint->Y;
  104.                UnitNormal.Z = NormalEndpoint->Z - NormalStartpoint->Z;
  105.                /* Calculate the diffuse shading component for each active
  106.                   spotlight */
  107.                for (Spot=0; Spot<MAX_SPOTS; Spot++) {
  108.                   if (SpotOn[Spot] != 0) {
  109.                      /* Spot is on, so sum, for each color component, the
  110.                         intensity, accounting for the angle of the light rays
  111.                         relative to the orientation of the polygon */
  112.                      /* Calculate cosine of angle between the light and the
  113.                         polygon normal; skip if spot is shining from behind
  114.                         the polygon */
  115.                      if ((Diffusion = DOT_PRODUCT(SpotDirectionView[Spot],
  116.                            UnitNormal)) > 0) {
  117.                         IntensityTemp.Red +=
  118.                               FixedMul(SpotIntensity[Spot].Red, Diffusion);
  119.                         IntensityTemp.Green +=
  120.                               FixedMul(SpotIntensity[Spot].Green, Diffusion);
  121.                         IntensityTemp.Blue +=
  122.                               FixedMul(SpotIntensity[Spot].Blue, Diffusion);
  123.                      }
  124.                   }
  125.                }
  126.             }
  127.  
  128.             /* Convert the drawing color to the desired fraction of the
  129.                brightest possible color */
  130.             IntensityAdjustColor(&ColorTemp, &FacePtr->FullColor,
  131.                   &IntensityTemp);
  132.  
  133.             /* Draw with the cumulative shading, converting from the general
  134.                color representation to the best-match color index */
  135.             DRAW_POLYGON(Vertices, NumVertices,
  136.                   ModelColorToColorIndex(&ColorTemp), 0, 0);
  137.          }
  138.       }
  139.    }
  140. }
  141.  
  142.