nuclear@0: /* nuclear@0: 256-color 3D graphics hack for real-mode DOS. nuclear@0: Copyright (C) 2011 John Tsiombikas nuclear@0: nuclear@0: This program is free software: you can redistribute it and/or modify nuclear@0: it under the terms of the GNU General Public License as published by nuclear@0: the Free Software Foundation, either version 3 of the License, or nuclear@0: (at your option) any later version. nuclear@0: nuclear@0: This program is distributed in the hope that it will be useful, nuclear@0: but WITHOUT ANY WARRANTY; without even the implied warranty of nuclear@0: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the nuclear@0: GNU General Public License for more details. nuclear@0: nuclear@0: You should have received a copy of the GNU General Public License nuclear@0: along with this program. If not, see . nuclear@0: */ nuclear@0: static void SCAN_EDGE(struct vertex *v0, struct vertex *v1) nuclear@0: { nuclear@0: int i, start, end; nuclear@0: float dx, dy, dfdx; nuclear@0: #ifdef INTERP_DEPTH nuclear@0: float z, dz, dfdz; nuclear@0: #endif nuclear@0: #ifdef INTERP_ENERGY nuclear@0: float e, de, dfde; nuclear@0: #endif nuclear@0: float x, y; nuclear@0: struct vertex *edge; nuclear@0: nuclear@0: dy = v1->pos.y - v0->pos.y; nuclear@0: if(dy < 1e-6 && dy > -1e-6) { nuclear@0: return; nuclear@0: } nuclear@0: nuclear@0: dx = v1->pos.x - v0->pos.x; nuclear@0: dfdx = dx / dy; nuclear@0: nuclear@0: #ifdef INTERP_DEPTH nuclear@0: assert(fb->zbuf); nuclear@0: dz = v1->pos.z - v0->pos.z; nuclear@0: dfdz = dz / dy; nuclear@0: #endif nuclear@0: #ifdef INTERP_ENERGY nuclear@0: de = v1->energy - v0->energy; nuclear@0: dfde = de / dy; nuclear@0: #endif nuclear@0: nuclear@0: if(dy < 0.0) { nuclear@0: struct 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@0: start = (int)ROUND(v0->pos.y); nuclear@0: end = (int)ROUND(v1->pos.y); nuclear@0: nuclear@0: x = v0->pos.x; nuclear@0: #ifdef INTERP_DEPTH nuclear@0: z = v0->pos.z; nuclear@0: #endif nuclear@0: #ifdef INTERP_ENERGY nuclear@0: e = v0->energy; nuclear@0: #endif 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@0: } nuclear@0: } nuclear@0: nuclear@0: static void SCAN_LINE(int y, unsigned char *sline) nuclear@0: { nuclear@0: int i, x0, x1, len, tmp, cidx; nuclear@0: #if defined(INTERP_DEPTH) || defined(INTERP_ENERGY) nuclear@0: float x, dx; nuclear@0: #endif nuclear@0: #ifdef INTERP_DEPTH nuclear@0: float z, dz, dfdz; nuclear@0: #endif nuclear@0: #ifdef INTERP_ENERGY nuclear@0: float e, de, dfde; nuclear@0: #endif nuclear@0: struct vertex *left, *right; nuclear@0: nuclear@0: x0 = (int)ROUND(vleft[y].pos.x); nuclear@0: x1 = (int)ROUND(vright[y].pos.x); nuclear@0: len = x1 - x0; nuclear@0: nuclear@0: if(x1 < x0) { nuclear@0: if(st->flags & MGL_CULL_FACE) { nuclear@0: return; nuclear@0: } nuclear@0: tmp = x0; nuclear@0: x0 = x1; nuclear@0: x1 = tmp; nuclear@0: len = -len; 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@0: if(x0 < 0) x0 = 0; nuclear@0: if(x1 >= fb->width) x1 = fb->width - 1; nuclear@0: nuclear@0: assert(len >= 0); nuclear@0: nuclear@0: cidx = left[y].cidx; nuclear@0: #if !defined(INTERP_DEPTH) && !defined(INTERP_ENERGY) nuclear@0: /* no interpolation at all, just memset the whole scanline */ nuclear@0: memset(sline + x0, cidx + left[y].energy * 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@0: if(dx < 0.5 && dx > -0.5) { nuclear@0: return; nuclear@0: } nuclear@0: nuclear@0: #ifdef INTERP_DEPTH nuclear@0: z = left[y].pos.z; nuclear@0: dz = right[y].pos.z - z; nuclear@0: dfdz = dz / dx; nuclear@0: #endif nuclear@0: #ifdef INTERP_ENERGY nuclear@0: e = left[y].energy; nuclear@0: de = right[y].energy - e; nuclear@0: dfde = de / dx; nuclear@0: #endif nuclear@0: nuclear@0: for(i=0; icol_range; nuclear@0: e += dfde; nuclear@0: #endif nuclear@0: sline[x0 + i] = cidx; nuclear@0: } nuclear@0: #endif /* flat */ nuclear@0: }