mouse.c

来自「FreeFem++可以生成高质量的有限元网格。可以用于流体力学」· C语言 代码 · 共 439 行

C
439
字号
#include "medit.h"#include "extern.h"#include "sproto.h"	#ifndef  ON#define  ON     1#define  OFF    0#endifGLuint    lasttime;GLboolean tracking = GL_FALSE,ctracking = GL_FALSE;GLboolean picking = GL_FALSE;int       cbutton  = 0;int       startx,starty,curx,cury;int       rxi,ryi,rx1,rx2,ry1,ry2; #define MinWH   0.1#define MaxWH   0.9#ifndef GLUT_BUTTON_3#define GLUT_BUTTON_3   2#define GLUT_BUTTON_4   3#endif/* project x,y, onto a hemi-sphere */static void point2Vect(int x,int y,int w,int h,float *v) {  double   d,a,areax,areay;  areax = (w-startx) / w;  areay = (h-starty) / h;  if ( areax > MinWH && areax < MaxWH && areay > MinWH && areay < MaxWH ) {    v[0] = (2.0 * x - w) / w;    v[1] = (h - 2.0 * y) / h;    v[2] = 1.0f;  }  else {    v[0] =  2.0f*(x-startx) / w;    v[1] = -2.0f*(y-starty) / h;    v[2] = 1.0f;  }  d = v[0]*v[0]+v[1]*v[1];  if ( d == 0.0f )  return;  d = sqrt(d);  v[2] = cos(M_PI_2 * ((d < 1.0) ? d : 1.0));  d    = v[0]*v[0]+v[1]*v[1]+v[2]*v[2];  a    = 1.0f / sqrt(d);  v[0] *= a;    v[1] *= a;    v[2] *= a;}void ortho2D(pScene sc,ubyte mode) {  if ( mode == ON ) {    glMatrixMode(GL_PROJECTION);    glPushMatrix();    glLoadIdentity();    gluOrtho2D(0,sc->par.xs,0.,sc->par.ys);    glDisable(GL_LIGHTING);    glDisable(GL_DEPTH_TEST);    glMatrixMode(GL_MODELVIEW);  }  else if ( mode == OFF ) {    glMatrixMode(GL_PROJECTION);    glPopMatrix();    glMatrixMode(GL_MODELVIEW);    glEnable(GL_DEPTH_TEST);    glLineWidth(1.);  }}static void drawRubberBand(int xa,int ya,int xb,int yb) {  glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);  glLineWidth(2.0);  glColor3f(0.5,0.5,0.5);  glRecti(xa,ya,xb,yb);}static void rubberMotion(int x,int y) {  pScene      sc;  pPersp      p;  sc = cv.scene[currentScene()];  p  = sc->persp;  glEnable(GL_COLOR_LOGIC_OP);  glLogicOp(GL_XOR);  /* draw frame */  drawRubberBand(rxi,ryi,rx1,ry1);  rx2 = x;  ry2 = sc->par.ys-y;  drawRubberBand(rxi,ryi,rx2,ry2);  glFlush();  glLogicOp(GL_COPY);  glDisable(GL_COLOR_LOGIC_OP);  /* keep old coords */  rx1 = rx2;  ry1 = ry2;}void zoomMotion(int x,int y) {  pScene      sc;  pPersp      p;  int         dy;  sc = cv.scene[currentScene()];  p  = sc->persp;  dy = starty - y;  if ( dy > 0 )    if ( p->fovy < 1.0e-02 )        return;    else       p->fovy = max(0.95*p->fovy,1e-05);  else if ( p->fovy > 160.0 )  return;  else    p->fovy = min(1.1*p->fovy,179.0);  farclip(1);  starty = y;  glutPostRedisplay();}void mouse(int button,int state,int x,int y) {  pScene      sc;  pTransform  tr;  pPersp      p;  int         keyact,idw = currentScene();  static int  olds = -1;    picking=GL_FALSE;  /* default */  if ( ddebug ) printf("control mouse %d\n",state);  sc = cv.scene[idw];  p  = sc->persp;  if ( sc->cube->active & C_EDIT )    tr = sc->cube->cubetr;  else if ( sc->clip->active & C_EDIT )     tr = sc->clip->cliptr;  else    tr = sc->view;  tr->mstate  = state;  tr->mbutton = button;  /* check if ctrl-shift-alt pressed */  keyact = glutGetModifiers();  if ( state == GLUT_DOWN ) {    tracking = GL_TRUE;    lasttime = glutGet(GLUT_ELAPSED_TIME);    if ( button == GLUT_LEFT_BUTTON ) {      if ( keyact & GLUT_ACTIVE_SHIFT ) {        /* entity designation */        picking = GL_TRUE;	if ( sc->picklist ) glDeleteLists(sc->picklist,1);	sc->picklist = pickingScene(sc,x,y,0);	return;      }      else if ( keyact & GLUT_ACTIVE_ALT ) {	    /* zoom */	    starty = y;	    glutMotionFunc(zoomMotion);	    return;      }      else if ( keyact & GLUT_ACTIVE_CTRL ) {        /* rubberband selection */        glutSetCursor(GLUT_CURSOR_CROSSHAIR);        p->rubix  = p->rubfx = x;        p->rubiy  = p->rubfy = sc->par.ys-y;        rxi = rx1 = x;        ryi = ry1 = sc->par.ys-y;        p->rubber = 1;        glDrawBuffer(GL_BACK_LEFT);        ortho2D(sc,ON);        glutMotionFunc(rubberMotion);        return;      }    }        else if ( button == GLUT_MIDDLE_BUTTON && keyact & GLUT_ACTIVE_SHIFT ) {      picking = GL_TRUE;      if ( sc->picklist ) glDeleteLists(sc->picklist,1);      sc->picklist = pickingScene(sc,x,y,LPoint);      return;    }    /* transformation */    startx = x;    starty = y;    point2Vect(x,y,sc->par.xs,sc->par.ys,tr->pos);    glutSetCursor(GLUT_CURSOR_INFO);  }  else if ( state == GLUT_UP ) {    if ( button == GLUT_LEFT_BUTTON ) {            if ( keyact & GLUT_ACTIVE_CTRL ) {        /* rubberband selection */        p->rubfx  = x;        p->rubfy  = sc->par.ys-y;        p->rubber = 2;        glDrawBuffer(GL_BACK_LEFT);        ortho2D(sc,OFF);        glutMotionFunc(motion);        return;      }            else if ( keyact & GLUT_ACTIVE_ALT ) {        glutMotionFunc(motion);	    return;      }      else if ( picking == GL_TRUE ) {        picking = GL_FALSE;        reshapeScene(sc->par.xs,sc->par.ys);        glutPostRedisplay();      }    }        glutMotionFunc(motion);    if ( sc->clip->active & C_EDIT )      sc->clip->active |= C_REDO;    /* transformation */    glutSetCursor(GLUT_CURSOR_INHERIT);    tracking = GL_FALSE;    if ( glutGet(GLUT_ELAPSED_TIME) >= lasttime ) {       if ( tr->manim == GL_TRUE )  glutIdleFunc(glutIdle);      else  tr->angle = 0.0;      /*if ( abs(startx-x) + abs(starty-y) > 0 )*/        glutPostRedisplay();    }    else if ( tr->manim == GL_TRUE && olds == idw )        glutIdleFunc(NULL);  }  olds = idw;}void motion(int x,int y) {  pScene      sc;  pTransform  tr;  pPersp      p;  GLuint      gtime;  double      deltax,deltay;  float       coeff,pos[3],dx,dy,dz;  int         idw = currentScene();  /* default */  if ( picking )  return;  if ( ddebug ) fprintf(stdout,"motion\n");  if ( tracking == GL_FALSE )  return;  sc = cv.scene[idw];  p  = sc->persp;  if ( p->rubber == 1 )  return;  /* what is transformed ? */  if ( sc->cube->active & C_EDIT )     tr = sc->cube->cubetr;  else if ( sc->clip->active & C_EDIT )     tr = sc->clip->cliptr;  else    tr = sc->view;  if ( tr->mstate != GLUT_DOWN )  return;  if ( picking )  tr->angle = 0.0f;  gtime = glutGet(GLUT_ELAPSED_TIME);  if ( (animate || sc->type & S_FOLLOW) && gtime < lasttime+40 )  return;  if ( tr->mbutton == GLUT_LEFT_BUTTON ) {    /* calculate axis of rotation: cross product */    point2Vect(x,y,sc->par.xs,sc->par.ys,pos);    tr->axis[0] = tr->pos[1]*pos[2] - tr->pos[2]*pos[1];    tr->axis[1] = tr->pos[2]*pos[0] - tr->pos[0]*pos[2];    tr->axis[2] = tr->pos[0]*pos[1] - tr->pos[1]*pos[0];     /* calculate angle to rotate by */    if ( animate && saveimg )      tr->angle = 2.0f;    else {      dx = pos[0] - tr->pos[0];      dy = pos[1] - tr->pos[1];      dz = pos[2] - tr->pos[2];      tr->angle = 180.0*sqrt(dx*dx+dy*dy+dz*dz);    }    /* reset for next time */    tr->pos[0] = pos[0];    tr->pos[1] = pos[1];    tr->pos[2] = pos[2];    lasttime   = gtime;    if ( sc->cube->active & C_ON && sc->cube->active & C_EDIT )      sc->cube->active |= C_UPDATE;    else if ( sc->clip->active & C_ON && 	         (sc->clip->active & C_EDIT || sc->clip->active & C_FREEZE) )      sc->clip->active |= C_UPDATE;    glutPostRedisplay();  }  else if ( tr->mbutton == GLUT_MIDDLE_BUTTON ) {    coeff  = tr->manim == GL_TRUE ? 0.2 : 2.0;    deltax = coeff * (x-startx) / (float)sc->par.xs;    deltay = coeff * (starty-y) / (float)sc->par.ys;    if ( deltax != 0.0 )      tr->panx += -deltax * p->depth * tan(p->fovy/360.*M_PI);    if ( deltay != 0.0 )      tr->pany += -deltay * p->depth * tan(p->fovy/360.*M_PI);    tr->angle = 0.0;    startx = x;    starty = y;    lasttime = gtime;    if ( sc->cube->active & C_ON && sc->cube->active & C_EDIT )      sc->cube->active |= C_UPDATE;    else if ( sc->clip->active & C_ON &&         (sc->clip->active & C_EDIT || sc->clip->active & C_FREEZE) )      sc->clip->active |= C_UPDATE;    glutPostRedisplay();  }}void mouseCamera(int button,int state,int x,int y) {  /* default */  if ( ddebug ) printf("control mouse camera %d button %d\n",state,button);  cbutton = button;  if ( state == GLUT_DOWN ) {    ctracking = GL_TRUE;    startx = x;    starty = y;    curx   = x;    cury   = y;  }  else {    startx = x;    starty = y;    ctracking = GL_FALSE;  }}void motionCamera(int x,int y) {  pScene   sc;  pCamera  c;  double   dazim,delev,azim,elev;  float    cfelev,cfazim;  /* keep current pos */  curx = x;  cury = y;  if ( animate ) return;  sc = cv.scene[currentScene()];  c  = sc->camera;  azim  = Azimuth(c);  elev  = Elevation(c);   switch (cbutton) {    case GLUT_LEFT_BUTTON:      cfelev = 50.0;      cfazim = 50.0;      delev  = cfelev * (y-starty)/(float)sc->par.ys;      dazim  = cfazim * (x-startx)/(float)sc->par.xs;      startx = x;      starty = y;      elev  += delev;      azim  -= dazim;      break;    case GLUT_MIDDLE_BUTTON:      break;    case GLUT_BUTTON_3:      puts("button3");      break;    case GLUT_BUTTON_4:      puts("button4");      break;  }  updateCamera(sc,c,azim,elev);  reshapeScene(sc->par.xs,sc->par.ys);  glutPostRedisplay();}void animateCamera() {  pScene   sc;  pCamera  c;  double   dazim,delev,azim,elev;  float    cfelev,cfazim;  if ( !animate || !ctracking )  return;  sc = cv.scene[currentScene()];  c  = sc->camera;  azim  = Azimuth(c);  elev  = Elevation(c);  switch (cbutton) {    case GLUT_LEFT_BUTTON:      cfelev = 3.0;      cfazim = 3.0;      delev  = 2.0*(cury-starty)/(float)sc->par.ys;      dazim  = 2.0*(curx-startx)/(float)sc->par.xs;      if ( delev >= 0.0 ) delev *= delev;      else                delev = -delev*delev;      if ( dazim >= 0.0 ) dazim *= dazim;      else                dazim  = -dazim*dazim;      elev += cfelev * delev;      azim -= cfazim * dazim;      break;        case GLUT_MIDDLE_BUTTON:      break;    case GLUT_BUTTON_3:      puts("button3");      break;    case GLUT_BUTTON_4:      puts("button4");      break;  }  updateCamera(sc,c,azim,elev);  reshapeScene(sc->par.xs,sc->par.ys);  glutPostRedisplay();}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?