-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathagviewer.h
326 lines (263 loc) · 9.4 KB
/
agviewer.h
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
/*
* fracviewer.h [from agviewer.h (version 1.0)]
*
* AGV: a glut viewer. Routines for viewing a 3d scene w/ glut
*
* The two view movement modes are POLAR and FLYING. Both move the eye, NOT
* THE OBJECT. You can never be upside down or twisted (roll) in either mode.
*
* A nice addition would be an examiner type trackball mode where you are
* moving the object and so could see it from any angle. Also less restricted
* flying and polar modes (fly upside down, do rolls, etc.).
*
* Controls for Polar are just left and middle buttons -- for flying it's
* those plus 0-9 number keys and +/- for speed adjustment.
*
* See agv_example.c and agviewer.c for more info. Probably want to make
* a copy of these and then edit for each program. This isn't meant to be
* a library, just something to graft onto your own programs.
*
* I welcome any feedback or improved versions.
*
* Philip Winston - 4/11/95
* http://www.cs.hmc.edu/people/pwinston
*/
/*
* move (mostly) all into one class - Kai-Uwe Behrmann 2004 - 2005
*
*/
#ifndef AGVIEWER_H
#define AGVIEWER_H
#include "icc_utils.h" // ICC Examin
#if __APPLE__
# include <OpenGL/glu.h>
#else
# include <GL/glu.h> // added for FLTK
#endif
#include "icc_model_observer.h"
class GL_View;
class Agviewer : public icc_examin_ns::Model
{
public:
GL_View* parent;
Agviewer (GL_View* p) {
parent = p;
/***************************************************************/
/************************** SETTINGS ***************************/
/***************************************************************/
/* Initial polar movement settings */
init_polar_az = 90.0;
init_polar_el = 90.0;
init_dist = init_dist_a = init_dist_b = 4.74;
init_az_spin = 0.0;
init_el_spin = 0.0;
/* Start in this mode */
MoveMode = POLAR; /* FLYING or POLAR mode? */
/* Initial flying movement settings */
init_move = 0.01;
minmove = 0.001;
Ex = 0.0; /* flying parameters */
Ey = -2.0;
Ez = -2.0;
EyeMove = (GLfloat)init_move;
EyeDist = (GLfloat)init_dist; /* polar params */
AzSpin = (GLfloat)init_az_spin;
ElSpin = (GLfloat)init_el_spin;
EyeAz = (GLfloat)init_polar_az; /* used by both */
EyeEl = (GLfloat)init_polar_el;
/* Multiply EyeMove by (1+-movefraction) when +/- hit in FLYING mode */
movefraction = 0.25;
/* What to multiply number of pixels mouse moved by to get rotation amount */
el_sens = 0.5;
az_sens = 0.5;
/* What to multiply number of pixels mouse moved by for movement amounts */
dist_sens = 0.01;
e_sens = 0.01;
/* Minimum spin to allow in polar (lower forced to zero) */
min_azspin = 0.1;
min_elspin = 0.1;
/* Factors used in computing dAz and dEl (which determine AzSpin, ElSpin) */
slow_daz = 0.90;
slow_del = 0.90;
prev_daz = 0.80;
prev_del = 0.80;
cur_daz = 0.20;
cur_del = 0.20;
downb = -1;
AdjustingAzEl = 0;
can_move_ = false;
thin = false;
}
void reparent( GL_View* p ) { parent = p; }
~Agviewer () {; }
/*
* Call agvInit() with glut's current window set to the window in
* which you want to run the viewer. Right after creating it is fine. It
* will remember that window for possible later use (see below) and
* registers mouse, motion, and keyboard handlers for that window (see below).
*
* allowidle is 1 or 0 depnding on whether you will let AGV install
* and uninstall an idle function. 0 means you will not let it (because
* you will be having your own idle function). In this case it is your
* responsibility to put a statement like:
*
* if (agvMoving)
* agvMove();
*
* at the end of your idle function, to let AGV update the viewpoint if it
* is moving.
*
* If allowidle is 1 it means AGV will install its own idle which
* will update the viewpoint as needed and send glutPostRedisplay() to the
* window which was current when agvInit() was called.
*
* agvSetIdleAllow changes this value so you can let AGV install its idle
* when your idle isn't installed.
*
*/
void agvInit(int allowidle);
void agvSetAllowIdle(int allowidle);
/*
* Set which movement mode you are in.
*/
typedef enum {
FLYING = 100,
POLAR ,
ICCPOLAR ,
ICCFLY_L,
ICCFLY_a,
ICCFLY_b,
AGV_STOP
} MovementType;
void agvSwitchMoveMode(int move);
// thin slice visualisation
bool thin;
/*
* agvViewTransform basically does the appropriate gluLookAt() for the
* current position. So call it in your display on the projection matrix
*/
void agvViewTransform(void);
/*
* agvMoving will be set by AGV according to whether it needs you to call
* agvMove() at the end of your idle function. You only need these if
* you aren't allowing AGV to do its own idle.
* (Don't change the value of agvMoving)
*/
int agvMoving; /* Currently moving? */
void agvMove_(void);
//static void agvMove_statisch(void* agv);
//! allow to rotate
bool can_move_;
/*
* These are the routines AGV registers to deal with mouse and keyboard input.
* Keyboard input only matters in flying mode, and then only to set speed.
* Mouse input only uses left two buttons in both modes.
* These are all registered with agvInit(), but you could register
* something else which called these, or reregister these as needed
*/
void agvHandleButton(int button, int event, int x, int y);
void agvHandleMotion(int x, int y);
void agvHandleKeys_(unsigned char key, int &x, int &y);
/*
* Just an extra routine which makes an x-y-z axes (about 10x10x10)
* which is nice for aligning things and debugging. Pass it an available
* displaylist number.
*/
void agvMakeAxesList(int displaylist);
private:
/* map 0-9 to an EyeMove value when number key is hit in FLYING mode */
#define SPEEDFUNCTION(x) ((x)*(x)*0.001)
double movefraction,
el_sens,
az_sens,
dist_sens,
e_sens,
min_azspin,
min_elspin,
slow_daz,
slow_del,
prev_daz,
prev_del,
cur_daz,
cur_del;
/***************************************************************/
/************************** GLOBALS ****************************/
/***************************************************************/
int MoveMode; /* FLYING or POLAR mode? */
GLfloat Ex, /* flying parameters */
Ey,
Ez,
EyeMove,
EyeDist, /* polar params */
AzSpin,
ElSpin,
EyeAz, /* used by both */
EyeEl;
int downx, downy, /* for tracking mouse position */
lastx, lasty,
downb; /* and button status */
GLfloat downDist, downEl, downAz, /* for saving state of things */
downEx, downEy, downEz, /* when button is pressed */
downEyeMove;
GLfloat dAz, dEl, lastAz, lastEl; /* to calculate spinning w/ polar motion */
int AdjustingAzEl;
/* Initial polar movement settings */
double init_polar_az,
init_polar_el,
init_dist,
init_dist_a,
init_dist_b,
init_az_spin,
init_el_spin,
init_move,
minmove;
public:
float eyeX () const { return Ex; } // ICC Examin
float eyeY () const { return Ey; } // ICC Examin
float eyeZ () const { return Ez; } // ICC Examin
float eyeDist () const { return EyeDist; } // ICC Examin
void eyeDist(double d) { EyeDist = (GLfloat)d; }
float eyeAzimuth () const { return EyeAz; } // ICC Examin
float eyeElevation () const { return EyeEl; } // ICC Examin
void distA(double a) { init_dist_a = a; }
void distB(double b) { init_dist_b = b; }
double distA() { return init_dist_a; }
double distB() { return init_dist_b; }
double dist() { return init_dist; }
int RedisplayWindow; // glutWindow
public:
int redisplayWindow() { return RedisplayWindow; }
void setIdle(bool set);
/* send all observers a draw message */
void notify (int infos)
{ icc_examin_ns::Model::notify( infos ); }
private:
/* If AllowIdle is 1 it means AGV will install its own idle which
* will update the viewpoint as needed and send glutPostRedisplay() to the
* window RedisplayWindow which was set in agvInit(). AllowIdle of 0
* means AGV won't install an idle funciton, and something like
* "if (agvMoving) agvMove()" should exist at the end of the running
* idle function.
*/
# define TORAD(x) ((M_PI/180.0)*(x))
# define TODEG(x) ((180.0/M_PI)*(x))
/***************************************************************/
/************************ PROTOTYPES ***************************/
/***************************************************************/
/*
* these are functions meant for internal use only
* the other prototypes are in agviewer.h
*/
void PolarLookFrom(GLfloat dist, GLfloat elevation, GLfloat azimuth);
void FlyLookFrom(GLfloat x, GLfloat y, GLfloat z,
GLfloat az, GLfloat el);
int ConstrainEl(void);
void MoveOn(int v);
void SetMove(float newmove);
void normalize(GLfloat v[3]);
void ncrossprod(float v1[3], float v2[3], float cp[3]);
};
namespace agv {
}
#endif // AGVIEWER_H