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