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