nuclear@25: static void SCAN_EDGE(VERTEX *v0, VERTEX *v1) nuclear@0: { nuclear@0: int i, start, end; nuclear@25: fixed dx, dy, dfdx; nuclear@0: #ifdef INTERP_DEPTH nuclear@25: fixed z, dz, dfdz; nuclear@0: #endif nuclear@0: #ifdef INTERP_ENERGY nuclear@25: fixed e, de, dfde; nuclear@0: #endif nuclear@3: #ifdef INTERP_TEX nuclear@25: fixed u, v, du, dv, dfdu, dfdv; nuclear@3: #endif nuclear@25: fixed x; nuclear@25: VERTEX *edge; nuclear@0: nuclear@0: dy = v1->pos.y - v0->pos.y; nuclear@25: if(dy < FIXED_EPSILON && dy > -FIXED_EPSILON) { nuclear@0: return; nuclear@0: } nuclear@0: nuclear@0: dx = v1->pos.x - v0->pos.x; nuclear@25: dfdx = fixed_div(dx, dy); nuclear@0: nuclear@0: #ifdef INTERP_DEPTH nuclear@0: dz = v1->pos.z - v0->pos.z; nuclear@25: dfdz = fixed_div(dz, dy); nuclear@0: #endif nuclear@0: #ifdef INTERP_ENERGY nuclear@0: de = v1->energy - v0->energy; nuclear@25: dfde = fixed_div(de, dy); nuclear@0: #endif nuclear@3: #ifdef INTERP_TEX nuclear@3: du = v1->tc.x - v0->tc.x; nuclear@3: dv = v1->tc.y - v0->tc.y; nuclear@25: dfdu = fixed_div(du, dy); nuclear@25: dfdv = fixed_div(dv, dy); nuclear@3: #endif nuclear@0: nuclear@25: if(dy < 0) { nuclear@25: VERTEX *tmp = v0; nuclear@0: v0 = v1; nuclear@0: v1 = tmp; nuclear@0: edge = (st->ord == MGL_CCW) ? vright : vleft; nuclear@0: } else { nuclear@0: edge = (st->ord == MGL_CCW) ? vleft : vright; nuclear@0: } nuclear@0: nuclear@25: start = (int)fixed_round(v0->pos.y); nuclear@25: end = (int)fixed_round(v1->pos.y); nuclear@0: nuclear@9: if(start >= 0) { nuclear@9: nuclear@9: x = v0->pos.x; nuclear@0: #ifdef INTERP_DEPTH nuclear@9: z = v0->pos.z; nuclear@0: #endif nuclear@0: #ifdef INTERP_ENERGY nuclear@9: e = v0->energy; nuclear@0: #endif nuclear@3: #ifdef INTERP_TEX nuclear@9: u = v0->tc.x; nuclear@9: v = v0->tc.y; nuclear@3: #endif nuclear@9: } else { nuclear@25: fixed lines = -v0->pos.y; nuclear@9: nuclear@25: x = v0->pos.x + fixed_mul(dfdx, lines); nuclear@9: #ifdef INTERP_DEPTH nuclear@25: z = v0->pos.z + fixed_mul(dfdz, lines); nuclear@9: #endif nuclear@9: #ifdef INTERP_ENERGY nuclear@25: e = v0->energy + fixed_mul(dfde, lines); nuclear@9: #endif nuclear@9: #ifdef INTERP_TEX nuclear@25: u = v0->tc.x + fixed_mul(dfdu, lines); nuclear@25: v = v0->tc.y + fixed_mul(dfdv, lines); nuclear@9: #endif nuclear@9: start = 0; nuclear@9: } nuclear@9: nuclear@9: if(end >= fb->height) { nuclear@9: end = fb->height - 1; nuclear@9: } nuclear@9: nuclear@9: nuclear@0: for(i=start; icidx; nuclear@0: #ifdef INTERP_DEPTH nuclear@0: edge[i].pos.z = z; nuclear@0: z += dfdz; nuclear@0: #endif nuclear@0: nuclear@0: #ifdef INTERP_ENERGY nuclear@0: edge[i].energy = e; nuclear@0: e += dfde; nuclear@0: #else nuclear@0: edge[i].energy = v0->energy; nuclear@0: #endif nuclear@3: nuclear@3: #ifdef INTERP_TEX nuclear@3: edge[i].tc.x = u; nuclear@3: edge[i].tc.y = v; nuclear@3: u += dfdu; nuclear@3: v += dfdv; nuclear@3: #endif nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: static void SCAN_LINE(int y, unsigned char *sline) nuclear@0: { nuclear@3: int x0, x1, len, tmp, cidx; nuclear@3: #if defined(INTERP_DEPTH) || defined(INTERP_ENERGY) || defined(INTERP_TEX) nuclear@3: int i; nuclear@25: fixed x, dx; nuclear@0: #endif nuclear@0: #ifdef INTERP_DEPTH nuclear@25: fixed z, dz, dfdz; nuclear@0: #endif nuclear@0: #ifdef INTERP_ENERGY nuclear@25: fixed e, de, dfde; nuclear@0: #endif nuclear@3: #ifdef INTERP_TEX nuclear@17: unsigned int tx, ty; nuclear@25: fixed u, v, du, dv, dfdu, dfdv; nuclear@3: #endif nuclear@25: VERTEX *left, *right; nuclear@0: nuclear@25: x0 = (int)fixed_round(vleft[y].pos.x); nuclear@25: x1 = (int)fixed_round(vright[y].pos.x); nuclear@0: nuclear@0: if(x1 < x0) { nuclear@28: if(IS_ENABLED(st->flags, MGL_CULL_FACE)) { nuclear@0: return; nuclear@0: } nuclear@0: tmp = x0; nuclear@0: x0 = x1; nuclear@0: x1 = tmp; nuclear@0: nuclear@0: left = vright; nuclear@0: right = vleft; nuclear@0: } else { nuclear@0: left = vleft; nuclear@0: right = vright; nuclear@0: } nuclear@0: nuclear@9: if(x1 >= fb->width) { nuclear@9: x1 = fb->width - 1; nuclear@9: } nuclear@0: nuclear@0: cidx = left[y].cidx; nuclear@3: #if !defined(INTERP_DEPTH) && !defined(INTERP_ENERGY) && !defined(INTERP_TEX) nuclear@9: if(x0 < 0) x0 = 0; nuclear@9: len = x1 - x0; nuclear@9: assert(len >= 0); nuclear@0: /* no interpolation at all, just memset the whole scanline */ nuclear@25: memset(sline + x0, cidx + fixed_int(fixed_mul(left[y].energy, fixedi(st->col_range))), len); nuclear@0: #else nuclear@0: /* otherwise do a loop and interpolate whatever needs interpolating */ nuclear@0: x = left[y].pos.x; nuclear@0: dx = right[y].pos.x - x; nuclear@0: nuclear@25: if(dx < fixedf(0.5) && dx > -fixedf(0.5)) { nuclear@0: return; nuclear@0: } nuclear@0: nuclear@9: if(x0 >= 0) { nuclear@0: #ifdef INTERP_DEPTH nuclear@9: z = left[y].pos.z; nuclear@9: dz = right[y].pos.z - z; nuclear@25: dfdz = fixed_div(dz, dx); nuclear@0: #endif nuclear@0: #ifdef INTERP_ENERGY nuclear@9: e = left[y].energy; nuclear@9: de = right[y].energy - e; nuclear@25: dfde = fixed_div(de, dx); nuclear@0: #endif nuclear@3: #ifdef INTERP_TEX nuclear@9: u = left[y].tc.x; nuclear@9: v = left[y].tc.y; nuclear@9: du = right[y].tc.x - u; nuclear@9: dv = right[y].tc.y - v; nuclear@25: dfdu = fixed_div(du, dx); nuclear@25: dfdv = fixed_div(dv, dx); nuclear@3: #endif nuclear@9: } else { nuclear@25: fixed dist = -left[y].pos.x; nuclear@9: nuclear@9: #ifdef INTERP_DEPTH nuclear@9: dz = right[y].pos.z - left[y].pos.z; nuclear@25: dfdz = fixed_div(dz, dx); nuclear@25: z = left[y].pos.z + fixed_mul(dfdz, dist); nuclear@9: #endif nuclear@9: #ifdef INTERP_ENERGY nuclear@9: de = right[y].energy - left[y].energy; nuclear@25: dfde = fixed_div(de, dx); nuclear@25: e = left[y].energy + fixed_mul(dfde, dist); nuclear@9: #endif nuclear@9: #ifdef INTERP_TEX nuclear@9: du = right[y].tc.x - left[y].tc.x; nuclear@9: dv = right[y].tc.y - left[y].tc.y; nuclear@25: dfdu = fixed_div(du, dx); nuclear@25: dfdv = fixed_div(dv, dx); nuclear@25: u = left[y].tc.x + fixed_mul(dfdu, dist); nuclear@25: v = left[y].tc.y + fixed_mul(dfdv, dist); nuclear@9: #endif nuclear@9: x0 = 0; nuclear@9: } nuclear@9: nuclear@9: len = x1 - x0; nuclear@0: nuclear@0: for(i=0; ipixels; nuclear@25: #ifdef RAST_FLOAT nuclear@9: unsigned short zval = (unsigned short)(z * USHRT_MAX); nuclear@25: #else nuclear@25: unsigned short zval = (unsigned short)((z >> 1) & 0xffff); nuclear@25: #endif nuclear@9: unsigned short *zptr = fb->zbuf[ZTILE(pix)] + ZTILE_OFFS(pix); nuclear@9: nuclear@25: if(z < 0 || z >= fixedi(1) || zval > *zptr) { nuclear@9: # ifdef INTERP_TEX nuclear@9: u += dfdu; nuclear@9: v += dfdv; nuclear@9: # endif nuclear@9: # ifdef INTERP_ENERGY nuclear@9: e += dfde; nuclear@9: # endif nuclear@9: z += dfdz; nuclear@9: continue; nuclear@9: } nuclear@9: nuclear@9: *zptr = zval; nuclear@3: z += dfdz; nuclear@3: #endif nuclear@3: #ifdef INTERP_TEX nuclear@25: tx = (unsigned int)fixed_int(fixed_mul(u, fixedi(st->tex.width))) & st->tex.xmask; nuclear@25: ty = (unsigned int)fixed_int(fixed_mul(v, fixedi(st->tex.height))) & st->tex.ymask; nuclear@3: c = st->tex.pixels[(ty << st->tex.xshift) + tx]; nuclear@3: nuclear@3: u += dfdu; nuclear@3: v += dfdv; nuclear@3: #endif nuclear@0: #ifdef INTERP_ENERGY nuclear@25: c += fixed_int(fixed_mul(e, fixedi(st->col_range))); nuclear@0: e += dfde; nuclear@3: #else nuclear@25: c += fixed_int(fixed_mul(left[y].energy, fixedi(st->col_range))); nuclear@0: #endif nuclear@3: sline[x0 + i] = c; nuclear@0: } nuclear@0: #endif /* flat */ nuclear@0: }