deepstone
changeset 38:17a5107b6fa4
- added perspective correct interpolation
- added recording functionality
- added video capture functionality
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Mon, 10 Mar 2014 17:24:42 +0200 |
parents | e234f2a4b6fa |
children | f9b1ff21fd62 |
files | GNUmakefile Makefile src/dosemu/dosemu.c src/main.c src/mglrast.c src/mingl.c src/record.c src/record.h src/scantmpl.h src/test.c src/wvga.c src/wvga.h |
diffstat | 12 files changed, 422 insertions(+), 466 deletions(-) [+] |
line diff
1.1 --- a/GNUmakefile Mon Sep 23 07:42:56 2013 +0300 1.2 +++ b/GNUmakefile Mon Mar 10 17:24:42 2014 +0200 1.3 @@ -1,4 +1,4 @@ 1.4 -obj = src/main.o \ 1.5 +obj = src/main.o src/record.o \ 1.6 src/mingl.o src/mglrast.o src/mglclip.o src/mglgen.o \ 1.7 src/texture.o src/palman.o \ 1.8 src/scene.o src/cvec.o src/fixedp.o \ 1.9 @@ -7,11 +7,12 @@ 1.10 bin = deepstone 1.11 1.12 dbg = -g 1.13 -#opt = -O3 -ffast-math 1.14 +opt = -O3 -ffast-math 1.15 +def = -DRAST_FLOAT -DDBG_USE_FLOAT -DTEXMAP_PERSP_CORRECT 1.16 1.17 CC = gcc 1.18 -CFLAGS = -pedantic -Wall $(dbg) $(opt) `pkg-config --cflags sdl` -Isrc -Isrc/dosemu $(add_cflags) -DRAST_FLOAT -DDBG_USE_FLOAT 1.19 -LDFLAGS = `pkg-config --libs sdl` -lm 1.20 +CFLAGS = -pedantic -Wall $(dbg) $(opt) `pkg-config --cflags sdl` -Isrc -Isrc/dosemu $(add_cflags) $(def) 1.21 +LDFLAGS = `pkg-config --libs sdl` -lm -limago 1.22 #LDFLAGS = -Llib64 -Wl,-rpath=./lib64 -lSDL -lm 1.23 #LDFLAGS = -m32 -Llib32 -Wl,-rpath=./lib32 -lSDL-1.2 -lm 1.24
2.1 --- a/Makefile Mon Sep 23 07:42:56 2013 +0300 2.2 +++ b/Makefile Mon Mar 10 17:24:42 2014 +0200 2.3 @@ -1,4 +1,4 @@ 2.4 -obj = main.obj & 2.5 +obj = main.obj record.obj & 2.6 wvga.obj dpmi.obj timer.obj mouse.obj keyb.obj & 2.7 mingl.obj mglrast.obj mglclip.obj mglgen.obj & 2.8 texture.obj palman.obj scene.obj cvec.obj &
3.1 --- a/src/dosemu/dosemu.c Mon Sep 23 07:42:56 2013 +0300 3.2 +++ b/src/dosemu/dosemu.c Mon Mar 10 17:24:42 2014 +0200 3.3 @@ -5,6 +5,7 @@ 3.4 #include <stdlib.h> 3.5 #include <assert.h> 3.6 #include <SDL.h> 3.7 +#include <imago2.h> 3.8 #include "wvga.h" 3.9 #include "conio.h" 3.10 #include "mouse.h" 3.11 @@ -12,6 +13,7 @@ 3.12 #include "timer.h" 3.13 3.14 static void proc_events(void); 3.15 +static void capture_frame(unsigned char *frame); 3.16 3.17 static void init_sdl() 3.18 { 3.19 @@ -29,6 +31,12 @@ 3.20 /* ----- graphics (wvga.c implementation) ----- */ 3.21 static SDL_Surface *fbsurf; 3.22 static int scale = 3; 3.23 +static int frames_to_capture; 3.24 + 3.25 +static struct { 3.26 + unsigned char r, g, b; 3.27 +} palette[256]; 3.28 + 3.29 3.30 int set_video_mode(int mode) 3.31 { 3.32 @@ -99,6 +107,10 @@ 3.33 if(SDL_SetPalette(fbsurf, SDL_LOGPAL | SDL_PHYSPAL, &col, idx, 1) != 1) { 3.34 fprintf(stderr, "set_palette failed to set the required color\n"); 3.35 } 3.36 + 3.37 + palette[idx].r = r; 3.38 + palette[idx].g = g; 3.39 + palette[idx].b = b; 3.40 } 3.41 3.42 void copy_frame(void *pixels) 3.43 @@ -130,6 +142,10 @@ 3.44 } 3.45 SDL_Flip(fbsurf); 3.46 3.47 + if(frames_to_capture > 0) { 3.48 + capture_frame(pixels); 3.49 + --frames_to_capture; 3.50 + } 3.51 3.52 /* also print fps every second ... */ 3.53 { 3.54 @@ -150,10 +166,77 @@ 3.55 } 3.56 } 3.57 3.58 +#define spin_delay(ms) \ 3.59 + do { \ 3.60 + unsigned int end = SDL_GetTicks() + ms; \ 3.61 + while((prev_msec = SDL_GetTicks()) < end); \ 3.62 + } while(0) 3.63 + 3.64 +#define FRAME_INTERVAL (1000/70) 3.65 void wait_vsync(void) 3.66 { 3.67 + static int prev_msec; 3.68 + int msec, dt, tleft; 3.69 + 3.70 + msec = SDL_GetTicks(); 3.71 + 3.72 + dt = msec - prev_msec; 3.73 + 3.74 + tleft = FRAME_INTERVAL - dt; 3.75 + if(tleft > 0) { 3.76 + int coarse = tleft & 0xfffffff8; 3.77 + tleft = tleft & 7; 3.78 + 3.79 + if(coarse) { 3.80 + SDL_Delay(coarse); 3.81 + } 3.82 + if(tleft) { 3.83 + spin_delay(tleft); 3.84 + } else { 3.85 + prev_msec = SDL_GetTicks(); 3.86 + } 3.87 + } else { 3.88 + prev_msec = msec; 3.89 + } 3.90 } 3.91 3.92 +static int cap_count = 0; 3.93 +void begin_capture(int frames) 3.94 +{ 3.95 + frames_to_capture = frames; 3.96 +} 3.97 + 3.98 +void end_capture(void) 3.99 +{ 3.100 + cap_count = 0; 3.101 + frames_to_capture = 0; 3.102 +} 3.103 + 3.104 +#define NUMPIX (320 * 200) 3.105 +static void capture_frame(unsigned char *frame) 3.106 +{ 3.107 + static unsigned char rgbpix[NUMPIX * 4]; 3.108 + char fname[32]; 3.109 + int i; 3.110 + unsigned char *src, *dest; 3.111 + 3.112 + sprintf(fname, "frame%04d.png", cap_count++); 3.113 + 3.114 + src = frame; 3.115 + dest = rgbpix; 3.116 + 3.117 + for(i=0; i<NUMPIX; i++) { 3.118 + unsigned char c = *src++; 3.119 + *dest++ = palette[c].r; 3.120 + *dest++ = palette[c].g; 3.121 + *dest++ = palette[c].b; 3.122 + *dest++ = 255; 3.123 + } 3.124 + 3.125 + img_save_pixels(fname, rgbpix, 320, 200, IMG_FMT_RGBA32); 3.126 +} 3.127 + 3.128 + 3.129 /* ----- event handling (conio.h) ----- */ 3.130 static SDL_Event *keybev; 3.131 static int mousex, mousey, bnmask;
4.1 --- a/src/main.c Mon Sep 23 07:42:56 2013 +0300 4.2 +++ b/src/main.c Mon Mar 10 17:24:42 2014 +0200 4.3 @@ -1,6 +1,8 @@ 4.4 #include <stdio.h> 4.5 #include <stdlib.h> 4.6 +#include <string.h> 4.7 #include <math.h> 4.8 +#include <limits.h> 4.9 #include <signal.h> 4.10 #include <conio.h> 4.11 #include "wvga.h" 4.12 @@ -11,35 +13,46 @@ 4.13 #include "texture.h" 4.14 #include "palman.h" 4.15 #include "scene.h" 4.16 +#include "record.h" 4.17 4.18 #define DEG2RAD(x) (M_PI * (x) / 180.0) 4.19 4.20 static int init(void); 4.21 static void shutdown(void); 4.22 -static void update(unsigned long dtmsec); 4.23 +static void update(unsigned long msec, unsigned long dtmsec); 4.24 static void redraw(void); 4.25 static int proc_events(void); 4.26 static void mouse_button(int bn, int x, int y); 4.27 static void mouse_motion(int x, int y); 4.28 static void sighandler(int s); 4.29 +static int parse_args(int argc, char **argv); 4.30 4.31 4.32 static float cam_x, cam_y, cam_z; 4.33 static float cam_theta, cam_phi; 4.34 4.35 static float walk_speed = 6.0; 4.36 -static float look_speed = 1.0; 4.37 +static float look_speed = 0.3; 4.38 4.39 static int mouse_look = 1; 4.40 +static int use_vsync; 4.41 4.42 static void *fbuf; 4.43 static struct scene scn; 4.44 4.45 +#define REC_FNAME "game.rec" 4.46 +static int rec_playing, rec_recording; 4.47 +static unsigned long rec_start_time; 4.48 4.49 -int main(void) 4.50 + 4.51 +int main(int argc, char **argv) 4.52 { 4.53 unsigned long prev_msec = 0; 4.54 4.55 + if(parse_args(argc, argv) == -1) { 4.56 + return 1; 4.57 + } 4.58 + 4.59 if(init() == -1) { 4.60 return 1; 4.61 } 4.62 @@ -53,7 +66,7 @@ 4.63 break; 4.64 } 4.65 4.66 - update(dt); 4.67 + update(msec, dt); 4.68 redraw(); 4.69 } 4.70 4.71 @@ -144,7 +157,7 @@ 4.72 cam_z -= -sin(angle) * dx + cos(angle) * dy; 4.73 } 4.74 4.75 -static void update(unsigned long dtmsec) 4.76 +static void update(unsigned long msec, unsigned long dtmsec) 4.77 { 4.78 float dt = (float)dtmsec / 1000.0f; 4.79 float offs = walk_speed * dt; 4.80 @@ -160,6 +173,21 @@ 4.81 4.82 if(kb_isdown('d') || kb_isdown('D')) 4.83 cam_move(offs, 0); 4.84 + 4.85 + if(rec_playing) { 4.86 + rec_get(msec - rec_start_time, &cam_x, &cam_y, &cam_z, &cam_theta, &cam_phi); 4.87 + } else if(rec_recording) { 4.88 + static float px, py, pz, ptheta, pphi; 4.89 + 4.90 + if(cam_x != px || cam_y != py || cam_z != pz || cam_theta != ptheta || cam_phi != pphi) { 4.91 + rec_add(msec - rec_start_time, cam_x, cam_y, cam_z, cam_theta, cam_phi); 4.92 + px = cam_x; 4.93 + py = cam_y; 4.94 + pz = cam_z; 4.95 + ptheta = cam_theta; 4.96 + pphi = cam_phi; 4.97 + } 4.98 + } 4.99 } 4.100 4.101 static void redraw(void) 4.102 @@ -181,6 +209,9 @@ 4.103 scn_render(&scn); 4.104 4.105 copy_frame(fbuf); 4.106 + if(use_vsync) { 4.107 + wait_vsync(); 4.108 + } 4.109 } 4.110 4.111 static int proc_events(void) 4.112 @@ -194,10 +225,66 @@ 4.113 case 27: 4.114 return 0; 4.115 4.116 + case '\b': 4.117 + begin_capture(1); 4.118 + break; 4.119 + case '\\': 4.120 + { 4.121 + static int capturing; 4.122 + if(capturing) { 4.123 + printf("stop video capture\n"); 4.124 + end_capture(); 4.125 + capturing = 0; 4.126 + } else { 4.127 + printf("start video capture\n"); 4.128 + begin_capture(INT_MAX); 4.129 + capturing = 1; 4.130 + } 4.131 + } 4.132 + break; 4.133 + 4.134 case '`': 4.135 mouse_look = !mouse_look; 4.136 break; 4.137 4.138 + case 'r': 4.139 + if(rec_recording) { 4.140 + /* stop recording and save it */ 4.141 + rec_recording = 0; 4.142 + printf("done, saving %s\n", REC_FNAME); 4.143 + rec_save(REC_FNAME); 4.144 + } else { 4.145 + printf("recording ...\n"); 4.146 + rec_recording = 1; 4.147 + rec_playing = 0; 4.148 + rec_reset(); 4.149 + rec_start_time = get_msec(); 4.150 + } 4.151 + break; 4.152 + 4.153 + case 'l': 4.154 + printf("loading recording %s\n", REC_FNAME); 4.155 + rec_recording = 0; 4.156 + rec_playing = 0; 4.157 + rec_reset(); 4.158 + rec_load(REC_FNAME); 4.159 + break; 4.160 + 4.161 + case ' ': 4.162 + if(rec_recording) { 4.163 + break; 4.164 + } 4.165 + 4.166 + if(rec_playing) { 4.167 + printf("stop rec playback\n"); 4.168 + rec_playing = 0; 4.169 + } else { 4.170 + printf("start rec playback\n"); 4.171 + rec_playing = 1; 4.172 + rec_start_time = get_msec(); 4.173 + } 4.174 + break; 4.175 + 4.176 default: 4.177 break; 4.178 } 4.179 @@ -285,3 +372,26 @@ 4.180 4.181 exit(1); 4.182 } 4.183 + 4.184 +static int parse_args(int argc, char **argv) 4.185 +{ 4.186 + int i; 4.187 + 4.188 + for(i=1; i<argc; i++) { 4.189 + if(argv[i][0] == '-') { 4.190 + if(strcmp(argv[i], "-vsync") == 0) { 4.191 + use_vsync = 1; 4.192 + } else { 4.193 + goto invalid; 4.194 + } 4.195 + } else { 4.196 + goto invalid; 4.197 + } 4.198 + } 4.199 + 4.200 + return 0; 4.201 + 4.202 +invalid: 4.203 + fprintf(stderr, "invalid argument: %s\n", argv[i]); 4.204 + return -1; 4.205 +}
5.1 --- a/src/mglrast.c Mon Sep 23 07:42:56 2013 +0300 5.2 +++ b/src/mglrast.c Mon Mar 10 17:24:42 2014 +0200 5.3 @@ -187,6 +187,14 @@ 5.4 ybeg = fb->height; 5.5 yend = 0; 5.6 5.7 +#ifdef TEXMAP_PERSP_CORRECT 5.8 + for(i=0; i<numv; i++) { 5.9 + v[i].tc.x /= v[i].pos.w; 5.10 + v[i].tc.y /= v[i].pos.w; 5.11 + v[i].pos.w = 1.0 / v[i].pos.w; 5.12 + } 5.13 +#endif 5.14 + 5.15 for(i=0; i<numv; i++) { 5.16 struct vertex *v0 = v + i; 5.17 struct vertex *v1 = v + (i + 1) % numv;
6.1 --- a/src/mingl.c Mon Sep 23 07:42:56 2013 +0300 6.2 +++ b/src/mingl.c Mon Mar 10 17:24:42 2014 +0200 6.3 @@ -553,6 +553,7 @@ 6.4 xform[10] = c; 6.5 xform[11] = -1.0f; 6.6 xform[14] = d; 6.7 + xform[15] = 0; 6.8 6.9 mgl_mult_matrix(xform); 6.10 }
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/src/record.c Mon Mar 10 17:24:42 2014 +0200 7.3 @@ -0,0 +1,135 @@ 7.4 +#include <stdio.h> 7.5 +#include <stdlib.h> 7.6 +#include <string.h> 7.7 +#include <errno.h> 7.8 +#include "record.h" 7.9 + 7.10 +struct event { 7.11 + unsigned long tm; 7.12 + float x, y, z; 7.13 + float theta, phi; 7.14 + 7.15 + struct event *next; 7.16 +}; 7.17 + 7.18 +static struct event *head, *tail; 7.19 +static struct event *iter; 7.20 +static int num_events; 7.21 + 7.22 +void rec_reset(void) 7.23 +{ 7.24 + while(head) { 7.25 + iter = head; 7.26 + head = head->next; 7.27 + free(iter); 7.28 + } 7.29 + num_events = 0; 7.30 +} 7.31 + 7.32 +int rec_load(const char *fname) 7.33 +{ 7.34 + FILE *fp; 7.35 + int i; 7.36 + 7.37 + if(!(fp = fopen(fname, "rb"))) { 7.38 + fprintf(stderr, "failed to open recording: %s: %s\n", fname, strerror(errno)); 7.39 + return -1; 7.40 + } 7.41 + fread(&num_events, sizeof num_events, 1, fp); 7.42 + 7.43 + head = tail = 0; 7.44 + 7.45 + for(i=0; i<num_events; i++) { 7.46 + struct event *ev = malloc(sizeof *ev); 7.47 + if(!ev) { 7.48 + perror("failed to allocate event structure"); 7.49 + fclose(fp); 7.50 + return -1; 7.51 + } 7.52 + if(fread(ev, sizeof *ev, 1, fp) < 1) { 7.53 + perror("unexpected end of file"); 7.54 + fclose(fp); 7.55 + return -1; 7.56 + } 7.57 + 7.58 + if(!head) { 7.59 + head = tail = ev; 7.60 + } else { 7.61 + tail->next = ev; 7.62 + tail = ev; 7.63 + } 7.64 + ev->next = 0; 7.65 + } 7.66 + iter = 0; 7.67 + 7.68 + fclose(fp); 7.69 + return 0; 7.70 +} 7.71 + 7.72 +int rec_save(const char *fname) 7.73 +{ 7.74 + FILE *fp; 7.75 + struct event *ev; 7.76 + 7.77 + if(!(fp = fopen(fname, "wb"))) { 7.78 + fprintf(stderr, "failed to open recording: %s: %s\n", fname, strerror(errno)); 7.79 + return -1; 7.80 + } 7.81 + fwrite(&num_events, sizeof num_events, 1, fp); 7.82 + 7.83 + ev = head; 7.84 + while(ev) { 7.85 + fwrite(ev, sizeof *ev, 1, fp); 7.86 + ev = ev->next; 7.87 + } 7.88 + 7.89 + fclose(fp); 7.90 + return 0; 7.91 +} 7.92 + 7.93 +void rec_add(unsigned long tm, float x, float y, float z, float theta, float phi) 7.94 +{ 7.95 + struct event *ev = malloc(sizeof *ev); 7.96 + if(!ev) { 7.97 + fprintf(stderr, "failed to append rec-event: %s\n", strerror(errno)); 7.98 + return; 7.99 + } 7.100 + ev->tm = tm; 7.101 + ev->x = x; 7.102 + ev->y = y; 7.103 + ev->z = z; 7.104 + ev->theta = theta; 7.105 + ev->phi = phi; 7.106 + 7.107 + ev->next = 0; 7.108 + if(head) { 7.109 + tail->next = ev; 7.110 + tail = ev; 7.111 + } else { 7.112 + head = tail = ev; 7.113 + } 7.114 + 7.115 + num_events++; 7.116 +} 7.117 + 7.118 +void rec_get(unsigned long tm, float *x, float *y, float *z, float *theta, float *phi) 7.119 +{ 7.120 + if(!iter || iter->tm > tm) { 7.121 + iter = head; 7.122 + } 7.123 + 7.124 + while(iter && iter->next) { 7.125 + if(iter->next->tm > tm) { 7.126 + break; 7.127 + } 7.128 + iter = iter->next; 7.129 + } 7.130 + 7.131 + if(iter) { 7.132 + *x = iter->x; 7.133 + *y = iter->y; 7.134 + *z = iter->z; 7.135 + *theta = iter->theta; 7.136 + *phi = iter->phi; 7.137 + } 7.138 +}
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/src/record.h Mon Mar 10 17:24:42 2014 +0200 8.3 @@ -0,0 +1,11 @@ 8.4 +#ifndef RECORD_H_ 8.5 +#define RECORD_H_ 8.6 + 8.7 +int rec_load(const char *fname); 8.8 +int rec_save(const char *fname); 8.9 + 8.10 +void rec_reset(void); 8.11 +void rec_add(unsigned long tm, float x, float y, float z, float theta, float phi); 8.12 +void rec_get(unsigned long tm, float *x, float *y, float *z, float *theta, float *phi); 8.13 + 8.14 +#endif /* RECORD_H_ */
9.1 --- a/src/scantmpl.h Mon Sep 23 07:42:56 2013 +0300 9.2 +++ b/src/scantmpl.h Mon Mar 10 17:24:42 2014 +0200 9.3 @@ -9,6 +9,9 @@ 9.4 fixed e, de, dfde; 9.5 #endif 9.6 #ifdef INTERP_TEX 9.7 +#ifdef TEXMAP_PERSP_CORRECT 9.8 + fixed w, dw, dfdw; 9.9 +#endif 9.10 fixed u, v, du, dv, dfdu, dfdv; 9.11 #endif 9.12 fixed x; 9.13 @@ -31,6 +34,11 @@ 9.14 dfde = fixed_div(de, dy); 9.15 #endif 9.16 #ifdef INTERP_TEX 9.17 +#ifdef TEXMAP_PERSP_CORRECT 9.18 + dw = v1->pos.w - v0->pos.w; 9.19 + dfdw = fixed_div(dw, dy); 9.20 +#endif 9.21 + 9.22 du = v1->tc.x - v0->tc.x; 9.23 dv = v1->tc.y - v0->tc.y; 9.24 dfdu = fixed_div(du, dy); 9.25 @@ -59,6 +67,9 @@ 9.26 e = v0->energy; 9.27 #endif 9.28 #ifdef INTERP_TEX 9.29 +#ifdef TEXMAP_PERSP_CORRECT 9.30 + w = v0->pos.w; 9.31 +#endif 9.32 u = v0->tc.x; 9.33 v = v0->tc.y; 9.34 #endif 9.35 @@ -73,6 +84,9 @@ 9.36 e = v0->energy + fixed_mul(dfde, lines); 9.37 #endif 9.38 #ifdef INTERP_TEX 9.39 +#ifdef TEXMAP_PERSP_CORRECT 9.40 + w = v0->pos.w + fixed_mul(dfdw, lines); 9.41 +#endif 9.42 u = v0->tc.x + fixed_mul(dfdu, lines); 9.43 v = v0->tc.y + fixed_mul(dfdv, lines); 9.44 #endif 9.45 @@ -102,6 +116,11 @@ 9.46 #endif 9.47 9.48 #ifdef INTERP_TEX 9.49 +#ifdef TEXMAP_PERSP_CORRECT 9.50 + edge[i].pos.w = w; 9.51 + w += dfdw; 9.52 +#endif 9.53 + 9.54 edge[i].tc.x = u; 9.55 edge[i].tc.y = v; 9.56 u += dfdu; 9.57 @@ -126,6 +145,8 @@ 9.58 #ifdef INTERP_TEX 9.59 unsigned int tx, ty; 9.60 fixed u, v, du, dv, dfdu, dfdv; 9.61 + fixed w, dw, dfdw; 9.62 + fixed tu, tv; 9.63 #endif 9.64 VERTEX *left, *right; 9.65 9.66 @@ -179,6 +200,12 @@ 9.67 dfde = fixed_div(de, dx); 9.68 #endif 9.69 #ifdef INTERP_TEX 9.70 +#ifdef TEXMAP_PERSP_CORRECT 9.71 + w = left[y].pos.w; 9.72 + dw = right[y].pos.w - w; 9.73 + dfdw = fixed_div(dw, dx); 9.74 +#endif 9.75 + 9.76 u = left[y].tc.x; 9.77 v = left[y].tc.y; 9.78 du = right[y].tc.x - u; 9.79 @@ -200,6 +227,12 @@ 9.80 e = left[y].energy + fixed_mul(dfde, dist); 9.81 #endif 9.82 #ifdef INTERP_TEX 9.83 +#ifdef TEXMAP_PERSP_CORRECT 9.84 + dw = right[y].pos.w - left[y].pos.w; 9.85 + dfdw = fixed_div(dw, dx); 9.86 + w = left[y].pos.w + fixed_mul(dfdw, dist); 9.87 +#endif 9.88 + 9.89 du = right[y].tc.x - left[y].tc.x; 9.90 dv = right[y].tc.y - left[y].tc.y; 9.91 dfdu = fixed_div(du, dx); 9.92 @@ -225,13 +258,16 @@ 9.93 unsigned short *zptr = fb->zbuf[ZTILE(pix)] + ZTILE_OFFS(pix); 9.94 9.95 if(z < 0 || z >= fixedi(1) || zval > *zptr) { 9.96 -# ifdef INTERP_TEX 9.97 +#ifdef INTERP_TEX 9.98 u += dfdu; 9.99 v += dfdv; 9.100 -# endif 9.101 -# ifdef INTERP_ENERGY 9.102 +#ifdef TEXMAP_PERSP_CORRECT 9.103 + w += dfdw; 9.104 +#endif 9.105 +#endif /* INTERP_TEX */ 9.106 +#ifdef INTERP_ENERGY 9.107 e += dfde; 9.108 -# endif 9.109 +#endif 9.110 z += dfdz; 9.111 continue; 9.112 } 9.113 @@ -240,13 +276,23 @@ 9.114 z += dfdz; 9.115 #endif 9.116 #ifdef INTERP_TEX 9.117 - tx = (unsigned int)fixed_int(fixed_mul(u, fixedi(st->tex.width))) & st->tex.xmask; 9.118 - ty = (unsigned int)fixed_int(fixed_mul(v, fixedi(st->tex.height))) & st->tex.ymask; 9.119 +#ifdef TEXMAP_PERSP_CORRECT 9.120 + tu = fixed_div(u, w); 9.121 + tv = fixed_div(v, w); 9.122 +#else 9.123 + tu = u; 9.124 + tv = v; 9.125 +#endif 9.126 + tx = (unsigned int)fixed_int(fixed_mul(tu, fixedi(st->tex.width))) & st->tex.xmask; 9.127 + ty = (unsigned int)fixed_int(fixed_mul(tv, fixedi(st->tex.height))) & st->tex.ymask; 9.128 c = st->tex.pixels[(ty << st->tex.xshift) + tx]; 9.129 9.130 u += dfdu; 9.131 v += dfdv; 9.132 +#ifdef TEXMAP_PERSP_CORRECT 9.133 + w += dfdw; 9.134 #endif 9.135 +#endif /* INTERP_TEX */ 9.136 #ifdef INTERP_ENERGY 9.137 c += fixed_int(fixed_mul(e, fixedi(st->col_range))); 9.138 e += dfde;
10.1 --- a/src/test.c Mon Sep 23 07:42:56 2013 +0300 10.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 10.3 @@ -1,450 +0,0 @@ 10.4 -#include <stdio.h> 10.5 -#include <stdlib.h> 10.6 -#include <string.h> 10.7 -#include <signal.h> 10.8 -#include <conio.h> 10.9 -#include "wvga.h" 10.10 -#include "mingl.h" 10.11 -#include "timer.h" 10.12 -#include "mouse.h" 10.13 -#include "palman.h" 10.14 -#include "texture.h" 10.15 - 10.16 -static int init(void); 10.17 -static void shutdown(void); 10.18 -static void redraw(void); 10.19 -static void draw_cursor(unsigned char *fb, int xsz, int ysz, int mx, int my, int cidx); 10.20 -static int keyb(char key); 10.21 -static void mouse_button(int bn, int x, int y); 10.22 -static void mouse_motion(int x, int y); 10.23 -static void sighandler(int s); 10.24 -static int parse_args(int argc, char **argv); 10.25 -static void print_perf(void); 10.26 - 10.27 -static unsigned char *fbuf; 10.28 - 10.29 -static struct texture *tex; 10.30 -static char *texfile; 10.31 - 10.32 -static int white_base, red_base, green_base, blue_base; 10.33 -static int grad_range; 10.34 - 10.35 -static int use_vsync = 1; 10.36 -static int under_windows = 0; 10.37 -static unsigned long num_frm; 10.38 - 10.39 -enum { CUBE, SPHERE, TORUS, NUM_PRIMS }; 10.40 -static int prim = SPHERE; 10.41 -static int auto_rotate = 1; 10.42 -static float cam_theta, cam_phi, cam_zoom = 4.0; 10.43 - 10.44 -static int mx, my; 10.45 - 10.46 -int main(int argc, char **argv) 10.47 -{ 10.48 - int mbn, prev_mx = -1, prev_my = -1, prev_mbn = 0; 10.49 - 10.50 - if(parse_args(argc, argv) == -1) { 10.51 - return 1; 10.52 - } 10.53 - 10.54 - if(init() == -1) { 10.55 - return 1; 10.56 - } 10.57 - 10.58 - reset_timer(); 10.59 - 10.60 - for(;;) { 10.61 - if(kbhit()) { 10.62 - if(keyb(getch()) == 0) { 10.63 - break; 10.64 - } 10.65 - } 10.66 - 10.67 - mbn = read_mouse(&mx, &my); 10.68 - if(mbn != prev_mbn) { 10.69 - mouse_button(mbn, mx, my); 10.70 - prev_mbn = mbn; 10.71 - } 10.72 - if(mx != prev_mx || my != prev_my) { 10.73 - if(mbn) { 10.74 - mouse_motion(mx, my); 10.75 - } 10.76 - prev_mx = mx; 10.77 - prev_my = my; 10.78 - } 10.79 - 10.80 - redraw(); 10.81 - } 10.82 - 10.83 - shutdown(); 10.84 - print_perf(); 10.85 - return 0; 10.86 -} 10.87 - 10.88 -static int init(void) 10.89 -{ 10.90 - int i; 10.91 - struct palm_color *pal; 10.92 - 10.93 - init_timer(under_windows ? 0 : 100); 10.94 - 10.95 - set_video_mode(0x13); 10.96 - 10.97 - signal(SIGINT, sighandler); 10.98 - signal(SIGSEGV, sighandler); 10.99 - signal(SIGFPE, sighandler); 10.100 - signal(SIGILL, sighandler); 10.101 - signal(SIGABRT, sighandler); 10.102 - 10.103 - have_mouse(); 10.104 - 10.105 - 10.106 - if(mgl_init(320, 200) == -1) { 10.107 - fprintf(stderr, "mgl init failed\n"); 10.108 - return -1; 10.109 - } 10.110 - fbuf = mgl_framebuffer(); 10.111 - 10.112 - 10.113 - if(!texfile) { 10.114 - palm_add_color(255, 255, 255); 10.115 - palm_add_color(255, 0, 0); 10.116 - palm_add_color(0, 255, 0); 10.117 - palm_add_color(0, 0, 255); 10.118 - palm_build(); 10.119 - 10.120 - white_base = palm_color_base(255, 255, 255); 10.121 - red_base = palm_color_base(255, 0, 0); 10.122 - green_base = palm_color_base(0, 255, 0); 10.123 - blue_base = palm_color_base(0, 0, 255); 10.124 - 10.125 - tex = tex_gen_checker(64, 64, 3, 3, red_base, blue_base); 10.126 - } else { 10.127 - if(!(tex = load_texture(texfile))) { 10.128 - return -1; 10.129 - } 10.130 - 10.131 - palm_build(); 10.132 - get_texture_pixels(tex); 10.133 - 10.134 - mgl_enable(MGL_TEXTURE_2D); 10.135 - } 10.136 - 10.137 - grad_range = palm_color_range(); 10.138 - 10.139 - pal = palm_palette(); 10.140 - for(i=0; i<palm_palette_size(); i++) { 10.141 - set_pal_entry(i, pal[i].r, pal[i].g, pal[i].b); 10.142 - } 10.143 - 10.144 - mgl_enable(MGL_CULL_FACE); 10.145 - mgl_enable(MGL_DEPTH_TEST); 10.146 - mgl_enable(MGL_SMOOTH); 10.147 - mgl_color_range(grad_range - 1); /* gradient range */ 10.148 - 10.149 - mgl_enable(MGL_LIGHTING); 10.150 - mgl_light_intensity(0, 1.0); 10.151 - mgl_light_position(0, -0.5, 0.5, 1, 0); 10.152 - 10.153 - mgl_matrix_mode(MGL_PROJECTION); 10.154 - mgl_load_identity(); 10.155 - mgl_perspective(45.0, 320.0 / 200.0, 0.5, 100.0); 10.156 - 10.157 - mgl_teximage(tex->width, tex->height, tex->pixels); 10.158 - 10.159 - return 0; 10.160 -} 10.161 - 10.162 -static void shutdown(void) 10.163 -{ 10.164 - mgl_free(); 10.165 - set_video_mode(3); 10.166 -} 10.167 - 10.168 -static void redraw(void) 10.169 -{ 10.170 - float angle = get_msec() / 10.0; 10.171 - mgl_clear(0); 10.172 - mgl_clear_depth(); 10.173 - 10.174 - mgl_matrix_mode(MGL_MODELVIEW); 10.175 - mgl_load_identity(); 10.176 - mgl_translate(0, 0, -cam_zoom); 10.177 - if(auto_rotate) { 10.178 - mgl_rotate(angle * 0.5, 1, 0, 0); 10.179 - mgl_rotate(angle, 0, 0, 1); 10.180 - } else { 10.181 - mgl_rotate(cam_phi, 1, 0, 0); 10.182 - mgl_rotate(cam_theta, 0, 1, 0); 10.183 - } 10.184 - 10.185 - switch(prim) { 10.186 - case TORUS: 10.187 - mgl_index(green_base); 10.188 - mgl_torus(1.0, 0.25, 16, 8); 10.189 - break; 10.190 - case SPHERE: 10.191 - mgl_index(blue_base); 10.192 - mgl_sphere(1.0, 16, 8); 10.193 - break; 10.194 - case CUBE: 10.195 - mgl_index(red_base); 10.196 - mgl_cube(1.0); 10.197 - } 10.198 - 10.199 - if(!auto_rotate) { 10.200 - draw_cursor(fbuf, 320, 200, mx, my, white_base + grad_range - 1); 10.201 - } 10.202 - 10.203 - copy_frame(fbuf); 10.204 - if(use_vsync) { 10.205 - wait_vsync(); 10.206 - } 10.207 - num_frm++; 10.208 -} 10.209 - 10.210 -static void draw_cursor(unsigned char *fb, int xsz, int ysz, int mx, int my, int cidx) 10.211 -{ 10.212 - static char img[] = 10.213 - "oo........" 10.214 - "oxo......." 10.215 - "oxxo......" 10.216 - "oxxxo....." 10.217 - "oxxxxo...." 10.218 - "oxxxxxo..." 10.219 - "oxxxxxxo.." 10.220 - "oxxxxxxxo." 10.221 - "oxxxxxxxxo" 10.222 - "oxxxxxoooo" 10.223 - "oxxoxxo..." 10.224 - "oxo.oxxo.." 10.225 - "oo..oxxo.." 10.226 - ".....oxxo." 10.227 - ".....oxxo." 10.228 - "......oo.."; 10.229 - int i, j, w = 10, h = 16; 10.230 - 10.231 - if(mx < 0 || my < 0) { 10.232 - return; 10.233 - } 10.234 - if(mx + w >= xsz) { 10.235 - w = xsz - mx; 10.236 - } 10.237 - if(my + h >= ysz) { 10.238 - h = ysz - my; 10.239 - } 10.240 - 10.241 - fb += my * xsz + mx; 10.242 - for(i=0; i<h; i++) { 10.243 - for(j=0; j<w; j++) { 10.244 - char c = img[(i << 3) + (i << 1) + j]; 10.245 - if(c != '.') { 10.246 - fb[j] = c == 'x' ? 0 : cidx; 10.247 - } 10.248 - } 10.249 - fb += xsz; 10.250 - } 10.251 -} 10.252 - 10.253 -static int keyb(char key) 10.254 -{ 10.255 - switch(key) { 10.256 - case 'q': 10.257 - case 27: 10.258 - return 0; 10.259 - 10.260 - case 's': 10.261 - if(mgl_isenabled(MGL_SMOOTH)) { 10.262 - mgl_disable(MGL_SMOOTH); 10.263 - } else { 10.264 - mgl_enable(MGL_SMOOTH); 10.265 - } 10.266 - break; 10.267 - 10.268 - case 't': 10.269 - if(mgl_isenabled(MGL_TEXTURE_2D)) { 10.270 - mgl_disable(MGL_TEXTURE_2D); 10.271 - } else { 10.272 - mgl_enable(MGL_TEXTURE_2D); 10.273 - } 10.274 - break; 10.275 - 10.276 - case 'z': 10.277 - if(mgl_isenabled(MGL_DEPTH_TEST)) { 10.278 - mgl_disable(MGL_DEPTH_TEST); 10.279 - } else { 10.280 - mgl_enable(MGL_DEPTH_TEST); 10.281 - } 10.282 - break; 10.283 - 10.284 - case ' ': 10.285 - auto_rotate = !auto_rotate; 10.286 - break; 10.287 - 10.288 - case 'p': 10.289 - prim = (prim + 1) % NUM_PRIMS; 10.290 - break; 10.291 - 10.292 - case 'c': 10.293 - if(mgl_isenabled(MGL_CULL_FACE)) { 10.294 - mgl_disable(MGL_CULL_FACE); 10.295 - } else { 10.296 - mgl_enable(MGL_CULL_FACE); 10.297 - } 10.298 - break; 10.299 - 10.300 - default: 10.301 - break; 10.302 - } 10.303 - return 1; 10.304 -} 10.305 - 10.306 -static int bnstate; 10.307 -static int prev_x, prev_y; 10.308 - 10.309 -static void mouse_button(int bn, int x, int y) 10.310 -{ 10.311 - bnstate = bn; 10.312 - prev_x = x; 10.313 - prev_y = y; 10.314 -} 10.315 - 10.316 -static void mouse_motion(int x, int y) 10.317 -{ 10.318 - int dx, dy; 10.319 - 10.320 - dx = x - prev_x; 10.321 - dy = y - prev_y; 10.322 - prev_x = x; 10.323 - prev_y = y; 10.324 - 10.325 - if(bnstate & MOUSE_LEFT) { 10.326 - cam_theta += dx; 10.327 - cam_phi += dy; 10.328 - 10.329 - if(cam_phi > 90) cam_phi = 90; 10.330 - if(cam_phi < -90) cam_phi = -90; 10.331 - } 10.332 - if(bnstate & MOUSE_RIGHT) { 10.333 - cam_zoom += dy * 0.1; 10.334 - if(cam_zoom < 0.0) { 10.335 - cam_zoom = 0.0; 10.336 - } 10.337 - } 10.338 -} 10.339 - 10.340 -static void sighandler(int s) 10.341 -{ 10.342 - set_video_mode(3); 10.343 - 10.344 - switch(s) { 10.345 - case SIGABRT: 10.346 - fprintf(stderr, "abort\n"); 10.347 - break; 10.348 - 10.349 - case SIGILL: 10.350 - fprintf(stderr, "illegal operation\n"); 10.351 - break; 10.352 - 10.353 - case SIGSEGV: 10.354 - fprintf(stderr, "segmentation fault\n"); 10.355 - break; 10.356 - 10.357 - case SIGINT: 10.358 - fprintf(stderr, "interrupted\n"); 10.359 - break; 10.360 - 10.361 - case SIGFPE: 10.362 - fprintf(stderr, "floating point exception\n"); 10.363 - break; 10.364 - 10.365 - default: 10.366 - fprintf(stderr, "unexpected signal\n"); 10.367 - } 10.368 - 10.369 - exit(1); 10.370 -} 10.371 - 10.372 -static int parse_args(int argc, char **argv) 10.373 -{ 10.374 - int i; 10.375 - 10.376 - for(i=1; i<argc; i++) { 10.377 - if(argv[i][0] == '-') { 10.378 - if(argv[i][2] != 0) { 10.379 - goto invalid; 10.380 - } 10.381 - switch(argv[i][1]) { 10.382 - case 'a': 10.383 - auto_rotate = !auto_rotate; 10.384 - break; 10.385 - 10.386 - case 't': 10.387 - texfile = argv[++i]; 10.388 - break; 10.389 - 10.390 - case 'v': 10.391 - use_vsync = !use_vsync; 10.392 - break; 10.393 - 10.394 - case 'p': 10.395 - if(strcmp(argv[++i], "cube") == 0) { 10.396 - prim = CUBE; 10.397 - } else if(strcmp(argv[i], "sphere") == 0) { 10.398 - prim = SPHERE; 10.399 - } else if(strcmp(argv[i], "torus") == 0) { 10.400 - prim = TORUS; 10.401 - } else { 10.402 - goto invalid; 10.403 - } 10.404 - break; 10.405 - 10.406 - case 'w': 10.407 - under_windows = 1; 10.408 - break; 10.409 - 10.410 - case 'h': 10.411 - printf("Usage %s [options]\n", argv[0]); 10.412 - printf("options:\n"); 10.413 - printf(" -p select one of (cube|sphere|torus)\n"); 10.414 - printf(" -v use vsync\n"); 10.415 - printf(" -w run under windows\n"); 10.416 - printf(" -h print usage information and exit\n"); 10.417 - exit(0); 10.418 - 10.419 - default: 10.420 - goto invalid; 10.421 - } 10.422 - } else { 10.423 - goto invalid; 10.424 - } 10.425 - } 10.426 - 10.427 - return 0; 10.428 - 10.429 -invalid: 10.430 - fprintf(stderr, "invalid argument: %s\n", argv[i]); 10.431 - return -1; 10.432 -} 10.433 - 10.434 - 10.435 -static void print_perf(void) 10.436 -{ 10.437 - unsigned long msec, avg_frame_time; 10.438 - float sec, fps; 10.439 - 10.440 - msec = get_msec(); 10.441 - if(!num_frm || msec < 1000) { 10.442 - printf("leaving so soon? (%lu ms)\n", msec); 10.443 - return; 10.444 - } 10.445 - 10.446 - sec = msec / 1000.0f; 10.447 - fps = (float)num_frm / sec; 10.448 - avg_frame_time = msec / num_frm; 10.449 - 10.450 - printf("%lu frames in %.2f seconds\n", num_frm, sec); 10.451 - printf(" avg. frame time: %lu ms\n", avg_frame_time); 10.452 - printf(" avg. framerate: %.2f fps\n", fps); 10.453 -}