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