bless wasm polygon rasterizer for production
This commit is contained in:
parent
027430e7a7
commit
32dca7586c
4 changed files with 96 additions and 45 deletions
112
wasm/kiri-sla.c
112
wasm/kiri-sla.c
|
|
@ -15,6 +15,10 @@ struct poly {
|
|||
Uint16 length; // offset to end of record in bytes
|
||||
Uint16 inners; // number of inner polygons
|
||||
Uint16 points; // number of points in polygon
|
||||
Uint16 minx;
|
||||
Uint16 maxx;
|
||||
Uint16 miny;
|
||||
Uint16 maxy;
|
||||
};
|
||||
|
||||
struct point {
|
||||
|
|
@ -22,6 +26,9 @@ struct point {
|
|||
float y;
|
||||
};
|
||||
|
||||
const Uint8 ph_size = sizeof(struct poly);
|
||||
const Uint8 pt_size = sizeof(struct point);
|
||||
|
||||
extern void last(float a, float b);
|
||||
extern void report(int a, int b);
|
||||
|
||||
|
|
@ -34,29 +41,28 @@ Uint8 check_cross(Uint32 x, Uint32 y, struct point *p1, struct point *p2) {
|
|||
) ? 1 : 0;
|
||||
}
|
||||
|
||||
Uint8 check_inside(Uint32 x, Uint32 y, unsigned char *p) {
|
||||
struct poly *poly = (struct poly *)(p + readoff);
|
||||
Uint8 is_inside_poly(Uint32 x, Uint32 y, unsigned char *m, Uint32 o) {
|
||||
struct poly *poly = (struct poly *)(m + readoff);
|
||||
|
||||
Uint32 nextpoly = readoff + poly->length;
|
||||
Uint8 side = 0; // 0=outside, 1=inside
|
||||
Uint8 psize = sizeof(struct point);
|
||||
|
||||
// skip post header
|
||||
readoff += sizeof(struct poly);
|
||||
readoff += ph_size;
|
||||
|
||||
// save pointer to first point or last comparison
|
||||
struct point *pf = (struct point *)(p + readoff);
|
||||
struct point *pf = (struct point *)(m + readoff);
|
||||
struct point *p1 = pf;
|
||||
struct point *p2;
|
||||
|
||||
// skip past first point
|
||||
readoff += psize;
|
||||
readoff += pt_size;
|
||||
|
||||
// read and check point pairs updating `side`
|
||||
for (Uint16 i=1; i<poly->points; i++) {
|
||||
p2 = (struct point *)(p + readoff);
|
||||
p2 = (struct point *)(m + readoff);
|
||||
// increment read pointe
|
||||
readoff += psize;
|
||||
readoff += pt_size;
|
||||
// check current/previous point crossing
|
||||
if (check_cross(x, y, p1, p2)) {
|
||||
side = 1 - side;
|
||||
|
|
@ -69,20 +75,75 @@ Uint8 check_inside(Uint32 x, Uint32 y, unsigned char *p) {
|
|||
side = 1 - side;
|
||||
}
|
||||
|
||||
// check inner polygons only if inside the outer polygon
|
||||
if (side)
|
||||
for (Uint16 i=0; i<poly->inners; i++) {
|
||||
// if inside an inner, then actually outside poly and term
|
||||
if (check_inside(x, y, p + readoff)) {
|
||||
side = 0;
|
||||
break;
|
||||
return side;
|
||||
}
|
||||
|
||||
void rasterize_poly(unsigned char *m, Uint32 o, Uint32 height) {
|
||||
struct poly *poly = (struct poly *)(m + readoff);
|
||||
|
||||
Uint32 nextpoly = readoff + poly->length;
|
||||
|
||||
// skip post header
|
||||
readoff += ph_size;
|
||||
|
||||
// save pointer to first point or last comparison
|
||||
struct point *pf = (struct point *)(m + readoff);
|
||||
struct point *p1 = pf;
|
||||
struct point *p2;
|
||||
|
||||
// skip past first point
|
||||
readoff += pt_size;
|
||||
|
||||
// point data starts here
|
||||
Uint32 pstart = readoff;
|
||||
|
||||
// scan bounding area of polygon
|
||||
for (Uint32 x=poly->minx; x<poly->maxx; x++) {
|
||||
for (Uint32 y=poly->miny; y<poly->maxy; y++) {
|
||||
|
||||
Uint8 side = 0; // 0=outside, 1=inside
|
||||
|
||||
// re-start at point data offset for each x,y
|
||||
readoff = pstart;
|
||||
p1 = pf;
|
||||
|
||||
// read and check point pairs updating `side`
|
||||
for (Uint16 i=1; i<poly->points; i++) {
|
||||
p2 = (struct point *)(m + readoff);
|
||||
// increment read pointe
|
||||
readoff += pt_size;
|
||||
// check current/previous point crossing
|
||||
if (check_cross(x, y, p1, p2)) {
|
||||
side = 1 - side;
|
||||
}
|
||||
p1 = p2;
|
||||
}
|
||||
|
||||
// check last/first point crossing
|
||||
if (check_cross(x, y, p1, pf)) {
|
||||
side = 1 - side;
|
||||
}
|
||||
|
||||
// check inner polygons only if inside the outer polygon
|
||||
if (side)
|
||||
for (Uint16 i=0; i<poly->inners; i++) {
|
||||
// if inside an inner, then actually outside poly and term
|
||||
if (is_inside_poly(x, y, m, o)) {
|
||||
side = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (side) {
|
||||
Uint32 impos = y + (x * height);
|
||||
(m + o)[impos] = 255;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// update pointer to next polygon
|
||||
readoff = nextpoly;
|
||||
|
||||
return side;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
|
|
@ -90,23 +151,14 @@ Uint32 render(unsigned char *m, Uint32 i, Uint32 o) {
|
|||
struct info *info = (struct info *)(m + i);
|
||||
Uint32 impos;
|
||||
Uint8 inside;
|
||||
Uint32 maxpos = 0;
|
||||
Uint32 polypos = (sizeof (struct info)) + i;
|
||||
|
||||
memset(m+o, 0, info->width * info->height);
|
||||
|
||||
for (Uint32 x=0; x<info->width; x++) {
|
||||
for (Uint32 y=0; y<info->height; y++) {
|
||||
inside = 0;
|
||||
impos = y + (x * info->height);
|
||||
readoff = polypos;
|
||||
for (Uint32 p=0; p<info->polys; p++) {
|
||||
inside = inside | check_inside(x, y, m);
|
||||
}
|
||||
if (inside) (m + o)[impos] = 255;
|
||||
if (impos > maxpos) maxpos = impos;
|
||||
}
|
||||
readoff = polypos;
|
||||
for (Uint32 p=0; p<info->polys; p++) {
|
||||
rasterize_poly(m, o, info->height);
|
||||
}
|
||||
|
||||
return maxpos;
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue