36 files changed, 332 insertions, 176 deletions
diff --git a/src/controller/callbacks/mouse.c b/src/controller/callbacks/mouse.c new file mode 100644 index 0000000..fc48eff --- a/dev/null +++ b/src/controller/callbacks/mouse.c | |||
@@ -0,0 +1,127 @@ | |||
1 | #include "../../util/check_error.h" | ||
2 | #include "../../util/pick_convert.h" | ||
3 | #include "../../view/exp004geometry.h" | ||
4 | #include "../../view/exp004state0.h" | ||
5 | #include "../actions/process_hits.h" | ||
6 | #include "../actions/set_ortho.h" | ||
7 | #include "../actions/zoom.h" | ||
8 | #include "mouse.h" | ||
9 | #include "reshape.h" | ||
10 | #include <GL/glut.h> | ||
11 | #include <math.h> | ||
12 | #include <stdlib.h> | ||
13 | |||
14 | /* | ||
15 | * A simple alias to make the code more readable. | ||
16 | */ | ||
17 | #define S exp004state0 | ||
18 | |||
19 | void | ||
20 | mouse (int button, int state, int x, int y) | ||
21 | { | ||
22 | if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) | ||
23 | { | ||
24 | if (S.selection.active && S.selection.purpose == ZOOM) | ||
25 | { | ||
26 | /* | ||
27 | * NOOP if the mouse was not moved. | ||
28 | */ | ||
29 | if (x == S.selection.x || y == S.selection.y) | ||
30 | return; | ||
31 | |||
32 | GLint viewport[4]; | ||
33 | glGetIntegerv (GL_VIEWPORT, viewport); | ||
34 | |||
35 | zoom (S.selection.x, | ||
36 | viewport[3] - S.selection.y, | ||
37 | x, | ||
38 | viewport[3] - y); | ||
39 | } | ||
40 | |||
41 | /* | ||
42 | * Complete a selection if one was started and not cancelled. | ||
43 | */ | ||
44 | if (S.selection.active && S.selection.purpose == SET) | ||
45 | { | ||
46 | |||
47 | /* | ||
48 | * "Specify the array to be used for the returned hit records | ||
49 | * with glSelectBuffer () [Redbook]." | ||
50 | */ | ||
51 | GLuint *select_buf = calloc (S.rows, sizeof (GLuint)); | ||
52 | glSelectBuffer (S.rows, select_buf); | ||
53 | |||
54 | /* | ||
55 | * "Enter selection mode by specifying GL_SELECT with | ||
56 | * glRenderMode () [Redbook]." | ||
57 | */ | ||
58 | glRenderMode (GL_SELECT); | ||
59 | |||
60 | /* | ||
61 | * "Initialize the name stack using glInitNames () and glPush | ||
62 | * Names () [Redbook]." | ||
63 | */ | ||
64 | glInitNames (); | ||
65 | glPushName (0); | ||
66 | |||
67 | /* | ||
68 | * "Define the viewing volume you want to use for selection. | ||
69 | * Usually this is different from the viewing volume you | ||
70 | * originally used to draw the scene, so you probably want to | ||
71 | * save and then restore the current transformation state with | ||
72 | * glPushMatrix () and glPopMatrix () [Redbook]." | ||
73 | */ | ||
74 | glMatrixMode (GL_PROJECTION); | ||
75 | glPushMatrix (); | ||
76 | glLoadIdentity (); | ||
77 | |||
78 | GLint viewport[4]; | ||
79 | glGetIntegerv (GL_VIEWPORT, viewport); | ||
80 | |||
81 | double c_x = 0.0; | ||
82 | double c_y = 0.0; | ||
83 | double w = 0.0; | ||
84 | double h = 0.0; | ||
85 | pick_convert (S.selection.x, S.selection.y, x, y, | ||
86 | &c_x, &c_y, &w, &h); | ||
87 | |||
88 | gluPickMatrix (c_x, (GLdouble) viewport[3] - c_y, w, h, viewport); | ||
89 | |||
90 | set_ortho (); | ||
91 | |||
92 | /* | ||
93 | * "Alternately issue primitive drawing commands and commands to | ||
94 | * manipulate the name stack so that each primitive of interest | ||
95 | * has appropriate names assigned [Redbook]." | ||
96 | */ | ||
97 | exp004geometry (GL_SELECT); | ||
98 | |||
99 | glMatrixMode (GL_PROJECTION); | ||
100 | glPopMatrix (); | ||
101 | glutSwapBuffers (); | ||
102 | |||
103 | /* | ||
104 | * "Exit selection mode and process the returned selection data | ||
105 | * (the hit records) [Redbook]." | ||
106 | */ | ||
107 | GLint hits = glRenderMode (GL_RENDER); | ||
108 | check_error (__FILE__, __LINE__); | ||
109 | |||
110 | /* "process hits from selection mode rendering [Angel,2008]." */ | ||
111 | process_hits (hits, select_buf); | ||
112 | |||
113 | /* "normal render [Angel,2008]." */ | ||
114 | glutPostRedisplay (); | ||
115 | } | ||
116 | |||
117 | } | ||
118 | |||
119 | if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) | ||
120 | { | ||
121 | S.selection.active = true; | ||
122 | S.selection.x = x; | ||
123 | S.selection.y = y; | ||
124 | } | ||
125 | |||
126 | return; | ||
127 | } | ||