rayzor

changeset 9:70e332156d02

moving along
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 10 Apr 2014 02:31:31 +0300
parents fcd06a15dfdd
children 235c8b764c0b
files .hgignore GNUmakefile Makefile src/dosemu/dosemu.c src/lines.c src/lines.h src/m3dimpl.h src/m3drast.c src/main.cc src/min3d.c src/min3d.h src/modeller.cc src/modeller.h src/object.cc src/rayzor.h src/rend.cc src/rend.h src/renderer.cc src/renderer.h src/screen.cc src/screen.h src/scrman.cc src/scrman.h src/stl/vector.h
diffstat 24 files changed, 824 insertions(+), 204 deletions(-) [+]
line diff
     1.1 --- a/.hgignore	Mon Apr 07 08:46:06 2014 +0300
     1.2 +++ b/.hgignore	Thu Apr 10 02:31:31 2014 +0300
     1.3 @@ -3,3 +3,11 @@
     1.4  \.swp$
     1.5  \.obj$
     1.6  \.exe$
     1.7 +^rayzor$
     1.8 +\.log$
     1.9 +\.sln$
    1.10 +\.vcproj$
    1.11 +\.vcxproj
    1.12 +\.suo$
    1.13 +Debug/
    1.14 +Release/
     2.1 --- a/GNUmakefile	Mon Apr 07 08:46:06 2014 +0300
     2.2 +++ b/GNUmakefile	Thu Apr 10 02:31:31 2014 +0300
     2.3 @@ -1,8 +1,9 @@
     2.4 -modelobj = src/main.o src/min3d.o src/m3drast.o src/logger.o
     2.5 -rendobj = src/rend.o src/vmath.o
     2.6 +baseobj = src/main.o src/logger.o src/screen.o src/scrman.o
     2.7 +modelobj = src/modeller.o src/min3d.o src/m3drast.o src/lines.o
     2.8 +rendobj = src/renderer.o src/vmath.o
     2.9  scnobj = src/scene.o src/object.o
    2.10  sysobj = src/dosemu/dosemu.o
    2.11 -obj = $(modelobj) $(rendobj) $(scnobj) $(sysobj)
    2.12 +obj = $(baseobj) $(modelobj) $(rendobj) $(scnobj) $(sysobj)
    2.13  dep = $(obj:.o=.d)
    2.14  bin = rayzor
    2.15  
    2.16 @@ -32,3 +33,7 @@
    2.17  .PHONY: cleandep
    2.18  cleandep:
    2.19  	rm -f $(dep)
    2.20 +
    2.21 +.PHONY: profile
    2.22 +profile:
    2.23 +	$(MAKE) CFLAGS="$(CFLAGS) -O3 -pg" LDFLAGS="$(LDFLAGS) -pg"
     3.1 --- a/Makefile	Mon Apr 07 08:46:06 2014 +0300
     3.2 +++ b/Makefile	Thu Apr 10 02:31:31 2014 +0300
     3.3 @@ -1,8 +1,9 @@
     3.4 -modelobj = main.obj min3d.obj m3drast.obj logger.obj
     3.5 -rendobj = rend.obj vmath.obj
     3.6 +baseobj = main.obj logger.obj screen.obj scrman.obj
     3.7 +modelobj = modeller.obj min3d.obj m3drast.obj lines.obj
     3.8 +rendobj = renderer.obj vmath.obj
     3.9  scnobj = scene.obj object.obj
    3.10  sysobj = gfx.obj vbe.obj dpmi.obj timer.obj mouse.obj keyb.obj
    3.11 -obj = $(modelobj) $(rendobj) $(scnobj) $(sysobj)
    3.12 +obj = $(baseobj) $(modelobj) $(rendobj) $(scnobj) $(sysobj)
    3.13  bin = rayzor.exe
    3.14  
    3.15  #dbg = -d2
     4.1 --- a/src/dosemu/dosemu.c	Mon Apr 07 08:46:06 2014 +0300
     4.2 +++ b/src/dosemu/dosemu.c	Thu Apr 10 02:31:31 2014 +0300
     4.3 @@ -10,10 +10,11 @@
     4.4  #include "keyb.h"
     4.5  #include "timer.h"
     4.6  
     4.7 +static void cleanup(void);
     4.8  static void proc_events(void);
     4.9  static void capture_frame(unsigned char *frame);
    4.10  
    4.11 -static void init_sdl()
    4.12 +static void init_sdl(void)
    4.13  {
    4.14  	const SDL_version *ver;
    4.15  
    4.16 @@ -23,9 +24,15 @@
    4.17  		if((ver = SDL_Linked_Version())) {
    4.18  			printf("SDL %d.%d.%d initialized\n", ver->major, ver->minor, ver->patch);
    4.19  		}
    4.20 +		atexit(cleanup);
    4.21  	}
    4.22  }
    4.23  
    4.24 +static void cleanup(void)
    4.25 +{
    4.26 +	SDL_Quit();
    4.27 +}
    4.28 +
    4.29  /* ----- graphics (gfx.c (vbe) implementation) ----- */
    4.30  static SDL_Surface *fbsurf;
    4.31  static int scale = 1;
    4.32 @@ -74,7 +81,6 @@
    4.33  {
    4.34  	SDL_ShowCursor(1);
    4.35  	SDL_EnableKeyRepeat(0, 0);
    4.36 -	SDL_Quit();
    4.37  	return 0;
    4.38  }
    4.39  
    4.40 @@ -178,7 +184,7 @@
    4.41  	}
    4.42  
    4.43  	/* also print fps every second ... */
    4.44 -	{
    4.45 +	/*{
    4.46  		static long prev_fps, num_frames;
    4.47  		long msec, dt;
    4.48  
    4.49 @@ -193,7 +199,7 @@
    4.50  		} else {
    4.51  			num_frames++;
    4.52  		}
    4.53 -	}
    4.54 +	}*/
    4.55  }
    4.56  
    4.57  #define spin_delay(ms) \
    4.58 @@ -206,14 +212,15 @@
    4.59  
    4.60  void wait_vsync(void)
    4.61  {
    4.62 -	static int prev_msec;
    4.63 -	int msec, dt, tleft;
    4.64 +	/*static int prev_msec;
    4.65 +	int msec, dt, tleft;*/
    4.66  
    4.67  	if(!copy_frame_called) {
    4.68  		copy_frame(0);
    4.69  		copy_frame_called = 0;
    4.70  	}
    4.71  
    4.72 +	/*
    4.73  	msec = SDL_GetTicks();
    4.74  
    4.75  	dt = msec - prev_msec;
    4.76 @@ -234,6 +241,7 @@
    4.77  	} else {
    4.78  		prev_msec = msec;
    4.79  	}
    4.80 +	*/
    4.81  }
    4.82  
    4.83  static int cap_count = 0;
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/lines.c	Thu Apr 10 02:31:31 2014 +0300
     5.3 @@ -0,0 +1,146 @@
     5.4 +#include "lines.h"
     5.5 +
     5.6 +enum {
     5.7 +	IN		= 0,
     5.8 +	LEFT	= 1,
     5.9 +	RIGHT	= 2,
    5.10 +	TOP		= 4,
    5.11 +	BOTTOM	= 8
    5.12 +};
    5.13 +
    5.14 +static int outcode(int x, int y, int minx, int miny, int maxx, int maxy)
    5.15 +{
    5.16 +	int code = 0;
    5.17 +
    5.18 +	if(x < minx) {
    5.19 +		code |= LEFT;
    5.20 +	} else if(x > maxx) {
    5.21 +		code |= RIGHT;
    5.22 +	}
    5.23 +	if(y < miny) {
    5.24 +		code |= TOP;
    5.25 +	} else if(y > maxy) {
    5.26 +		code |= BOTTOM;
    5.27 +	}
    5.28 +	return code;
    5.29 +}
    5.30 +
    5.31 +#define FIXMUL(a, b)	(((a) * (b)) >> 8)
    5.32 +#define FIXDIV(a, b)	(((a) << 8) / (b))
    5.33 +
    5.34 +#define LERP(a, b, t)	((a) + FIXMUL((b) - (a), (t)))
    5.35 +
    5.36 +int clip_line2d(int *x0, int *y0, int *x1, int *y1, const int *vp)
    5.37 +{
    5.38 +	int oc_out;
    5.39 +	int minx = vp[0];
    5.40 +	int miny = vp[1];
    5.41 +	int maxx = vp[0] + vp[2] - 1;
    5.42 +	int maxy = vp[1] + vp[3] - 1;
    5.43 +
    5.44 +	int oc0 = outcode(*x0, *y0, minx, miny, maxx, maxy);
    5.45 +	int oc1 = outcode(*x1, *y1, minx, miny, maxx, maxy);
    5.46 +
    5.47 +	int32_t fx0, fy0, fx1, fy1, fminx, fminy, fmaxx, fmaxy;
    5.48 +
    5.49 +	if(!(oc0 | oc1)) return 1;	/* both points are inside */
    5.50 +
    5.51 +	fx0 = *x0 << 8;
    5.52 +	fy0 = *y0 << 8;
    5.53 +	fx1 = *x1 << 8;
    5.54 +	fy1 = *y1 << 8;
    5.55 +	fminx = minx << 8;
    5.56 +	fminy = miny << 8;
    5.57 +	fmaxx = maxx << 8;
    5.58 +	fmaxy = maxy << 8;
    5.59 +
    5.60 +	for(;;) {
    5.61 +		int32_t x, y, t;
    5.62 +
    5.63 +		if(oc0 & oc1) return 0;		/* both have points with the same outbit, not visible */
    5.64 +		if(!(oc0 | oc1)) break;		/* both points are inside */
    5.65 +
    5.66 +		oc_out = oc0 ? oc0 : oc1;
    5.67 +
    5.68 +		if(oc_out & TOP) {
    5.69 +			t = FIXDIV(fminy - fy0, fy1 - fy0);
    5.70 +			x = LERP(fx0, fx1, t);
    5.71 +			y = fminy;
    5.72 +		} else if(oc_out & BOTTOM) {
    5.73 +			t = FIXDIV(fmaxy - fy0, fy1 - fy0);
    5.74 +			x = LERP(fx0, fx1, t);
    5.75 +			y = fmaxy;
    5.76 +		} else if(oc_out & LEFT) {
    5.77 +			t = FIXDIV(fminx - fx0, fx1 - fx0);
    5.78 +			x = fminx;
    5.79 +			y = LERP(fy0, fy1, t);
    5.80 +		} else if(oc_out & RIGHT) {
    5.81 +			t = FIXDIV(fmaxx - fx0, fx1 - fx0);
    5.82 +			x = fmaxx;
    5.83 +			y = LERP(fy0, fy1, t);
    5.84 +		}
    5.85 +
    5.86 +		if(oc_out == oc0) {
    5.87 +			fx0 = x;
    5.88 +			fy0 = y;
    5.89 +			oc0 = outcode(fx0 >> 8, fy0 >> 8, minx, miny, maxx, maxy);
    5.90 +		} else {
    5.91 +			fx1 = x;
    5.92 +			fy1 = y;
    5.93 +			oc1 = outcode(fx1 >> 8, fy1 >> 8, minx, miny, maxx, maxy);
    5.94 +		}
    5.95 +	}
    5.96 +
    5.97 +	*x0 = fx0 >> 8;
    5.98 +	*y0 = fy0 >> 8;
    5.99 +	*x1 = fx1 >> 8;
   5.100 +	*y1 = fy1 >> 8;
   5.101 +	return 1;
   5.102 +}
   5.103 +
   5.104 +void draw_line(uint32_t *fb, int fbwidth, uint32_t col, int x0, int y0, int x1, int y1)
   5.105 +{
   5.106 +	int i, dx, dy, x_inc, y_inc, error;
   5.107 +
   5.108 +	fb += y0 * fbwidth + x0;
   5.109 +
   5.110 +	dx = x1 - x0;
   5.111 +	dy = y1 - y0;
   5.112 +
   5.113 +	if(dx >= 0) {
   5.114 +		x_inc = 1;
   5.115 +	} else {
   5.116 +		x_inc = -1;
   5.117 +		dx = -dx;
   5.118 +	}
   5.119 +	if(dy >= 0) {
   5.120 +		y_inc = fbwidth;
   5.121 +	} else {
   5.122 +		y_inc = -fbwidth;
   5.123 +		dy = -dy;
   5.124 +	}
   5.125 +
   5.126 +	if(dx > dy) {
   5.127 +		error = dy * 2 - dx;
   5.128 +		for(i=0; i<=dx; i++) {
   5.129 +			*fb = col;
   5.130 +			if(error >= 0) {
   5.131 +				error -= dx * 2;
   5.132 +				fb += y_inc;
   5.133 +			}
   5.134 +			error += dy * 2;
   5.135 +			fb += x_inc;
   5.136 +		}
   5.137 +	} else {
   5.138 +		error = dx * 2 - dy;
   5.139 +		for(i=0; i<=dy; i++) {
   5.140 +			*fb = col;
   5.141 +			if(error >= 0) {
   5.142 +				error -= dy * 2;
   5.143 +				fb += x_inc;
   5.144 +			}
   5.145 +			error += dx * 2;
   5.146 +			fb += y_inc;
   5.147 +		}
   5.148 +	}
   5.149 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/src/lines.h	Thu Apr 10 02:31:31 2014 +0300
     6.3 @@ -0,0 +1,9 @@
     6.4 +#ifndef LINES_H_
     6.5 +#define LINES_H_
     6.6 +
     6.7 +#include "inttypes.h"
     6.8 +
     6.9 +int clip_line2d(int *x0, int *y0, int *x1, int *y1, const int *vp);
    6.10 +void draw_line(uint32_t *fb, int fbwidth, uint32_t col, int x0, int y0, int x1, int y1);
    6.11 +
    6.12 +#endif	/* LINES_H_ */
     7.1 --- a/src/m3dimpl.h	Mon Apr 07 08:46:06 2014 +0300
     7.2 +++ b/src/m3dimpl.h	Thu Apr 10 02:31:31 2014 +0300
     7.3 @@ -12,7 +12,7 @@
     7.4  
     7.5  struct min3d_vertex {
     7.6  	float pos[4];
     7.7 -	float color[4];
     7.8 +	uint32_t color;
     7.9  	float normal[4];
    7.10  	float tex[2];
    7.11  };
    7.12 @@ -50,8 +50,10 @@
    7.13  
    7.14  extern struct min3d_context *m3dctx;
    7.15  
    7.16 -void draw_point(struct min3d_vertex *v);
    7.17 -void draw_line(struct min3d_vertex *v);
    7.18 -void draw_poly(struct min3d_vertex *v, int numv);
    7.19 +#define ENABLED(x)	(m3dctx->state & (1 << x))
    7.20 +
    7.21 +void m3d_draw_point(struct min3d_vertex *v);
    7.22 +void m3d_draw_line(struct min3d_vertex *v);
    7.23 +void m3d_draw_poly(struct min3d_vertex *v, int numv);
    7.24  
    7.25  #endif	/* M3DIMPL_H_ */
     8.1 --- a/src/m3drast.c	Mon Apr 07 08:46:06 2014 +0300
     8.2 +++ b/src/m3drast.c	Thu Apr 10 02:31:31 2014 +0300
     8.3 @@ -1,25 +1,56 @@
     8.4  #include "m3dimpl.h"
     8.5 +#include "lines.h"
     8.6  
     8.7  
     8.8 -void draw_point(struct min3d_vertex *v)
     8.9 +void m3d_draw_point(struct min3d_vertex *v)
    8.10  {
    8.11  	int x = v->pos[0] + 0.5;
    8.12  	int y = v->pos[1] + 0.5;
    8.13  	int xsz = m3dctx->cbuf->xsz;
    8.14 -	unsigned char *ptr = m3dctx->cbuf->pixels + (y * xsz + x) * 3;
    8.15 -
    8.16 -	int r = (int)(v->color[0] * 255.0);
    8.17 -	int g = (int)(v->color[1] * 255.0);
    8.18 -	int b = (int)(v->color[2] * 255.0);
    8.19 -	ptr[0] = r > 255 ? 255 : r;
    8.20 -	ptr[1] = g > 255 ? 255 : g;
    8.21 -	ptr[2] = b > 255 ? 255 : b;
    8.22 +	m3dctx->cbuf->pixels[y * xsz + x] = v->color;
    8.23  }
    8.24  
    8.25 -void draw_line(struct min3d_vertex *v)
    8.26 +void m3d_draw_line(struct min3d_vertex *v)
    8.27  {
    8.28 +	int x0, y0, x1, y1;
    8.29 +
    8.30 +	x0 = v[0].pos[0];
    8.31 +	y0 = v[0].pos[1];
    8.32 +	x1 = v[1].pos[0];
    8.33 +	y1 = v[1].pos[1];
    8.34 +
    8.35 +	if(clip_line2d(&x0, &y0, &x1, &y1, m3dctx->vport)) {
    8.36 +		draw_line(m3dctx->cbuf->pixels, m3dctx->cbuf->xsz, v->color, x0, y0, x1, y1);
    8.37 +	}
    8.38  }
    8.39  
    8.40 -void draw_poly(struct min3d_vertex *v, int numv)
    8.41 +void m3d_draw_poly(struct min3d_vertex *v, int numv)
    8.42  {
    8.43 +	int i;
    8.44 +	struct min3d_vertex last[2];
    8.45 +
    8.46 +	if(ENABLED(M3D_CULL_FACE)) {
    8.47 +		float a[2], b[2], crossz = 0;
    8.48 +
    8.49 +		for(i=1; i<numv - 1; i++) {
    8.50 +			int n = i + 1;
    8.51 +			a[0] = v[i].pos[0] - v[0].pos[0];
    8.52 +			a[1] = v[i].pos[1] - v[0].pos[1];
    8.53 +
    8.54 +			b[0] = v[n].pos[0] - v[0].pos[0];
    8.55 +			b[1] = v[n].pos[1] - v[0].pos[1];
    8.56 +
    8.57 +			crossz += a[0] * b[1] - a[1] * b[0];
    8.58 +		}
    8.59 +
    8.60 +		if(crossz < 0) return;
    8.61 +	}
    8.62 +
    8.63 +	last[0] = v[numv - 1];
    8.64 +	last[1] = v[0];
    8.65 +
    8.66 +	for(i=0; i<numv - 1; i++) {
    8.67 +		m3d_draw_line(v++);
    8.68 +	}
    8.69 +	m3d_draw_line(last);
    8.70  }
     9.1 --- a/src/main.cc	Mon Apr 07 08:46:06 2014 +0300
     9.2 +++ b/src/main.cc	Thu Apr 10 02:31:31 2014 +0300
     9.3 @@ -8,41 +8,40 @@
     9.4  #include "keyb.h"
     9.5  #include "mouse.h"
     9.6  #include "logger.h"
     9.7 -#include "min3d.h"
     9.8  #include "scene.h"
     9.9 +#include "rayzor.h"
    9.10 +#include "screen.h"
    9.11 +#include "modeller.h"
    9.12 +#include "renderer.h"
    9.13 +#include "scrman.h"
    9.14  
    9.15  static bool init();
    9.16  static void cleanup();
    9.17  static void display();
    9.18  static void swap_buffers();
    9.19 -static void draw_cursor(unsigned char *buf, int mx, int my);
    9.20 +static void draw_cursor(uint32_t *buf, int mx, int my);
    9.21  static void handle_keyboard();
    9.22  static void handle_mouse();
    9.23 -static void mouse_button(int bn, int x, int y);
    9.24 -static void mouse_motion(int x, int y);
    9.25  static bool parse_args(int argc, char **argv);
    9.26  static void sig(int s);
    9.27  
    9.28 -static int xsz = 640;
    9.29 -static int ysz = 480;
    9.30 -static int bpp = 24;
    9.31 +uint32_t *fb_pixels;
    9.32 +int fb_width = 640;
    9.33 +int fb_height = 480;
    9.34 +int fb_bpp = 32;
    9.35 +Scene *scene;
    9.36 +
    9.37  static int bytespp;
    9.38  static bool novideo;
    9.39 -static unsigned char *fb;
    9.40 -static unsigned char *backbuf;
    9.41 +static void *fb;
    9.42  static int rbits, gbits, bbits;
    9.43  static int rshift, gshift, bshift;
    9.44  static unsigned int rmask, gmask, bmask;
    9.45  
    9.46 -static int mx, my;	// mouse cursor
    9.47 -static float cam_theta, cam_phi = 25, cam_dist = 8;
    9.48 -
    9.49  static bool use_mouse;
    9.50 +static int mouse_x, mouse_y;
    9.51  static bool quit;
    9.52  
    9.53 -struct m3d_image rbuf;
    9.54 -static Scene *scn;
    9.55 -
    9.56  int main(int argc, char **argv)
    9.57  {
    9.58  	if(!parse_args(argc, argv)) {
    9.59 @@ -68,6 +67,11 @@
    9.60  	return 0;
    9.61  }
    9.62  
    9.63 +void quit_app()
    9.64 +{
    9.65 +	quit = true;
    9.66 +}
    9.67 +
    9.68  static bool init()
    9.69  {
    9.70  	signal(SIGINT, sig);
    9.71 @@ -81,62 +85,65 @@
    9.72  			return false;
    9.73  		}
    9.74  
    9.75 -		if(!(fb = (unsigned char*)set_video_mode(xsz, ysz, bpp))) {
    9.76 +		if(!(fb = set_video_mode(fb_width, fb_height, fb_bpp))) {
    9.77  			set_text_mode();
    9.78 -			fprintf(stderr, "failed to set video mode: %dx%d %dbpp\n", xsz, ysz, bpp);
    9.79 +			fprintf(stderr, "failed to set video mode: %dx%d %dbpp\n", fb_width, fb_height, fb_bpp);
    9.80  			return false;
    9.81  		}
    9.82 -		bpp = get_color_depth();
    9.83 +		fb_bpp = get_color_depth();
    9.84  		get_color_bits(&rbits, &gbits, &bbits);
    9.85  		get_color_shift(&rshift, &gshift, &bshift);
    9.86  		get_color_mask(&rmask, &gmask, &bmask);
    9.87 -		bytespp = (int)ceil(bpp / 8.0);
    9.88 +		bytespp = (int)ceil(fb_bpp / 8.0);
    9.89  
    9.90 -		printlog("bpp: %d (%d %d %d)\n", bpp, rbits, gbits, bbits);
    9.91 +		printlog("bpp: %d (%d %d %d)\n", fb_bpp, rbits, gbits, bbits);
    9.92  		printlog("shift: %d %d %d\n", rshift, gshift, bshift);
    9.93  		printlog("mask: %x %x %x\n", rmask, gmask, bmask);
    9.94  
    9.95  		if(have_mouse()) {
    9.96  			use_mouse = true;
    9.97 -			set_mouse_limits(0, 0, xsz - 1, ysz - 1);
    9.98 +			set_mouse_limits(0, 0, fb_width - 1, fb_height - 1);
    9.99  		}
   9.100  	} else {
   9.101  		logger_output(stdout);
   9.102  		printlog("novideo (debug) mode\n");
   9.103 -		bpp = 24;
   9.104 +		fb_bpp = 32;
   9.105  		rbits = gbits = bbits = 8;
   9.106  		bytespp = 3;
   9.107  	}
   9.108  
   9.109 -	backbuf = new unsigned char[xsz * ysz * 3];
   9.110 -	if(!backbuf) {
   9.111 +	fb_pixels = new uint32_t[fb_width * fb_height * 4];
   9.112 +	if(!fb_pixels) {
   9.113  		return false;
   9.114  	}
   9.115  
   9.116 -	m3d_init();
   9.117 -	rbuf.pixels = backbuf;
   9.118 -	rbuf.xsz = xsz;
   9.119 -	rbuf.ysz = ysz;
   9.120 -	m3d_set_buffers(&rbuf, 0);
   9.121 -
   9.122 -	m3d_matrix_mode(M3D_PROJECTION);
   9.123 -	m3d_load_identity();
   9.124 -	m3d_perspective(50.0, (float)xsz / (float)ysz, 0.5, 500.0);
   9.125 -
   9.126 -	scn = new Scene;
   9.127 +	scene = new Scene;
   9.128  
   9.129  	Sphere *sph = new Sphere;
   9.130 -	scn->add_object(sph);
   9.131 +	scene->add_object(sph);
   9.132  
   9.133 +	Modeller *modeller = new Modeller;
   9.134 +	if(!modeller->init()) {
   9.135 +		return false;
   9.136 +	}
   9.137 +	add_screen(modeller);
   9.138 +
   9.139 +	Renderer *renderer = new Renderer;
   9.140 +	if(!renderer->init()) {
   9.141 +		return false;
   9.142 +	}
   9.143 +	add_screen(renderer);
   9.144 +
   9.145 +	activate_screen(modeller); // start the modeller screen
   9.146  	return true;
   9.147  }
   9.148  
   9.149  static void cleanup()
   9.150  {
   9.151 -	delete scn;
   9.152 +	delete scene;
   9.153 +	delete [] fb_pixels;
   9.154  
   9.155 -	m3d_shutdown();
   9.156 -	delete [] backbuf;
   9.157 +	destroy_screens();
   9.158  
   9.159  	if(!novideo) {
   9.160  		set_text_mode();
   9.161 @@ -144,22 +151,17 @@
   9.162  	}
   9.163  }
   9.164  
   9.165 -
   9.166  static void display()
   9.167  {
   9.168 -	m3d_clear(M3D_COLOR_BUFFER_BIT);
   9.169 -
   9.170 -	m3d_matrix_mode(M3D_MODELVIEW);
   9.171 -	m3d_load_identity();
   9.172 -	m3d_translate(0, 0, -cam_dist);
   9.173 -	m3d_rotate(cam_phi, 1, 0, 0);
   9.174 -	m3d_rotate(cam_theta, 0, 1, 0);
   9.175 -
   9.176 -	scn->draw();
   9.177 +	Screen *scr = active_screen();
   9.178 +	if(scr) {
   9.179 +		scr->update();
   9.180 +		scr->draw();
   9.181 +	}
   9.182  
   9.183  	// draw the mouse cursor
   9.184  	if(use_mouse) {
   9.185 -		draw_cursor(backbuf, mx, my);
   9.186 +		draw_cursor(fb_pixels, mouse_x, mouse_y);
   9.187  	}
   9.188  
   9.189  	if(!novideo) {
   9.190 @@ -173,36 +175,43 @@
   9.191  	 (((g) << gshift) & gmask) | \
   9.192  	 (((b) << bshift) & bmask))
   9.193  
   9.194 +#define UNPACK_RED(c)	(((c) >> 16) & 0xff)
   9.195 +#define UNPACK_GREEN(c)	(((c) >> 8) & 0xff)
   9.196 +#define UNPACK_BLUE(c)	((c) & 0xff)
   9.197 +
   9.198  static void swap_buffers()
   9.199  {
   9.200 -	unsigned char *src = backbuf;
   9.201 -	int num_pixels = xsz * ysz;
   9.202 +	uint32_t *src = fb_pixels;
   9.203 +	int num_pixels = fb_width * fb_height;
   9.204  
   9.205 -	switch(bpp) {
   9.206 +	switch(fb_bpp) {
   9.207  	case 32:
   9.208 -		{
   9.209 -			uint32_t *dest = (uint32_t*)fb;
   9.210 -			for(int i=0; i<num_pixels; i++) {
   9.211 -				*dest++ = PACK_RGB(src[0], src[1], src[2]);
   9.212 -				src += 3;
   9.213 -			}
   9.214 -		}
   9.215 +		memcpy(fb, fb_pixels, num_pixels * 4);
   9.216  		break;
   9.217  
   9.218  	case 24:
   9.219 -		memcpy(fb, backbuf, num_pixels * 3);
   9.220 +		{
   9.221 +			unsigned char *dest = (unsigned char*)fb;
   9.222 +			for(int i=0; i<num_pixels; i++) {
   9.223 +				uint32_t c = *src++;
   9.224 +				*dest++ = UNPACK_RED(c);
   9.225 +				*dest++ = UNPACK_GREEN(c);
   9.226 +				*dest++ = UNPACK_BLUE(c);
   9.227 +			}
   9.228 +		}
   9.229  		break;
   9.230  
   9.231  	case 16:
   9.232  	case 15:
   9.233  		{
   9.234 -			int srs = 8 - rbits;
   9.235 -			int sgs = 8 - gbits;
   9.236 -			int sbs = 8 - bbits;
   9.237  			uint16_t *dest = (uint16_t*)fb;
   9.238  			for(int i=0; i<num_pixels; i++) {
   9.239 -				*dest++ = PACK_RGB(src[0] >> srs, src[1] >> sgs, src[2] >> sbs);
   9.240 -				src += 3;
   9.241 +				uint32_t c = *src++;
   9.242 +				unsigned char r = UNPACK_RED(c);
   9.243 +				unsigned char g = UNPACK_GREEN(c);
   9.244 +				unsigned char b = UNPACK_BLUE(c);
   9.245 +
   9.246 +				*dest++ = PACK_RGB(r, g, b);
   9.247  			}
   9.248  		}
   9.249  		break;
   9.250 @@ -212,104 +221,72 @@
   9.251  	}
   9.252  }
   9.253  
   9.254 -static void draw_cursor(unsigned char *buf, int mx, int my)
   9.255 +static void draw_cursor(uint32_t *buf, int mx, int my)
   9.256  {
   9.257 -	unsigned char *cptr = buf + (my * xsz + mx) * 3;
   9.258 +	uint32_t *cptr = buf + my * fb_width + mx;
   9.259  	int i, cw[2] = {4, 4}, ch[2] = {4, 4};
   9.260  
   9.261  	if(mx < cw[0]) cw[0] = mx;
   9.262  	if(my < ch[0]) ch[0] = my;
   9.263 -	if(xsz - mx < cw[1]) cw[1] = xsz - mx - 1;
   9.264 -	if(ysz - my < ch[1]) ch[1] = ysz - my - 1;
   9.265 +	if(fb_width - mx < cw[1]) cw[1] = fb_width - mx - 1;
   9.266 +	if(fb_height - my < ch[1]) ch[1] = fb_height - my - 1;
   9.267  
   9.268  	for(i=1; i<cw[0]; i++) {
   9.269 -		int idx = -i * 3;
   9.270 -		cptr[idx] = 255;
   9.271 -		cptr[idx + 1] = 255;
   9.272 -		cptr[idx + 2] = 255;
   9.273 +		int idx = -i;
   9.274 +		cptr[idx] = 0xffffff;
   9.275  	}
   9.276  	for(i=1; i<cw[1]; i++) {
   9.277 -		int idx = i * 3;
   9.278 -		cptr[idx] = 255;
   9.279 -		cptr[idx + 1] = 255;
   9.280 -		cptr[idx + 2] = 255;
   9.281 +		int idx = i;
   9.282 +		cptr[idx] = 0xffffff;
   9.283  	}
   9.284  	for(i=1; i<ch[0]; i++) {
   9.285 -		int idx = -i * xsz * 3;
   9.286 -		cptr[idx] = 255;
   9.287 -		cptr[idx + 1] = 255;
   9.288 -		cptr[idx + 2] = 255;
   9.289 +		int idx = -i * fb_width;
   9.290 +		cptr[idx] = 0xffffff;
   9.291  	}
   9.292  	for(i=1; i<ch[1]; i++) {
   9.293 -		int idx = i * xsz * 3;
   9.294 -		cptr[idx] = 255;
   9.295 -		cptr[idx + 1] = 255;
   9.296 -		cptr[idx + 2] = 255;
   9.297 +		int idx = i * fb_width;
   9.298 +		cptr[idx] = 0xffffff;
   9.299  	}
   9.300  }
   9.301  
   9.302  static void handle_keyboard()
   9.303  {
   9.304  	int key;
   9.305 +	Screen *scr = active_screen();
   9.306  
   9.307  	if(novideo) return;
   9.308  
   9.309  	while((key = kb_getkey()) != -1) {
   9.310 -		switch(key) {
   9.311 -		case 27:
   9.312 -			quit = true;
   9.313 -			return;
   9.314 -		}
   9.315 +		scr->handle_keyboard(key, true);	// TODO also generate release events...
   9.316  	}
   9.317  }
   9.318  
   9.319  static void handle_mouse()
   9.320  {
   9.321 -	static int prev_mx, prev_my, prev_bnmask;
   9.322 -	int /*mx, my,*/ bnmask;
   9.323 +	static int prev_mx, prev_my, prev_bnmask, bndiff;
   9.324 +	int mx, my, bnmask;
   9.325 +	Screen *scr = active_screen();
   9.326  
   9.327  	if(!use_mouse || novideo) return;
   9.328  
   9.329  	bnmask = read_mouse(&mx, &my);
   9.330 -	if(bnmask != prev_bnmask) {
   9.331 -		mouse_button(bnmask, mx, my);
   9.332 -		prev_bnmask = bnmask;
   9.333 +	if(scr && (bndiff = bnmask ^ prev_bnmask)) {
   9.334 +		for(int i=0; i<8; i++) {
   9.335 +			int bit = 1 << i;
   9.336 +			if(bndiff & bit) {
   9.337 +				scr->handle_mbutton(i, bnmask & bit, mx, my);
   9.338 +			}
   9.339 +		}
   9.340  	}
   9.341 -	if(mx != prev_mx || my != prev_my) {
   9.342 -		mouse_motion(mx, my);
   9.343 -		prev_mx = mx;
   9.344 -		prev_my = my;
   9.345 +	prev_bnmask = bnmask;
   9.346 +
   9.347 +	if(scr && (mx != prev_mx || my != prev_my)) {
   9.348 +		scr->handle_mmotion(mx, my);
   9.349  	}
   9.350 +	prev_mx = mx;
   9.351 +	prev_my = my;
   9.352  }
   9.353  
   9.354 -static int bnstate;
   9.355 -static int prev_x = -1, prev_y;
   9.356 -static void mouse_button(int bn, int x, int y)
   9.357 -{
   9.358 -	bnstate = bn;
   9.359 -	prev_x = x;
   9.360 -	prev_y = y;
   9.361 -}
   9.362 -
   9.363 -static void mouse_motion(int x, int y)
   9.364 -{
   9.365 -	int dx = x - prev_x;
   9.366 -	int dy = y - prev_y;
   9.367 -	prev_x = x;
   9.368 -	prev_y = y;
   9.369 -
   9.370 -	if(bnstate & 1) {
   9.371 -		cam_theta += dx * 0.5;
   9.372 -		cam_phi += dy * 0.5;
   9.373 -
   9.374 -		if(cam_phi < -90) cam_phi = -90;
   9.375 -		if(cam_phi > 90) cam_phi = 90;
   9.376 -	}
   9.377 -	if(bnstate & 2) {
   9.378 -		cam_dist += dy * 0.1;
   9.379 -		if(cam_dist < 0) cam_dist = 0;
   9.380 -	}
   9.381 -}
   9.382  
   9.383  static struct {
   9.384  	int opt;
   9.385 @@ -353,7 +330,7 @@
   9.386  
   9.387  			switch(opt) {
   9.388  			case 's':
   9.389 -				if(sscanf(argv[++i], "%dx%d:%d", &xsz, &ysz, &bpp) < 2) {
   9.390 +				if(sscanf(argv[++i], "%dx%d:%d", &fb_width, &fb_height, &fb_bpp) < 2) {
   9.391  					fprintf(stderr, "%s must be followed by a resolution: WxH\n", argv[i - 1]);
   9.392  					return false;
   9.393  				}
   9.394 @@ -383,4 +360,5 @@
   9.395  {
   9.396  	cleanup();
   9.397  	fprintf(stderr, "signal caught: %d\n", s);
   9.398 +	exit(1);
   9.399  }
    10.1 --- a/src/min3d.c	Mon Apr 07 08:46:06 2014 +0300
    10.2 +++ b/src/min3d.c	Thu Apr 10 02:31:31 2014 +0300
    10.3 @@ -37,9 +37,7 @@
    10.4  	m3dctx->cbuf = cbuf;
    10.5  	m3dctx->zbuf = zbuf;
    10.6  
    10.7 -	m3dctx->vport[0] = m3dctx->vport[1] = 0;
    10.8 -	m3dctx->vport[2] = cbuf->xsz;
    10.9 -	m3dctx->vport[3] = cbuf->ysz;
   10.10 +	m3d_viewport(0, 0, cbuf->xsz, cbuf->ysz);
   10.11  }
   10.12  
   10.13  void m3d_clear_color(float r, float g, float b)
   10.14 @@ -51,9 +49,11 @@
   10.15  
   10.16  void m3d_clear(unsigned int bmask)
   10.17  {
   10.18 -	int i, num_pixels = m3dctx->cbuf->xsz * m3dctx->cbuf->ysz;
   10.19 +	int num_pixels = m3dctx->cbuf->xsz * m3dctx->cbuf->ysz;
   10.20  	if(bmask & M3D_COLOR_BUFFER_BIT) {
   10.21 -		/*memset(m3dctx->cbuf->pixels, 0, num_pixels * 3);*/
   10.22 +		memset(m3dctx->cbuf->pixels, 0, num_pixels * 4);
   10.23 +		/*
   10.24 +		int i;
   10.25  		unsigned char *ptr = m3dctx->cbuf->pixels;
   10.26  		unsigned char r = m3dctx->clear_color[0];
   10.27  		unsigned char g = m3dctx->clear_color[1];
   10.28 @@ -62,7 +62,7 @@
   10.29  			*ptr++ = r;
   10.30  			*ptr++ = g;
   10.31  			*ptr++ = b;
   10.32 -		}
   10.33 +		}*/
   10.34  	}
   10.35  	if(bmask & M3D_DEPTH_BUFFER_BIT) {
   10.36  		memset(m3dctx->zbuf, 0xff, num_pixels * sizeof *m3dctx->zbuf);
   10.37 @@ -80,6 +80,14 @@
   10.38  	m3dctx->state &= ~(1 << bit);
   10.39  }
   10.40  
   10.41 +void m3d_viewport(int x, int y, int xsz, int ysz)
   10.42 +{
   10.43 +	m3dctx->vport[0] = x;
   10.44 +	m3dctx->vport[1] = y;
   10.45 +	m3dctx->vport[2] = xsz;
   10.46 +	m3dctx->vport[3] = ysz;
   10.47 +}
   10.48 +
   10.49  
   10.50  /* matrix stack */
   10.51  void m3d_matrix_mode(int mode)
   10.52 @@ -275,7 +283,7 @@
   10.53  		res[i].pos[2] /= res[i].pos[3];
   10.54  
   10.55  		res[i].pos[0] = (res[i].pos[0] * 0.5 + 0.5) * vport[2] + vport[0];
   10.56 -		res[i].pos[1] = (res[i].pos[1] * 0.5 + 0.5) * vport[3] + vport[1];
   10.57 +		res[i].pos[1] = (-res[i].pos[1] * 0.5 + 0.5) * vport[3] + vport[1];
   10.58  	}
   10.59  	return vcount;
   10.60  }
   10.61 @@ -313,37 +321,76 @@
   10.62  	if(!varr) return;
   10.63  
   10.64  	for(i=0; i<vcount; i++) {
   10.65 +		int r, g, b;
   10.66  		int idx = i % prim;
   10.67  
   10.68  		v[idx].pos[0] = *varr++;
   10.69  		v[idx].pos[1] = *varr++;
   10.70  		v[idx].pos[2] = *varr++;
   10.71  		v[idx].pos[3] = 1.0;
   10.72 -		v[idx].color[0] = carr ? *carr++ : m3dctx->im_color[0];
   10.73 -		v[idx].color[1] = carr ? *carr++ : m3dctx->im_color[1];
   10.74 -		v[idx].color[2] = carr ? *carr++ : m3dctx->im_color[2];
   10.75 +		r = (carr ? *carr++ : m3dctx->im_color[0]) * 255.0;
   10.76 +		g = (carr ? *carr++ : m3dctx->im_color[1]) * 255.0;
   10.77 +		b = (carr ? *carr++ : m3dctx->im_color[2]) * 255.0;
   10.78 +		v[idx].color = (r << 16) | (g << 8) | b;
   10.79  
   10.80  		if(idx == prim - 1) {
   10.81  			int resnum = proc_prim(prim, resv, v);
   10.82  			switch(resnum) {
   10.83  			case 1:
   10.84 -				draw_point(resv);
   10.85 +				m3d_draw_point(resv);
   10.86  				break;
   10.87  
   10.88 -			case '2':
   10.89 -				draw_line(resv);
   10.90 +			case 2:
   10.91 +				m3d_draw_line(resv);
   10.92  				break;
   10.93  
   10.94  			default:
   10.95 -				draw_poly(resv, resnum);
   10.96 +				m3d_draw_poly(resv, resnum);
   10.97  			}
   10.98  		}
   10.99  	}
  10.100  }
  10.101  
  10.102 -void m3d_draw_indexed(int prim, const int *idxarr, int icount)
  10.103 +void m3d_draw_indexed(int prim, const unsigned int *idxarr, int icount)
  10.104  {
  10.105 -	/* TODO */
  10.106 +	int i, vcount = prim;
  10.107 +	struct min3d_vertex v[4];
  10.108 +	struct min3d_vertex resv[16];
  10.109 +	const float *varr = m3dctx->vert_array;
  10.110 +	const float *carr = m3dctx->col_array;
  10.111 +
  10.112 +	if(!varr) return;
  10.113 +
  10.114 +	for(i=0; i<icount; i++) {
  10.115 +		int r, g, b;
  10.116 +		int vnum = i % vcount;
  10.117 +		int index = idxarr[i];
  10.118 +
  10.119 +		v[vnum].pos[0] = varr[index * 3];
  10.120 +		v[vnum].pos[1] = varr[index * 3 + 1];
  10.121 +		v[vnum].pos[2] = varr[index * 3 + 2];
  10.122 +		v[vnum].pos[3] = 1.0;
  10.123 +		r = (carr ? carr[index * 3] : m3dctx->im_color[0]) * 255.0;
  10.124 +		g = (carr ? carr[index * 3 + 1] : m3dctx->im_color[1]) * 255.0;
  10.125 +		b = (carr ? carr[index * 3 + 2] : m3dctx->im_color[2]) * 255.0;
  10.126 +		v[vnum].color = (r << 16) | (g << 8) | b;
  10.127 +
  10.128 +		if(vnum == vcount - 1) {
  10.129 +			int resnum = proc_prim(prim, resv, v);
  10.130 +			switch(resnum) {
  10.131 +			case 1:
  10.132 +				m3d_draw_point(resv);
  10.133 +				break;
  10.134 +
  10.135 +			case 2:
  10.136 +				m3d_draw_line(resv);
  10.137 +				break;
  10.138 +
  10.139 +			default:
  10.140 +				m3d_draw_poly(resv, resnum);
  10.141 +			}
  10.142 +		}
  10.143 +	}
  10.144  }
  10.145  
  10.146  void m3d_begin(int prim)
    11.1 --- a/src/min3d.h	Mon Apr 07 08:46:06 2014 +0300
    11.2 +++ b/src/min3d.h	Thu Apr 10 02:31:31 2014 +0300
    11.3 @@ -36,7 +36,7 @@
    11.4  
    11.5  struct m3d_image {
    11.6  	int xsz, ysz;
    11.7 -	unsigned char *pixels;
    11.8 +	uint32_t *pixels;
    11.9  };
   11.10  
   11.11  #ifdef __cplusplus
   11.12 @@ -53,6 +53,8 @@
   11.13  void m3d_enable(int bit);
   11.14  void m3d_disable(int bit);
   11.15  
   11.16 +void m3d_viewport(int x, int y, int xsz, int ysz);
   11.17 +
   11.18  /* matrix stack */
   11.19  void m3d_matrix_mode(int mode);
   11.20  void m3d_push_matrix(void);
   11.21 @@ -73,7 +75,7 @@
   11.22  void m3d_texcoord_array(const float *tcarr);
   11.23  
   11.24  void m3d_draw(int prim, int vcount);
   11.25 -void m3d_draw_indexed(int prim, const int *idxarr, int icount);
   11.26 +void m3d_draw_indexed(int prim, const unsigned int *idxarr, int icount);
   11.27  
   11.28  /* immediate mode interface */
   11.29  void m3d_begin(int prim);
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/src/modeller.cc	Thu Apr 10 02:31:31 2014 +0300
    12.3 @@ -0,0 +1,150 @@
    12.4 +#include <string.h>
    12.5 +#include <assert.h>
    12.6 +#include "modeller.h"
    12.7 +#include "min3d.h"
    12.8 +#include "rayzor.h"
    12.9 +#include "scene.h"
   12.10 +
   12.11 +struct ModellerImpl {
   12.12 +	int mx, my;
   12.13 +	float cam_theta, cam_phi, cam_dist;
   12.14 +
   12.15 +	struct m3d_image rbuf;
   12.16 +
   12.17 +	bool bnstate[8];
   12.18 +	int prev_x, prev_y;
   12.19 +};
   12.20 +
   12.21 +static void draw_grid(float size, float spacing);
   12.22 +
   12.23 +Modeller::Modeller()
   12.24 +{
   12.25 +	set_name("modeller");
   12.26 +}
   12.27 +
   12.28 +Modeller::~Modeller()
   12.29 +{
   12.30 +	shutdown();
   12.31 +}
   12.32 +
   12.33 +bool Modeller::init()
   12.34 +{
   12.35 +	mod = new ModellerImpl;
   12.36 +	memset(mod, 0, sizeof *mod);
   12.37 +
   12.38 +	mod->cam_phi = 25;
   12.39 +	mod->cam_dist = 5;
   12.40 +
   12.41 +	m3d_init();
   12.42 +	mod->rbuf.pixels = fb_pixels;
   12.43 +	mod->rbuf.xsz = fb_width;
   12.44 +	mod->rbuf.ysz = fb_height;
   12.45 +	m3d_set_buffers(&mod->rbuf, 0);
   12.46 +
   12.47 +	m3d_matrix_mode(M3D_PROJECTION);
   12.48 +	m3d_load_identity();
   12.49 +	m3d_perspective(50.0, (float)fb_width / (float)fb_height, 0.5, 500.0);
   12.50 +
   12.51 +	m3d_enable(M3D_CULL_FACE);
   12.52 +	return true;
   12.53 +}
   12.54 +
   12.55 +void Modeller::shutdown()
   12.56 +{
   12.57 +	if(mod) {
   12.58 +		m3d_shutdown();
   12.59 +
   12.60 +		delete mod;
   12.61 +		mod = 0;
   12.62 +	}
   12.63 +}
   12.64 +
   12.65 +void Modeller::draw() const
   12.66 +{
   12.67 +	m3d_clear(M3D_COLOR_BUFFER_BIT);
   12.68 +
   12.69 +	m3d_matrix_mode(M3D_MODELVIEW);
   12.70 +	m3d_load_identity();
   12.71 +	m3d_translate(0, 0, -mod->cam_dist);
   12.72 +	m3d_rotate(mod->cam_phi, 1, 0, 0);
   12.73 +	m3d_rotate(mod->cam_theta, 0, 1, 0);
   12.74 +
   12.75 +	draw_grid(10.0, 1.0);
   12.76 +
   12.77 +	scene->draw();
   12.78 +}
   12.79 +
   12.80 +
   12.81 +static void draw_grid(float size, float spacing)
   12.82 +{
   12.83 +	int num_lines = size / spacing;
   12.84 +	float dist = size / 2.0;
   12.85 +
   12.86 +	m3d_disable(M3D_LIGHTING);
   12.87 +
   12.88 +	m3d_begin(M3D_LINES);
   12.89 +	m3d_color(0.4, 0.4, 0.4);
   12.90 +
   12.91 +	float x = -dist;
   12.92 +	for(int i=0; i<=num_lines; i++) {
   12.93 +		if(i != num_lines / 2) {
   12.94 +			m3d_vertex(-dist, 0, x);
   12.95 +			m3d_vertex(dist, 0, x);
   12.96 +			m3d_vertex(x, 0, -dist);
   12.97 +			m3d_vertex(x, 0, dist);
   12.98 +		}
   12.99 +		x += spacing;
  12.100 +	}
  12.101 +	m3d_end();
  12.102 +
  12.103 +	m3d_begin(M3D_LINES);
  12.104 +	m3d_color(1.0, 0, 0);
  12.105 +	m3d_vertex(-dist, 0, 0);
  12.106 +	m3d_vertex(dist, 0, 0);
  12.107 +	m3d_color(0, 1.0, 0);
  12.108 +	m3d_vertex(0, 0, -dist);
  12.109 +	m3d_vertex(0, 0, dist);
  12.110 +	m3d_end();
  12.111 +}
  12.112 +
  12.113 +
  12.114 +void Modeller::handle_keyboard(int key, bool press)
  12.115 +{
  12.116 +	if(press) {
  12.117 +		switch(key) {
  12.118 +		case 27:
  12.119 +			quit_app();
  12.120 +			break;
  12.121 +
  12.122 +		default:
  12.123 +			break;
  12.124 +		}
  12.125 +	}
  12.126 +}
  12.127 +
  12.128 +void Modeller::handle_mbutton(int bn, bool press, int x, int y)
  12.129 +{
  12.130 +	mod->bnstate[bn] = press;
  12.131 +	mod->prev_x = x;
  12.132 +	mod->prev_y = y;
  12.133 +}
  12.134 +
  12.135 +void Modeller::handle_mmotion(int x, int y)
  12.136 +{
  12.137 +	int dx = x - mod->prev_x;
  12.138 +	int dy = y - mod->prev_y;
  12.139 +	mod->prev_x = x;
  12.140 +	mod->prev_y = y;
  12.141 +
  12.142 +	if(mod->bnstate[0]) {
  12.143 +		mod->cam_theta += dx * 0.5;
  12.144 +		mod->cam_phi += dy * 0.5;
  12.145 +
  12.146 +		if(mod->cam_phi < -90) mod->cam_phi = -90;
  12.147 +		if(mod->cam_phi > 90) mod->cam_phi = 90;
  12.148 +	}
  12.149 +	if(mod->bnstate[1]) {
  12.150 +		mod->cam_dist += dy * 0.1;
  12.151 +		if(mod->cam_dist < 0) mod->cam_dist = 0;
  12.152 +	}
  12.153 +}
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/src/modeller.h	Thu Apr 10 02:31:31 2014 +0300
    13.3 @@ -0,0 +1,26 @@
    13.4 +#ifndef MODELLER_H_
    13.5 +#define MODELLER_H_
    13.6 +
    13.7 +#include "screen.h"
    13.8 +
    13.9 +struct ModellerImpl;
   13.10 +
   13.11 +class Modeller : public Screen {
   13.12 +private:
   13.13 +	ModellerImpl *mod;
   13.14 +
   13.15 +public:
   13.16 +	Modeller();
   13.17 +	~Modeller();
   13.18 +
   13.19 +	bool init();
   13.20 +	void shutdown();
   13.21 +
   13.22 +	void draw() const;
   13.23 +
   13.24 +	void handle_keyboard(int key, bool press);
   13.25 +	void handle_mbutton(int bn, bool press, int x, int y);
   13.26 +	void handle_mmotion(int x, int y);
   13.27 +};
   13.28 +
   13.29 +#endif	// MODELLER_H_
    14.1 --- a/src/object.cc	Mon Apr 07 08:46:06 2014 +0300
    14.2 +++ b/src/object.cc	Thu Apr 10 02:31:31 2014 +0300
    14.3 @@ -1,6 +1,7 @@
    14.4  #include "object.h"
    14.5  #include "vmath.h"
    14.6  #include "min3d.h"
    14.7 +#include "logger.h"
    14.8  
    14.9  Object::Object()
   14.10  {
   14.11 @@ -19,37 +20,60 @@
   14.12  {
   14.13  }
   14.14  
   14.15 -#define USUB	32
   14.16 -#define VSUB	16
   14.17 +#define USUB	12
   14.18 +#define VSUB	6
   14.19  
   14.20  void Sphere::draw() const
   14.21  {
   14.22  	static Vector3 *varr;
   14.23 -	static int num_verts;
   14.24 +	static unsigned int *iarr;
   14.25 +	static int num_verts, num_indices;
   14.26  	if(!varr) {
   14.27 +		int i, j;
   14.28  		int uverts = USUB;
   14.29  		int vverts = VSUB + 1;
   14.30 +
   14.31  		num_verts = uverts * vverts;
   14.32  		varr = new Vector3[num_verts];
   14.33  
   14.34  		Vector3 *vptr = varr;
   14.35 -		for(int i=0; i<uverts; i++) {
   14.36 -			float u = (float)i / (float)USUB;
   14.37 -			float theta = u * M_PI * 2.0;
   14.38 -			for(int j=0; j<vverts; j++) {
   14.39 -				float v = (float)j / (float)VSUB;
   14.40 -				float phi = (v - 0.5) * M_PI;
   14.41 +		for(i=0; i<vverts; i++) {
   14.42 +			float v = (float)i / (float)VSUB;
   14.43 +			float phi = v * M_PI;
   14.44 +			for(j=0; j<uverts; j++) {
   14.45 +				float u = (float)j / (float)uverts;
   14.46 +				float theta = u * M_PI * 2.0;
   14.47  
   14.48 -				float x = sin(theta) * cos(phi);
   14.49 -				float y = sin(phi);
   14.50 -				float z = cos(theta) * cos(phi);
   14.51 +				float x = sin(theta) * sin(phi);
   14.52 +				float y = cos(phi);
   14.53 +				float z = cos(theta) * sin(phi);
   14.54  
   14.55  				*vptr++ = Vector3(x, y, z);
   14.56  			}
   14.57  		}
   14.58 +
   14.59 +		num_indices = USUB * VSUB * 4;
   14.60 +		iarr = new unsigned int[num_indices];
   14.61 +
   14.62 +		unsigned int *iptr = iarr;
   14.63 +		for(i=0; i<VSUB; i++) {
   14.64 +			for(j=0; j<USUB; j++) {
   14.65 +				iptr[0] = i * uverts + j;
   14.66 +				iptr[1] = i * uverts + ((j + 1) % uverts);
   14.67 +				iptr[2] = iptr[1] + uverts;
   14.68 +				iptr[3] = iptr[0] + uverts;
   14.69 +				iptr += 4;
   14.70 +			}
   14.71 +		}
   14.72 +
   14.73 +		printlog("created sphere mesh\n");
   14.74 +		printlog("  vertices: %d (%d slices, %d stacks)\n", num_verts, uverts, vverts);
   14.75 +		printlog("  quads: %d (%d indices, %d usub, %d vsub)\n", USUB * VSUB, num_indices, USUB, VSUB);
   14.76  	}
   14.77  
   14.78 +	m3d_color(1, 1, 1);
   14.79 +
   14.80  	m3d_vertex_array(&varr->x);
   14.81 -	m3d_draw(M3D_POINTS, num_verts);
   14.82 +	m3d_draw_indexed(M3D_QUADS, iarr, num_indices);
   14.83  	m3d_vertex_array(0);
   14.84  }
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/src/rayzor.h	Thu Apr 10 02:31:31 2014 +0300
    15.3 @@ -0,0 +1,14 @@
    15.4 +#ifndef RAYZOR_H_
    15.5 +#define RAYZOR_H_
    15.6 +
    15.7 +// global framebuffer (back buffer)
    15.8 +extern uint32_t *fb_pixels;
    15.9 +extern int fb_width, fb_height;
   15.10 +extern int fb_bpp;
   15.11 +
   15.12 +class Scene;
   15.13 +extern Scene *scene;
   15.14 +
   15.15 +void quit_app();
   15.16 +
   15.17 +#endif	/* RAYZOR_H_ */
    16.1 --- a/src/rend.cc	Mon Apr 07 08:46:06 2014 +0300
    16.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.3 @@ -1,10 +0,0 @@
    16.4 -#include "rend.h"
    16.5 -
    16.6 -bool rend_init()
    16.7 -{
    16.8 -	return false;
    16.9 -}
   16.10 -
   16.11 -void rend_shutdown()
   16.12 -{
   16.13 -}
    17.1 --- a/src/rend.h	Mon Apr 07 08:46:06 2014 +0300
    17.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.3 @@ -1,7 +0,0 @@
    17.4 -#ifndef REND_H_
    17.5 -#define REND_H_
    17.6 -
    17.7 -bool rend_init();
    17.8 -void rend_shutdown();
    17.9 -
   17.10 -#endif	// REND_H_
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/src/renderer.cc	Thu Apr 10 02:31:31 2014 +0300
    18.3 @@ -0,0 +1,10 @@
    18.4 +#include "renderer.h"
    18.5 +
    18.6 +Renderer::Renderer()
    18.7 +{
    18.8 +	set_name("renderer");
    18.9 +}
   18.10 +
   18.11 +void Renderer::draw() const
   18.12 +{
   18.13 +}
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/src/renderer.h	Thu Apr 10 02:31:31 2014 +0300
    19.3 @@ -0,0 +1,13 @@
    19.4 +#ifndef RENDERER_H_
    19.5 +#define RENDERER_H_
    19.6 +
    19.7 +#include "screen.h"
    19.8 +
    19.9 +class Renderer : public Screen {
   19.10 +public:
   19.11 +	Renderer();
   19.12 +
   19.13 +	void draw() const;
   19.14 +};
   19.15 +
   19.16 +#endif	// RENDERER_H_
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/src/screen.cc	Thu Apr 10 02:31:31 2014 +0300
    20.3 @@ -0,0 +1,49 @@
    20.4 +#include <string.h>
    20.5 +#include "screen.h"
    20.6 +
    20.7 +Screen::Screen()
    20.8 +{
    20.9 +	name = 0;
   20.10 +}
   20.11 +
   20.12 +Screen::~Screen()
   20.13 +{
   20.14 +	delete [] name;
   20.15 +}
   20.16 +
   20.17 +bool Screen::init()
   20.18 +{
   20.19 +	return true;
   20.20 +}
   20.21 +
   20.22 +void Screen::shutdown()
   20.23 +{
   20.24 +}
   20.25 +
   20.26 +void Screen::set_name(const char *name)
   20.27 +{
   20.28 +	delete [] this->name;
   20.29 +	this->name = new char[strlen(name) + 1];
   20.30 +	strcpy(this->name, name);
   20.31 +}
   20.32 +
   20.33 +const char *Screen::get_name() const
   20.34 +{
   20.35 +	return name ? name : "<unnamed>";
   20.36 +}
   20.37 +
   20.38 +void Screen::update()
   20.39 +{
   20.40 +}
   20.41 +
   20.42 +void Screen::handle_keyboard(int key, bool press)
   20.43 +{
   20.44 +}
   20.45 +
   20.46 +void Screen::handle_mbutton(int bn, bool press, int x, int y)
   20.47 +{
   20.48 +}
   20.49 +
   20.50 +void Screen::handle_mmotion(int x, int y)
   20.51 +{
   20.52 +}
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/src/screen.h	Thu Apr 10 02:31:31 2014 +0300
    21.3 @@ -0,0 +1,26 @@
    21.4 +#ifndef SCREEN_H_
    21.5 +#define SCREEN_H_
    21.6 +
    21.7 +class Screen {
    21.8 +private:
    21.9 +	char *name;
   21.10 +
   21.11 +public:
   21.12 +	Screen();
   21.13 +	virtual ~Screen();
   21.14 +
   21.15 +	virtual bool init();
   21.16 +	virtual void shutdown();
   21.17 +
   21.18 +	virtual void set_name(const char *name);
   21.19 +	virtual const char *get_name() const;
   21.20 +
   21.21 +	virtual void update();
   21.22 +	virtual void draw() const = 0;
   21.23 +
   21.24 +	virtual void handle_keyboard(int key, bool press);
   21.25 +	virtual void handle_mbutton(int bn, bool press, int x, int y);
   21.26 +	virtual void handle_mmotion(int x, int y);
   21.27 +};
   21.28 +
   21.29 +#endif	// SCREEN_H_
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/src/scrman.cc	Thu Apr 10 02:31:31 2014 +0300
    22.3 @@ -0,0 +1,50 @@
    22.4 +#include <string.h>
    22.5 +#include "vector.h"
    22.6 +#include "scrman.h"
    22.7 +
    22.8 +static vector<Screen*> screens;
    22.9 +static vector<Screen*> active;
   22.10 +
   22.11 +void add_screen(Screen *s)
   22.12 +{
   22.13 +	screens.push_back(s);
   22.14 +}
   22.15 +
   22.16 +Screen *get_screen(const char *name)
   22.17 +{
   22.18 +	for(size_t i=0; i<screens.size(); i++) {
   22.19 +		if(strcmp(screens[i]->get_name(), name) == 0) {
   22.20 +			return screens[i];
   22.21 +		}
   22.22 +	}
   22.23 +	return 0;
   22.24 +}
   22.25 +
   22.26 +void destroy_screens()
   22.27 +{
   22.28 +	for(size_t i=0; i<screens.size(); i++) {
   22.29 +		screens[i]->shutdown();
   22.30 +		delete screens[i];
   22.31 +	}
   22.32 +	screens.clear();
   22.33 +	active.clear();
   22.34 +}
   22.35 +
   22.36 +void activate_screen(Screen *s)
   22.37 +{
   22.38 +	active.push_back(s);
   22.39 +}
   22.40 +
   22.41 +Screen *deactivate_screen()
   22.42 +{
   22.43 +	Screen *s = active_screen();
   22.44 +	if(!s) return 0;
   22.45 +
   22.46 +	active.pop_back();
   22.47 +	return s;
   22.48 +}
   22.49 +
   22.50 +Screen *active_screen()
   22.51 +{
   22.52 +	return active.empty() ? 0 : active.back();
   22.53 +}
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/src/scrman.h	Thu Apr 10 02:31:31 2014 +0300
    23.3 @@ -0,0 +1,16 @@
    23.4 +#ifndef SCREEN_MANAGER_H_
    23.5 +#define SCREEN_MANAGER_H_
    23.6 +
    23.7 +#include "screen.h"
    23.8 +
    23.9 +void add_screen(Screen *s);
   23.10 +Screen *get_screen(const char *name);
   23.11 +
   23.12 +void destroy_screens();	// destroy all managed screens
   23.13 +
   23.14 +// active screen stack
   23.15 +void activate_screen(Screen *s);
   23.16 +Screen *deactivate_screen();
   23.17 +Screen *active_screen();
   23.18 +
   23.19 +#endif	// SCREEN_MANAGER_H_
    24.1 --- a/src/stl/vector.h	Mon Apr 07 08:46:06 2014 +0300
    24.2 +++ b/src/stl/vector.h	Thu Apr 10 02:31:31 2014 +0300
    24.3 @@ -47,6 +47,7 @@
    24.4  	void clear()
    24.5  	{
    24.6  		delete [] data;
    24.7 +		data = 0;
    24.8  		max_items = num_items = 0;
    24.9  	}
   24.10  
   24.11 @@ -89,6 +90,27 @@
   24.12  		data[num_items++] = item;
   24.13  	}
   24.14  
   24.15 +	void pop_back()
   24.16 +	{
   24.17 +		if(--num_items <= 0) {
   24.18 +			num_items = 0;
   24.19 +		}
   24.20 +
   24.21 +		if(num_items < max_items / 3) {
   24.22 +			resize(max_items / 2);
   24.23 +		}
   24.24 +	}
   24.25 +
   24.26 +	T &back()
   24.27 +	{
   24.28 +		return data[num_items - 1];
   24.29 +	}
   24.30 +
   24.31 +	const T &back() const
   24.32 +	{
   24.33 +		return data[num_items - 1];
   24.34 +	}
   24.35 +
   24.36  	T &operator [](int idx)
   24.37  	{
   24.38  		return data[idx];