/* 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) {
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; }