From e0ac25fbb0e71dd0b522b31facdc794c53345f21 Mon Sep 17 00:00:00 2001 From: Lephenixnoir Date: Fri, 1 Mar 2024 22:26:39 +0000 Subject: [PATCH] render: improve implementation of dpoly() * Honor dwindow settings immediately (avoids useless dline() calls) * Bound to ymin/ymax instead of doing many useless cut computations * Remove the need for floating-point operations and division --- CMakeLists.txt | 1 + include/gint/display.h | 15 +++++ src/render/dpoly.c | 126 ++++++++++++++++++++--------------------- 3 files changed, 79 insertions(+), 63 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 714b552..a8307e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -107,6 +107,7 @@ set(SOURCES_COMMON src/render/dhline.c src/render/dimage.c src/render/dline.c + src/render/dpoly.c src/render/dprint.c src/render/drect_border.c src/render/dtext.c diff --git a/include/gint/display.h b/include/gint/display.h index a1c6166..599fd15 100644 --- a/include/gint/display.h +++ b/include/gint/display.h @@ -244,6 +244,21 @@ void dcircle(int xm, int ym, int r, int fill_color, int border_color); void dellipse(int x1, int y1, int x2, int y2, int fill_color, int border_color); +/* dpoly(): Render an arbitrary polygon + + Renders the polygon defined by vertices (x[i], y[i]) for 0 < i < N. A fill + color and border color can be specified separately. For filling, N must be + at least 3. For border, N must be at least 2. + + Note: this is a fairly slow function, not designed for rendering triangles + in 3D games. There are faster methods for that. + + @x @y Arrays of vertex coordinates + @N Number of vertices (length of x and y) + @fill_color Color of the polygon's interior, C_NONE to disable + @border_color Color of the polygon's border, C_NONE to disable */ +void dpoly(int const *x, int const *y, int N, int fill_color, int border_color); + //--- // Text rendering (topti) //--- diff --git a/src/render/dpoly.c b/src/render/dpoly.c index 5d317be..43bf79d 100644 --- a/src/render/dpoly.c +++ b/src/render/dpoly.c @@ -1,67 +1,67 @@ #include #include +#include -void dpoly(int *polyX, int *polyY, int polyCorners, int fill_color, int border_color){ - - if (polyCorners<=2) return; - - if (fill_color == C_NONE && border_color == C_NONE) - return; - - if (fill_color != C_NONE) { - - float *nodeX, pixelX, pixelY, swap ; - int i, j, nodes; - - nodeX = malloc( polyCorners * sizeof(float)); - - // Loop through the rows of the image. - for (pixelY=0; pixelY=(float) pixelY) - || (polyY[j]<(float) pixelY && polyY[i]>=(float) pixelY)) { - nodeX[nodes++]=(int) (polyX[i]+(pixelY-polyY[i])/(polyY[j]-polyY[i])*(polyX[j]-polyX[i])); - } - j=i; - } - - // Sort the nodes, via a simple “Bubble” sort. - i=0; - while (inodeX[i+1]) { - swap=nodeX[i]; nodeX[i]=nodeX[i+1]; nodeX[i+1]=swap; if (i) i--; - } - else { - i++; - } - } - - // Fill the pixels between node pairs. - for (i=0; i=DWIDTH) break; - if (nodeX[i+1]<= 0 ) break; - if (nodeX[i ]< 0 ) nodeX[i ]=0 ; - if (nodeX[i+1]> DWIDTH) nodeX[i+1]=DWIDTH; - //for (pixelX=nodeX[i]; pixelX= dwindow.right || nodeX[i+1] < dwindow.left) break; + nodeX[i] = max(nodeX[i], dwindow.left); + nodeX[i+1] = min(nodeX[i+1], dwindow.right); + dline(nodeX[i], pixelY, nodeX[i+1], pixelY, color); + } + } + + free(nodeX); +} + +static void dpoly_border(int const *x, int const *y, int N, int color) +{ + for(int i = 0; i < N - 1; i++) + dline(x[i], y[i], x[i+1], y[i+1], color); + dline(x[N-1], y[N-1], x[0], y[0], color); +} + +void dpoly(int const *x, int const *y, int N, int fill_color, int border_color) +{ + if(N > 2 && fill_color != C_NONE) + dpoly_fill(x, y, N, fill_color); + if(N >= 2 && border_color != C_NONE) + dpoly_border(x, y, N, border_color); }