291 lines
6.0 KiB
C
291 lines
6.0 KiB
C
|
extern int finite(double);
|
||
|
|
||
|
/* undef'ing this makes things look a bit nicer, but slower */
|
||
|
#define DBL_PIXELS
|
||
|
|
||
|
void
|
||
|
NAME(fzort_ctx *ctx, struct pvertex *v1,
|
||
|
struct pvertex *v2, struct pvertex *v3)
|
||
|
{
|
||
|
long x_left, x_right, dxdy_left, dxdy_right;
|
||
|
struct pvertex *v_min, *v_mid, *v_max;
|
||
|
struct edge e_maj, e_top, e_bot, *e_left, *e_right;
|
||
|
float area, inv_area, bf = 1.f;
|
||
|
long dudy, dudy_left, u_left;
|
||
|
long dvdy, dvdy_left, v_left;
|
||
|
int sub_tri, left_to_right, y, lines;
|
||
|
int xa, xb, adjx;
|
||
|
PIXEL_TYPE *scanline_ptr;
|
||
|
PIXEL_TYPE *texture_ptr;
|
||
|
register int l;
|
||
|
register long u, v, dudx, dvdx;
|
||
|
#if (defined DBL_PIXELS) && !(defined MONOCHROME)
|
||
|
register PIXEL_TYPE t;
|
||
|
register long dudx2, dvdx2, dudx4, dvdx4;
|
||
|
#endif
|
||
|
register PIXEL_TYPE *pixel_ptr;
|
||
|
#ifdef MONOCHROME
|
||
|
register unsigned int mask, bits;
|
||
|
register unsigned int *dither_ptr;
|
||
|
#endif
|
||
|
|
||
|
texture_ptr = (PIXEL_TYPE *)ctx->texture;
|
||
|
|
||
|
if (v1->y_scr <= v2->y_scr) {
|
||
|
if (v2->y_scr <= v3->y_scr) {
|
||
|
v_min = v1; v_mid = v2; v_max = v3;
|
||
|
} else if (v3->y_scr <= v1->y_scr) {
|
||
|
v_min = v3; v_mid = v1; v_max = v2;
|
||
|
} else {
|
||
|
v_min = v1; v_mid = v3; v_max = v2;
|
||
|
bf = -bf;
|
||
|
}
|
||
|
} else {
|
||
|
if (v1->y_scr <= v3->y_scr) {
|
||
|
v_min = v2; v_mid = v1; v_max = v3;
|
||
|
bf = -bf;
|
||
|
} else if (v3->y_scr <= v2->y_scr) {
|
||
|
v_min = v3; v_mid = v2; v_max = v1;
|
||
|
bf = -bf;
|
||
|
} else {
|
||
|
v_min = v2; v_mid = v3; v_max = v1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
area = (v_max->x_scr - v_min->x_scr)*(v_mid->y_scr - v_min->y_scr) -
|
||
|
(v_mid->x_scr - v_min->x_scr)*(v_max->y_scr - v_min->y_scr);
|
||
|
|
||
|
if (!finite(area) || area == 0.)
|
||
|
return;
|
||
|
|
||
|
if (area*bf < 0.)
|
||
|
return;
|
||
|
|
||
|
init_edge(ctx, &e_maj, v_min, v_max);
|
||
|
|
||
|
if (e_maj.lines == 0)
|
||
|
return;
|
||
|
|
||
|
init_edge(ctx, &e_top, v_mid, v_max);
|
||
|
init_edge(ctx, &e_bot, v_min, v_mid);
|
||
|
|
||
|
left_to_right = area < 0.; /* inter edge is to the left */
|
||
|
|
||
|
inv_area = 1./area;
|
||
|
|
||
|
dudx = (long) (inv_area*(e_maj.du*e_bot.dy - e_maj.dy*e_bot.du));
|
||
|
dudy = (long) (inv_area*(e_maj.dx*e_bot.du - e_maj.du*e_bot.dx));
|
||
|
|
||
|
dvdx = (long) (inv_area*(e_maj.dv*e_bot.dy - e_maj.dy*e_bot.dv));
|
||
|
dvdy = (long) (inv_area*(e_maj.dx*e_bot.dv - e_maj.dv*e_bot.dx));
|
||
|
|
||
|
#if (defined DBL_PIXELS) && !(defined MONOCHROME)
|
||
|
dudx2 = dudx*2;
|
||
|
dvdx2 = dvdx*2;
|
||
|
|
||
|
dudx4 = dudx2*2;
|
||
|
dvdx4 = dvdx2*2;
|
||
|
#endif
|
||
|
|
||
|
x_left = x_right = dxdy_left = dxdy_right = 0; /* shut up compiler */
|
||
|
u_left = dudy_left = v_left = dvdy_left = 0;
|
||
|
|
||
|
for (sub_tri = 0; sub_tri <= 1; sub_tri++) {
|
||
|
if (sub_tri == 0) {
|
||
|
if (left_to_right) {
|
||
|
e_left = &e_maj;
|
||
|
e_right = &e_bot;
|
||
|
lines = e_right->lines;
|
||
|
} else {
|
||
|
e_left = &e_bot;
|
||
|
e_right = &e_maj;
|
||
|
lines = e_left->lines;
|
||
|
}
|
||
|
|
||
|
x_left = e_left->sx;
|
||
|
dxdy_left = e_left->dxdy;
|
||
|
|
||
|
x_right = e_right->sx;
|
||
|
dxdy_right = e_right->dxdy;
|
||
|
|
||
|
dudy_left = fp_mul(dxdy_left, dudx) + dudy;
|
||
|
u_left = v_min->u_txt;
|
||
|
|
||
|
dvdy_left = fp_mul(dxdy_left, dvdx) + dvdy;
|
||
|
v_left = v_min->v_txt;
|
||
|
|
||
|
if (e_left->adjy) {
|
||
|
u_left += e_left->adjy*dudy_left;
|
||
|
v_left += e_left->adjy*dvdy_left;
|
||
|
}
|
||
|
|
||
|
y = e_left->sy;
|
||
|
} else {
|
||
|
if (left_to_right) {
|
||
|
e_right = &e_top;
|
||
|
lines = e_right->lines;
|
||
|
y = e_right->sy;
|
||
|
|
||
|
x_right = e_right->sx;
|
||
|
dxdy_right = e_right->dxdy;
|
||
|
} else {
|
||
|
e_left = &e_top;
|
||
|
lines = e_left->lines;
|
||
|
y = e_left->sy;
|
||
|
|
||
|
x_left = e_left->sx;
|
||
|
dxdy_left = e_left->dxdy;
|
||
|
|
||
|
dudy_left = fp_mul(dxdy_left, dudx) + dudy;
|
||
|
u_left = v_mid->u_txt;
|
||
|
|
||
|
dvdy_left = fp_mul(dxdy_left, dvdx) + dvdy;
|
||
|
v_left = v_mid->v_txt;
|
||
|
|
||
|
if (e_left->adjy) {
|
||
|
u_left += e_left->adjy*dudy_left;
|
||
|
v_left += e_left->adjy*dvdy_left;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (lines > 0) {
|
||
|
scanline_ptr = (PIXEL_TYPE *)((unsigned char *)ctx->raster.bits +
|
||
|
y*ctx->raster.pitch);
|
||
|
|
||
|
while (lines--) {
|
||
|
xa = FP_ICEIL(x_left);
|
||
|
xb = FP_IFLOOR(x_right);
|
||
|
|
||
|
if (xa < ctx->clip.x_min) {
|
||
|
adjx = ctx->clip.x_min - xa;
|
||
|
xa = ctx->clip.x_min;
|
||
|
} else {
|
||
|
adjx = 0;
|
||
|
}
|
||
|
|
||
|
if (xb > ctx->clip.x_max) {
|
||
|
xb = ctx->clip.x_max;
|
||
|
}
|
||
|
|
||
|
if (xb >= ctx->clip.x_min && xa <= xb) {
|
||
|
u = u_left;
|
||
|
v = v_left;
|
||
|
|
||
|
if (adjx) {
|
||
|
u += dudx*adjx;
|
||
|
v += dvdx*adjx;
|
||
|
}
|
||
|
|
||
|
#ifdef MONOCHROME
|
||
|
pixel_ptr = scanline_ptr + (xa>>3);
|
||
|
dither_ptr = &dither6[y&7][xa&7];
|
||
|
#ifdef LSB_TO_MSB
|
||
|
mask = 1 << (xa&7);
|
||
|
#else
|
||
|
mask = 1 << (7 - (xa&7));
|
||
|
#endif
|
||
|
#else
|
||
|
pixel_ptr = scanline_ptr + xa;
|
||
|
#endif
|
||
|
|
||
|
l = 1 + xb - xa;
|
||
|
|
||
|
#define TEXTURE_PIXEL texture_ptr[(FP_TO_INT(v)&(TEXTURE_SIZE - 1)) + \
|
||
|
(FP_TO_INT(u)&(TEXTURE_SIZE - 1))*TEXTURE_SIZE]
|
||
|
|
||
|
#ifdef MONOCHROME
|
||
|
bits = *pixel_ptr;
|
||
|
|
||
|
while (l--) {
|
||
|
if ((TEXTURE_PIXEL>>2) > *dither_ptr++)
|
||
|
bits |= mask;
|
||
|
else
|
||
|
bits &= ~mask;
|
||
|
#ifdef LSB_TO_MSB
|
||
|
if ((mask <<= 1) == (1<<8)) {
|
||
|
#else
|
||
|
if (!(mask >>= 1)) {
|
||
|
#endif
|
||
|
*pixel_ptr++ = bits;
|
||
|
bits = *pixel_ptr;
|
||
|
dither_ptr -= 8;
|
||
|
#ifdef LSB_TO_MSB
|
||
|
mask = 1;
|
||
|
#else
|
||
|
mask = 1<<7;
|
||
|
#endif
|
||
|
}
|
||
|
u += dudx; v += dvdx;
|
||
|
}
|
||
|
|
||
|
*pixel_ptr = bits;
|
||
|
#else
|
||
|
if (l & 1) {
|
||
|
*pixel_ptr++ = TEXTURE_PIXEL;
|
||
|
u += dudx; v += dvdx;
|
||
|
}
|
||
|
|
||
|
l >>= 1;
|
||
|
|
||
|
if (l & 1) {
|
||
|
#ifdef DBL_PIXELS
|
||
|
t = TEXTURE_PIXEL;
|
||
|
pixel_ptr[0] = t; pixel_ptr[1] = t;
|
||
|
pixel_ptr += 2;
|
||
|
u += dudx2; v += dvdx2;
|
||
|
#else
|
||
|
*pixel_ptr++ = TEXTURE_PIXEL;
|
||
|
u += dudx; v += dvdx;
|
||
|
|
||
|
*pixel_ptr++ = TEXTURE_PIXEL;
|
||
|
u += dudx; v += dvdx;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
l >>= 1;
|
||
|
|
||
|
while (l--) {
|
||
|
#ifdef DBL_PIXELS
|
||
|
t = TEXTURE_PIXEL;
|
||
|
pixel_ptr[0] = t; pixel_ptr[1] = t;
|
||
|
pixel_ptr[2] = t; pixel_ptr[3] = t;
|
||
|
pixel_ptr += 4;
|
||
|
u += dudx4; v += dvdx4;
|
||
|
#else
|
||
|
*pixel_ptr++ = TEXTURE_PIXEL;
|
||
|
u += dudx; v += dvdx;
|
||
|
|
||
|
*pixel_ptr++ = TEXTURE_PIXEL;
|
||
|
u += dudx; v += dvdx;
|
||
|
|
||
|
*pixel_ptr++ = TEXTURE_PIXEL;
|
||
|
u += dudx; v += dvdx;
|
||
|
|
||
|
*pixel_ptr++ = TEXTURE_PIXEL;
|
||
|
u += dudx; v += dvdx;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
#endif /* MONOCHROME */
|
||
|
|
||
|
#undef TEXTURE_PIXEL
|
||
|
}
|
||
|
|
||
|
scanline_ptr += ctx->raster.pitch/sizeof(*scanline_ptr);
|
||
|
x_left += dxdy_left;
|
||
|
x_right += dxdy_right;
|
||
|
u_left += dudy_left;
|
||
|
v_left += dvdy_left;
|
||
|
y++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#undef LSB_TO_MSB
|
||
|
#undef MONOCHROME
|
||
|
#undef FILL_SCANLINE
|
||
|
#undef PIXEL_TYPE
|
||
|
#undef NAME
|