deepstone

changeset 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 ad6b185723cd
children 61d97b17cd2b
files Makefile dosemu/dosemu.c src/fixed_point.c src/fixed_point.h src/mglimpl.h src/mglrast.c src/scantmpl.h src/test.c src/vmath.h
diffstat 9 files changed, 353 insertions(+), 90 deletions(-) [+]
line diff
     1.1 --- a/Makefile	Sat Sep 21 20:18:28 2013 +0300
     1.2 +++ b/Makefile	Sun Sep 22 02:21:30 2013 +0300
     1.3 @@ -1,14 +1,15 @@
     1.4  obj = src/test.o \
     1.5  	  src/mingl.o src/mglrast.o src/mglgen.o \
     1.6  	  src/texture.o src/palman.o \
     1.7 -	  src/scene.o src/cvec.o \
     1.8 +	  src/scene.o src/cvec.o src/fixed_point.o \
     1.9  	  dosemu/dosemu.o
    1.10  dep = $(obj:.o=.d)
    1.11 -bin = test
    1.12 +bin = deepstone
    1.13  
    1.14  CC = gcc
    1.15  CFLAGS = -pedantic -Wall -g `pkg-config --cflags sdl` -Isrc -Idosemu
    1.16 -LDFLAGS = `pkg-config --libs sdl`
    1.17 +#-DRAST_FLOAT -DDBG_USE_FLOAT
    1.18 +LDFLAGS = `pkg-config --libs sdl` -lm
    1.19  
    1.20  $(bin): $(obj)
    1.21  	$(CC) -o $@ $(obj) $(LDFLAGS)
     2.1 --- a/dosemu/dosemu.c	Sat Sep 21 20:18:28 2013 +0300
     2.2 +++ b/dosemu/dosemu.c	Sun Sep 22 02:21:30 2013 +0300
     2.3 @@ -38,6 +38,7 @@
     2.4  			fprintf(stderr, "failed to set video mode\n");
     2.5  			abort();
     2.6  		}
     2.7 +		SDL_WM_SetCaption("Deepstone", 0);
     2.8  		SDL_ShowCursor(0);
     2.9  		SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
    2.10  		break;
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/src/fixed_point.c	Sun Sep 22 02:21:30 2013 +0300
     3.3 @@ -0,0 +1,52 @@
     3.4 +#include <math.h>
     3.5 +#include "fixed_point.h"
     3.6 +
     3.7 +const fixed fixed_zero = 0;
     3.8 +const fixed fixed_one = fixedi(1);
     3.9 +const fixed fixed_half = fixedf(0.5);
    3.10 +const fixed fixed_tenth = fixedf(0.1);
    3.11 +const fixed fixed_255 = fixedi(255);
    3.12 +
    3.13 +#ifndef DBG_USE_FLOAT
    3.14 +
    3.15 +#define PI			3.1415927
    3.16 +#define TWO_PI		6.2831853
    3.17 +
    3.18 +#define LUT_SIZE	256
    3.19 +
    3.20 +static fixed sin_lut[LUT_SIZE], cos_lut[LUT_SIZE];
    3.21 +static int initialized;
    3.22 +
    3.23 +static void precalc_lut(void)
    3.24 +{
    3.25 +	int i;
    3.26 +
    3.27 +	for(i=0; i<LUT_SIZE; i++) {
    3.28 +		float angle = TWO_PI * (float)i / (float)LUT_SIZE;
    3.29 +
    3.30 +		sin_lut[i] = FLOAT_TO_FIXED(sin(angle));
    3.31 +		cos_lut[i] = FLOAT_TO_FIXED(cos(angle));
    3.32 +	}
    3.33 +
    3.34 +	initialized = 1;
    3.35 +}
    3.36 +
    3.37 +static const fixed fix_two_pi = FLOAT_TO_FIXED(TWO_PI);
    3.38 +
    3.39 +fixed fixed_sin(fixed angle) {
    3.40 +	int a;
    3.41 +
    3.42 +	if(!initialized) precalc_lut();
    3.43 +	a = FIXED_INT_PART(fixed_div(angle, fix_two_pi) * 255) % 256;
    3.44 +	return a >= 0 ? sin_lut[a] : -sin_lut[-a];
    3.45 +}
    3.46 +
    3.47 +fixed fixed_cos(fixed angle) {
    3.48 +	int a;
    3.49 +
    3.50 +	if(!initialized) precalc_lut();
    3.51 +	a = FIXED_INT_PART(fixed_div(angle, fix_two_pi) * 255) % 256;
    3.52 +	return a >= 0 ? cos_lut[a] : cos_lut[-a];
    3.53 +}
    3.54 +
    3.55 +#endif
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/fixed_point.h	Sun Sep 22 02:21:30 2013 +0300
     4.3 @@ -0,0 +1,106 @@
     4.4 +#ifndef FIXED_POINT_H_
     4.5 +#define FIXED_POINT_H_
     4.6 +
     4.7 +#include "inttypes.h"
     4.8 +
     4.9 +#ifdef DBG_USE_FLOAT
    4.10 +typedef float fixed;
    4.11 +#else
    4.12 +typedef int32_t fixed;
    4.13 +#endif
    4.14 +
    4.15 +/* valid choices for DECIMAL_BITS
    4.16 + *      8: for fixed point 24:8
    4.17 + *     16: for fixed point 16:16
    4.18 + */
    4.19 +#define DECIMAL_BITS	16
    4.20 +
    4.21 +#if DECIMAL_BITS == 8
    4.22 +#define FIXED_SHIFT		8
    4.23 +#define FLT_SCALE		256.0f
    4.24 +#define FRAC_MASK		0xff
    4.25 +#else	/* DECIMAL_BITS == 16 */
    4.26 +#define FIXED_SHIFT		16
    4.27 +#define FLT_SCALE		65536.0f
    4.28 +#define FRAC_MASK		0xffff
    4.29 +#endif	/* DECIMAL_BITS */
    4.30 +
    4.31 +/*extern const fixed fixed_zero;
    4.32 +extern const fixed fixed_one;
    4.33 +extern const fixed fixed_half;
    4.34 +extern const fixed fixed_tenth;
    4.35 +extern const fixed fixed_255;*/
    4.36 +
    4.37 +#ifdef DBG_USE_FLOAT
    4.38 +/* ------- debug mode, use floating point -------- */
    4.39 +#define FIXED_INT_PART(n)	((int)(n))
    4.40 +#define FIXED_FRAC_PART(n)	((n) > 0.0f ? (FIXED_INT_PART(n) - (n)) : (FIXED_INT_PART(n) + (n)))
    4.41 +#define FIXED_ROUND(n)		FIXED_INT_PART((n) >= 0.0 ? (n) + 0.5f : (n) - 0.5f)
    4.42 +
    4.43 +#define FIXED_TO_FLOAT(n)	(n)
    4.44 +#define FLOAT_TO_FIXED(n)	(n)
    4.45 +#define INT_TO_FIXED(n)		((float)(n))
    4.46 +
    4.47 +#define FIXED_EPSILON		(1e-6)
    4.48 +
    4.49 +#else	/* ---- really fixed point ---- */
    4.50 +
    4.51 +#define FIXED_INT_PART(n)	((n) >> FIXED_SHIFT)
    4.52 +#define FIXED_FRAC_PART(n)	((n) & FRAC_MASK)
    4.53 +#define FIXED_ROUND(n)		FIXED_INT_PART((n) >= 0 ? (n) + fixedf(0.5) : (n) - fixedf(0.5))
    4.54 +/*#define FIXED_ROUND(n)		FIXED_INT_PART(n)*/
    4.55 +
    4.56 +#define FIXED_TO_FLOAT(n)	(float)((n) / FLT_SCALE)
    4.57 +#define FLOAT_TO_FIXED(n)	(fixed)((n) * FLT_SCALE)
    4.58 +#define INT_TO_FIXED(n)		(fixed)((n) << FIXED_SHIFT)
    4.59 +
    4.60 +#define FIXED_EPSILON		(1)
    4.61 +
    4.62 +#endif
    4.63 +
    4.64 +
    4.65 +#define fixed_int(n)		FIXED_INT_PART(n)
    4.66 +#define fixed_frac(n)		FIXED_FRAC_PART(n)
    4.67 +#define fixed_float(n)		FIXED_TO_FLOAT(n)
    4.68 +#define fixed_round(n)		FIXED_ROUND(n)
    4.69 +
    4.70 +#define fixedf(n)			FLOAT_TO_FIXED(n)
    4.71 +#define fixedi(n)			INT_TO_FIXED(n)
    4.72 +
    4.73 +#define fixed_add(n1, n2)	((n1) + (n2))
    4.74 +#define fixed_sub(n1, n2)	((n1) - (n2))
    4.75 +
    4.76 +
    4.77 +
    4.78 +#ifdef DBG_USE_FLOAT
    4.79 +
    4.80 +#define fixed_mul(n1, n2)	((n1) * (n2))
    4.81 +#define fixed_div(n1, n2)	((n1) / (n2))
    4.82 +
    4.83 +#define fixed_sin(x)	(fixed)sin(x)
    4.84 +#define fixed_cos(x)	(fixed)cos(x)
    4.85 +
    4.86 +#else
    4.87 +
    4.88 +#if DECIMAL_BITS == 8
    4.89 +#define fixed_mul(n1, n2)	(fixed)((n1) * (n2) >> FIXED_SHIFT)
    4.90 +#define fixed_div(n1, n2)	(((n1) << FIXED_SHIFT) / (n2))
    4.91 +#else
    4.92 +#define fixed_div(n1, n2)	(((int64_t)(n1) << FIXED_SHIFT) / (int64_t)(n2))
    4.93 +#define fixed_mul(n1, n2)	(((n1) >> 8) * ((n2) >> 8))
    4.94 +#endif	/* DECIMAL_BITS */
    4.95 +
    4.96 +#ifdef __cplusplus
    4.97 +extern "C" {
    4.98 +#endif
    4.99 +
   4.100 +fixed fixed_sin(fixed angle);
   4.101 +fixed fixed_cos(fixed angle);
   4.102 +
   4.103 +#ifdef __cplusplus
   4.104 +}
   4.105 +#endif
   4.106 +
   4.107 +#endif
   4.108 +
   4.109 +#endif	/* FIXED_POINT_H_ */
     5.1 --- a/src/mglimpl.h	Sat Sep 21 20:18:28 2013 +0300
     5.2 +++ b/src/mglimpl.h	Sun Sep 22 02:21:30 2013 +0300
     5.3 @@ -26,6 +26,14 @@
     5.4  	int cidx;
     5.5  };
     5.6  
     5.7 +struct fixed_vertex {
     5.8 +	vec4x_t pos;
     5.9 +	vec4x_t norm;
    5.10 +	vec2x_t tc;
    5.11 +	fixed energy;
    5.12 +	int cidx;
    5.13 +};
    5.14 +
    5.15  struct texture {
    5.16  	int width, height;
    5.17  	int xshift, yshift;
    5.18 @@ -57,6 +65,25 @@
    5.19  };
    5.20  
    5.21  
    5.22 +#define vertex_to_fixedvertex(v, vx) \
    5.23 +	do { \
    5.24 +		vec4_to_fixed4((v).pos, (vx).pos); \
    5.25 +		vec3_to_fixed3((v).norm, (vx).norm); \
    5.26 +		vec2_to_fixed2((v).tc, (vx).tc); \
    5.27 +		(vx).energy = fixedf((v).energy); \
    5.28 +		(vx).cidx = (v).cidx; \
    5.29 +	} while(0)
    5.30 +
    5.31 +#define fixedvertex_to_vertex(vx, v) \
    5.32 +	do { \
    5.33 +		fixed4_to_vec4((vx).pos, (v).pos); \
    5.34 +		fixed3_to_vec3((vx).norm, (v).norm); \
    5.35 +		fixed2_to_vec2((vx).tc, (v).tc); \
    5.36 +		(v).energy = fixed_float((vx).energy); \
    5.37 +		(v).cidx = (vx).cidx; \
    5.38 +	} while(0)
    5.39 +
    5.40 +
    5.41  int mgl_rast_init(struct state *state, struct framebuffer *fbuf);
    5.42  void mgl_rast_cleanup(void);
    5.43  void mgl_rast_prepare(void);
     6.1 --- a/src/mglrast.c	Sat Sep 21 20:18:28 2013 +0300
     6.2 +++ b/src/mglrast.c	Sun Sep 22 02:21:30 2013 +0300
     6.3 @@ -1,20 +1,3 @@
     6.4 -/*
     6.5 -256-color 3D graphics hack for real-mode DOS.
     6.6 -Copyright (C) 2011  John Tsiombikas <nuclear@member.fsf.org>
     6.7 -
     6.8 -This program is free software: you can redistribute it and/or modify
     6.9 -it under the terms of the GNU General Public License as published by
    6.10 -the Free Software Foundation, either version 3 of the License, or
    6.11 -(at your option) any later version.
    6.12 -
    6.13 -This program is distributed in the hope that it will be useful,
    6.14 -but WITHOUT ANY WARRANTY; without even the implied warranty of
    6.15 -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    6.16 -GNU General Public License for more details.
    6.17 -
    6.18 -You should have received a copy of the GNU General Public License
    6.19 -along with this program.  If not, see <http://www.gnu.org/licenses/>.
    6.20 -*/
    6.21  #include <stdio.h>
    6.22  #include <stdlib.h>
    6.23  #include <string.h>
    6.24 @@ -24,7 +7,13 @@
    6.25  #include "mglimpl.h"
    6.26  
    6.27  
    6.28 -static struct vertex *vleft, *vright;
    6.29 +#ifdef RAST_FLOAT
    6.30 +typedef struct vertex VERTEX;
    6.31 +#else
    6.32 +typedef struct fixed_vertex VERTEX;
    6.33 +#endif
    6.34 +
    6.35 +static VERTEX *vleft, *vright;
    6.36  static struct framebuffer *fb;
    6.37  static struct state *st;
    6.38  
    6.39 @@ -102,9 +91,10 @@
    6.40  #undef SCAN_LINE
    6.41  
    6.42  
    6.43 -static void (*scan_edge)(struct vertex*, struct vertex*);
    6.44 +static void (*scan_edge)(VERTEX*, VERTEX*);
    6.45  static void (*scan_line)(int, unsigned char*);
    6.46  
    6.47 +
    6.48  int mgl_rast_init(struct state *state, struct framebuffer *fbuf)
    6.49  {
    6.50  	fb = fbuf;
    6.51 @@ -132,7 +122,7 @@
    6.52  
    6.53  void mgl_rast_prepare(void)
    6.54  {
    6.55 -	static void (*sedge[])(struct vertex*, struct vertex*) = {
    6.56 +	static void (*sedge[])(VERTEX*, VERTEX*) = {
    6.57  							/* tez */
    6.58  		scan_edge_flat,		/* 000 */
    6.59  		scan_edge_z,		/* 001 */
    6.60 @@ -190,6 +180,7 @@
    6.61  
    6.62  void mgl_draw_poly(struct vertex *v, int numv)
    6.63  {
    6.64 +#ifdef RAST_FLOAT
    6.65  	int ybeg, yend, i;
    6.66  	unsigned char *sline;
    6.67  
    6.68 @@ -215,4 +206,37 @@
    6.69  		scan_line(i, sline);
    6.70  		sline += fb->width;
    6.71  	}
    6.72 +#else
    6.73 +	int ybeg, yend, i;
    6.74 +	unsigned char *sline;
    6.75 +
    6.76 +	ybeg = fb->height;
    6.77 +	yend = 0;
    6.78 +
    6.79 +	for(i=0; i<numv; i++) {
    6.80 +		int y;
    6.81 +		struct vertex *v0 = v + i;
    6.82 +		struct vertex *v1 = v + (i + 1) % numv;
    6.83 +		struct fixed_vertex vx0, vx1;
    6.84 +
    6.85 +		vertex_to_fixedvertex(*v0, vx0);
    6.86 +		vertex_to_fixedvertex(*v1, vx1);
    6.87 +
    6.88 +		y = fixed_round(vx0.pos.y);
    6.89 +
    6.90 +		scan_edge(&vx0, &vx1);
    6.91 +
    6.92 +		if(y > yend) yend = y;
    6.93 +		if(y < ybeg) ybeg = y;
    6.94 +	}
    6.95 +
    6.96 +	if(ybeg < 0) ybeg = 0;
    6.97 +	if(yend >= fb->height) yend = fb->height - 1;
    6.98 +
    6.99 +	sline = fb->pixels + ybeg * fb->width;
   6.100 +	for(i=ybeg; i<yend; i++) {
   6.101 +		scan_line(i, sline);
   6.102 +		sline += fb->width;
   6.103 +	}
   6.104 +#endif
   6.105  }
     7.1 --- a/src/scantmpl.h	Sat Sep 21 20:18:28 2013 +0300
     7.2 +++ b/src/scantmpl.h	Sun Sep 22 02:21:30 2013 +0300
     7.3 @@ -1,61 +1,44 @@
     7.4 -/*
     7.5 -256-color 3D graphics hack for real-mode DOS.
     7.6 -Copyright (C) 2011  John Tsiombikas <nuclear@member.fsf.org>
     7.7 -
     7.8 -This program is free software: you can redistribute it and/or modify
     7.9 -it under the terms of the GNU General Public License as published by
    7.10 -the Free Software Foundation, either version 3 of the License, or
    7.11 -(at your option) any later version.
    7.12 -
    7.13 -This program is distributed in the hope that it will be useful,
    7.14 -but WITHOUT ANY WARRANTY; without even the implied warranty of
    7.15 -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    7.16 -GNU General Public License for more details.
    7.17 -
    7.18 -You should have received a copy of the GNU General Public License
    7.19 -along with this program.  If not, see <http://www.gnu.org/licenses/>.
    7.20 -*/
    7.21 -static void SCAN_EDGE(struct vertex *v0, struct vertex *v1)
    7.22 +static void SCAN_EDGE(VERTEX *v0, VERTEX *v1)
    7.23  {
    7.24  	int i, start, end;
    7.25 -	float dx, dy, dfdx;
    7.26 +	fixed dx, dy, dfdx;
    7.27  #ifdef INTERP_DEPTH
    7.28 -	float z, dz, dfdz;
    7.29 +	fixed z, dz, dfdz;
    7.30  #endif
    7.31  #ifdef INTERP_ENERGY
    7.32 -	float e, de, dfde;
    7.33 +	fixed e, de, dfde;
    7.34  #endif
    7.35  #ifdef INTERP_TEX
    7.36 -	float u, v, du, dv, dfdu, dfdv;
    7.37 +	fixed u, v, du, dv, dfdu, dfdv;
    7.38  #endif
    7.39 -	float x;
    7.40 -	struct vertex *edge;
    7.41 +	fixed x;
    7.42 +	VERTEX *edge;
    7.43  
    7.44  	dy = v1->pos.y - v0->pos.y;
    7.45 -	if(dy < 1e-6 && dy > -1e-6) {
    7.46 +	if(dy < FIXED_EPSILON && dy > -FIXED_EPSILON) {
    7.47  		return;
    7.48  	}
    7.49  
    7.50  	dx = v1->pos.x - v0->pos.x;
    7.51 -	dfdx = dx / dy;
    7.52 +	dfdx = fixed_div(dx, dy);
    7.53  
    7.54  #ifdef INTERP_DEPTH
    7.55  	dz = v1->pos.z - v0->pos.z;
    7.56 -	dfdz = dz / dy;
    7.57 +	dfdz = fixed_div(dz, dy);
    7.58  #endif
    7.59  #ifdef INTERP_ENERGY
    7.60  	de = v1->energy - v0->energy;
    7.61 -	dfde = de / dy;
    7.62 +	dfde = fixed_div(de, dy);
    7.63  #endif
    7.64  #ifdef INTERP_TEX
    7.65  	du = v1->tc.x - v0->tc.x;
    7.66  	dv = v1->tc.y - v0->tc.y;
    7.67 -	dfdu = du / dy;
    7.68 -	dfdv = dv / dy;
    7.69 +	dfdu = fixed_div(du, dy);
    7.70 +	dfdv = fixed_div(dv, dy);
    7.71  #endif
    7.72  
    7.73 -	if(dy < 0.0) {
    7.74 -		struct vertex *tmp = v0;
    7.75 +	if(dy < 0) {
    7.76 +		VERTEX *tmp = v0;
    7.77  		v0 = v1;
    7.78  		v1 = tmp;
    7.79  		edge = (st->ord == MGL_CCW) ? vright : vleft;
    7.80 @@ -63,8 +46,8 @@
    7.81  		edge = (st->ord == MGL_CCW) ? vleft : vright;
    7.82  	}
    7.83  
    7.84 -	start = (int)ROUND(v0->pos.y);
    7.85 -	end = (int)ROUND(v1->pos.y);
    7.86 +	start = (int)fixed_round(v0->pos.y);
    7.87 +	end = (int)fixed_round(v1->pos.y);
    7.88  
    7.89  	if(start >= 0) {
    7.90  
    7.91 @@ -80,18 +63,18 @@
    7.92  		v = v0->tc.y;
    7.93  #endif
    7.94  	} else {
    7.95 -		float lines = -v0->pos.y;
    7.96 +		fixed lines = -v0->pos.y;
    7.97  
    7.98 -		x = v0->pos.x + dfdx * lines;
    7.99 +		x = v0->pos.x + fixed_mul(dfdx, lines);
   7.100  #ifdef INTERP_DEPTH
   7.101 -		z = v0->pos.z + dfdz * lines;
   7.102 +		z = v0->pos.z + fixed_mul(dfdz, lines);
   7.103  #endif
   7.104  #ifdef INTERP_ENERGY
   7.105 -		e = v0->energy + dfde * lines;
   7.106 +		e = v0->energy + fixed_mul(dfde, lines);
   7.107  #endif
   7.108  #ifdef INTERP_TEX
   7.109 -		u = v0->tc.x + dfdu * lines;
   7.110 -		v = v0->tc.y + dfdv * lines;
   7.111 +		u = v0->tc.x + fixed_mul(dfdu, lines);
   7.112 +		v = v0->tc.y + fixed_mul(dfdv, lines);
   7.113  #endif
   7.114  		start = 0;
   7.115  	}
   7.116 @@ -132,22 +115,22 @@
   7.117  	int x0, x1, len, tmp, cidx;
   7.118  #if defined(INTERP_DEPTH) || defined(INTERP_ENERGY) || defined(INTERP_TEX)
   7.119  	int i;
   7.120 -	float x, dx;
   7.121 +	fixed x, dx;
   7.122  #endif
   7.123  #ifdef INTERP_DEPTH
   7.124 -	float z, dz, dfdz;
   7.125 +	fixed z, dz, dfdz;
   7.126  #endif
   7.127  #ifdef INTERP_ENERGY
   7.128 -	float e, de, dfde;
   7.129 +	fixed e, de, dfde;
   7.130  #endif
   7.131  #ifdef INTERP_TEX
   7.132  	unsigned int tx, ty;
   7.133 -	float u, v, du, dv, dfdu, dfdv;
   7.134 +	fixed u, v, du, dv, dfdu, dfdv;
   7.135  #endif
   7.136 -	struct vertex *left, *right;
   7.137 +	VERTEX *left, *right;
   7.138  
   7.139 -	x0 = (int)ROUND(vleft[y].pos.x);
   7.140 -	x1 = (int)ROUND(vright[y].pos.x);
   7.141 +	x0 = (int)fixed_round(vleft[y].pos.x);
   7.142 +	x1 = (int)fixed_round(vright[y].pos.x);
   7.143  
   7.144  	if(x1 < x0) {
   7.145  		if(st->flags & MGL_CULL_FACE) {
   7.146 @@ -174,13 +157,13 @@
   7.147  	len = x1 - x0;
   7.148  	assert(len >= 0);
   7.149  	/* no interpolation at all, just memset the whole scanline */
   7.150 -	memset(sline + x0, cidx + left[y].energy * st->col_range, len);
   7.151 +	memset(sline + x0, cidx + fixed_int(fixed_mul(left[y].energy, fixedi(st->col_range))), len);
   7.152  #else
   7.153  	/* otherwise do a loop and interpolate whatever needs interpolating */
   7.154  	x = left[y].pos.x;
   7.155  	dx = right[y].pos.x - x;
   7.156  
   7.157 -	if(dx < 0.5 && dx > -0.5) {
   7.158 +	if(dx < fixedf(0.5) && dx > -fixedf(0.5)) {
   7.159  		return;
   7.160  	}
   7.161  
   7.162 @@ -188,41 +171,41 @@
   7.163  #ifdef INTERP_DEPTH
   7.164  		z = left[y].pos.z;
   7.165  		dz = right[y].pos.z - z;
   7.166 -		dfdz = dz / dx;
   7.167 +		dfdz = fixed_div(dz, dx);
   7.168  #endif
   7.169  #ifdef INTERP_ENERGY
   7.170  		e = left[y].energy;
   7.171  		de = right[y].energy - e;
   7.172 -		dfde = de / dx;
   7.173 +		dfde = fixed_div(de, dx);
   7.174  #endif
   7.175  #ifdef INTERP_TEX
   7.176  		u = left[y].tc.x;
   7.177  		v = left[y].tc.y;
   7.178  		du = right[y].tc.x - u;
   7.179  		dv = right[y].tc.y - v;
   7.180 -		dfdu = du / dx;
   7.181 -		dfdv = dv / dx;
   7.182 +		dfdu = fixed_div(du, dx);
   7.183 +		dfdv = fixed_div(dv, dx);
   7.184  #endif
   7.185  	} else {
   7.186 -		float dist = -left[y].pos.x;
   7.187 +		fixed dist = -left[y].pos.x;
   7.188  
   7.189  #ifdef INTERP_DEPTH
   7.190  		dz = right[y].pos.z - left[y].pos.z;
   7.191 -		dfdz = dz / dx;
   7.192 -		z = left[y].pos.z + dfdz * dist;
   7.193 +		dfdz = fixed_div(dz, dx);
   7.194 +		z = left[y].pos.z + fixed_mul(dfdz, dist);
   7.195  #endif
   7.196  #ifdef INTERP_ENERGY
   7.197  		de = right[y].energy - left[y].energy;
   7.198 -		dfde = de / dx;
   7.199 -		e = left[y].energy + dfde * dist;
   7.200 +		dfde = fixed_div(de, dx);
   7.201 +		e = left[y].energy + fixed_mul(dfde, dist);
   7.202  #endif
   7.203  #ifdef INTERP_TEX
   7.204  		du = right[y].tc.x - left[y].tc.x;
   7.205  		dv = right[y].tc.y - left[y].tc.y;
   7.206 -		dfdu = du / dx;
   7.207 -		dfdv = dv / dx;
   7.208 -		u = left[y].tc.x + dfdu * dist;
   7.209 -		v = left[y].tc.y + dfdv * dist;
   7.210 +		dfdu = fixed_div(du, dx);
   7.211 +		dfdv = fixed_div(dv, dx);
   7.212 +		u = left[y].tc.x + fixed_mul(dfdu, dist);
   7.213 +		v = left[y].tc.y + fixed_mul(dfdv, dist);
   7.214  #endif
   7.215  		x0 = 0;
   7.216  	}
   7.217 @@ -234,10 +217,14 @@
   7.218  
   7.219  #ifdef INTERP_DEPTH
   7.220  		long pix = (sline + x0 + i) - fb->pixels;
   7.221 +#ifdef RAST_FLOAT
   7.222  		unsigned short zval = (unsigned short)(z * USHRT_MAX);
   7.223 +#else
   7.224 +		unsigned short zval = (unsigned short)((z >> 1) & 0xffff);
   7.225 +#endif
   7.226  		unsigned short *zptr = fb->zbuf[ZTILE(pix)] + ZTILE_OFFS(pix);
   7.227  
   7.228 -		if(z < 0.0 || z >= 1.0 || zval > *zptr) {
   7.229 +		if(z < 0 || z >= fixedi(1) || zval > *zptr) {
   7.230  # ifdef INTERP_TEX
   7.231  			u += dfdu;
   7.232  			v += dfdv;
   7.233 @@ -253,18 +240,18 @@
   7.234  		z += dfdz;
   7.235  #endif
   7.236  #ifdef INTERP_TEX
   7.237 -		tx = (unsigned int)(u * st->tex.width) & st->tex.xmask;
   7.238 -		ty = (unsigned int)(v * st->tex.height) & st->tex.ymask;
   7.239 +		tx = (unsigned int)fixed_int(fixed_mul(u, fixedi(st->tex.width))) & st->tex.xmask;
   7.240 +		ty = (unsigned int)fixed_int(fixed_mul(v, fixedi(st->tex.height))) & st->tex.ymask;
   7.241  		c = st->tex.pixels[(ty << st->tex.xshift) + tx];
   7.242  
   7.243  		u += dfdu;
   7.244  		v += dfdv;
   7.245  #endif
   7.246  #ifdef INTERP_ENERGY
   7.247 -		c += e * st->col_range;
   7.248 +		c += fixed_int(fixed_mul(e, fixedi(st->col_range)));
   7.249  		e += dfde;
   7.250  #else
   7.251 -		c += left[y].energy * st->col_range;
   7.252 +		c += fixed_int(fixed_mul(left[y].energy, fixedi(st->col_range)));
   7.253  #endif
   7.254  		sline[x0 + i] = c;
   7.255  	}
     8.1 --- a/src/test.c	Sat Sep 21 20:18:28 2013 +0300
     8.2 +++ b/src/test.c	Sun Sep 22 02:21:30 2013 +0300
     8.3 @@ -270,6 +270,14 @@
     8.4  		}
     8.5  		break;
     8.6  
     8.7 +	case 'z':
     8.8 +		if(mgl_isenabled(MGL_DEPTH_TEST)) {
     8.9 +			mgl_disable(MGL_DEPTH_TEST);
    8.10 +		} else {
    8.11 +			mgl_enable(MGL_DEPTH_TEST);
    8.12 +		}
    8.13 +		break;
    8.14 +
    8.15  	case ' ':
    8.16  		auto_rotate = !auto_rotate;
    8.17  		break;
     9.1 --- a/src/vmath.h	Sat Sep 21 20:18:28 2013 +0300
     9.2 +++ b/src/vmath.h	Sun Sep 22 02:21:30 2013 +0300
     9.3 @@ -2,6 +2,7 @@
     9.4  #define VMATH_H_
     9.5  
     9.6  #include <math.h>
     9.7 +#include "fixed_point.h"
     9.8  
     9.9  #ifndef M_PI
    9.10  #define M_PI	3.1415926536
    9.11 @@ -19,5 +20,61 @@
    9.12  	float x, y;
    9.13  } vec2_t;
    9.14  
    9.15 +typedef struct {
    9.16 +	fixed x, y, z, w;
    9.17 +} vec4x_t;
    9.18 +
    9.19 +typedef struct {
    9.20 +	fixed x, y, z;
    9.21 +} vec3x_t;
    9.22 +
    9.23 +typedef struct {
    9.24 +	fixed x, y;
    9.25 +} vec2x_t;
    9.26 +
    9.27 +
    9.28 +#define vec2_to_fixed2(v, f) \
    9.29 +	do { \
    9.30 +		f.x = fixedf(v.x); \
    9.31 +		f.y = fixedf(v.y); \
    9.32 +	} while(0)
    9.33 +
    9.34 +#define vec3_to_fixed3(v, f) \
    9.35 +	do { \
    9.36 +		f.x = fixedf(v.x); \
    9.37 +		f.y = fixedf(v.y); \
    9.38 +		f.z = fixedf(v.z); \
    9.39 +	} while(0)
    9.40 +
    9.41 +#define vec4_to_fixed4(v, f) \
    9.42 +	do { \
    9.43 +		f.x = fixedf(v.x); \
    9.44 +		f.y = fixedf(v.y); \
    9.45 +		f.z = fixedf(v.z); \
    9.46 +		f.w = fixedf(v.w); \
    9.47 +	} while(0)
    9.48 +
    9.49 +
    9.50 +#define fixed2_to_vec2(f, v) \
    9.51 +	do { \
    9.52 +		v.x = fixed_float(f.x); \
    9.53 +		v.y = fixed_float(f.y); \
    9.54 +	} while(0)
    9.55 +
    9.56 +#define fixed3_to_vec3(f, v) \
    9.57 +	do { \
    9.58 +		v.x = fixed_float(f.x); \
    9.59 +		v.y = fixed_float(f.y); \
    9.60 +		v.z = fixed_float(f.z); \
    9.61 +	} while(0)
    9.62 +
    9.63 +#define fixed4_to_vec4(f, v) \
    9.64 +	do { \
    9.65 +		v.x = fixed_float(f.x); \
    9.66 +		v.y = fixed_float(f.y); \
    9.67 +		v.z = fixed_float(f.z); \
    9.68 +		v.w = fixed_float(f.w); \
    9.69 +	} while(0)
    9.70 +
    9.71  
    9.72  #endif	/* VMATH_H_ */