deepstone

diff src/scantmpl.h @ 25:5ff8ce78059a

first pass at converting the rasterizer to fixed point
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 22 Sep 2013 02:21:30 +0300
parents 1e9f0b3616fa
children 11d14f688485
line diff
     1.1 --- a/src/scantmpl.h	Sat Sep 21 20:18:28 2013 +0300
     1.2 +++ b/src/scantmpl.h	Sun Sep 22 02:21:30 2013 +0300
     1.3 @@ -1,61 +1,44 @@
     1.4 -/*
     1.5 -256-color 3D graphics hack for real-mode DOS.
     1.6 -Copyright (C) 2011  John Tsiombikas <nuclear@member.fsf.org>
     1.7 -
     1.8 -This program is free software: you can redistribute it and/or modify
     1.9 -it under the terms of the GNU General Public License as published by
    1.10 -the Free Software Foundation, either version 3 of the License, or
    1.11 -(at your option) any later version.
    1.12 -
    1.13 -This program is distributed in the hope that it will be useful,
    1.14 -but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.15 -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.16 -GNU General Public License for more details.
    1.17 -
    1.18 -You should have received a copy of the GNU General Public License
    1.19 -along with this program.  If not, see <http://www.gnu.org/licenses/>.
    1.20 -*/
    1.21 -static void SCAN_EDGE(struct vertex *v0, struct vertex *v1)
    1.22 +static void SCAN_EDGE(VERTEX *v0, VERTEX *v1)
    1.23  {
    1.24  	int i, start, end;
    1.25 -	float dx, dy, dfdx;
    1.26 +	fixed dx, dy, dfdx;
    1.27  #ifdef INTERP_DEPTH
    1.28 -	float z, dz, dfdz;
    1.29 +	fixed z, dz, dfdz;
    1.30  #endif
    1.31  #ifdef INTERP_ENERGY
    1.32 -	float e, de, dfde;
    1.33 +	fixed e, de, dfde;
    1.34  #endif
    1.35  #ifdef INTERP_TEX
    1.36 -	float u, v, du, dv, dfdu, dfdv;
    1.37 +	fixed u, v, du, dv, dfdu, dfdv;
    1.38  #endif
    1.39 -	float x;
    1.40 -	struct vertex *edge;
    1.41 +	fixed x;
    1.42 +	VERTEX *edge;
    1.43  
    1.44  	dy = v1->pos.y - v0->pos.y;
    1.45 -	if(dy < 1e-6 && dy > -1e-6) {
    1.46 +	if(dy < FIXED_EPSILON && dy > -FIXED_EPSILON) {
    1.47  		return;
    1.48  	}
    1.49  
    1.50  	dx = v1->pos.x - v0->pos.x;
    1.51 -	dfdx = dx / dy;
    1.52 +	dfdx = fixed_div(dx, dy);
    1.53  
    1.54  #ifdef INTERP_DEPTH
    1.55  	dz = v1->pos.z - v0->pos.z;
    1.56 -	dfdz = dz / dy;
    1.57 +	dfdz = fixed_div(dz, dy);
    1.58  #endif
    1.59  #ifdef INTERP_ENERGY
    1.60  	de = v1->energy - v0->energy;
    1.61 -	dfde = de / dy;
    1.62 +	dfde = fixed_div(de, dy);
    1.63  #endif
    1.64  #ifdef INTERP_TEX
    1.65  	du = v1->tc.x - v0->tc.x;
    1.66  	dv = v1->tc.y - v0->tc.y;
    1.67 -	dfdu = du / dy;
    1.68 -	dfdv = dv / dy;
    1.69 +	dfdu = fixed_div(du, dy);
    1.70 +	dfdv = fixed_div(dv, dy);
    1.71  #endif
    1.72  
    1.73 -	if(dy < 0.0) {
    1.74 -		struct vertex *tmp = v0;
    1.75 +	if(dy < 0) {
    1.76 +		VERTEX *tmp = v0;
    1.77  		v0 = v1;
    1.78  		v1 = tmp;
    1.79  		edge = (st->ord == MGL_CCW) ? vright : vleft;
    1.80 @@ -63,8 +46,8 @@
    1.81  		edge = (st->ord == MGL_CCW) ? vleft : vright;
    1.82  	}
    1.83  
    1.84 -	start = (int)ROUND(v0->pos.y);
    1.85 -	end = (int)ROUND(v1->pos.y);
    1.86 +	start = (int)fixed_round(v0->pos.y);
    1.87 +	end = (int)fixed_round(v1->pos.y);
    1.88  
    1.89  	if(start >= 0) {
    1.90  
    1.91 @@ -80,18 +63,18 @@
    1.92  		v = v0->tc.y;
    1.93  #endif
    1.94  	} else {
    1.95 -		float lines = -v0->pos.y;
    1.96 +		fixed lines = -v0->pos.y;
    1.97  
    1.98 -		x = v0->pos.x + dfdx * lines;
    1.99 +		x = v0->pos.x + fixed_mul(dfdx, lines);
   1.100  #ifdef INTERP_DEPTH
   1.101 -		z = v0->pos.z + dfdz * lines;
   1.102 +		z = v0->pos.z + fixed_mul(dfdz, lines);
   1.103  #endif
   1.104  #ifdef INTERP_ENERGY
   1.105 -		e = v0->energy + dfde * lines;
   1.106 +		e = v0->energy + fixed_mul(dfde, lines);
   1.107  #endif
   1.108  #ifdef INTERP_TEX
   1.109 -		u = v0->tc.x + dfdu * lines;
   1.110 -		v = v0->tc.y + dfdv * lines;
   1.111 +		u = v0->tc.x + fixed_mul(dfdu, lines);
   1.112 +		v = v0->tc.y + fixed_mul(dfdv, lines);
   1.113  #endif
   1.114  		start = 0;
   1.115  	}
   1.116 @@ -132,22 +115,22 @@
   1.117  	int x0, x1, len, tmp, cidx;
   1.118  #if defined(INTERP_DEPTH) || defined(INTERP_ENERGY) || defined(INTERP_TEX)
   1.119  	int i;
   1.120 -	float x, dx;
   1.121 +	fixed x, dx;
   1.122  #endif
   1.123  #ifdef INTERP_DEPTH
   1.124 -	float z, dz, dfdz;
   1.125 +	fixed z, dz, dfdz;
   1.126  #endif
   1.127  #ifdef INTERP_ENERGY
   1.128 -	float e, de, dfde;
   1.129 +	fixed e, de, dfde;
   1.130  #endif
   1.131  #ifdef INTERP_TEX
   1.132  	unsigned int tx, ty;
   1.133 -	float u, v, du, dv, dfdu, dfdv;
   1.134 +	fixed u, v, du, dv, dfdu, dfdv;
   1.135  #endif
   1.136 -	struct vertex *left, *right;
   1.137 +	VERTEX *left, *right;
   1.138  
   1.139 -	x0 = (int)ROUND(vleft[y].pos.x);
   1.140 -	x1 = (int)ROUND(vright[y].pos.x);
   1.141 +	x0 = (int)fixed_round(vleft[y].pos.x);
   1.142 +	x1 = (int)fixed_round(vright[y].pos.x);
   1.143  
   1.144  	if(x1 < x0) {
   1.145  		if(st->flags & MGL_CULL_FACE) {
   1.146 @@ -174,13 +157,13 @@
   1.147  	len = x1 - x0;
   1.148  	assert(len >= 0);
   1.149  	/* no interpolation at all, just memset the whole scanline */
   1.150 -	memset(sline + x0, cidx + left[y].energy * st->col_range, len);
   1.151 +	memset(sline + x0, cidx + fixed_int(fixed_mul(left[y].energy, fixedi(st->col_range))), len);
   1.152  #else
   1.153  	/* otherwise do a loop and interpolate whatever needs interpolating */
   1.154  	x = left[y].pos.x;
   1.155  	dx = right[y].pos.x - x;
   1.156  
   1.157 -	if(dx < 0.5 && dx > -0.5) {
   1.158 +	if(dx < fixedf(0.5) && dx > -fixedf(0.5)) {
   1.159  		return;
   1.160  	}
   1.161  
   1.162 @@ -188,41 +171,41 @@
   1.163  #ifdef INTERP_DEPTH
   1.164  		z = left[y].pos.z;
   1.165  		dz = right[y].pos.z - z;
   1.166 -		dfdz = dz / dx;
   1.167 +		dfdz = fixed_div(dz, dx);
   1.168  #endif
   1.169  #ifdef INTERP_ENERGY
   1.170  		e = left[y].energy;
   1.171  		de = right[y].energy - e;
   1.172 -		dfde = de / dx;
   1.173 +		dfde = fixed_div(de, dx);
   1.174  #endif
   1.175  #ifdef INTERP_TEX
   1.176  		u = left[y].tc.x;
   1.177  		v = left[y].tc.y;
   1.178  		du = right[y].tc.x - u;
   1.179  		dv = right[y].tc.y - v;
   1.180 -		dfdu = du / dx;
   1.181 -		dfdv = dv / dx;
   1.182 +		dfdu = fixed_div(du, dx);
   1.183 +		dfdv = fixed_div(dv, dx);
   1.184  #endif
   1.185  	} else {
   1.186 -		float dist = -left[y].pos.x;
   1.187 +		fixed dist = -left[y].pos.x;
   1.188  
   1.189  #ifdef INTERP_DEPTH
   1.190  		dz = right[y].pos.z - left[y].pos.z;
   1.191 -		dfdz = dz / dx;
   1.192 -		z = left[y].pos.z + dfdz * dist;
   1.193 +		dfdz = fixed_div(dz, dx);
   1.194 +		z = left[y].pos.z + fixed_mul(dfdz, dist);
   1.195  #endif
   1.196  #ifdef INTERP_ENERGY
   1.197  		de = right[y].energy - left[y].energy;
   1.198 -		dfde = de / dx;
   1.199 -		e = left[y].energy + dfde * dist;
   1.200 +		dfde = fixed_div(de, dx);
   1.201 +		e = left[y].energy + fixed_mul(dfde, dist);
   1.202  #endif
   1.203  #ifdef INTERP_TEX
   1.204  		du = right[y].tc.x - left[y].tc.x;
   1.205  		dv = right[y].tc.y - left[y].tc.y;
   1.206 -		dfdu = du / dx;
   1.207 -		dfdv = dv / dx;
   1.208 -		u = left[y].tc.x + dfdu * dist;
   1.209 -		v = left[y].tc.y + dfdv * dist;
   1.210 +		dfdu = fixed_div(du, dx);
   1.211 +		dfdv = fixed_div(dv, dx);
   1.212 +		u = left[y].tc.x + fixed_mul(dfdu, dist);
   1.213 +		v = left[y].tc.y + fixed_mul(dfdv, dist);
   1.214  #endif
   1.215  		x0 = 0;
   1.216  	}
   1.217 @@ -234,10 +217,14 @@
   1.218  
   1.219  #ifdef INTERP_DEPTH
   1.220  		long pix = (sline + x0 + i) - fb->pixels;
   1.221 +#ifdef RAST_FLOAT
   1.222  		unsigned short zval = (unsigned short)(z * USHRT_MAX);
   1.223 +#else
   1.224 +		unsigned short zval = (unsigned short)((z >> 1) & 0xffff);
   1.225 +#endif
   1.226  		unsigned short *zptr = fb->zbuf[ZTILE(pix)] + ZTILE_OFFS(pix);
   1.227  
   1.228 -		if(z < 0.0 || z >= 1.0 || zval > *zptr) {
   1.229 +		if(z < 0 || z >= fixedi(1) || zval > *zptr) {
   1.230  # ifdef INTERP_TEX
   1.231  			u += dfdu;
   1.232  			v += dfdv;
   1.233 @@ -253,18 +240,18 @@
   1.234  		z += dfdz;
   1.235  #endif
   1.236  #ifdef INTERP_TEX
   1.237 -		tx = (unsigned int)(u * st->tex.width) & st->tex.xmask;
   1.238 -		ty = (unsigned int)(v * st->tex.height) & st->tex.ymask;
   1.239 +		tx = (unsigned int)fixed_int(fixed_mul(u, fixedi(st->tex.width))) & st->tex.xmask;
   1.240 +		ty = (unsigned int)fixed_int(fixed_mul(v, fixedi(st->tex.height))) & st->tex.ymask;
   1.241  		c = st->tex.pixels[(ty << st->tex.xshift) + tx];
   1.242  
   1.243  		u += dfdu;
   1.244  		v += dfdv;
   1.245  #endif
   1.246  #ifdef INTERP_ENERGY
   1.247 -		c += e * st->col_range;
   1.248 +		c += fixed_int(fixed_mul(e, fixedi(st->col_range)));
   1.249  		e += dfde;
   1.250  #else
   1.251 -		c += left[y].energy * st->col_range;
   1.252 +		c += fixed_int(fixed_mul(left[y].energy, fixedi(st->col_range)));
   1.253  #endif
   1.254  		sline[x0 + i] = c;
   1.255  	}