polyfill debugging mode
[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
9 struct mesh {
10         int prim;
11         struct g3d_vertex *varr;
12         int16_t *iarr;
13         int vcount, icount;
14 };
15
16 static int init(void);
17 static void destroy(void);
18 static void start(long trans_time);
19 static void draw(void);
20 static void draw_mesh(struct mesh *mesh);
21 static int gen_cube(struct mesh *mesh, float sz);
22 static int gen_torus(struct mesh *mesh, float rad, float ringrad, int usub, int vsub);
23 static void zsort(struct mesh *m);
24
25 static struct screen scr = {
26         "polytest",
27         init,
28         destroy,
29         start, 0,
30         draw
31 };
32
33 static struct mesh cube, torus;
34
35 struct screen *polytest_screen(void)
36 {
37         return &scr;
38 }
39
40 static int init(void)
41 {
42         gen_cube(&cube, 1.0);
43         gen_torus(&torus, 1.0, 0.25, 24, 12);
44         return 0;
45 }
46
47 static void destroy(void)
48 {
49         free(cube.varr);
50         free(torus.varr);
51         free(torus.iarr);
52 }
53
54 static void start(long trans_time)
55 {
56         g3d_matrix_mode(G3D_PROJECTION);
57         g3d_load_identity();
58         g3d_perspective(50.0, 1.3333333, 0.5, 100.0);
59
60         g3d_enable(G3D_CULL_FACE);
61 }
62
63 static void draw(void)
64 {
65         static int prev_mx, prev_my;
66         static float theta, phi = 25;
67
68         int dx = mouse_x - prev_mx;
69         int dy = mouse_y - prev_my;
70         prev_mx = mouse_x;
71         prev_my = mouse_y;
72
73         if(dx || dy) {
74                 theta += dx * 2.0;
75                 phi += dy * 2.0;
76
77                 if(phi < -90) phi = -90;
78                 if(phi > 90) phi = 90;
79         }
80
81         /*float angle = (float)time_msec / 50.0;*/
82
83         memset(fb_pixels, 0, fb_width * fb_height * 2);
84
85         g3d_matrix_mode(G3D_MODELVIEW);
86         g3d_load_identity();
87         g3d_translate(0, 0, -3);
88         g3d_rotate(phi, 1, 0, 0);
89         g3d_rotate(theta, 0, 1, 0);
90
91         /*zsort(&torus);*/
92         draw_mesh(&cube);
93
94         swap_buffers(fb_pixels);
95 }
96
97 static void draw_mesh(struct mesh *mesh)
98 {
99         if(mesh->iarr) {
100                 g3d_draw_indexed(mesh->prim, mesh->varr, mesh->vcount, mesh->iarr, mesh->icount);
101         } else {
102                 g3d_draw(mesh->prim, mesh->varr, mesh->vcount);
103         }
104 }
105
106 #define NORMAL(vp, x, y, z) do { vp->nx = x; vp->ny = y; vp->nz = z; } while(0)
107 #define COLOR(vp, cr, cg, cb) do { vp->r = cr; vp->g = cg; vp->b = cb; } while(0)
108 #define TEXCOORD(vp, tu, tv) do { vp->u = tu; vp->v = tv; } while(0)
109 #define VERTEX(vp, vx, vy, vz) \
110         do { \
111                 vp->x = vx; vp->y = vy; vp->z = vz; vp->w = 1.0f; \
112                 ++vp; \
113         } while(0)
114
115 static int gen_cube(struct mesh *mesh, float sz)
116 {
117         struct g3d_vertex *vptr;
118         float hsz = sz / 2.0;
119
120         mesh->prim = G3D_QUADS;
121         mesh->iarr = 0;
122         mesh->icount = 0;
123
124         mesh->vcount = 24;
125         if(!(mesh->varr = malloc(mesh->vcount * sizeof *mesh->varr))) {
126                 return -1;
127         }
128         vptr = mesh->varr;
129
130         /* -Z */
131         NORMAL(vptr, 0, 0, -1);
132         COLOR(vptr, 255, 0, 255);
133         VERTEX(vptr, hsz, -hsz, -hsz);
134         VERTEX(vptr, -hsz, -hsz, -hsz);
135         VERTEX(vptr, -hsz, hsz, -hsz);
136         VERTEX(vptr, hsz, hsz, -hsz);
137         /* -Y */
138         NORMAL(vptr, 0, -1, 0);
139         COLOR(vptr, 0, 255, 255);
140         VERTEX(vptr, -hsz, -hsz, -hsz);
141         VERTEX(vptr, hsz, -hsz, -hsz);
142         VERTEX(vptr, hsz, -hsz, hsz);
143         VERTEX(vptr, -hsz, -hsz, hsz);
144         /* -X */
145         NORMAL(vptr, -1, 0, 0);
146         COLOR(vptr, 255, 255, 0);
147         VERTEX(vptr, -hsz, -hsz, -hsz);
148         VERTEX(vptr, -hsz, -hsz, hsz);
149         VERTEX(vptr, -hsz, hsz, hsz);
150         VERTEX(vptr, -hsz, hsz, -hsz);
151         /* +X */
152         NORMAL(vptr, 1, 0, 0);
153         COLOR(vptr, 255, 0, 0);
154         VERTEX(vptr, hsz, -hsz, hsz);
155         VERTEX(vptr, hsz, -hsz, -hsz);
156         VERTEX(vptr, hsz, hsz, -hsz);
157         VERTEX(vptr, hsz, hsz, hsz);
158         /* +Y */
159         NORMAL(vptr, 0, 1, 0);
160         COLOR(vptr, 0, 255, 0);
161         VERTEX(vptr, -hsz, hsz, hsz);
162         VERTEX(vptr, hsz, hsz, hsz);
163         VERTEX(vptr, hsz, hsz, -hsz);
164         VERTEX(vptr, -hsz, hsz, -hsz);
165         /* +Z */
166         NORMAL(vptr, 0, 0, 1);
167         COLOR(vptr, 0, 0, 255);
168         VERTEX(vptr, -hsz, -hsz, hsz);
169         VERTEX(vptr, hsz, -hsz, hsz);
170         VERTEX(vptr, hsz, hsz, hsz);
171         VERTEX(vptr, -hsz, hsz, hsz);
172
173         return 0;
174 }
175
176 static void torusvec(float *res, float theta, float phi, float mr, float rr)
177 {
178         float rx, ry, rz;
179         theta = -theta;
180
181         rx = -cos(phi) * rr + mr;
182         ry = sin(phi) * rr;
183         rz = 0.0f;
184
185         res[0] = rx * sin(theta) + rz * cos(theta);
186         res[1] = ry;
187         res[2] = -rx * cos(theta) + rz * sin(theta);
188 }
189
190 static int gen_torus(struct mesh *mesh, float rad, float ringrad, int usub, int vsub)
191 {
192         int i, j;
193         int nfaces, uverts, vverts;
194         struct g3d_vertex *vptr;
195         int16_t *iptr;
196
197         mesh->prim = G3D_QUADS;
198
199         if(usub < 4) usub = 4;
200         if(vsub < 2) vsub = 2;
201
202         uverts = usub + 1;
203         vverts = vsub + 1;
204
205         mesh->vcount = uverts * vverts;
206         nfaces = usub * vsub;
207         mesh->icount = nfaces * 4;
208
209         if(!(mesh->varr = malloc(mesh->vcount * sizeof *mesh->varr))) {
210                 return -1;
211         }
212         if(!(mesh->iarr = malloc(mesh->icount * sizeof *mesh->iarr))) {
213                 return -1;
214         }
215         vptr = mesh->varr;
216         iptr = mesh->iarr;
217
218         for(i=0; i<uverts; i++) {
219                 float u = (float)i / (float)(uverts - 1);
220                 float theta = u * 2.0 * M_PI;
221                 float rcent[3];
222
223                 torusvec(rcent, theta, 0, rad, 0);
224
225                 for(j=0; j<vverts; j++) {
226                         float v = (float)j / (float)(vverts - 1);
227                         float phi = v * 2.0 * M_PI;
228                         int chess = (i & 1) == (j & 1);
229
230                         torusvec(&vptr->x, theta, phi, rad, ringrad);
231
232                         vptr->nx = (vptr->x - rcent[0]) / ringrad;
233                         vptr->ny = (vptr->y - rcent[1]) / ringrad;
234                         vptr->nz = (vptr->z - rcent[2]) / ringrad;
235                         vptr->u = u;
236                         vptr->v = v;
237                         vptr->r = chess ? 255 : 64;
238                         vptr->g = 128;
239                         vptr->b = chess ? 64 : 255;
240                         ++vptr;
241
242                         if(i < usub && j < vsub) {
243                                 int idx = i * vverts + j;
244                                 *iptr++ = idx;
245                                 *iptr++ = idx + 1;
246                                 *iptr++ = idx + vverts + 1;
247                                 *iptr++ = idx + vverts;
248                         }
249                 }
250         }
251         return 0;
252 }
253
254
255 static struct {
256         struct g3d_vertex *varr;
257         const float *xform;
258 } zsort_cls;
259
260 static int zsort_cmp(const void *aptr, const void *bptr)
261 {
262         const int16_t *a = (const int16_t*)aptr;
263         const int16_t *b = (const int16_t*)bptr;
264
265         const float *m = zsort_cls.xform;
266
267         const struct g3d_vertex *va = zsort_cls.varr + a[0];
268         const struct g3d_vertex *vb = zsort_cls.varr + b[0];
269
270         float za = m[2] * va->x + m[6] * va->y + m[10] * va->z + m[14];
271         float zb = m[2] * vb->x + m[6] * vb->y + m[10] * vb->z + m[14];
272
273         va = zsort_cls.varr + a[2];
274         vb = zsort_cls.varr + b[2];
275
276         za += m[2] * va->x + m[6] * va->y + m[10] * va->z + m[14];
277         zb += m[2] * vb->x + m[6] * vb->y + m[10] * vb->z + m[14];
278
279         return za - zb;
280 }
281
282 static void zsort(struct mesh *m)
283 {
284         int nfaces = m->icount / m->prim;
285
286         zsort_cls.varr = m->varr;
287         zsort_cls.xform = g3d_get_matrix(G3D_MODELVIEW, 0);
288
289         qsort(m->iarr, nfaces, m->prim * sizeof *m->iarr, zsort_cmp);
290 }