shell mesh
[meshfrac] / main.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <assert.h>
4 #include "opengl.h"
5 #include <GL/glut.h>
6 #include <cgmath/cgmath.h>
7 #include "cmesh.h"
8 #include "meshgen.h"
9 #include "frac.h"
10 #include "sdr.h"
11 #include "dynarr.h"
12
13 static const char *vsdr_src =
14         "varying vec3 v_norm, v_ldir, v_vdir;\n"
15         "void main()\n"
16         "{\n"
17         "       gl_Position = ftransform();\n"
18         "       vec3 vpos = (gl_ModelViewMatrix * gl_Vertex).xyz;\n"
19         "       v_vdir = -vpos;\n"
20         "       v_norm = gl_NormalMatrix * gl_Normal;\n"
21         "       v_ldir = gl_LightSource[0].position.xyz - vpos;\n"
22         "}\n";
23
24 static const char *psdr_src =
25         "varying vec3 v_norm, v_ldir, v_vdir;\n"
26         "void main()\n"
27         "{\n"
28         "       vec3 n = normalize(v_norm);\n"
29         "       vec3 v = normalize(v_vdir);\n"
30         "       vec3 l = normalize(v_ldir);\n"
31         "       vec3 h = normalize(v + l);\n"
32         "       float ndotl = max(dot(n, l), 0.0);\n"
33         "       float ndoth = max(dot(n, h), 0.0);\n"
34         "       float spec = pow(ndoth, gl_FrontMaterial.shininess);\n"
35         "       vec3 dcol = gl_FrontMaterial.diffuse.rgb * ndotl;\n"
36         "       vec3 scol = gl_FrontMaterial.specular.rgb * spec;\n"
37         "       gl_FragColor = vec4(dcol + scol, 1.0);\n"
38         "}\n";
39
40 static int init(void);
41 static void cleanup(void);
42 static void display(void);
43 static void reshape(int x, int y);
44 static void keydown(unsigned char key, int x, int y);
45 static void mouse(int bn, int st, int x, int y);
46 static void motion(int x, int y);
47
48 static int win_width, win_height;
49 static cgm_vec3 view_pos;
50 static float view_theta, view_phi = 0.6, view_dist = 8;
51 static float proj_mat[16], view_mat[16];
52 static int bnstate[8];
53 static int mx, my;
54
55 static struct fracture frac;
56 static struct cmesh *mesh;
57 static unsigned int sdr;
58
59 static int cur, pending;
60 static int show_orig = 1;
61 static int show_points, show_planes, show_shell;
62 static int cur_cell;
63
64
65 int main(int argc, char **argv)
66 {
67         glutInit(&argc, argv);
68         glutInitWindowSize(1280, 800);
69         glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
70         glutCreateWindow("meshfrac");
71
72         glutDisplayFunc(display);
73         glutReshapeFunc(reshape);
74         glutKeyboardFunc(keydown);
75         glutMouseFunc(mouse);
76         glutMotionFunc(motion);
77
78         if(init() == -1) {
79                 return 1;
80         }
81         atexit(cleanup);
82
83         glutMainLoop();
84         return 0;
85 }
86
87 static int init(void)
88 {
89         unsigned int vsdr, psdr;
90         float diffuse[] = {0.2, 0.3, 0.8, 1};
91         float specular[] = {0.8, 0.8, 0.8, 1};
92 #ifdef __glew_h__
93         glewInit();
94 #endif
95
96         if(!(vsdr = create_vertex_shader(vsdr_src))) {
97                 return -1;
98         }
99         if(!(psdr = create_pixel_shader(psdr_src))) {
100                 free_shader(vsdr);
101                 return -1;
102         }
103         if(!(sdr = create_program_link(vsdr, psdr, 0))) {
104                 free_shader(vsdr);
105                 free_shader(psdr);
106                 return -1;
107         }
108
109         glEnable(GL_CULL_FACE);
110         glEnable(GL_DEPTH_TEST);
111         glEnable(GL_LIGHTING);
112         glEnable(GL_LIGHT0);
113
114         glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, diffuse);
115         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
116         glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 60);
117
118         mesh = cmesh_alloc();
119         gen_torus(mesh, 2, 0.8, 24, 12, 1, 1);
120
121         if(frac_init(&frac) == -1) {
122                 return -1;
123         }
124         frac_mesh(&frac, mesh);
125
126         return 0;
127 }
128
129 static void cleanup(void)
130 {
131         cmesh_free(mesh);
132         free_program(sdr);
133 }
134
135 static void update(void)
136 {
137         if(pending > cur) {
138                 switch(cur) {
139                 case 0:
140                         printf("Generate points...\n");
141                         if(frac_gen_points(&frac, 16) != -1) {
142                                 cur++;
143                         } else {
144                                 pending = cur;
145                         }
146                         show_points = 1;
147                         break;
148
149                 case 1:
150                         printf("Build cells...\n");
151                         if(frac_build_cells(&frac) != -1) {
152                                 cur++;
153                         } else {
154                                 pending = cur;
155                         }
156                         show_planes = 1;
157                         break;
158
159                 case 2:
160                         printf("Construct shell...\n");
161                         if(frac_build_shell(&frac) != -1) {
162                                 cur++;
163                         } else {
164                                 pending = cur;
165                         }
166                         show_orig = 0;
167                         show_shell = 1;
168                         break;
169
170                 case 3:
171                         printf("Construct walls...\n");
172                         if(frac_build_walls(&frac) != -1) {
173                                 cur++;
174                         } else {
175                                 pending = cur;
176                         }
177                         break;
178
179                 default:
180                         break;
181                 }
182                 if(pending > cur) glutPostRedisplay();
183         }
184 }
185
186 static void display(void)
187 {
188         int i, j, num;
189         struct poly *poly;
190
191         update();
192
193         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
194
195         cgm_mtranslation(view_mat, 0, 0, -view_dist);
196         cgm_mprerotate_x(view_mat, view_phi);
197         cgm_mprerotate_y(view_mat, view_theta);
198         cgm_mpretranslate(view_mat, -view_pos.x, -view_pos.y, -view_pos.z);
199         glMatrixMode(GL_MODELVIEW);
200         glLoadMatrixf(view_mat);
201
202         if(show_orig) {
203                 bind_program(sdr);
204                 cmesh_draw(mesh);
205         }
206         if(show_points) {
207                 num = frac_num_cells(&frac);
208                 bind_program(0);
209
210                 glPushAttrib(GL_ENABLE_BIT);
211                 glDisable(GL_LIGHTING);
212                 glDisable(GL_DEPTH_TEST);
213                 glEnable(GL_BLEND);
214                 glBlendFunc(GL_ONE, GL_ONE);
215
216                 glPointSize(2.0f);
217                 glBegin(GL_POINTS);
218                 for(i=0; i<num; i++) {
219                         if(cur_cell == i) {
220                                 glColor3f(0.8, 1, 0.1);
221                         } else {
222                                 glColor3f(0.1, 0.8, 0.1);
223                         }
224                         glVertex3fv(&frac.cells[i].pt.x);
225                 }
226                 glEnd();
227
228                 glPopAttrib();
229         }
230
231         if(show_planes) {
232                 bind_program(0);
233
234                 glPushAttrib(GL_ENABLE_BIT);
235                 glDisable(GL_LIGHTING);
236
237                 poly = frac.cells[cur_cell].polys;
238                 for(i=0; i<frac.cells[cur_cell].num_polys; i++) {
239                         glBegin(GL_LINE_LOOP);
240                         glColor3f(0.5, 0.5, 0);
241                         for(j=0; j<dynarr_size(poly->verts); j++) {
242                                 glVertex3fv(&poly->verts[j].pos.x);
243                         }
244                         glEnd();
245                         poly++;
246                 }
247
248                 glPopAttrib();
249         }
250
251         if(show_shell) {
252                 bind_program(sdr);
253                 cmesh_draw(frac.cells[cur_cell].mesh);
254         }
255
256         assert(glGetError() == GL_NO_ERROR);
257         glutSwapBuffers();
258 }
259
260 static void reshape(int x, int y)
261 {
262         win_width = x;
263         win_height = y;
264         glViewport(0, 0, x, y);
265
266         cgm_mperspective(proj_mat, cgm_deg_to_rad(50), (float)x / y, 0.5, 500.0);
267         glMatrixMode(GL_PROJECTION);
268         glLoadMatrixf(proj_mat);
269 }
270
271 static void keydown(unsigned char key, int x, int y)
272 {
273         int n;
274
275         switch(key) {
276         case 27:
277                 exit(0);
278
279         case 'o':
280                 show_orig ^= 1;
281                 glutPostRedisplay();
282                 break;
283
284         case 'p':
285                 show_points ^= 1;
286                 glutPostRedisplay();
287                 break;
288
289         case 'P':
290                 show_planes ^= 1;
291                 glutPostRedisplay();
292                 break;
293
294         case ']':
295                 cur_cell = (cur_cell + 1) % frac_num_cells(&frac);
296                 printf("current cell: %d\n", cur_cell);
297                 glutPostRedisplay();
298                 break;
299
300         case '[':
301                 if(--cur_cell < 0) {
302                         cur_cell = frac_num_cells(&frac) - 1;
303                         printf("current cell: %d\n", cur_cell);
304                         glutPostRedisplay();
305                 }
306                 break;
307
308         default:
309                 if(key >= '1' && key <= '4') {
310                         n = key - '0';
311                         if(cur < n) {
312                                 pending = n;
313                                 glutPostRedisplay();
314                         }
315                 }
316         }
317 }
318
319 static void mouse(int bn, int st, int x, int y)
320 {
321         int bidx = bn - GLUT_LEFT_BUTTON;
322         if(bidx < 8) {
323                 bnstate[bidx] = st == GLUT_DOWN;
324         }
325         mx = x;
326         my = y;
327 }
328
329 static void motion(int x, int y)
330 {
331         int dx = x - mx;
332         int dy = y - my;
333         mx = x;
334         my = y;
335
336         if(!(dx | dy)) return;
337
338         if(bnstate[0]) {
339                 view_theta += cgm_deg_to_rad(dx * 0.5);
340                 view_phi += cgm_deg_to_rad(dy * 0.5);
341                 if(view_phi < -M_PI / 2) view_phi = -M_PI / 2;
342                 if(view_phi > M_PI / 2) view_phi = M_PI / 2;
343                 glutPostRedisplay();
344         }
345         if(bnstate[1]) {
346                 cgm_vec3 up, right;
347
348                 up.x = -sin(view_theta) * sin(view_phi);
349                 up.y = -cos(view_phi);
350                 up.z = cos(view_theta) * sin(view_phi);
351                 right.x = cos(view_theta);
352                 right.y = 0;
353                 right.z = sin(view_theta);
354
355                 view_pos.x -= (right.x * dx + up.x * dy) * 0.01;
356                 view_pos.y -= up.y * dy * 0.01;
357                 view_pos.z -= (right.z * dx + up.z * dy) * 0.01;
358                 glutPostRedisplay();
359         }
360         if(bnstate[2]) {
361                 view_dist += dy * 0.1;
362                 if(view_dist < 0) view_dist = 0;
363                 glutPostRedisplay();
364         }
365 }