3d4b3162822d02542f8a5ffd29cfa933fbab078d
[megadrive_tetris] / tools / tilegen / src / main.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <errno.h>
5 #include <assert.h>
6 #include <GL/glut.h>
7
8 struct vec3 {
9         float x, y, z;
10 };
11
12 void disp(void);
13 void draw_field(int xcells, int ycells);
14 void draw_tile(int col, int row, int xcells, int ycells);
15 void set_view_matrix(int eye, float ipd);
16 void set_proj_matrix(int eye, float ipd);
17 void reshape(int x, int y);
18 void keyb(unsigned char key, int x, int y);
19 void save_tiles(void);
20 int save_tile(const char *fname, unsigned char *pixptr, int xsz, int ysz, int pitch);
21
22 static int win_width = 320;
23 static int win_height = 640;
24 static int grid_cols = 10;
25 static int grid_rows = 20;
26 static float aspect;
27 static int view = 0;
28 static float eye_dist = 1.3;
29
30 int main(int argc, char **argv)
31 {
32         glutInit(&argc, argv);
33         glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
34         glutInitWindowSize(win_width, win_height);
35         glutCreateWindow("tilegen");
36
37         glutDisplayFunc(disp);
38         glutReshapeFunc(reshape);
39         glutKeyboardFunc(keyb);
40
41         glClearColor(0.05, 0.05, 0.05, 1);
42         glEnable(GL_CULL_FACE);
43         glShadeModel(GL_FLAT);
44
45         glutMainLoop();
46         return 0;
47 }
48
49 void disp(void)
50 {
51         glClear(GL_COLOR_BUFFER_BIT);
52
53         glColorMask(1, 0, 0, 0);
54
55         set_proj_matrix(-1, eye_dist);
56         set_view_matrix(-1, eye_dist);
57         glTranslatef(0, 0, -1);
58
59         draw_field(grid_cols, grid_rows);
60
61         glColorMask(0, 1, 1, 0);
62
63         set_proj_matrix(1, eye_dist);
64         set_view_matrix(1, eye_dist);
65         glTranslatef(0, 0, -1);
66
67         draw_field(grid_cols, grid_rows);
68
69         glColorMask(1, 1, 1, 1);
70
71         glutSwapBuffers();
72         assert(glGetError() == GL_NO_ERROR);
73 }
74
75 void draw_field(int xcells, int ycells)
76 {
77         int i, j;
78
79         for(i=0; i<ycells; i++) {
80                 for(j=0; j<xcells; j++) {
81                         draw_tile(j, i, xcells, ycells);
82                 }
83         }
84 }
85
86 #define DX      0.4
87 #define DZ      0.35
88
89 static struct vec3 tileverts[] = {
90         {-1, -1, 0}, {1, -1, 0}, {1, 1, 0}, {-1, 1, 0},
91         {-1 + DX, -1 + DX, DZ}, {1 - DX, -1 + DX, DZ},
92         {1 - DX, 1 - DX, DZ}, {-1 + DX, 1 - DX, DZ}
93 };
94 static struct vec3 tilecol[] = {
95         {0.5, 0.5, 0.5},        /* left */
96         {0.2, 0.2, 0.2},        /* bottom */
97         {0.5, 0.5, 0.5},        /* right */
98         {0.8, 0.8, 0.8},        /* top */
99         {0.65, 0.65, 0.65},     /* front */
100         {0, 0, 0}, {0, 0, 0}, {0, 0, 0}
101 };
102 static uint16_t tileidx[] = { /* 3 +---------+ 2 */
103         4, 7, 3, 0,               /*   |\ 7   6 /|   */
104         5, 4, 0, 1,               /*   | +-----+ |   */
105         6, 5, 1, 2,               /*   | |     | |   */
106         7, 6, 2, 3,               /*   | +-----+ |   */
107         5, 6, 7, 4                /*   |/ 4   5 \|   */
108 };                            /* 0 +---------+ 1 */
109
110 void draw_tile(int col, int row, int xcells, int ycells)
111 {
112         int ncells = xcells > ycells ? xcells : ycells;
113         float cellsz = 2.0 / ncells;
114
115         glPushMatrix();
116         glTranslatef((col - xcells / 2.0 + 0.5) * cellsz, (row - ycells / 2.0 + 0.5) * cellsz, 0);
117         glScalef(cellsz * 0.5, cellsz * 0.5, cellsz * 0.5);
118
119         glEnableClientState(GL_VERTEX_ARRAY);
120         glEnableClientState(GL_COLOR_ARRAY);
121         glVertexPointer(3, GL_FLOAT, 0, tileverts);
122         glColorPointer(3, GL_FLOAT, 0, tilecol);
123         glDrawElements(GL_QUADS, 20, GL_UNSIGNED_SHORT, tileidx);
124         glDisableClientState(GL_VERTEX_ARRAY);
125         glDisableClientState(GL_COLOR_ARRAY);
126
127         glPopMatrix();
128 }
129
130 void set_view_matrix(int eye, float ipd)
131 {
132         const float offs[] = {0.5, 0.0, -0.5};
133
134         glMatrixMode(GL_MODELVIEW);
135         glLoadIdentity();
136         glTranslatef(offs[eye + 1] * ipd, 0, 0);
137 }
138
139 void set_proj_matrix(int eye, float ipd)
140 {
141         const float offs[] = {1.0, 0.0, -1.0};
142         float vpsz = 0.5;
143
144         float right = aspect * vpsz;
145         float top = vpsz;
146         float shift = offs[eye + 1] * ipd * 0.25; /* 0.25 -> 0.5 * znear */
147
148         glMatrixMode(GL_PROJECTION);
149         glLoadIdentity();
150         glFrustum(-right + shift, right + shift, -top, top, 0.5, 500.0);
151 }
152
153 void reshape(int x, int y)
154 {
155         win_width = x;
156         win_height = y;
157         aspect = (float)win_width / (float)win_height;
158         glViewport(0, 0, x, y);
159 }
160
161 void keyb(unsigned char key, int x, int y)
162 {
163         switch(key) {
164         case 27:
165                 exit(0);
166
167         case '1':
168         case '2':
169         case '3':
170                 view = key - '2';
171                 glutPostRedisplay();
172                 break;
173
174         case 's':
175                 save_tiles();
176                 break;
177
178         case ' ':
179                 if(win_height > 160) {
180                         glutReshapeWindow(win_width / 4, win_height / 4);
181                 } else {
182                         glutReshapeWindow(win_width * 4, win_height * 4);
183                 }
184                 glutPostRedisplay();
185                 break;
186         }
187 }
188
189
190 void save_tiles(void)
191 {
192         unsigned char *pixels, *tilepix;
193         int i, j, tilesz = win_height / grid_rows;
194         char fname[256];
195
196         if(!(pixels = malloc(win_width * win_height * 3))) {
197                 fprintf(stderr, "failed to allocate pixel buffer\n");
198                 return;
199         }
200         glReadPixels(0, 0, win_width, win_height, GL_RGB, GL_UNSIGNED_BYTE, pixels);
201
202         for(i=0; i<grid_rows; i++) {
203                 for(j=0; j<grid_cols; j++) {
204                         tilepix = pixels + (i * win_width + j) * tilesz * 3;
205
206                         sprintf(fname, "tile-%02d%02d.ppm", j, i);
207                         save_tile(fname, tilepix, tilesz, tilesz, win_width * 3);
208                 }
209         }
210 }
211
212 int save_tile(const char *fname, unsigned char *pixptr, int xsz, int ysz, int pitch)
213 {
214         int i, j;
215         FILE *fp;
216
217         printf("saving tile: %s\n", fname);
218
219         if(!(fp = fopen(fname, "wb"))) {
220                 fprintf(stderr, "failed to open %s for writing: %s\n", fname, strerror(errno));
221                 return -1;
222         }
223
224         pixptr += ysz * pitch;
225         fprintf(fp, "P6\n%d %d\n255\n", xsz, ysz);
226         for(i=0; i<ysz; i++) {
227                 pixptr -= pitch;
228                 for(j=0; j<xsz; j++) {
229                         int r = pixptr[j * 3];
230                         int g = pixptr[j * 3 + 1];
231                         int b = pixptr[j * 3 + 2];
232                         fputc(r, fp);
233                         fputc(g, fp);
234                         fputc(b, fp);
235                 }
236         }
237
238         fclose(fp);
239         return 0;
240 }