1 #include "medit.h"
2 #include "extern.h"
3 #include "sproto.h"
4
5 #ifndef ON
6 #define ON 1
7 #define OFF 0
8 #endif
9
10
11 GLuint lasttime;
12 GLboolean tracking = GL_FALSE,ctracking = GL_FALSE;
13 GLboolean picking = GL_FALSE;
14 int cbutton = 0;
15 int startx,starty,curx,cury;
16 int rxi,ryi,rx1,rx2,ry1,ry2;
17
18 #define MinWH 0.1
19 #define MaxWH 0.9
20
21 #ifndef GLUT_BUTTON_3
22 #define GLUT_BUTTON_3 2
23 #define GLUT_BUTTON_4 3
24 #endif
25
26 /* project x,y, onto a hemi-sphere */
point2Vect(int x,int y,int w,int h,float * v)27 static void point2Vect(int x,int y,int w,int h,float *v) {
28 double d,a,areax,areay;
29
30 areax = (w-startx) / w;
31 areay = (h-starty) / h;
32 if ( areax > MinWH && areax < MaxWH && areay > MinWH && areay < MaxWH ) {
33 v[0] = (2.0 * x - w) / w;
34 v[1] = (h - 2.0 * y) / h;
35 v[2] = 1.0f;
36 }
37 else {
38 v[0] = 2.0f*(x-startx) / w;
39 v[1] = -2.0f*(y-starty) / h;
40 v[2] = 1.0f;
41 }
42 d = v[0]*v[0]+v[1]*v[1];
43 if ( d == 0.0f ) return;
44 d = sqrt(d);
45
46 v[2] = cos(M_PI_2 * ((d < 1.0) ? d : 1.0));
47 d = v[0]*v[0]+v[1]*v[1]+v[2]*v[2];
48 a = 1.0f / sqrt(d);
49 v[0] *= a;
50 v[1] *= a;
51 v[2] *= a;
52 }
53
54
ortho2D(pScene sc,ubyte mode)55 void ortho2D(pScene sc,ubyte mode) {
56 if ( mode == ON ) {
57 glMatrixMode(GL_PROJECTION);
58 glPushMatrix();
59 glLoadIdentity();
60 gluOrtho2D(0,sc->par.xs,0.,sc->par.ys);
61 glDisable(GL_LIGHTING);
62 glDisable(GL_DEPTH_TEST);
63 glMatrixMode(GL_MODELVIEW);
64 }
65 else if ( mode == OFF ) {
66 glMatrixMode(GL_PROJECTION);
67 glPopMatrix();
68 glMatrixMode(GL_MODELVIEW);
69 glEnable(GL_DEPTH_TEST);
70 glLineWidth(1.);
71 }
72 }
73
drawRubberBand(int xa,int ya,int xb,int yb)74 static void drawRubberBand(int xa,int ya,int xb,int yb) {
75 glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
76 glLineWidth(2.0);
77 glColor3f(0.5,0.5,0.5);
78 glRecti(xa,ya,xb,yb);
79 }
80
rubberMotion(int x,int y)81 static void rubberMotion(int x,int y) {
82 pScene sc;
83 pPersp p;
84
85 sc = cv.scene[currentScene()];
86 p = sc->persp;
87
88 glEnable(GL_COLOR_LOGIC_OP);
89 glLogicOp(GL_XOR);
90
91 /* draw frame */
92 drawRubberBand(rxi,ryi,rx1,ry1);
93 rx2 = x;
94 ry2 = sc->par.ys-y;
95 drawRubberBand(rxi,ryi,rx2,ry2);
96 glFlush();
97
98 glLogicOp(GL_COPY);
99 glDisable(GL_COLOR_LOGIC_OP);
100
101 /* keep old coords */
102 rx1 = rx2;
103 ry1 = ry2;
104 }
105
106
zoomMotion(int x,int y)107 void zoomMotion(int x,int y) {
108 pScene sc;
109 pPersp p;
110 int dy;
111
112 sc = cv.scene[currentScene()];
113 p = sc->persp;
114
115 dy = starty - y;
116 if ( dy > 0 )
117 if ( p->fovy < 1.0e-02 )
118 return;
119 else
120 p->fovy = max(0.95*p->fovy,1e-05);
121 else if ( p->fovy > 160.0 ) return;
122 else
123 p->fovy = min(1.1*p->fovy,179.0);
124
125 farclip(1);
126 starty = y;
127 glutPostRedisplay();
128 }
129
130
mouse(int button,int state,int x,int y)131 void mouse(int button,int state,int x,int y) {
132 pScene sc;
133 pTransform tr;
134 pPersp p;
135 int keyact,idw = currentScene();
136 static int olds = -1;
137
138 picking=GL_FALSE;
139
140 /* default */
141 if ( ddebug ) printf("control mouse %d\n",state);
142 sc = cv.scene[idw];
143 p = sc->persp;
144 if ( sc->cube->active & C_EDIT )
145 tr = sc->cube->cubetr;
146 else if ( sc->clip->active & C_EDIT )
147 tr = sc->clip->cliptr;
148 else
149 tr = sc->view;
150 tr->mstate = state;
151 tr->mbutton = button;
152
153 /* check if ctrl-shift-alt pressed */
154 keyact = glutGetModifiers();
155
156 if ( state == GLUT_DOWN ) {
157 tracking = GL_TRUE;
158 lasttime = glutGet(GLUT_ELAPSED_TIME);
159
160 if ( button == GLUT_LEFT_BUTTON ) {
161 if ( keyact & GLUT_ACTIVE_SHIFT ) {
162 /* entity designation */
163 picking = GL_TRUE;
164 if ( sc->picklist ) glDeleteLists(sc->picklist,1);
165 sc->picklist = pickingScene(sc,x,y,0);
166 return;
167 }
168
169 else if ( keyact & GLUT_ACTIVE_ALT ) {
170 /* zoom */
171 starty = y;
172 glutMotionFunc(zoomMotion);
173 return;
174 }
175
176 else if ( keyact & GLUT_ACTIVE_CTRL ) {
177 /* rubberband selection */
178 glutSetCursor(GLUT_CURSOR_CROSSHAIR);
179 p->rubix = p->rubfx = x;
180 p->rubiy = p->rubfy = sc->par.ys-y;
181 rxi = rx1 = x;
182 ryi = ry1 = sc->par.ys-y;
183 p->rubber = 1;
184 glDrawBuffer(GL_BACK_LEFT);
185 ortho2D(sc,ON);
186 glutMotionFunc(rubberMotion);
187 return;
188 }
189 }
190
191 else if ( button == GLUT_MIDDLE_BUTTON && keyact & GLUT_ACTIVE_SHIFT ) {
192 picking = GL_TRUE;
193 if ( sc->picklist ) glDeleteLists(sc->picklist,1);
194 sc->picklist = pickingScene(sc,x,y,LPoint);
195 return;
196 }
197
198 /* transformation */
199 startx = x;
200 starty = y;
201 point2Vect(x,y,sc->par.xs,sc->par.ys,tr->pos);
202 glutSetCursor(GLUT_CURSOR_INFO);
203 }
204
205 else if ( state == GLUT_UP ) {
206
207 if ( button == GLUT_LEFT_BUTTON ) {
208
209 if ( keyact & GLUT_ACTIVE_CTRL ) {
210 /* rubberband selection */
211 p->rubfx = x;
212 p->rubfy = sc->par.ys-y;
213 p->rubber = 2;
214 glDrawBuffer(GL_BACK_LEFT);
215 ortho2D(sc,OFF);
216 glutMotionFunc(motion);
217 return;
218 }
219
220 else if ( keyact & GLUT_ACTIVE_ALT ) {
221 glutMotionFunc(motion);
222 return;
223 }
224
225 else if ( picking == GL_TRUE ) {
226 picking = GL_FALSE;
227 reshapeScene(sc->par.xs,sc->par.ys);
228 glutPostRedisplay();
229 }
230 }
231
232 glutMotionFunc(motion);
233 if ( sc->clip->active & C_EDIT )
234 sc->clip->active |= C_REDO;
235
236 /* transformation */
237 glutSetCursor(GLUT_CURSOR_INHERIT);
238 tracking = GL_FALSE;
239 if ( glutGet(GLUT_ELAPSED_TIME) >= lasttime ) {
240 if ( tr->manim == GL_TRUE ) glutIdleFunc(glutIdle);
241 else tr->angle = 0.0;
242 /*if ( abs(startx-x) + abs(starty-y) > 0 )*/
243 glutPostRedisplay();
244 }
245 else if ( tr->manim == GL_TRUE && olds == idw )
246 glutIdleFunc(NULL);
247 }
248
249 olds = idw;
250 }
251
motion(int x,int y)252 void motion(int x,int y) {
253 pScene sc;
254 pTransform tr;
255 pPersp p;
256 GLuint gtime;
257 double deltax,deltay;
258 float coeff,pos[3],dx,dy,dz;
259 int idw = currentScene();
260
261 /* default */
262 if ( picking ) return;
263 if ( ddebug ) fprintf(stdout,"motion\n");
264
265 if ( tracking == GL_FALSE ) return;
266 sc = cv.scene[idw];
267 p = sc->persp;
268 if ( p->rubber == 1 ) return;
269
270 /* what is transformed ? */
271 if ( sc->cube->active & C_EDIT )
272 tr = sc->cube->cubetr;
273 else if ( sc->clip->active & C_EDIT )
274 tr = sc->clip->cliptr;
275 else
276 tr = sc->view;
277
278 if ( tr->mstate != GLUT_DOWN ) return;
279 if ( picking ) tr->angle = 0.0f;
280
281 gtime = glutGet(GLUT_ELAPSED_TIME);
282 if ( (animate || sc->type & S_FOLLOW) && gtime < lasttime+40 ) return;
283
284 if ( tr->mbutton == GLUT_LEFT_BUTTON ) {
285 /* calculate axis of rotation: cross product */
286 point2Vect(x,y,sc->par.xs,sc->par.ys,pos);
287 tr->axis[0] = tr->pos[1]*pos[2] - tr->pos[2]*pos[1];
288 tr->axis[1] = tr->pos[2]*pos[0] - tr->pos[0]*pos[2];
289 tr->axis[2] = tr->pos[0]*pos[1] - tr->pos[1]*pos[0];
290
291 /* calculate angle to rotate by */
292 if ( animate && saveimg )
293 tr->angle = 2.0f;
294 else {
295 dx = pos[0] - tr->pos[0];
296 dy = pos[1] - tr->pos[1];
297 dz = pos[2] - tr->pos[2];
298 tr->angle = 180.0*sqrt(dx*dx+dy*dy+dz*dz);
299 }
300
301 /* reset for next time */
302 tr->pos[0] = pos[0];
303 tr->pos[1] = pos[1];
304 tr->pos[2] = pos[2];
305 lasttime = gtime;
306
307 if ( sc->cube->active & C_ON && sc->cube->active & C_EDIT )
308 sc->cube->active |= C_UPDATE;
309 else if ( sc->clip->active & C_ON &&
310 (sc->clip->active & C_EDIT || sc->clip->active & C_FREEZE) )
311 sc->clip->active |= C_UPDATE;
312
313 glutPostRedisplay();
314 }
315
316 else if ( tr->mbutton == GLUT_MIDDLE_BUTTON ) {
317 coeff = tr->manim == GL_TRUE ? 0.2 : 2.0;
318 deltax = coeff * (x-startx) / (float)sc->par.xs;
319 deltay = coeff * (starty-y) / (float)sc->par.ys;
320
321 if ( deltax != 0.0 )
322 tr->panx += -deltax * p->depth * tan(p->fovy/360.*M_PI);
323 if ( deltay != 0.0 )
324 tr->pany += -deltay * p->depth * tan(p->fovy/360.*M_PI);
325 tr->angle = 0.0;
326 startx = x;
327 starty = y;
328
329 lasttime = gtime;
330 if ( sc->cube->active & C_ON && sc->cube->active & C_EDIT )
331 sc->cube->active |= C_UPDATE;
332 else if ( sc->clip->active & C_ON &&
333 (sc->clip->active & C_EDIT || sc->clip->active & C_FREEZE) )
334 sc->clip->active |= C_UPDATE;
335
336 glutPostRedisplay();
337 }
338 }
339
mouseCamera(int button,int state,int x,int y)340 void mouseCamera(int button,int state,int x,int y) {
341 /* default */
342 if ( ddebug ) printf("control mouse camera %d button %d\n",state,button);
343
344 cbutton = button;
345 if ( state == GLUT_DOWN ) {
346 ctracking = GL_TRUE;
347 startx = x;
348 starty = y;
349 curx = x;
350 cury = y;
351 }
352 else {
353 startx = x;
354 starty = y;
355 ctracking = GL_FALSE;
356 }
357 }
358
motionCamera(int x,int y)359 void motionCamera(int x,int y) {
360 pScene sc;
361 pCamera c;
362 double dazim,delev,azim,elev;
363 float cfelev,cfazim;
364
365 /* keep current pos */
366 curx = x;
367 cury = y;
368
369 if ( animate ) return;
370 sc = cv.scene[currentScene()];
371 c = sc->camera;
372 azim = Azimuth(c);
373 elev = Elevation(c);
374 switch (cbutton) {
375 case GLUT_LEFT_BUTTON:
376 cfelev = 50.0;
377 cfazim = 50.0;
378 delev = cfelev * (y-starty)/(float)sc->par.ys;
379 dazim = cfazim * (x-startx)/(float)sc->par.xs;
380 startx = x;
381 starty = y;
382 elev += delev;
383 azim -= dazim;
384 break;
385 case GLUT_MIDDLE_BUTTON:
386 break;
387 case GLUT_BUTTON_3:
388 puts("button3");
389 break;
390 case GLUT_BUTTON_4:
391 puts("button4");
392 break;
393 }
394 updateCamera(sc,c,azim,elev);
395 reshapeScene(sc->par.xs,sc->par.ys);
396 glutPostRedisplay();
397 }
398
399
animateCamera()400 void animateCamera() {
401 pScene sc;
402 pCamera c;
403 double dazim,delev,azim,elev;
404 float cfelev,cfazim;
405
406 if ( !animate || !ctracking ) return;
407 sc = cv.scene[currentScene()];
408 c = sc->camera;
409 azim = Azimuth(c);
410 elev = Elevation(c);
411
412 switch (cbutton) {
413 case GLUT_LEFT_BUTTON:
414 cfelev = 3.0;
415 cfazim = 3.0;
416 delev = 2.0*(cury-starty)/(float)sc->par.ys;
417 dazim = 2.0*(curx-startx)/(float)sc->par.xs;
418 if ( delev >= 0.0 ) delev *= delev;
419 else delev = -delev*delev;
420 if ( dazim >= 0.0 ) dazim *= dazim;
421 else dazim = -dazim*dazim;
422 elev += cfelev * delev;
423 azim -= cfazim * dazim;
424 break;
425
426 case GLUT_MIDDLE_BUTTON:
427 break;
428 case GLUT_BUTTON_3:
429 puts("button3");
430 break;
431 case GLUT_BUTTON_4:
432 puts("button4");
433 break;
434 }
435 updateCamera(sc,c,azim,elev);
436 reshapeScene(sc->par.xs,sc->par.ys);
437 glutPostRedisplay();
438 }
439