removed mesh dump
[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, -5);
88         g3d_rotate(phi, 1, 0, 0);
89         g3d_rotate(theta, 0, 1, 0);
90
91         zsort(&torus);
92         draw_mesh(&torus);
93 }
94
95 static void draw_mesh(struct mesh *mesh)
96 {
97         if(mesh->iarr) {
98                 g3d_draw_indexed(mesh->prim, mesh->varr, mesh->vcount, mesh->iarr, mesh->icount);
99         } else {
100                 g3d_draw(mesh->prim, mesh->varr, mesh->vcount);
101         }
102 }
103
104 #define NORMAL(vp, x, y, z) do { vp->nx = x; vp->ny = y; vp->nz = z; } while(0)
105 #define COLOR(vp, cr, cg, cb) do { vp->r = cr; vp->g = cg; vp->b = cb; } while(0)
106 #define TEXCOORD(vp, tu, tv) do { vp->u = tu; vp->v = tv; } while(0)
107 #define VERTEX(vp, vx, vy, vz) \
108         do { \
109                 vp->x = vx; vp->y = vy; vp->z = vz; vp->w = 1.0f; \
110                 ++vp; \
111         } while(0)
112
113 static int gen_cube(struct mesh *mesh, float sz)
114 {
115         struct g3d_vertex *vptr;
116         float hsz = sz / 2.0;
117
118         mesh->prim = G3D_QUADS;
119         mesh->iarr = 0;
120         mesh->icount = 0;
121
122         mesh->vcount = 24;
123         if(!(mesh->varr = malloc(mesh->vcount * sizeof *mesh->varr))) {
124                 return -1;
125         }
126         vptr = mesh->varr;
127
128         /* -Z */
129         NORMAL(vptr, 0, 0, -1);
130         COLOR(vptr, 255, 0, 255);
131         VERTEX(vptr, hsz, -hsz, -hsz);
132         VERTEX(vptr, -hsz, -hsz, -hsz);
133         VERTEX(vptr, -hsz, hsz, -hsz);
134         VERTEX(vptr, hsz, hsz, -hsz);
135         /* -Y */
136         NORMAL(vptr, 0, -1, 0);
137         COLOR(vptr, 0, 255, 255);
138         VERTEX(vptr, -hsz, -hsz, -hsz);
139         VERTEX(vptr, hsz, -hsz, -hsz);
140         VERTEX(vptr, hsz, -hsz, hsz);
141         VERTEX(vptr, -hsz, -hsz, hsz);
142         /* -X */
143         NORMAL(vptr, -1, 0, 0);
144         COLOR(vptr, 255, 255, 0);
145         VERTEX(vptr, -hsz, -hsz, -hsz);
146         VERTEX(vptr, -hsz, -hsz, hsz);
147         VERTEX(vptr, -hsz, hsz, hsz);
148         VERTEX(vptr, -hsz, hsz, -hsz);
149         /* +X */
150         NORMAL(vptr, 1, 0, 0);
151         COLOR(vptr, 255, 0, 0);
152         VERTEX(vptr, hsz, -hsz, hsz);
153         VERTEX(vptr, hsz, -hsz, -hsz);
154         VERTEX(vptr, hsz, hsz, -hsz);
155         VERTEX(vptr, hsz, hsz, hsz);
156         /* +Y */
157         NORMAL(vptr, 0, 1, 0);
158         COLOR(vptr, 0, 255, 0);
159         VERTEX(vptr, -hsz, hsz, hsz);
160         VERTEX(vptr, hsz, hsz, hsz);
161         VERTEX(vptr, hsz, hsz, -hsz);
162         VERTEX(vptr, -hsz, hsz, -hsz);
163         /* +Z */
164         NORMAL(vptr, 0, 0, 1);
165         COLOR(vptr, 0, 0, 255);
166         VERTEX(vptr, -hsz, -hsz, hsz);
167         VERTEX(vptr, hsz, -hsz, hsz);
168         VERTEX(vptr, hsz, hsz, hsz);
169         VERTEX(vptr, -hsz, hsz, hsz);
170
171         return 0;
172 }
173
174 static void torusvec(float *res, float theta, float phi, float mr, float rr)
175 {
176         float rx, ry, rz;
177         theta = -theta;
178
179         rx = -cos(phi) * rr + mr;
180         ry = sin(phi) * rr;
181         rz = 0.0f;
182
183         res[0] = rx * sin(theta) + rz * cos(theta);
184         res[1] = ry;
185         res[2] = -rx * cos(theta) + rz * sin(theta);
186 }
187
188 static int gen_torus(struct mesh *mesh, float rad, float ringrad, int usub, int vsub)
189 {
190         int i, j;
191         int nfaces, uverts, vverts;
192         struct g3d_vertex *vptr;
193         int16_t *iptr;
194
195         mesh->prim = G3D_QUADS;
196
197         if(usub < 4) usub = 4;
198         if(vsub < 2) vsub = 2;
199
200         uverts = usub + 1;
201         vverts = vsub + 1;
202
203         mesh->vcount = uverts * vverts;
204         nfaces = usub * vsub;
205         mesh->icount = nfaces * 4;
206
207         if(!(mesh->varr = malloc(mesh->vcount * sizeof *mesh->varr))) {
208                 return -1;
209         }
210         if(!(mesh->iarr = malloc(mesh->icount * sizeof *mesh->iarr))) {
211                 return -1;
212         }
213         vptr = mesh->varr;
214         iptr = mesh->iarr;
215
216         for(i=0; i<uverts; i++) {
217                 float u = (float)i / (float)(uverts - 1);
218                 float theta = u * 2.0 * M_PI;
219                 float rcent[3];
220
221                 torusvec(rcent, theta, 0, rad, 0);
222
223                 for(j=0; j<vverts; j++) {
224                         float v = (float)j / (float)(vverts - 1);
225                         float phi = v * 2.0 * M_PI;
226                         int chess = (i & 1) == (j & 1);
227
228                         torusvec(&vptr->x, theta, phi, rad, ringrad);
229
230                         vptr->nx = (vptr->x - rcent[0]) / ringrad;
231                         vptr->ny = (vptr->y - rcent[1]) / ringrad;
232                         vptr->nz = (vptr->z - rcent[2]) / ringrad;
233                         vptr->u = u;
234                         vptr->v = v;
235                         vptr->r = chess ? 255 : 64;
236                         vptr->g = 128;
237                         vptr->b = chess ? 64 : 255;
238                         ++vptr;
239
240                         if(i < usub && j < vsub) {
241                                 int idx = i * vverts + j;
242                                 *iptr++ = idx;
243                                 *iptr++ = idx + 1;
244                                 *iptr++ = idx + vverts + 1;
245                                 *iptr++ = idx + vverts;
246                         }
247                 }
248         }
249         return 0;
250 }
251
252
253 static struct {
254         struct g3d_vertex *varr;
255         const float *xform;
256 } zsort_cls;
257
258 static int zsort_cmp(const void *aptr, const void *bptr)
259 {
260         const int16_t *a = (const int16_t*)aptr;
261         const int16_t *b = (const int16_t*)bptr;
262
263         const float *m = zsort_cls.xform;
264
265         const struct g3d_vertex *va = zsort_cls.varr + a[0];
266         const struct g3d_vertex *vb = zsort_cls.varr + b[0];
267
268         float za = m[2] * va->x + m[6] * va->y + m[10] * va->z + m[14];
269         float zb = m[2] * vb->x + m[6] * vb->y + m[10] * vb->z + m[14];
270
271         va = zsort_cls.varr + a[2];
272         vb = zsort_cls.varr + b[2];
273
274         za += m[2] * va->x + m[6] * va->y + m[10] * va->z + m[14];
275         zb += m[2] * vb->x + m[6] * vb->y + m[10] * vb->z + m[14];
276
277         return za - zb;
278 }
279
280 static void zsort(struct mesh *m)
281 {
282         int nfaces = m->icount / m->prim;
283
284         zsort_cls.varr = m->varr;
285         zsort_cls.xform = g3d_get_matrix(G3D_MODELVIEW, 0);
286
287         qsort(m->iarr, nfaces, m->prim * sizeof *m->iarr, zsort_cmp);
288 }