bless wasm polygon rasterizer for production

This commit is contained in:
Stewart Allen 2020-05-02 11:08:30 -04:00
commit 32dca7586c
4 changed files with 96 additions and 45 deletions

View file

@ -48,9 +48,9 @@ let gs_kiri_sla = exports;
work_total, work_total,
work_remain; work_remain;
if (!self.OffscreenCanvas) { // if (!self.OffscreenCanvas) {
return ondone("browser lacks support for OffscreenCanvas",true); // return ondone("browser lacks support for OffscreenCanvas",true);
} // }
// calculate % complete and call onupdate() // calculate % complete and call onupdate()
function doupdate(work, msg) { function doupdate(work, msg) {
@ -609,8 +609,8 @@ let gs_kiri_sla = exports;
layermax = Math.max(widget.slices.length); layermax = Math.max(widget.slices.length);
}); });
let render = renderLayer; // let render = renderLayer;
// let render = renderLayerWasm; let render = renderLayerWasm;
// generate layer 8-bit bitaps using canvas // generate layer 8-bit bitaps using canvas
for (let index=0; index < layermax; index++) { for (let index=0; index < layermax; index++) {
@ -1296,10 +1296,12 @@ let gs_kiri_sla = exports;
function scaleMovePoly(poly) { function scaleMovePoly(poly) {
let points = poly.points; let points = poly.points;
let bounds = poly.bounds = BASE.newBounds();
for (let i=0, il=points.length; i<il; i++) { for (let i=0, il=points.length; i<il; i++) {
let p = points[i]; let p = points[i];
p.y = height - (p.y * scaleY + height2); p.y = height - (p.y * scaleY + height2);
p.x = p.x * scaleX + width2; p.x = p.x * scaleX + width2;
bounds.update(p);
} }
if (poly.inner) { if (poly.inner) {
for (let i=0, ia=poly.inner, il=poly.inner.length; i<il; i++) { for (let i=0, ia=poly.inner, il=poly.inner.length; i<il; i++) {
@ -1313,7 +1315,12 @@ let gs_kiri_sla = exports;
let inner = poly.inner; let inner = poly.inner;
writer.writeU16(inner ? inner.length : 0, true); writer.writeU16(inner ? inner.length : 0, true);
let points = poly.points; let points = poly.points;
let bounds = poly.bounds;
writer.writeU16(points.length, true); writer.writeU16(points.length, true);
writer.writeU16(bounds.minx, true);
writer.writeU16(bounds.maxx, true);
writer.writeU16(bounds.miny, true);
writer.writeU16(bounds.maxy, true);
for (let j=0, jl=points.length; j<jl; j++) { for (let j=0, jl=points.length; j<jl; j++) {
let point = points[j]; let point = points[j];
writer.writeF32(point.x, true); writer.writeF32(point.x, true);
@ -1321,7 +1328,7 @@ let gs_kiri_sla = exports;
} }
if (inner && inner.length) { if (inner && inner.length) {
for (let i=0, il=inner.length; i<il; i++) { for (let i=0, il=inner.length; i<il; i++) {
writePoly(inner[i]); writePoly(writer, inner[i]);
} }
} }
// write total struct length at struct head // write total struct length at struct head
@ -1355,14 +1362,6 @@ let gs_kiri_sla = exports;
let out = wasm.render(0, imagelen, 0); let out = wasm.render(0, imagelen, 0);
let data = wasm.heap.slice(0, imagelen); let data = wasm.heap.slice(0, imagelen);
// console.log({
// pos: writer.pos,
// arr: array.length,
// mem: wasm.memory.buffer.slice(imagelen,writer.pos),
// out,
// data: data.filter(v => v !== 0)
// });
return { data: data, end: count === 0 }; return { data: data, end: count === 0 };
} }

View file

@ -1,7 +1,7 @@
var exports = { var exports = {
COPYRIGHT:"Copyright (C) Stewart Allen <sa@grid.space> - All Rights Reserved", COPYRIGHT:"Copyright (C) Stewart Allen <sa@grid.space> - All Rights Reserved",
LICENSE:"See the license.md file included with the source distribution", LICENSE:"See the license.md file included with the source distribution",
VERSION:"1.9.7" VERSION:"1.9.8"
}; };
if (!module) var module = {}; if (!module) var module = {};
module.exports = exports; module.exports = exports;

View file

@ -15,6 +15,10 @@ struct poly {
Uint16 length; // offset to end of record in bytes Uint16 length; // offset to end of record in bytes
Uint16 inners; // number of inner polygons Uint16 inners; // number of inner polygons
Uint16 points; // number of points in polygon Uint16 points; // number of points in polygon
Uint16 minx;
Uint16 maxx;
Uint16 miny;
Uint16 maxy;
}; };
struct point { struct point {
@ -22,6 +26,9 @@ struct point {
float y; 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 last(float a, float b);
extern void report(int a, int b); extern void report(int a, int b);
@ -34,29 +41,77 @@ Uint8 check_cross(Uint32 x, Uint32 y, struct point *p1, struct point *p2) {
) ? 1 : 0; ) ? 1 : 0;
} }
Uint8 check_inside(Uint32 x, Uint32 y, unsigned char *p) { Uint8 is_inside_poly(Uint32 x, Uint32 y, unsigned char *m, Uint32 o) {
struct poly *poly = (struct poly *)(p + readoff); struct poly *poly = (struct poly *)(m + readoff);
Uint32 nextpoly = readoff + poly->length; Uint32 nextpoly = readoff + poly->length;
Uint8 side = 0; // 0=outside, 1=inside Uint8 side = 0; // 0=outside, 1=inside
Uint8 psize = sizeof(struct point);
// skip post header // skip post header
readoff += sizeof(struct poly); readoff += ph_size;
// save pointer to first point or last comparison // 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 *p1 = pf;
struct point *p2; struct point *p2;
// skip past first point // skip past first point
readoff += psize; readoff += pt_size;
// read and check point pairs updating `side` // read and check point pairs updating `side`
for (Uint16 i=1; i<poly->points; i++) { for (Uint16 i=1; i<poly->points; i++) {
p2 = (struct point *)(p + readoff); p2 = (struct point *)(m + readoff);
// increment read pointe // increment read pointe
readoff += psize; 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;
}
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 // check current/previous point crossing
if (check_cross(x, y, p1, p2)) { if (check_cross(x, y, p1, p2)) {
side = 1 - side; side = 1 - side;
@ -73,16 +128,22 @@ Uint8 check_inside(Uint32 x, Uint32 y, unsigned char *p) {
if (side) if (side)
for (Uint16 i=0; i<poly->inners; i++) { for (Uint16 i=0; i<poly->inners; i++) {
// if inside an inner, then actually outside poly and term // if inside an inner, then actually outside poly and term
if (check_inside(x, y, p + readoff)) { if (is_inside_poly(x, y, m, o)) {
side = 0; side = 0;
break; break;
} }
} }
if (side) {
Uint32 impos = y + (x * height);
(m + o)[impos] = 255;
}
}
}
// update pointer to next polygon // update pointer to next polygon
readoff = nextpoly; readoff = nextpoly;
return side;
} }
EMSCRIPTEN_KEEPALIVE EMSCRIPTEN_KEEPALIVE
@ -90,23 +151,14 @@ Uint32 render(unsigned char *m, Uint32 i, Uint32 o) {
struct info *info = (struct info *)(m + i); struct info *info = (struct info *)(m + i);
Uint32 impos; Uint32 impos;
Uint8 inside; Uint8 inside;
Uint32 maxpos = 0;
Uint32 polypos = (sizeof (struct info)) + i; Uint32 polypos = (sizeof (struct info)) + i;
memset(m+o, 0, info->width * info->height); 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; readoff = polypos;
for (Uint32 p=0; p<info->polys; p++) { for (Uint32 p=0; p<info->polys; p++) {
inside = inside | check_inside(x, y, m); rasterize_poly(m, o, info->height);
}
if (inside) (m + o)[impos] = 255;
if (impos > maxpos) maxpos = impos;
}
} }
return maxpos; return 1;
} }

BIN
wasm/kiri-sla.wasm Normal file

Binary file not shown.