|
|
researchv9-SUN3(old)
#include <jerq.h>
static emax(a,b) { return((a<b)? b:a); }
static emin(a,b) { return((a>b)? b:a); }
static ycmp(), xcmp(), xcut();
typedef struct Edge
{
Point p1, p2;
short dolow;
} Edge;
static Edge edges[300];
static Edge *canon();
polyture(bp, pts, n, t, mode)
Bitmap *bp;
Point *pts;
Texture *t;
{
register Edge *eend, *e, *estart;
register y;
int ymin, ymax, flag;
Point p;
int xcuts[64], *xp, *x;
eend = canon(pts, n, &ymax);
qsort(edges, eend-edges, sizeof(edges[0]), ycmp);
ymin = edges->p1.y;
eend->p1.y = eend->p2.y = ymax+1;
/*
traditional scanline
*/
for(estart = eend = edges, y = ymin; y <= ymax; y++)
{
while(estart->p2.y < y) estart++;
while(eend->p1.y <= y) eend++;
for(e = estart, xp = xcuts; e < eend; e++)
if((y < e->p2.y) || (e->dolow && (y == e->p2.y)))
*xp++ = xcut(y, e);
qsort(xcuts, xp-xcuts, sizeof(*xp), xcmp);
for(x = xcuts; x < xp; x += 2)
texture(bp, Rect(*x, y, x[1]+1, y+1), t, mode);
}
}
static Edge *
canon(pts, n, ymax)
register Point *pts;
register *ymax;
{
register Edge *le, *e;
register Point *p, *lp, pt;
int vert;
/*
delete horizontal edges; compact vertical edges into one
*/
p = pts;
lp = p+n;
e = edges;
*ymax = p->y;
e->p1 = *p++;
for(vert = 0; p < lp; p++)
{
if(*ymax < p->y) *ymax = p->y;
if(p->y == p[-1].y)
{
vert = 0;
e->p1 = *p;
continue;
}
if(vert && (p->x == p[-1].x))
e->p2.y = p->y;
else
{
if(vert)
e[1].p1 = e->p2, e++;
e++->p2 = *p;
e->p1 = *p;
if(vert = p->x == p[-1].x) e--;
}
}
if(vert) e++;
le = e;
*le = edges[0];
le[1] = edges[1];
for(e = edges+1; e <= le; e++)
{
if(e->p1.y < e->p2.y) /* going down */
e->dolow = (e[1].p1.y-e[1].p2.y) > 0;
else
e->dolow = (e[-1].p1.y-e[-1].p2.y) < 0;
}
edges[0] = *le;
/*
canonise the edges so that p1.y < p2.y
or if p1.y == p2.y then p1.x < p2.x.
*/
for(e = edges; e < le; e++)
{
if((e->p1.y > e->p2.y) || ((e->p1.y == e->p2.y)&&(e->p1.x > e->p2.x)))
pt = e->p1, e->p1 = e->p2, e->p2 = pt;
}
return(le);
}
static
ycmp(a, b)
register Edge *a, *b;
{
register k;
if(k = a->p1.y - b->p1.y)
return(k);
return(a->p2.y - b->p2.y);
}
static
xcmp(a, b)
register int *a, *b;
{
return(*a - *b);
}
static
xcut(y, e)
register Edge *e;
{
return(e->p1.x + muldiv(e->p2.x-e->p1.x, y-e->p1.y, e->p2.y-e->p1.y));
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.