ropesim: gimbal movement
[dosdemo] / tools / ropesim / src / main.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <GL/glut.h>
4 #include "cmesh.h"
5 #include "cgmath/cgmath.h"
6
7 int init(void);
8 void cleanup(void);
9 void display(void);
10 void idle(void);
11 void reshape(int x, int y);
12 void keyb(unsigned char key, int x, int y);
13 void mouse(int bn, int st, int x, int y);
14 void motion(int x, int y);
15 void sball_motion(int x, int y, int z);
16 void sball_rotate(int rx, int ry, int rz);
17 void sball_button(int bn, int st);
18
19 float cam_theta, cam_phi, cam_dist = 10;
20 int prev_mx, prev_my;
21 int bnstate[8];
22
23 long start_msec;
24
25 struct cmesh *scn;
26 struct cmesh *mesh_gout, *mesh_gin, *mesh_suz;
27
28 cgm_vec3 gmove;
29 /*cgm_quat grot = {0, 0, 0, 1};*/
30 float grot_theta, grot_phi;
31 float ginner_xform[16], gouter_xform[16];
32 cgm_vec3 ganchor[4];
33
34 cgm_vec3 dbgvec[4];
35
36 int main(int argc, char **argv)
37 {
38         glutInit(&argc, argv);
39         glutInitWindowSize(1280, 800);
40         glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
41         glutCreateWindow("ropesim");
42
43         glutDisplayFunc(display);
44         glutIdleFunc(idle);
45         glutReshapeFunc(reshape);
46         glutKeyboardFunc(keyb);
47         glutMouseFunc(mouse);
48         glutMotionFunc(motion);
49         glutSpaceballMotionFunc(sball_motion);
50         glutSpaceballRotateFunc(sball_rotate);
51         glutSpaceballButtonFunc(sball_button);
52
53         if(init() == -1) {
54                 return 1;
55         }
56         atexit(cleanup);
57
58         start_msec = glutGet(GLUT_ELAPSED_TIME);
59         glutMainLoop();
60         return 0;
61 }
62
63
64 int init(void)
65 {
66         static const char *meshnames[] = {"suzanne", "gimbal_outer", "gimbal_inner"};
67         static struct cmesh **meshes[] = {&mesh_suz, &mesh_gout, &mesh_gin};
68         static const float amb[] = {0.05, 0.05, 0.08, 1};
69         int i;
70
71         glEnable(GL_CULL_FACE);
72         glEnable(GL_DEPTH_TEST);
73         glEnable(GL_LIGHTING);
74         glEnable(GL_LIGHT0);
75         glEnable(GL_LIGHT1);
76         glEnable(GL_LIGHT2);
77
78         glLightModelfv(GL_LIGHT_MODEL_AMBIENT, amb);
79
80         if(!(scn = cmesh_alloc()) || cmesh_load(scn, "gimbal.obj") == -1) {
81                 fprintf(stderr, "failed to load scene file\n");
82                 return -1;
83         }
84
85         for(i=0; i<sizeof meshes / sizeof *meshes; i++) {
86                 int idx;
87                 if((idx = cmesh_find_submesh(scn, meshnames[i])) == -1) {
88                         fprintf(stderr, "failed to locate required submesh (%s)\n", meshnames[i]);
89                         return -1;
90                 }
91                 if(!(*meshes[i] = cmesh_alloc()) || cmesh_clone_submesh(*meshes[i], scn, idx) == -1) {
92                         fprintf(stderr, "failed to clone submesh\n");
93                         return -1;
94                 }
95                 cmesh_remove_submesh(scn, idx);
96         }
97
98         /* anchor points on the inner gimbal */
99         for(i=0; i<4; i++) {
100                 ganchor[i].x = (float)(((i & 1) << 1) - 1) * 1.5f;
101                 ganchor[i].y = (float)((i & 2) - 1) * 1.5f;
102                 ganchor[i].z = 0;
103         }
104
105         return 0;
106 }
107
108 void cleanup(void)
109 {
110         cmesh_free(mesh_suz);
111         cmesh_free(mesh_gout);
112         cmesh_free(mesh_gin);
113         cmesh_free(scn);
114 }
115
116 void update(long tmsec, float dt)
117 {
118         int i;
119         cgm_vec3 apt0, apt1;
120         float theta, phi, brot;
121
122         /*
123         cgm_mrotation_quat(ginner_xform, &grot);
124         cgm_mtranslate(ginner_xform, gmove.x, gmove.y, gmove.z);
125         */
126
127         theta = cgm_deg_to_rad(grot_theta);
128         phi = cgm_deg_to_rad(grot_phi);
129
130         cgm_mrotation_euler(ginner_xform, phi, theta, 0, CGM_EULER_XYZ);
131         cgm_mrotation_euler(gouter_xform, phi, 0, 0, CGM_EULER_XYZ);
132
133         for(i=0; i<4; i++) {
134                 apt0 = ganchor[i];
135                 cgm_vmul_m4v3(&apt0, ginner_xform);
136
137                 dbgvec[i] = apt0;
138         }
139 }
140
141 void display(void)
142 {
143         static const float lpos[][4] = {
144                 {-100, 100, 200, 1},
145                 {100, 80, 50, 1},
146                 {20, -50, -150, 1}
147         };
148         static const float lcol[][4] = {
149                 {0.9, 0.9, 0.9, 1},
150                 {0.5, 0.3, 0.2, 1},
151                 {0.2, 0.3, 0.2, 1}
152         };
153         int i, count;
154         long tmsec = glutGet(GLUT_ELAPSED_TIME) - start_msec;
155         static long prev_tmsec;
156
157         update(tmsec, (float)(tmsec - prev_tmsec) / 1000.0f);
158         prev_tmsec = tmsec;
159
160         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
161
162         glMatrixMode(GL_MODELVIEW);
163         glLoadIdentity();
164         glTranslatef(0, 0, -cam_dist);
165         glRotatef(cam_phi, 1, 0, 0);
166         glRotatef(cam_theta, 0, 1, 0);
167
168         for(i=0; i<3; i++) {
169                 glLightfv(GL_LIGHT0 + i, GL_POSITION, lpos[i]);
170                 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, lcol[i]);
171         }
172
173         count = cmesh_submesh_count(scn);
174         for(i=0; i<count; i++) {
175                 cmesh_draw_submesh(scn, i);
176         }
177
178         glPushMatrix();
179         glMultMatrixf(gouter_xform);
180         cmesh_draw(mesh_gout);
181         glPopMatrix();
182
183         glPushMatrix();
184         glMultMatrixf(ginner_xform);
185         cmesh_draw(mesh_gin);
186         glPopMatrix();
187
188         cmesh_draw(mesh_suz);
189
190         glPointSize(7);
191         glBegin(GL_POINTS);
192         for(i=0; i<4; i++) {
193                 glVertex3f(dbgvec[i].x, dbgvec[i].y, dbgvec[i].z);
194         }
195         glEnd();
196
197         glutSwapBuffers();
198 }
199 void idle(void)
200 {
201         glutPostRedisplay();
202 }
203
204 void reshape(int x, int y)
205 {
206         glViewport(0, 0, x, y);
207         glMatrixMode(GL_PROJECTION);
208         glLoadIdentity();
209         gluPerspective(50.0, (float)x / (float)y, 0.5, 500.0);
210 }
211
212 void keyb(unsigned char key, int x, int y)
213 {
214         switch(key) {
215         case 27:
216                 exit(0);
217         }
218 }
219
220 void mouse(int bn, int st, int x, int y)
221 {
222         prev_mx = x;
223         prev_my = y;
224         bnstate[bn - GLUT_LEFT_BUTTON] = st == GLUT_DOWN;
225 }
226
227 void motion(int x, int y)
228 {
229         int dx = x - prev_mx;
230         int dy = y - prev_my;
231         prev_mx = x;
232         prev_my = y;
233
234         if(!(dx | dy)) return;
235
236         if(bnstate[0]) {
237                 cam_theta += dx * 0.5;
238                 cam_phi += dy * 0.5;
239                 if(cam_phi < -90) cam_phi = -90;
240                 if(cam_phi > 90) cam_phi = 90;
241         }
242
243         if(bnstate[1]) {
244                 grot_theta += dx * 0.5;
245                 grot_phi += dy * 0.5;
246         }
247
248         if(bnstate[2]) {
249                 cam_dist += dy * 0.1;
250                 if(cam_dist < 0.0f) cam_dist = 0.0f;
251         }
252 }
253
254 void sball_motion(int x, int y, int z)
255 {
256         gmove.x += x * 0.001f;
257         gmove.y += y * 0.001f;
258         gmove.z -= z * 0.001f;
259 }
260
261 void sball_rotate(int x, int y, int z)
262 {
263         /*
264         float axis_len, s;
265         axis_len = (float)sqrt(x * x + y * y + z * z);
266         s = axis_len == 0.0f ? 1.0f : 1.0f / axis_len;
267         cgm_qrotate(&grot, axis_len * 0.001f, -x * s, -y * s, z * s);
268         */
269
270         grot_theta += y * 0.03f;
271         grot_phi += x * 0.03f;
272 }
273
274 void sball_button(int bn, int st)
275 {
276         if(st == GLUT_DOWN) {
277                 /*cgm_qcons(&grot, 0, 0, 0, 1);*/
278                 grot_theta = grot_phi = 0.0f;
279                 cgm_vcons(&gmove, 0, 0, 0);
280         }
281 }