updated files from meshfrac_alt
[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         //gen_sphere(mesh, 2, 12, 6, 1, 1);
121         gen_box(mesh, 2, 2, 2, 0, 0);
122
123         if(frac_init(&frac) == -1) {
124                 return -1;
125         }
126         frac_mesh(&frac, mesh);
127         frac.cell_gap = 0.1;
128
129         //frac_gen_points(&frac, 16);
130         frac_point(&frac, -5, 0, 0);
131         frac_point(&frac, 5, 0, 0);
132         show_points = 1;
133         cur = 1;
134
135         return 0;
136 }
137
138 static void cleanup(void)
139 {
140         cmesh_free(mesh);
141         free_program(sdr);
142 }
143
144 static void update(void)
145 {
146         if(pending > cur) {
147                 switch(cur) {
148                 case 0:
149                         printf("Generate points...\n");
150                         if(frac_gen_points(&frac, 2) != -1) {
151                                 cur++;
152                         } else {
153                                 pending = cur;
154                         }
155                         show_points = 1;
156                         break;
157
158                 case 1:
159                         printf("Build cells...\n");
160                         if(frac_build_cells(&frac) != -1) {
161                                 cur++;
162                         } else {
163                                 pending = cur;
164                         }
165                         show_planes = 1;
166                         break;
167
168                 case 2:
169                         printf("Construct shell...\n");
170                         if(frac_build_shell(&frac) != -1) {
171                                 cur++;
172                         } else {
173                                 pending = cur;
174                         }
175                         show_orig = 0;
176                         show_shell = 1;
177                         break;
178
179                 case 3:
180                         printf("Construct walls...\n");
181                         if(frac_build_walls(&frac) != -1) {
182                                 cur++;
183                         } else {
184                                 pending = cur;
185                         }
186                         break;
187
188                 default:
189                         break;
190                 }
191                 if(pending > cur) glutPostRedisplay();
192         }
193 }
194
195 static void display(void)
196 {
197         int i, j, num;
198         struct poly *poly;
199
200         update();
201
202         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
203
204         cgm_mtranslation(view_mat, 0, 0, -view_dist);
205         cgm_mprerotate_x(view_mat, view_phi);
206         cgm_mprerotate_y(view_mat, view_theta);
207         cgm_mpretranslate(view_mat, -view_pos.x, -view_pos.y, -view_pos.z);
208         glMatrixMode(GL_MODELVIEW);
209         glLoadMatrixf(view_mat);
210
211         bind_program(0);
212         glShadeModel(GL_FLAT);
213
214         if(show_orig) {
215                 //bind_program(sdr);
216                 cmesh_draw(mesh);
217                 bind_program(0);
218         }
219         if(show_points) {
220                 num = frac_num_cells(&frac);
221
222                 glPushAttrib(GL_ENABLE_BIT);
223                 glDisable(GL_LIGHTING);
224                 glDisable(GL_DEPTH_TEST);
225                 glEnable(GL_BLEND);
226                 glBlendFunc(GL_ONE, GL_ONE);
227
228                 glPointSize(2.0f);
229                 glBegin(GL_POINTS);
230                 for(i=0; i<num; i++) {
231                         if(cur_cell == i) {
232                                 glColor3f(0.8, 1, 0.1);
233                         } else {
234                                 glColor3f(0.1, 0.8, 0.1);
235                         }
236                         glVertex3fv(&frac.cells[i].pt.x);
237                 }
238                 glEnd();
239
240                 glPopAttrib();
241         }
242
243         if(show_planes) {
244                 glPushAttrib(GL_ENABLE_BIT);
245                 glDisable(GL_LIGHTING);
246
247                 poly = frac.cells[cur_cell].polys;
248                 for(i=0; i<frac.cells[cur_cell].num_polys; i++) {
249                         glBegin(GL_LINE_LOOP);
250                         glColor3f(0.5, 0.5, 0);
251                         for(j=0; j<dynarr_size(poly->verts); j++) {
252                                 glVertex3fv(&poly->verts[j].pos.x);
253                         }
254                         glEnd();
255                         poly++;
256                 }
257
258                 glPopAttrib();
259         }
260
261         if(show_shell) {
262                 //bind_program(sdr);
263                 cmesh_draw(frac.cells[cur_cell].mesh);
264                 bind_program(0);
265         }
266
267         assert(glGetError() == GL_NO_ERROR);
268         glutSwapBuffers();
269 }
270
271 static void reshape(int x, int y)
272 {
273         win_width = x;
274         win_height = y;
275         glViewport(0, 0, x, y);
276
277         cgm_mperspective(proj_mat, cgm_deg_to_rad(50), (float)x / y, 0.5, 500.0);
278         glMatrixMode(GL_PROJECTION);
279         glLoadMatrixf(proj_mat);
280 }
281
282 static void keydown(unsigned char key, int x, int y)
283 {
284         int n;
285
286         switch(key) {
287         case 27:
288                 exit(0);
289
290         case 'o':
291                 show_orig ^= 1;
292                 glutPostRedisplay();
293                 break;
294
295         case 'p':
296                 show_points ^= 1;
297                 glutPostRedisplay();
298                 break;
299
300         case 'P':
301                 show_planes ^= 1;
302                 glutPostRedisplay();
303                 break;
304
305         case ']':
306                 cur_cell = (cur_cell + 1) % frac_num_cells(&frac);
307                 printf("current cell: %d\n", cur_cell);
308                 glutPostRedisplay();
309                 break;
310
311         case '[':
312                 if(--cur_cell < 0) {
313                         cur_cell = frac_num_cells(&frac) - 1;
314                         printf("current cell: %d\n", cur_cell);
315                         glutPostRedisplay();
316                 }
317                 break;
318
319         default:
320                 if(key >= '1' && key <= '4') {
321                         n = key - '0';
322                         if(cur < n) {
323                                 pending = n;
324                                 glutPostRedisplay();
325                         }
326                 }
327         }
328 }
329
330 static void mouse(int bn, int st, int x, int y)
331 {
332         int bidx = bn - GLUT_LEFT_BUTTON;
333         if(bidx < 8) {
334                 bnstate[bidx] = st == GLUT_DOWN;
335         }
336         mx = x;
337         my = y;
338 }
339
340 static void motion(int x, int y)
341 {
342         int dx = x - mx;
343         int dy = y - my;
344         mx = x;
345         my = y;
346
347         if(!(dx | dy)) return;
348
349         if(bnstate[0]) {
350                 view_theta += cgm_deg_to_rad(dx * 0.5);
351                 view_phi += cgm_deg_to_rad(dy * 0.5);
352                 if(view_phi < -M_PI / 2) view_phi = -M_PI / 2;
353                 if(view_phi > M_PI / 2) view_phi = M_PI / 2;
354                 glutPostRedisplay();
355         }
356         if(bnstate[1]) {
357                 cgm_vec3 up, right;
358
359                 up.x = -sin(view_theta) * sin(view_phi);
360                 up.y = -cos(view_phi);
361                 up.z = cos(view_theta) * sin(view_phi);
362                 right.x = cos(view_theta);
363                 right.y = 0;
364                 right.z = sin(view_theta);
365
366                 view_pos.x -= (right.x * dx + up.x * dy) * 0.01;
367                 view_pos.y -= up.y * dy * 0.01;
368                 view_pos.z -= (right.z * dx + up.z * dy) * 0.01;
369                 glutPostRedisplay();
370         }
371         if(bnstate[2]) {
372                 view_dist += dy * 0.1;
373                 if(view_dist < 0) view_dist = 0;
374                 glutPostRedisplay();
375         }
376 }