1 | /*
|
---|
2 | glh - is a platform-indepenedent C++ OpenGL helper library
|
---|
3 |
|
---|
4 |
|
---|
5 | Copyright (c) 2000 Cass Everitt
|
---|
6 | Copyright (c) 2000 NVIDIA Corporation
|
---|
7 | All rights reserved.
|
---|
8 |
|
---|
9 | Redistribution and use in source and binary forms, with or
|
---|
10 | without modification, are permitted provided that the following
|
---|
11 | conditions are met:
|
---|
12 |
|
---|
13 | * Redistributions of source code must retain the above
|
---|
14 | copyright notice, this list of conditions and the following
|
---|
15 | disclaimer.
|
---|
16 |
|
---|
17 | * Redistributions in binary form must reproduce the above
|
---|
18 | copyright notice, this list of conditions and the following
|
---|
19 | disclaimer in the documentation and/or other materials
|
---|
20 | provided with the distribution.
|
---|
21 |
|
---|
22 | * The names of contributors to this software may not be used
|
---|
23 | to endorse or promote products derived from this software
|
---|
24 | without specific prior written permission.
|
---|
25 |
|
---|
26 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
---|
27 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
---|
28 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
---|
29 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
---|
30 | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
---|
31 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
---|
32 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
---|
33 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
---|
34 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
---|
35 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
---|
36 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
---|
37 | POSSIBILITY OF SUCH DAMAGE.
|
---|
38 |
|
---|
39 |
|
---|
40 | Cass Everitt - cass@r3.nu
|
---|
41 | */
|
---|
42 |
|
---|
43 | #ifndef GLH_GLUT_H
|
---|
44 | #define GLH_GLUT_H
|
---|
45 |
|
---|
46 | // some helper functions and object to
|
---|
47 | // make writing simple glut programs even easier! :-)
|
---|
48 |
|
---|
49 | #ifdef MACOS
|
---|
50 | #include <GLUT/glut.h>
|
---|
51 | #else
|
---|
52 | #include <GL/glut.h>
|
---|
53 | #endif
|
---|
54 |
|
---|
55 | #include <glh/glh_convenience.h>
|
---|
56 | #include <algorithm>
|
---|
57 | #include <list>
|
---|
58 |
|
---|
59 | namespace glh
|
---|
60 | {
|
---|
61 |
|
---|
62 | class glut_interactor
|
---|
63 | {
|
---|
64 | public:
|
---|
65 | glut_interactor() { enabled = true; }
|
---|
66 |
|
---|
67 | virtual void display() {}
|
---|
68 | virtual void idle() {}
|
---|
69 | virtual void keyboard(unsigned char key, int x, int y) {}
|
---|
70 | virtual void menu_status(int status, int x, int y) {}
|
---|
71 | virtual void motion(int x, int y) {}
|
---|
72 | virtual void mouse(int button, int state, int x, int y) {}
|
---|
73 | virtual void passive_motion(int x, int y) {}
|
---|
74 | virtual void reshape(int w, int h) {}
|
---|
75 | virtual void special(int key, int x, int y) {}
|
---|
76 | virtual void timer(int value) {}
|
---|
77 | virtual void visibility(int v) {}
|
---|
78 |
|
---|
79 | virtual void enable() { enabled = true; }
|
---|
80 | virtual void disable() { enabled = false; }
|
---|
81 |
|
---|
82 | bool enabled;
|
---|
83 | };
|
---|
84 |
|
---|
85 | std::list<glut_interactor *> interactors;
|
---|
86 | bool propagate;
|
---|
87 |
|
---|
88 | void glut_display_function()
|
---|
89 | {
|
---|
90 | propagate = true;
|
---|
91 | for(std::list<glut_interactor *>::iterator it=interactors.begin(); it != interactors.end() && propagate; it++)
|
---|
92 | (*it)->display();
|
---|
93 | }
|
---|
94 |
|
---|
95 | void glut_idle_function()
|
---|
96 | {
|
---|
97 | propagate = true;
|
---|
98 | for(std::list<glut_interactor *>::iterator it=interactors.begin(); it != interactors.end() && propagate; it++)
|
---|
99 | (*it)->idle();
|
---|
100 | }
|
---|
101 |
|
---|
102 | void glut_keyboard_function(unsigned char k, int x, int y)
|
---|
103 | {
|
---|
104 | propagate = true;
|
---|
105 | for(std::list<glut_interactor *>::iterator it=interactors.begin(); it != interactors.end() && propagate; it++)
|
---|
106 | (*it)->keyboard(k, x, y);
|
---|
107 | }
|
---|
108 |
|
---|
109 | void glut_menu_status_function(int status, int x, int y)
|
---|
110 | {
|
---|
111 | propagate = true;
|
---|
112 | for(std::list<glut_interactor *>::iterator it=interactors.begin(); it != interactors.end() && propagate; it++)
|
---|
113 | (*it)->menu_status(status, x, y);
|
---|
114 | }
|
---|
115 |
|
---|
116 | void glut_motion_function(int x, int y)
|
---|
117 | {
|
---|
118 | propagate = true;
|
---|
119 | for(std::list<glut_interactor *>::iterator it=interactors.begin(); it != interactors.end() && propagate; it++)
|
---|
120 | (*it)->motion(x, y);
|
---|
121 | }
|
---|
122 |
|
---|
123 | void glut_mouse_function(int button, int state, int x, int y)
|
---|
124 | {
|
---|
125 | propagate = true;
|
---|
126 | for(std::list<glut_interactor *>::iterator it=interactors.begin(); it != interactors.end() && propagate; it++)
|
---|
127 | (*it)->mouse(button, state, x, y);
|
---|
128 | }
|
---|
129 |
|
---|
130 | void glut_passive_motion_function(int x, int y)
|
---|
131 | {
|
---|
132 | propagate = true;
|
---|
133 | for(std::list<glut_interactor *>::iterator it=interactors.begin(); it != interactors.end() && propagate; it++)
|
---|
134 | (*it)->passive_motion(x, y);
|
---|
135 | }
|
---|
136 |
|
---|
137 | void glut_reshape_function(int w, int h)
|
---|
138 | {
|
---|
139 | propagate = true;
|
---|
140 | for(std::list<glut_interactor *>::iterator it=interactors.begin(); it != interactors.end() && propagate; it++)
|
---|
141 | (*it)->reshape(w,h);
|
---|
142 | }
|
---|
143 |
|
---|
144 | void glut_special_function(int k, int x, int y)
|
---|
145 | {
|
---|
146 | propagate = true;
|
---|
147 | for(std::list<glut_interactor *>::iterator it=interactors.begin(); it != interactors.end() && propagate; it++)
|
---|
148 | (*it)->special(k, x, y);
|
---|
149 | }
|
---|
150 |
|
---|
151 | void glut_timer_function(int v)
|
---|
152 | {
|
---|
153 | propagate = true;
|
---|
154 | for(std::list<glut_interactor *>::iterator it=interactors.begin(); it != interactors.end() && propagate; it++)
|
---|
155 | (*it)->timer(v);
|
---|
156 | }
|
---|
157 |
|
---|
158 | void glut_visibility_function(int v)
|
---|
159 | {
|
---|
160 | propagate = true;
|
---|
161 | for(std::list<glut_interactor *>::iterator it=interactors.begin(); it != interactors.end() && propagate; it++)
|
---|
162 | (*it)->visibility(v);
|
---|
163 | }
|
---|
164 |
|
---|
165 | // stop processing the current event
|
---|
166 | inline void glut_event_processed()
|
---|
167 | {
|
---|
168 | propagate = false;
|
---|
169 | }
|
---|
170 |
|
---|
171 | inline void glut_helpers_initialize()
|
---|
172 | {
|
---|
173 | glutDisplayFunc(glut_display_function);
|
---|
174 | glutIdleFunc(0);
|
---|
175 | glutKeyboardFunc(glut_keyboard_function);
|
---|
176 | glutMenuStatusFunc(glut_menu_status_function);
|
---|
177 | glutMotionFunc(glut_motion_function);
|
---|
178 | glutMouseFunc(glut_mouse_function);
|
---|
179 | glutPassiveMotionFunc(glut_passive_motion_function);
|
---|
180 | glutReshapeFunc(glut_reshape_function);
|
---|
181 | glutSpecialFunc(glut_special_function);
|
---|
182 | glutVisibilityFunc(glut_visibility_function);
|
---|
183 | }
|
---|
184 |
|
---|
185 | inline void glut_remove_interactor(glut_interactor *gi)
|
---|
186 | {
|
---|
187 | std::list<glut_interactor *>::iterator it =
|
---|
188 | std::find(interactors.begin(), interactors.end(), gi);
|
---|
189 | if(it != interactors.end())
|
---|
190 | interactors.erase(it);
|
---|
191 | }
|
---|
192 |
|
---|
193 | inline void glut_add_interactor(glut_interactor *gi, bool append=true)
|
---|
194 | {
|
---|
195 | glut_remove_interactor(gi);
|
---|
196 | if(append)
|
---|
197 | interactors.push_back(gi);
|
---|
198 | else
|
---|
199 | interactors.push_front(gi);
|
---|
200 | }
|
---|
201 |
|
---|
202 | inline void glut_timer(int msec, int value)
|
---|
203 | {
|
---|
204 | glutTimerFunc(msec, glut_timer_function, value);
|
---|
205 | }
|
---|
206 |
|
---|
207 | inline void glut_idle(bool do_idle)
|
---|
208 | {
|
---|
209 | glutIdleFunc(do_idle ? glut_idle_function : 0);
|
---|
210 | }
|
---|
211 |
|
---|
212 | class glut_callbacks : public glut_interactor
|
---|
213 | {
|
---|
214 | public:
|
---|
215 | glut_callbacks() :
|
---|
216 | display_function(0),
|
---|
217 | idle_function(0),
|
---|
218 | keyboard_function(0),
|
---|
219 | menu_status_function(0),
|
---|
220 | motion_function(0),
|
---|
221 | mouse_function(0),
|
---|
222 | passive_motion_function(0),
|
---|
223 | reshape_function(0),
|
---|
224 | special_function(0),
|
---|
225 | timer_function(0),
|
---|
226 | visibility_function()
|
---|
227 | {}
|
---|
228 |
|
---|
229 | virtual void display()
|
---|
230 | { if(display_function) display_function(); }
|
---|
231 |
|
---|
232 | virtual void idle()
|
---|
233 | { if(idle_function) idle_function(); }
|
---|
234 |
|
---|
235 | virtual void keyboard(unsigned char k, int x, int y)
|
---|
236 | { if(keyboard_function) keyboard_function(k, x, y); }
|
---|
237 |
|
---|
238 | virtual void menu_status(int status, int x, int y)
|
---|
239 | { if(menu_status_function) menu_status_function(status, x, y); }
|
---|
240 |
|
---|
241 | virtual void motion(int x, int y)
|
---|
242 | { if(motion_function) motion_function(x,y); }
|
---|
243 |
|
---|
244 | virtual void mouse(int button, int state, int x, int y)
|
---|
245 | { if(mouse_function) mouse_function(button, state, x, y); }
|
---|
246 |
|
---|
247 | virtual void passive_motion(int x, int y)
|
---|
248 | { if(passive_motion_function) passive_motion_function(x, y); }
|
---|
249 |
|
---|
250 | virtual void reshape(int w, int h)
|
---|
251 | { if(reshape_function) reshape_function(w, h); }
|
---|
252 |
|
---|
253 | virtual void special(int key, int x, int y)
|
---|
254 | { if(special_function) special_function(key, x, y); }
|
---|
255 |
|
---|
256 | virtual void timer(int value)
|
---|
257 | { if(timer_function) timer_function(value); }
|
---|
258 |
|
---|
259 | virtual void visibility(int v)
|
---|
260 | { if(visibility_function) visibility_function(v); }
|
---|
261 |
|
---|
262 | void (* display_function) ();
|
---|
263 | void (* idle_function) ();
|
---|
264 | void (* keyboard_function) (unsigned char, int, int);
|
---|
265 | void (* menu_status_function) (int, int, int);
|
---|
266 | void (* motion_function) (int, int);
|
---|
267 | void (* mouse_function) (int, int, int, int);
|
---|
268 | void (* passive_motion_function) (int, int);
|
---|
269 | void (* reshape_function) (int, int);
|
---|
270 | void (* special_function) (int, int, int);
|
---|
271 | void (* timer_function) (int);
|
---|
272 | void (* visibility_function) (int);
|
---|
273 |
|
---|
274 | };
|
---|
275 |
|
---|
276 |
|
---|
277 |
|
---|
278 | class glut_perspective_reshaper : public glut_interactor
|
---|
279 | {
|
---|
280 | public:
|
---|
281 | glut_perspective_reshaper(float infovy = 60.f, float inzNear = .1f, float inzFar = 10.f)
|
---|
282 | : fovy(infovy), zNear(inzNear), zFar(inzFar), aspect_factor(1) {}
|
---|
283 |
|
---|
284 | void reshape(int w, int h)
|
---|
285 | {
|
---|
286 | width = w; height = h;
|
---|
287 |
|
---|
288 | if(enabled) apply();
|
---|
289 | }
|
---|
290 |
|
---|
291 | void apply()
|
---|
292 | {
|
---|
293 | glViewport(0,0,width,height);
|
---|
294 | glMatrixMode(GL_PROJECTION);
|
---|
295 | glLoadIdentity();
|
---|
296 | apply_perspective();
|
---|
297 | glMatrixMode(GL_MODELVIEW);
|
---|
298 | }
|
---|
299 | void apply_perspective()
|
---|
300 | {
|
---|
301 | aspect = aspect_factor * float(width)/float(height);
|
---|
302 | if ( aspect < 1 )
|
---|
303 | {
|
---|
304 | // fovy is a misnomer.. we really mean the fov applies to the
|
---|
305 | // smaller dimension
|
---|
306 | float fovx = fovy;
|
---|
307 | float real_fov = to_degrees(2 * atan(tan(to_radians(fovx/2))/aspect));
|
---|
308 | gluPerspective(real_fov, aspect, zNear, zFar);
|
---|
309 | }
|
---|
310 | else
|
---|
311 | gluPerspective(fovy, aspect, zNear, zFar);
|
---|
312 | }
|
---|
313 | int width, height;
|
---|
314 | float fovy, aspect, zNear, zFar;
|
---|
315 | float aspect_factor;
|
---|
316 | };
|
---|
317 |
|
---|
318 | // activates/deactivates on a particular mouse button
|
---|
319 | // and calculates deltas while active
|
---|
320 | class glut_simple_interactor : public glut_interactor
|
---|
321 | {
|
---|
322 | public:
|
---|
323 | glut_simple_interactor()
|
---|
324 | {
|
---|
325 | activate_on = GLUT_LEFT_BUTTON;
|
---|
326 | active = false;
|
---|
327 | use_modifiers = true;
|
---|
328 | modifiers = 0;
|
---|
329 | width = height = 0;
|
---|
330 | x0 = y0 = x = y = dx = dy = 0;
|
---|
331 | }
|
---|
332 |
|
---|
333 | virtual void mouse(int button, int state, int X, int Y)
|
---|
334 | {
|
---|
335 | if(enabled && button == activate_on && state == GLUT_DOWN &&
|
---|
336 | (! use_modifiers || (modifiers == glutGetModifiers())) )
|
---|
337 | {
|
---|
338 | active = true;
|
---|
339 | x = x0 = X;
|
---|
340 | y = y0 = Y;
|
---|
341 | dx = dy = 0;
|
---|
342 | }
|
---|
343 | else if (enabled && button == activate_on && state == GLUT_UP)
|
---|
344 | {
|
---|
345 | if(dx == 0 && dy == 0)
|
---|
346 | update();
|
---|
347 | active = false;
|
---|
348 | dx = dy = 0;
|
---|
349 | }
|
---|
350 | }
|
---|
351 |
|
---|
352 | virtual void motion(int X, int Y)
|
---|
353 | {
|
---|
354 | if(enabled && active)
|
---|
355 | {
|
---|
356 | dx = X - x; dy = y - Y;
|
---|
357 | x = X; y = Y;
|
---|
358 | update();
|
---|
359 | }
|
---|
360 | }
|
---|
361 |
|
---|
362 | void reshape(int w, int h)
|
---|
363 | {
|
---|
364 | width = w; height = h;
|
---|
365 | }
|
---|
366 |
|
---|
367 | virtual void apply_transform() = 0;
|
---|
368 | virtual void apply_inverse_transform() = 0;
|
---|
369 | virtual matrix4f get_transform() = 0;
|
---|
370 | virtual matrix4f get_inverse_transform() = 0;
|
---|
371 |
|
---|
372 | virtual void update() {}
|
---|
373 |
|
---|
374 | int activate_on;
|
---|
375 | bool use_modifiers;
|
---|
376 | int modifiers;
|
---|
377 | bool active;
|
---|
378 | int x0, y0;
|
---|
379 | int x, y;
|
---|
380 | int dx, dy;
|
---|
381 | int width, height;
|
---|
382 | };
|
---|
383 |
|
---|
384 |
|
---|
385 | class glut_pan : public glut_simple_interactor
|
---|
386 | {
|
---|
387 | public:
|
---|
388 | glut_pan()
|
---|
389 | {
|
---|
390 | scale = .01f;
|
---|
391 | invert_increment = false;
|
---|
392 | parent_rotation = 0;
|
---|
393 | }
|
---|
394 | void update()
|
---|
395 | {
|
---|
396 | vec3f v(dx, dy, 0);
|
---|
397 | if(parent_rotation != 0) parent_rotation->mult_vec(v);
|
---|
398 |
|
---|
399 | if(invert_increment)
|
---|
400 | pan -= v * scale;
|
---|
401 | else
|
---|
402 | pan += v * scale;
|
---|
403 | glutPostRedisplay();
|
---|
404 | }
|
---|
405 |
|
---|
406 | void apply_transform()
|
---|
407 | {
|
---|
408 | //cerr << "Applying transform: " << (x - x0) << ", " << (y - y0) << endl;
|
---|
409 | glTranslatef(pan[0], pan[1], pan[2]);
|
---|
410 | }
|
---|
411 |
|
---|
412 | void apply_inverse_transform()
|
---|
413 | {
|
---|
414 | //cerr << "Applying transform: " << (x - x0) << ", " << (y - y0) << endl;
|
---|
415 | glTranslatef(-pan[0], -pan[1], -pan[2]);
|
---|
416 | }
|
---|
417 |
|
---|
418 | matrix4f get_transform()
|
---|
419 | {
|
---|
420 | matrix4f m;
|
---|
421 | m.make_identity();
|
---|
422 | m.set_translate(pan);
|
---|
423 | return m;
|
---|
424 | }
|
---|
425 |
|
---|
426 | matrix4f get_inverse_transform()
|
---|
427 | {
|
---|
428 | matrix4f m;
|
---|
429 | m.make_identity();
|
---|
430 | m.set_translate(-pan);
|
---|
431 | return m;
|
---|
432 | }
|
---|
433 |
|
---|
434 |
|
---|
435 | bool invert_increment;
|
---|
436 | const rotationf * parent_rotation;
|
---|
437 | vec3f pan;
|
---|
438 | float scale;
|
---|
439 | };
|
---|
440 |
|
---|
441 |
|
---|
442 | class glut_dolly : public glut_simple_interactor
|
---|
443 | {
|
---|
444 | public:
|
---|
445 | glut_dolly()
|
---|
446 | {
|
---|
447 | scale = .01f;
|
---|
448 | invert_increment = false;
|
---|
449 | parent_rotation = 0;
|
---|
450 | }
|
---|
451 | void update()
|
---|
452 | {
|
---|
453 | vec3f v(0,0,dy);
|
---|
454 | if(parent_rotation != 0) parent_rotation->mult_vec(v);
|
---|
455 |
|
---|
456 | if(invert_increment)
|
---|
457 | dolly += v * scale;
|
---|
458 | else
|
---|
459 | dolly -= v * scale;
|
---|
460 | glutPostRedisplay();
|
---|
461 | }
|
---|
462 |
|
---|
463 | void apply_transform()
|
---|
464 | {
|
---|
465 | //cerr << "Applying transform: " << (x - x0) << ", " << (y - y0) << endl;
|
---|
466 | glTranslatef(dolly[0], dolly[1], dolly[2]);
|
---|
467 | }
|
---|
468 |
|
---|
469 | void apply_inverse_transform()
|
---|
470 | {
|
---|
471 | //cerr << "Applying transform: " << (x - x0) << ", " << (y - y0) << endl;
|
---|
472 | glTranslatef(-dolly[0], -dolly[1], -dolly[2]);
|
---|
473 | }
|
---|
474 |
|
---|
475 | matrix4f get_transform()
|
---|
476 | {
|
---|
477 | matrix4f m;
|
---|
478 | m.make_identity();
|
---|
479 | m.set_translate(dolly);
|
---|
480 | return m;
|
---|
481 | }
|
---|
482 |
|
---|
483 | matrix4f get_inverse_transform()
|
---|
484 | {
|
---|
485 | matrix4f m;
|
---|
486 | m.make_identity();
|
---|
487 | m.set_translate(-dolly);
|
---|
488 | return m;
|
---|
489 | }
|
---|
490 |
|
---|
491 |
|
---|
492 | bool invert_increment;
|
---|
493 | const rotationf * parent_rotation;
|
---|
494 | vec3f dolly;
|
---|
495 | float scale;
|
---|
496 | };
|
---|
497 |
|
---|
498 |
|
---|
499 | class glut_trackball : public glut_simple_interactor
|
---|
500 | {
|
---|
501 | public:
|
---|
502 | glut_trackball()
|
---|
503 | {
|
---|
504 | r = rotationf(vec3f(0, 1, 0), 0);
|
---|
505 | centroid = vec3f(0,0,0);
|
---|
506 | scale = 1;
|
---|
507 | invert_increment = false;
|
---|
508 | parent_rotation = 0;
|
---|
509 | legacy_mode = false;
|
---|
510 | }
|
---|
511 |
|
---|
512 | void update()
|
---|
513 | {
|
---|
514 | if(dx == 0 && dy == 0)
|
---|
515 | {
|
---|
516 | incr = rotationf();
|
---|
517 | return;
|
---|
518 | }
|
---|
519 |
|
---|
520 | if(legacy_mode)
|
---|
521 | {
|
---|
522 | vec3f v(dy, -dx, 0);
|
---|
523 | float len = v.normalize();
|
---|
524 | if(parent_rotation != 0) parent_rotation->mult_vec(v);
|
---|
525 | //r.mult_dir(vec3f(v), v);
|
---|
526 | if(invert_increment)
|
---|
527 | incr.set_value(v, -len * scale * -.01);
|
---|
528 | else
|
---|
529 | incr.set_value(v, len * scale * -.01);
|
---|
530 | }
|
---|
531 | else
|
---|
532 | {
|
---|
533 | float min = width < height ? width : height;
|
---|
534 | min /= 2.f;
|
---|
535 | vec3f offset(width/2.f, height/2.f, 0);
|
---|
536 | vec3f a(x-dx, height - (y+dy), 0);
|
---|
537 | vec3f b( x, height - y , 0);
|
---|
538 | a -= offset;
|
---|
539 | b -= offset;
|
---|
540 | a /= min;
|
---|
541 | b /= min;
|
---|
542 |
|
---|
543 | a[2] = pow(2.0f, -0.5f * a.length());
|
---|
544 | a.normalize();
|
---|
545 | b[2] = pow(2.0f, -0.5f * b.length());
|
---|
546 | b.normalize();
|
---|
547 |
|
---|
548 |
|
---|
549 | vec3f axis = a.cross(b);
|
---|
550 | axis.normalize();
|
---|
551 |
|
---|
552 | float angle = acos(a.dot(b));
|
---|
553 |
|
---|
554 | if(parent_rotation != 0) parent_rotation->mult_vec(axis);
|
---|
555 |
|
---|
556 | if(invert_increment)
|
---|
557 | incr.set_value(axis, -angle * scale);
|
---|
558 | else
|
---|
559 | incr.set_value(axis, angle * scale);
|
---|
560 |
|
---|
561 | }
|
---|
562 |
|
---|
563 | // fixme: shouldn't operator*() preserve 'r' in this case?
|
---|
564 | if(incr[3] != 0)
|
---|
565 | r = incr * r;
|
---|
566 | glutPostRedisplay();
|
---|
567 | }
|
---|
568 |
|
---|
569 | void increment_rotation()
|
---|
570 | {
|
---|
571 | if(active) return;
|
---|
572 | // fixme: shouldn't operator*() preserve 'r' in this case?
|
---|
573 | if(incr[3] != 0)
|
---|
574 | r = incr * r;
|
---|
575 | glutPostRedisplay();
|
---|
576 | }
|
---|
577 |
|
---|
578 | void apply_transform()
|
---|
579 | {
|
---|
580 | glTranslatef(centroid[0], centroid[1], centroid[2]);
|
---|
581 | glh_rotate(r);
|
---|
582 | glTranslatef(-centroid[0], -centroid[1], -centroid[2]);
|
---|
583 | }
|
---|
584 |
|
---|
585 | void apply_inverse_transform()
|
---|
586 | {
|
---|
587 | glTranslatef(centroid[0], centroid[1], centroid[2]);
|
---|
588 | glh_rotate(r.inverse());
|
---|
589 | glTranslatef(-centroid[0], -centroid[1], -centroid[2]);
|
---|
590 | }
|
---|
591 |
|
---|
592 |
|
---|
593 | matrix4f get_transform()
|
---|
594 | {
|
---|
595 | matrix4f mt, mr, minvt;
|
---|
596 | mt.set_translate(centroid);
|
---|
597 | r.get_value(mr);
|
---|
598 | minvt.set_translate(-centroid);
|
---|
599 | return mt * mr * minvt;
|
---|
600 | }
|
---|
601 |
|
---|
602 | matrix4f get_inverse_transform()
|
---|
603 | {
|
---|
604 | matrix4f mt, mr, minvt;
|
---|
605 | mt.set_translate(centroid);
|
---|
606 | r.inverse().get_value(mr);
|
---|
607 | minvt.set_translate(-centroid);
|
---|
608 | return mt * mr * minvt;
|
---|
609 | }
|
---|
610 |
|
---|
611 | bool invert_increment;
|
---|
612 | const rotationf * parent_rotation;
|
---|
613 | rotationf r;
|
---|
614 | vec3f centroid;
|
---|
615 | float scale;
|
---|
616 | bool legacy_mode;
|
---|
617 | rotationf incr;
|
---|
618 | };
|
---|
619 |
|
---|
620 |
|
---|
621 | class glut_rotate : public glut_simple_interactor
|
---|
622 | {
|
---|
623 | public:
|
---|
624 | glut_rotate()
|
---|
625 | {
|
---|
626 | rotate_x = rotate_y = 0;
|
---|
627 | scale = 1;
|
---|
628 | }
|
---|
629 | void update()
|
---|
630 | {
|
---|
631 | rotate_x += dx * scale;
|
---|
632 | rotate_y += dy * scale;
|
---|
633 | glutPostRedisplay();
|
---|
634 | }
|
---|
635 |
|
---|
636 | void apply_transform()
|
---|
637 | {
|
---|
638 | glRotatef(rotate_x, 0, 1, 0);
|
---|
639 | glRotatef(rotate_y, -1, 0, 0);
|
---|
640 | }
|
---|
641 |
|
---|
642 | void apply_inverse_transform()
|
---|
643 | {
|
---|
644 | glRotatef(-rotate_y, -1, 0, 0);
|
---|
645 | glRotatef(-rotate_x, 0, 1, 0);
|
---|
646 | }
|
---|
647 |
|
---|
648 | matrix4f get_transform()
|
---|
649 | {
|
---|
650 | rotationf rx(to_radians(rotate_x), 0, 1, 0);
|
---|
651 | rotationf ry(to_radians(rotate_y), -1, 0, 0);
|
---|
652 | matrix4f mx, my;
|
---|
653 | rx.get_value(mx);
|
---|
654 | ry.get_value(my);
|
---|
655 | return mx * my;
|
---|
656 | }
|
---|
657 |
|
---|
658 | matrix4f get_inverse_transform()
|
---|
659 | {
|
---|
660 | rotationf rx(to_radians(-rotate_x), 0, 1, 0);
|
---|
661 | rotationf ry(to_radians(-rotate_y), -1, 0, 0);
|
---|
662 | matrix4f mx, my;
|
---|
663 | rx.get_value(mx);
|
---|
664 | ry.get_value(my);
|
---|
665 | return my * mx;
|
---|
666 | }
|
---|
667 |
|
---|
668 | float rotate_x, rotate_y, scale;
|
---|
669 | };
|
---|
670 |
|
---|
671 | class glut_mouse_to_keyboard : public glut_simple_interactor
|
---|
672 | {
|
---|
673 | public:
|
---|
674 | glut_mouse_to_keyboard()
|
---|
675 | {
|
---|
676 | keyboard_function = 0;
|
---|
677 | pos_dx_key = neg_dx_key = pos_dy_key = neg_dy_key = 0;
|
---|
678 | }
|
---|
679 | void apply_transform() {}
|
---|
680 |
|
---|
681 | void apply_inverse_transform() {}
|
---|
682 |
|
---|
683 | matrix4f get_transform() {return matrix4f();}
|
---|
684 |
|
---|
685 | matrix4f get_inverse_transform() {return matrix4f();}
|
---|
686 |
|
---|
687 | void update()
|
---|
688 | {
|
---|
689 | if(!keyboard_function) return;
|
---|
690 | if(dx > 0)
|
---|
691 | keyboard_function(pos_dx_key, x, y);
|
---|
692 | else if(dx < 0)
|
---|
693 | keyboard_function(neg_dx_key, x, y);
|
---|
694 | if(dy > 0)
|
---|
695 | keyboard_function(pos_dy_key, x, y);
|
---|
696 | else if(dy < 0)
|
---|
697 | keyboard_function(neg_dy_key, x, y);
|
---|
698 | }
|
---|
699 | unsigned char pos_dx_key, neg_dx_key, pos_dy_key, neg_dy_key;
|
---|
700 | void (*keyboard_function)(unsigned char, int, int);
|
---|
701 | };
|
---|
702 |
|
---|
703 | inline void glut_exit_on_escape(unsigned char k, int x = 0, int y = 0)
|
---|
704 | { if(k==27) exit(0); }
|
---|
705 |
|
---|
706 | struct glut_simple_mouse_interactor : public glut_interactor
|
---|
707 | {
|
---|
708 |
|
---|
709 | public:
|
---|
710 | glut_simple_mouse_interactor(int num_buttons_to_use=3)
|
---|
711 | {
|
---|
712 | configure_buttons(num_buttons_to_use);
|
---|
713 | camera_mode = false;
|
---|
714 | }
|
---|
715 |
|
---|
716 | void enable()
|
---|
717 | {
|
---|
718 | trackball.enable();
|
---|
719 | pan.enable();
|
---|
720 | dolly.enable();
|
---|
721 | }
|
---|
722 |
|
---|
723 | void disable()
|
---|
724 | {
|
---|
725 | trackball.disable();
|
---|
726 | pan.disable();
|
---|
727 | dolly.disable();
|
---|
728 | }
|
---|
729 |
|
---|
730 | void set_camera_mode(bool cam)
|
---|
731 | {
|
---|
732 | camera_mode = cam;
|
---|
733 | if(camera_mode)
|
---|
734 | {
|
---|
735 | trackball.invert_increment = true;
|
---|
736 | pan.invert_increment = true;
|
---|
737 | dolly.invert_increment = true;
|
---|
738 | pan.parent_rotation = & trackball.r;
|
---|
739 | dolly.parent_rotation = & trackball.r;
|
---|
740 | }
|
---|
741 | else
|
---|
742 | {
|
---|
743 | trackball.invert_increment = false;
|
---|
744 | pan.invert_increment = false;
|
---|
745 | dolly.invert_increment = false;
|
---|
746 | if(pan.parent_rotation == &trackball.r) pan.parent_rotation = 0;
|
---|
747 | if(dolly.parent_rotation == &trackball.r) dolly.parent_rotation = 0;
|
---|
748 | }
|
---|
749 | }
|
---|
750 | void configure_buttons(int num_buttons_to_use = 3)
|
---|
751 | {
|
---|
752 | switch(num_buttons_to_use)
|
---|
753 | {
|
---|
754 | case 1:
|
---|
755 | trackball.activate_on = GLUT_LEFT_BUTTON;
|
---|
756 | trackball.modifiers = 0;
|
---|
757 |
|
---|
758 | pan.activate_on = GLUT_LEFT_BUTTON;
|
---|
759 | pan.modifiers = GLUT_ACTIVE_SHIFT;
|
---|
760 |
|
---|
761 |
|
---|
762 | dolly.activate_on = GLUT_LEFT_BUTTON;
|
---|
763 | dolly.modifiers = GLUT_ACTIVE_CTRL;
|
---|
764 |
|
---|
765 | break;
|
---|
766 |
|
---|
767 | case 2:
|
---|
768 | trackball.activate_on = GLUT_LEFT_BUTTON;
|
---|
769 | trackball.modifiers = 0;
|
---|
770 |
|
---|
771 | pan.activate_on = GLUT_MIDDLE_BUTTON;
|
---|
772 | pan.modifiers = 0;
|
---|
773 |
|
---|
774 |
|
---|
775 | dolly.activate_on = GLUT_LEFT_BUTTON;
|
---|
776 | dolly.modifiers = GLUT_ACTIVE_CTRL;
|
---|
777 |
|
---|
778 | break;
|
---|
779 |
|
---|
780 | case 3:
|
---|
781 | default:
|
---|
782 | trackball.activate_on = GLUT_LEFT_BUTTON;
|
---|
783 | trackball.modifiers = 0;
|
---|
784 |
|
---|
785 | pan.activate_on = GLUT_MIDDLE_BUTTON;
|
---|
786 | pan.modifiers = 0;
|
---|
787 |
|
---|
788 | dolly.activate_on = GLUT_RIGHT_BUTTON;
|
---|
789 | dolly.modifiers = 0;
|
---|
790 |
|
---|
791 | break;
|
---|
792 | }
|
---|
793 | }
|
---|
794 |
|
---|
795 | virtual void motion(int x, int y)
|
---|
796 | {
|
---|
797 |
|
---|
798 | trackball.motion(x,y);
|
---|
799 |
|
---|
800 | pan.motion(x,y);
|
---|
801 |
|
---|
802 | dolly.motion(x,y);
|
---|
803 | }
|
---|
804 | virtual void mouse(int button, int state, int x, int y)
|
---|
805 | {
|
---|
806 | trackball.mouse(button, state, x, y);
|
---|
807 | pan.mouse(button, state, x, y);
|
---|
808 | dolly.mouse(button, state, x, y);
|
---|
809 | }
|
---|
810 |
|
---|
811 | virtual void reshape(int x, int y)
|
---|
812 | {
|
---|
813 | trackball.reshape(x,y);
|
---|
814 | pan.reshape(x,y);
|
---|
815 | dolly.reshape(x,y);
|
---|
816 | }
|
---|
817 |
|
---|
818 | void apply_transform()
|
---|
819 | {
|
---|
820 | pan.apply_transform();
|
---|
821 | dolly.apply_transform();
|
---|
822 | trackball.apply_transform();
|
---|
823 | }
|
---|
824 |
|
---|
825 | void apply_inverse_transform()
|
---|
826 | {
|
---|
827 | trackball.apply_inverse_transform();
|
---|
828 | dolly.apply_inverse_transform();
|
---|
829 | pan.apply_inverse_transform();
|
---|
830 | }
|
---|
831 |
|
---|
832 | matrix4f get_transform()
|
---|
833 | {
|
---|
834 | return ( pan.get_transform() *
|
---|
835 | dolly.get_transform() *
|
---|
836 | trackball.get_transform() );
|
---|
837 | }
|
---|
838 |
|
---|
839 | matrix4f get_inverse_transform()
|
---|
840 | {
|
---|
841 | return ( trackball.get_inverse_transform() *
|
---|
842 | dolly.get_inverse_transform() *
|
---|
843 | pan.get_inverse_transform() );
|
---|
844 | }
|
---|
845 |
|
---|
846 | void set_parent_rotation(rotationf *rp)
|
---|
847 | {
|
---|
848 | trackball.parent_rotation = rp;
|
---|
849 | dolly.parent_rotation = rp;
|
---|
850 | pan.parent_rotation = rp;
|
---|
851 | }
|
---|
852 |
|
---|
853 | bool camera_mode;
|
---|
854 | glut_trackball trackball;
|
---|
855 | glut_pan pan;
|
---|
856 | glut_dolly dolly;
|
---|
857 | };
|
---|
858 |
|
---|
859 | }
|
---|
860 |
|
---|
861 | #endif
|
---|