mirror of
https://git.planet-casio.com/Lephenixnoir/gint.git
synced 2024-12-28 04:23:36 +01:00
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
This commit is contained in:
parent
b802e8edef
commit
e0ac25fbb0
3 changed files with 79 additions and 63 deletions
|
@ -107,6 +107,7 @@ set(SOURCES_COMMON
|
||||||
src/render/dhline.c
|
src/render/dhline.c
|
||||||
src/render/dimage.c
|
src/render/dimage.c
|
||||||
src/render/dline.c
|
src/render/dline.c
|
||||||
|
src/render/dpoly.c
|
||||||
src/render/dprint.c
|
src/render/dprint.c
|
||||||
src/render/drect_border.c
|
src/render/drect_border.c
|
||||||
src/render/dtext.c
|
src/render/dtext.c
|
||||||
|
|
|
@ -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,
|
void dellipse(int x1, int y1, int x2, int y2, int fill_color,
|
||||||
int border_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)
|
// Text rendering (topti)
|
||||||
//---
|
//---
|
||||||
|
|
|
@ -1,67 +1,67 @@
|
||||||
#include <gint/defs/util.h>
|
#include <gint/defs/util.h>
|
||||||
#include <gint/display.h>
|
#include <gint/display.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
void dpoly(int *polyX, int *polyY, int polyCorners, int fill_color, int border_color){
|
static int compare(void const *ptr1, void const *ptr2)
|
||||||
|
{
|
||||||
if (polyCorners<=2) return;
|
return *(int const *)ptr1 - *(int const *)ptr2;
|
||||||
|
}
|
||||||
if (fill_color == C_NONE && border_color == C_NONE)
|
|
||||||
return;
|
static void dpoly_fill(int const *x, int const *y, int N, int color)
|
||||||
|
{
|
||||||
if (fill_color != C_NONE) {
|
int *nodeX = malloc(N * sizeof *nodeX);
|
||||||
|
|
||||||
float *nodeX, pixelX, pixelY, swap ;
|
/* Find vertical bounds */
|
||||||
int i, j, nodes;
|
int ymin = y[0], ymax = y[0];
|
||||||
|
for(int i = 1; i < N; i++)
|
||||||
nodeX = malloc( polyCorners * sizeof(float));
|
{
|
||||||
|
ymin = min(ymin, y[i]);
|
||||||
// Loop through the rows of the image.
|
ymax = max(ymax, y[i]);
|
||||||
for (pixelY=0; pixelY<DHEIGHT; pixelY++) {
|
}
|
||||||
|
ymin = max(ymin, dwindow.top);
|
||||||
// Build a list of nodes.
|
ymax = min(ymax, dwindow.bottom);
|
||||||
nodes=0; j=polyCorners-1;
|
|
||||||
for (i=0; i<polyCorners; i++) {
|
/* For each row, find vertical cuts from the segments and fill in-between
|
||||||
if ((polyY[i]<(float) pixelY && polyY[j]>=(float) pixelY)
|
the cuts. */
|
||||||
|| (polyY[j]<(float) pixelY && polyY[i]>=(float) pixelY)) {
|
for(int pixelY = ymin; pixelY <= ymax; pixelY++) {
|
||||||
nodeX[nodes++]=(int) (polyX[i]+(pixelY-polyY[i])/(polyY[j]-polyY[i])*(polyX[j]-polyX[i]));
|
|
||||||
}
|
/* Build a list of nodes */
|
||||||
j=i;
|
int nodes = 0;
|
||||||
}
|
int j = N - 1;
|
||||||
|
for(int i = 0; i < N; i++)
|
||||||
// Sort the nodes, via a simple “Bubble” sort.
|
{
|
||||||
i=0;
|
if((y[i] < pixelY) != (y[j] < pixelY))
|
||||||
while (i<nodes-1) {
|
nodeX[nodes++] = x[i]+(pixelY-y[i])*(x[j]-x[i])/(y[j]-y[i]);
|
||||||
if (nodeX[i]>nodeX[i+1]) {
|
j = i;
|
||||||
swap=nodeX[i]; nodeX[i]=nodeX[i+1]; nodeX[i+1]=swap; if (i) i--;
|
}
|
||||||
}
|
|
||||||
else {
|
/* Sort the cuts' positions */
|
||||||
i++;
|
qsort(nodeX, nodes, sizeof nodeX[0], compare);
|
||||||
}
|
|
||||||
}
|
/* Fill the pixels between cut pairs */
|
||||||
|
for(int i = 0; i < nodes; i += 2)
|
||||||
// Fill the pixels between node pairs.
|
{
|
||||||
for (i=0; i<nodes; i+=2) {
|
if(nodeX[i] >= dwindow.right || nodeX[i+1] < dwindow.left) break;
|
||||||
if (nodeX[i ]>=DWIDTH) break;
|
nodeX[i] = max(nodeX[i], dwindow.left);
|
||||||
if (nodeX[i+1]<= 0 ) break;
|
nodeX[i+1] = min(nodeX[i+1], dwindow.right);
|
||||||
if (nodeX[i ]< 0 ) nodeX[i ]=0 ;
|
dline(nodeX[i], pixelY, nodeX[i+1], pixelY, color);
|
||||||
if (nodeX[i+1]> DWIDTH) nodeX[i+1]=DWIDTH;
|
}
|
||||||
//for (pixelX=nodeX[i]; pixelX<nodeX[i+1]; pixelX++) fillPixel(pixelX,pixelY);
|
}
|
||||||
dline(nodeX[i], pixelY, nodeX[i+1], pixelY, fill_color);
|
|
||||||
}
|
free(nodeX);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(nodeX);
|
static void dpoly_border(int const *x, int const *y, int N, int color)
|
||||||
}
|
{
|
||||||
|
for(int i = 0; i < N - 1; i++)
|
||||||
if (border_color != C_NONE) {
|
dline(x[i], y[i], x[i+1], y[i+1], color);
|
||||||
for (int i = 0; i < polyCorners; i++) {
|
dline(x[N-1], y[N-1], x[0], y[0], color);
|
||||||
int px = polyX[i];
|
}
|
||||||
int py = polyY[i];
|
|
||||||
int px2 = polyX[(i + 1) % polyCorners];
|
void dpoly(int const *x, int const *y, int N, int fill_color, int border_color)
|
||||||
int py2 = polyY[(i + 1) % polyCorners];
|
{
|
||||||
dline(px, py, px2, py2, 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);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue