afe20069968f53a34c0ab917d0c859a529d38dbb
[dosdemo] / src / polytest.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <math.h>
5 #include "screen.h"
6 #include "demo.h"
7 #include "3dgfx.h"
8 #include "gfxutil.h"
9 #include "polyfill.h"   /* just for struct pimage */
10 #include "cfgopt.h"
11 #include "mesh.h"
12 #include "bsptree.h"
13
14 static int init(void);
15 static void destroy(void);
16 static void start(long trans_time);
17 static void draw(void);
18 static void draw_lowres_raster(void);
19 static int gen_texture(struct pimage *img, int xsz, int ysz);
20
21 static struct screen scr = {
22         "polytest",
23         init,
24         destroy,
25         start, 0,
26         draw,
27         0
28 };
29
30 static float cam_theta, cam_phi = 25;
31 static float cam_dist = 3;
32 static struct g3d_mesh cube, torus;
33 static struct bsptree torus_bsp;
34
35 static struct pimage tex;
36
37 static int use_bsp = 1;
38
39 #define LOWRES_SCALE    10
40 static uint16_t *lowres_pixels;
41 static int lowres_width, lowres_height;
42
43 struct screen *polytest_screen(void)
44 {
45         return &scr;
46 }
47
48 static int init(void)
49 {
50         int i;
51
52         gen_cube_mesh(&cube, 1.0, 0);
53         gen_torus_mesh(&torus, 1.0, 0.25, 24, 12);
54         /* scale texcoords */
55         for(i=0; i<torus.vcount; i++) {
56                 torus.varr[i].u *= 4.0;
57                 torus.varr[i].v *= 2.0;
58         }
59
60         init_bsp(&torus_bsp);
61         if(bsp_add_mesh(&torus_bsp, &torus) == -1) {
62                 fprintf(stderr, "failed to construct torus BSP tree\n");
63                 return -1;
64         }
65
66         gen_texture(&tex, 128, 128);
67
68 #ifdef DEBUG_POLYFILL
69         lowres_width = fb_width / LOWRES_SCALE;
70         lowres_height = fb_height / LOWRES_SCALE;
71         lowres_pixels = malloc(lowres_width * lowres_height * 2);
72         scr.draw = draw_debug;
73 #endif
74
75         return 0;
76 }
77
78 static void destroy(void)
79 {
80         free(lowres_pixels);
81         free(cube.varr);
82         free(torus.varr);
83         free(torus.iarr);
84         destroy_bsp(&torus_bsp);
85 }
86
87 static void start(long trans_time)
88 {
89         g3d_matrix_mode(G3D_PROJECTION);
90         g3d_load_identity();
91         g3d_perspective(50.0, 1.3333333, 0.5, 100.0);
92
93         g3d_enable(G3D_CULL_FACE);
94         g3d_enable(G3D_LIGHTING);
95         g3d_enable(G3D_LIGHT0);
96
97         g3d_polygon_mode(G3D_TEX_GOURAUD);
98 }
99
100 static void update(void)
101 {
102         mouse_orbit_update(&cam_theta, &cam_phi, &cam_dist);
103 }
104
105
106 static void draw(void)
107 {
108         float vdir[3];
109         const float *mat;
110
111         update();
112
113         memset(fb_pixels, 0, fb_width * fb_height * 2);
114
115         g3d_matrix_mode(G3D_MODELVIEW);
116         g3d_load_identity();
117         g3d_translate(0, 0, -cam_dist);
118         if(opt.sball) {
119                 g3d_mult_matrix(sball_matrix);
120         } else {
121                 g3d_rotate(cam_phi, 1, 0, 0);
122                 g3d_rotate(cam_theta, 0, 1, 0);
123         }
124
125         g3d_light_pos(0, -10, 10, 20);
126
127         g3d_mtl_diffuse(0.4, 0.7, 1.0);
128         g3d_set_texture(tex.width, tex.height, tex.pixels);
129
130         if(use_bsp) {
131                 /* calc world-space view direction */
132                 mat = g3d_get_matrix(G3D_MODELVIEW, 0);
133                 /* transform (0, 0, -1) with transpose(mat3x3) */
134                 vdir[0] = -mat[2];
135                 vdir[1] = -mat[6];
136                 vdir[2] = -mat[10];
137
138                 draw_bsp(&torus_bsp, vdir[0], vdir[1], vdir[2]);
139         } else {
140                 zsort_mesh(&torus);
141                 draw_mesh(&torus);
142         }
143
144         /*draw_mesh(&cube);*/
145         swap_buffers(fb_pixels);
146 }
147
148 static void draw_debug(void)
149 {
150         update();
151
152         memset(lowres_pixels, 0, lowres_width * lowres_height * 2);
153
154         g3d_matrix_mode(G3D_MODELVIEW);
155         g3d_load_identity();
156         g3d_translate(0, 0, -cam_dist);
157         g3d_rotate(cam_phi, 1, 0, 0);
158         g3d_rotate(cam_theta, 0, 1, 0);
159
160         g3d_framebuffer(lowres_width, lowres_height, lowres_pixels);
161         /*zsort(&torus);*/
162         draw_mesh(&cube);
163
164         draw_lowres_raster();
165
166
167         g3d_framebuffer(fb_width, fb_height, fb_pixels);
168
169         g3d_polygon_mode(G3D_WIRE);
170         draw_mesh(&cube);
171         g3d_polygon_mode(G3D_FLAT);
172
173         swap_buffers(fb_pixels);
174 }
175
176
177 static void draw_huge_pixel(uint16_t *dest, int dest_width, uint16_t color)
178 {
179         int i, j;
180         uint16_t grid_color = PACK_RGB16(127, 127, 127);
181
182         for(i=0; i<LOWRES_SCALE; i++) {
183                 for(j=0; j<LOWRES_SCALE; j++) {
184                         dest[j] = i == 0 || j == 0 ? grid_color : color;
185                 }
186                 dest += dest_width;
187         }
188 }
189
190 static void draw_lowres_raster(void)
191 {
192         int i, j;
193         uint16_t *sptr = lowres_pixels;
194         uint16_t *dptr = fb_pixels;
195
196         for(i=0; i<lowres_height; i++) {
197                 for(j=0; j<lowres_width; j++) {
198                         draw_huge_pixel(dptr, fb_width, *sptr++);
199                         dptr += LOWRES_SCALE;
200                 }
201                 dptr += fb_width * LOWRES_SCALE - fb_width;
202         }
203 }
204
205 static int gen_texture(struct pimage *img, int xsz, int ysz)
206 {
207         int i, j;
208         uint16_t *pix;
209
210         if(!(img->pixels = malloc(xsz * ysz * sizeof *pix))) {
211                 return -1;
212         }
213         pix = img->pixels;
214
215         for(i=0; i<ysz; i++) {
216                 for(j=0; j<xsz; j++) {
217                         int val = i ^ j;
218
219                         *pix++ = PACK_RGB16(val, val, val);
220                 }
221         }
222
223         img->width = xsz;
224         img->height = ysz;
225         return 0;
226 }