示例#1
0
/* polygon:
 *  Draws a filled polygon with an arbitrary number of corners. Pass the
 *  number of vertices, then an array containing a series of x, y points
 *  (a total of vertices*2 values).
 */
void _soft_polygon(BITMAP *bmp, int vertices, AL_CONST int *points, int color)
{
   int c;
   int top = INT_MAX;
   int bottom = INT_MIN;
   AL_CONST int *i1, *i2;
   POLYGON_EDGE *edge, *next_edge;
   POLYGON_EDGE *active_edges = NULL;
   POLYGON_EDGE *inactive_edges = NULL;
   ASSERT(bmp);

   /* allocate some space and fill the edge table */
   _grow_scratch_mem(sizeof(POLYGON_EDGE) * vertices);

   edge = (POLYGON_EDGE *)_scratch_mem;
   i1 = points;
   i2 = points + (vertices-1) * 2;

   for (c=0; c<vertices; c++) {
      fill_edge_structure(edge, i1, i2);

      if (edge->bottom >= edge->top) {

         if (edge->top < top)
            top = edge->top;

         if (edge->bottom > bottom)
            bottom = edge->bottom;

         inactive_edges = _add_edge(inactive_edges, edge, FALSE);
         edge++;
      }

      i2 = i1;
      i1 += 2;
   }

   if (bottom >= bmp->cb)
      bottom = bmp->cb-1;

   acquire_bitmap(bmp);

   /* for each scanline in the polygon... */
   for (c=top; c<=bottom; c++) {
      int hid = 0;
      int b1 = 0;
      int e1 = 0;
      int up = 0;
      int draw = 0;
      int e;

      /* check for newly active edges */
      edge = inactive_edges;
      while ((edge) && (edge->top == c)) {
         next_edge = edge->next;
         inactive_edges = _remove_edge(inactive_edges, edge);
         active_edges = _add_edge(active_edges, edge, TRUE);
         edge = next_edge;
      }

      /* draw horizontal line segments */
      edge = active_edges;
      while (edge) {
         e = edge->w;
         if (edge->bottom != c) {
            up = 1 - up;
         }
         else {
            e = edge->w >> 1;
         }

         if (edge->top == c) {
            e = edge->w >> 1;
         }

         if ((draw < 1) && (up >= 1)) {
            b1 = (edge->x + e) >> POLYGON_FIX_SHIFT;
         }
         else if (draw >= 1) {
示例#2
0
void CSurface8::Polygon(int iNum, int *ipVtx, int iCol) {
  // Variables for polygon drawer
  int c, x1, x2, y;
  int top = INT_MAX;
  int bottom = INT_MIN;
  int *i1, *i2;
  CPolyEdge *edge, *next_edge, *edgebuf;
  CPolyEdge *active_edges = NULL;
  CPolyEdge *inactive_edges = NULL;
  BOOL use_qpb = FALSE;

  // Poly Buf
  if (iNum <= QuickPolyBufSize) {
    edgebuf = QuickPolyBuf;
    use_qpb = TRUE;
  } else if (!(edgebuf = new CPolyEdge[iNum])) {
    return;
  }

  // Fill the edge table
  edge = edgebuf;
  i1 = ipVtx;
  i2 = ipVtx + (iNum - 1) * 2;
  for (c = 0; c < iNum; c++) {
    if (i1[1] != i2[1]) {
      fill_edge_structure(edge, i1, i2);
      if (edge->bottom >= edge->y) {
        if (edge->y < top) top = edge->y;
        if (edge->bottom > bottom) bottom = edge->bottom;
        inactive_edges = add_edge(inactive_edges, edge, FALSE);
        edge++;
      }
    }
    i2 = i1;
    i1 += 2;
  }

  // For each scanline in the polygon...
  for (c = top; c <= bottom; c++) {
    // Check for newly active edges
    edge = inactive_edges;
    while ((edge) && (edge->y == c)) {
      next_edge = edge->next;
      inactive_edges = remove_edge(inactive_edges, edge);
      active_edges = add_edge(active_edges, edge, TRUE);
      edge = next_edge;
    }

    // Draw horizontal line segments
    edge = active_edges;
    while ((edge) && (edge->next)) {
      x1 = edge->x >> POLYGON_FIX_SHIFT;
      x2 = (edge->next->x + edge->next->w) >> POLYGON_FIX_SHIFT;
      y = c;
      // Fix coordinates
      if (x1 > x2) Swap(x1, x2);
      // Set line
      for (int xcnt = x2 - x1; xcnt >= 0; xcnt--) SetPix(x1 + xcnt, y, iCol);
      edge = edge->next->next;
    }

    // Update edges, sorting and removing dead ones
    edge = active_edges;
    while (edge) {
      next_edge = edge->next;
      if (c >= edge->bottom) {
        active_edges = remove_edge(active_edges, edge);
      } else {
        edge->x += edge->dx;
        while ((edge->prev) &&
               (edge->x + edge->w / 2 < edge->prev->x + edge->prev->w / 2)) {
          if (edge->next) edge->next->prev = edge->prev;
          edge->prev->next = edge->next;
          edge->next = edge->prev;
          edge->prev = edge->prev->prev;
          edge->next->prev = edge;
          if (edge->prev)
            edge->prev->next = edge;
          else
            active_edges = edge;
        }
      }
      edge = next_edge;
    }
  }

  // Clear scratch memory
  if (!use_qpb) delete[] edgebuf;
}