[c++ / qt] freefly camera problème souris

freefly camera problème souris [c++ / qt] - C++ - Programmation

Marsh Posté le 30-03-2010 à 12:39:15    

salut, j'essaie de faire un camera free fly en qt, ça marche presque mais un détail bug encore:
 
quand je fais un QCursor::setPos(x, y) pour pas que ma souris atteigne le bord de l'écran, il semble que ça interrompt le mouvement de la souris et du coup le déplacement accuse un accoup. Est-ce que quelqu'un à une idée pour régler ce problème??
 
voilà le code en cause :

Citation :


void COGLSpace::paintGL()
{
 glMatrixMode( GL_PROJECTION );
 glLoadIdentity( );
 gluPerspective(21.5, 1.0 ,0.001,10000);
 
 glEnable(GL_DEPTH_TEST);
 
 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
 
 glMatrixMode( GL_MODELVIEW );
 glLoadIdentity( );
 
 
// QPoint globalCursorPos = QCursor::pos();
 QPoint localCursorPos = this->mapFromGlobal(QCursor::pos());
 
 double newX = localCursorPos.x();
 
 double newY = localCursorPos.y();
 
 
 double relativeX = newX - m_mouseX;
 std::cout << newX << " - " << m_mouseX << " = " << relativeX << "\n";
 double relativeY = newY - m_mouseY;
 std::cout << newY << " - " << m_mouseY << " = " << relativeY << "\n";
 
 m_fpsCamera->updateDir(relativeX, relativeY);
 
 if(width()/4 < newX && newX < (3*width())/4 && height()/4 < newY && newY < (3*height())/4){
  m_mouseX = newX;
  m_mouseY = newY;
 }else{
  setMouseTracking(false);
  QCursor::setPos(this->mapToGlobal(QPoint(width()/2, height()/2)));
  setMouseTracking(true);
  this->grabMouse();
  m_mouseX = width()/2;
  m_mouseY = height()/2;
 }
 
 m_fpsCamera->updatePos(m_fpsCameraMoves);
// m_fpsCamera->updateDir(m_relativeX, m_relativeY);
 const double* cameraPosition = m_fpsCamera->getPosition();
 const double* cameraDirection = m_fpsCamera->getDirection();
 
// std::cout << "in paint gl pos = " << cameraPosition[0] << "/"
//   << cameraPosition[1] << "/" << cameraPosition[2] << "\n";
// std::cout << "in paint gl dir = " << cameraDirection[0] << "/"
//   << cameraDirection[1] << "/" << cameraDirection[2] << "\n";
 
 gluLookAt(cameraPosition[0], cameraPosition[1], cameraPosition[2],
     cameraPosition[0]+cameraDirection[0], cameraPosition[1]+cameraDirection[1], cameraPosition[2]+cameraDirection[2],
     0, 0, 1);
 
 glLineWidth(3.0);
 glBegin(GL_LINES);
 glColor3f(1.0f,0.0f,0.0f);     // red x axis
 glVertex3f(0.0,0.0,0.0);
 glVertex3f(0.1,0.0,0.0);
 glColor3f(0.0f,1.0f,0.0f);     // green y axis
 glVertex3f(0.0,0.0,0.0);
 glVertex3f(0.0,0.1,0.0);
 glColor3f(0.0f,0.0f,1.0f);     // blue z axis
 glVertex3f(0.0,0.0,0.0);
 glVertex3f(0.0,0.0,0.1);
 glEnd();
 
 
 
 if ( m_pOGLTiles != NULL )
 {
  glPushMatrix();
  glTranslatef(-m_cloudCenter[0], -m_cloudCenter[1], -m_cloudCenter[2]);
  displayCloud( m_pOGLTiles );
  if ( m_bPickState ){
   if ( m_iID > -1 && m_iID < m_pOGLTiles->m_iNbrPoints ){
    displayPickObjects();
   }
  }
  glPopMatrix();
 }
 
 
 glFlush();
 
}


 
merci d'avance pour vos réponses!

Reply

Marsh Posté le 30-03-2010 à 12:39:15   

Reply

Marsh Posté le 30-03-2010 à 18:11:06    

Bonjour,
Je ne m'y connais pas en Qt, mais je dirais que la gestion de la souris n'a rien a faire dans la fonction Paint!
 
Si tu as une fonction qui gère les mouvements de la souris (comme glutMouseFunc(mouse) avec la GLUT), enregistre sa position dans une variable globale (pour qu'elle soit accessible de ta fonction qui remet le monde a jour) et remet la a sa place de suite.


Message édité par breizhbugs le 30-03-2010 à 18:12:26
Reply

Marsh Posté le 30-03-2010 à 20:01:04    

ça change rien.
 
à mon avis c'est vraiment le QCursor::setPos() qui interfère avec le mouvement de la souris, mais je sais pas comment changer ça...

Reply

Marsh Posté le 31-03-2010 à 12:44:48    


Citation :


void COGLSpace::paintGL()
{
 
// QPoint globalCursorPos = QCursor::pos();
 QPoint localCursorPos = this->mapFromGlobal(QCursor::pos());
 
 double newX = localCursorPos.x();
 
 double newY = localCursorPos.y();
 
 
 double relativeX = newX - m_mouseX;
 std::cout << newX << " - " << m_mouseX << " = " << relativeX << "\n";
 double relativeY = newY - m_mouseY;
 std::cout << newY << " - " << m_mouseY << " = " << relativeY << "\n";
 
...
 if(width()/4 < newX && newX < (3*width())/4 && height()/4 < newY && newY < (3*height())/4){
  m_mouseX = newX;
  m_mouseY = newY;
 }else{
  setMouseTracking(false);
  QCursor::setPos(this->mapToGlobal(QPoint(width()/2, height()/2)));
  setMouseTracking(true);
  this->grabMouse();
  m_mouseX = width()/2;
  m_mouseY = height()/2;
 }
 
...
}


En faite je trouve ta gestion de la souris bizarre:
Si j'ai bien compris, tu n'initialises pas la souris au centre au début et tu ne l'y replaces que lorsqu'elle s'approche trop du centre!
 
Je crois que ce qu'il faut faire a chaque boucle:
1- positionner la souris au milieu de la fenetre
2- calculer deltax et deltay, correspondant a la nouvelle position de la souris - la position au centre de la fenetre
3- repositionner la souris au centre de la fenetre
4- utiliser deltax et deltay pour gerer la camera
 

Reply

Marsh Posté le 03-04-2010 à 14:26:07    

c'est ce que je voulais faire au début, mais ça marche pas : rien ne bouge, deltaX et deltaY sont toujours égal à 0. je pense que c'est du à la façon dont Qt gère la souris...

Reply

Marsh Posté le 03-04-2010 à 14:56:07    


"c'est ce que je voulais faire au début, mais ça marche pas : rien ne bouge, deltaX et deltaY sont toujours égal à 0. je pense que c'est du à la façon dont Qt gère la souris... "
 
Je pourrais pas tester mais je voudrais bien voir le code...


Message édité par breizhbugs le 03-04-2010 à 14:57:55
Reply

Marsh Posté le 08-04-2010 à 15:18:39    

voilà ça devait être à peu près ça :
 

Citation :

void COGLSpace::paintGL()
{
 glMatrixMode( GL_PROJECTION );
 glLoadIdentity( );
 gluPerspective(21.5, 1.0 ,0.001,10000);
 
 glEnable(GL_DEPTH_TEST);
 
 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
 
 glMatrixMode( GL_MODELVIEW );
 glLoadIdentity( );
 
 
// QPoint globalCursorPos = QCursor::pos();
 QPoint localCursorPos = this->mapFromGlobal(QCursor::pos());
 
 double newX = localCursorPos.x();
 
 double newY = localCursorPos.y();
 
 
 double relativeX = newX - m_mouseX;
 std::cout << newX << " - " << m_mouseX << " = " << relativeX << "\n";
 double relativeY = newY - m_mouseY;
 std::cout << newY << " - " << m_mouseY << " = " << relativeY << "\n";
 
 m_fpsCamera->updateDir(relativeX, relativeY);
 
  QCursor::setPos(this->mapToGlobal(QPoint(width()/2, height()/2)));
  m_mouseX = width()/2;
  m_mouseY = height()/2;
 }
 
 m_fpsCamera->updatePos(m_fpsCameraMoves);
// m_fpsCamera->updateDir(m_relativeX, m_relativeY);
 const double* cameraPosition = m_fpsCamera->getPosition();
 const double* cameraDirection = m_fpsCamera->getDirection();
 
// std::cout << "in paint gl pos = " << cameraPosition[0] << "/"
//   << cameraPosition[1] << "/" << cameraPosition[2] << "\n";
// std::cout << "in paint gl dir = " << cameraDirection[0] << "/"
//   << cameraDirection[1] << "/" << cameraDirection[2] << "\n";
 
 gluLookAt(cameraPosition[0], cameraPosition[1], cameraPosition[2],
     cameraPosition[0]+cameraDirection[0], cameraPosition[1]+cameraDirection[1], cameraPosition[2]+cameraDirection[2],
     0, 0, 1);
 
 glLineWidth(3.0);
 glBegin(GL_LINES);
 glColor3f(1.0f,0.0f,0.0f);     // red x axis
 glVertex3f(0.0,0.0,0.0);
 glVertex3f(0.1,0.0,0.0);
 glColor3f(0.0f,1.0f,0.0f);     // green y axis
 glVertex3f(0.0,0.0,0.0);
 glVertex3f(0.0,0.1,0.0);
 glColor3f(0.0f,0.0f,1.0f);     // blue z axis
 glVertex3f(0.0,0.0,0.0);
 glVertex3f(0.0,0.0,0.1);
 glEnd();
 
 
 
 if ( m_pOGLTiles != NULL )
 {
  glPushMatrix();
  glTranslatef(-m_cloudCenter[0], -m_cloudCenter[1], -m_cloudCenter[2]);
  displayCloud( m_pOGLTiles );
  if ( m_bPickState ){
   if ( m_iID > -1 && m_iID < m_pOGLTiles->m_iNbrPoints ){
    displayPickObjects();
   }
  }
  glPopMatrix();
 }
 
 
 glFlush();
 
}


 
en fait c'est la même chose sans tester si la souris est encore dans la fenêtre avant de la reseter...

Reply

Marsh Posté le 08-04-2010 à 16:07:31    

En fait on utilise une fonction idle qui est appelée quand il n'y a aucun autre message à traiter. Ci dessous est une partie d'un programme utilisant la glut montrant le principe: lorsque le programme n'a pas de message à traiter, motion() est appelée et recalcule l'angle de la caméra en fonction de la position de la souris.  A la fin on demande une mise à jour de l'affichage (et donc appel indirect a display() ). Le curseur de la souris (visible) saute une peu mais l'animation est fluide.
Par contre, le repositionnement souris est fait par les fonctions de l'api windows directement. Et toi es tu sous windows, linux? fais tu ton programme pour qu'il soit indépendant du système? Si non essai la gestion de la souris avec api native?
 

Code :
  1. // les variables globales
  2. int oldx, oldy;
  3. float anglexz = 270;
  4. float angleyz = 0;
  5. float ex=100.0, ey=120.0, ez=-100.0;
  6. float viewx=100.0, viewy=120.0, viewz=-110.0;
  7. int DISTANCE = 10;
  8. bool lighton = false;
  9. GLfloat nuit[]    = {0.2, 0.2, 0.2, 1.0};
  10. GLfloat jour[]    = {0.9, 0.9, 0.9, 1.0};
  11. GLfloat light_colambn[]    = {0.6, 0.6, 0.6, 1.0};
  12. GLfloat light_colambj[]    = {0.2, 0.2, 0.2, 1.0};
  13. POINT ptOld;                // previous cursor location
  14. ...
  15. void display()
  16. // la fonction qui dessine la monde
  17. {
  18.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  19.   glLoadIdentity();
  20.   glPushMatrix();
  21.     //pour la camera
  22.     gluLookAt(ex, ey, ez, viewx, viewy, viewz, 0.0, 1.0, 0.0);
  23.     //  printf("(vx, vy, vz)=(%f, %f, %f)\n", viewx-ex, viewy-ey, viewz-ez);
  24.     glDisable(GL_LIGHTING);
  25.       glBegin(GL_LINES);
  26.       glColor3f(1.0, 0.0, 0.0);
  27.       glVertex3f(0.0, 0.0, 0.0);
  28.       glVertex3f(5.0, 0.0, 0.0);
  29.       glColor3f(0.0, 1.0, 0.0);
  30.       glVertex3f(0.0, 0.0, 0.0);
  31.       glVertex3f(0.0, 5.0, 0.0);
  32.       glColor3f(0.0, 0.0, 1.0);
  33.       glVertex3f(0.0, 0.0, 0.0);
  34.       glVertex3f(0.0, 0.0, 5.0);
  35.     glEnd();
  36.     glEnable(GL_LIGHTING);
  37.     if(lighton)
  38.     {
  39.       glEnable(GL_LIGHT0);
  40.     }
  41.     else
  42.     {
  43.       glDisable(GL_LIGHT0);
  44.     }
  45.     glPushMatrix();
  46.       glTranslatef(90.0, 220.0, -180.0);
  47.       glutWireCube(10.0);
  48.     glPopMatrix();
  49.   drawMur();
  50.   glTranslatef(300.0, 0.0, 0.0);
  51.   glRotatef(-90, 0.0, 1.0, 0.0);
  52.   drawMur();
  53.   glPopMatrix();
  54.   glutSwapBuffers();
  55. }
  56. void motion()
  57. // cette fonction est appelée automatiquement quand il n'y a rien d'autre a faire
  58. {
  59.   POINT pt;
  60.   GetCursorPos(&pt); // on obtient la position du curseur
  61.   float deltax=((float)(ptOld.x - pt.x))/2; // je sais plus pourquoi on divise par deux... pour que ca aille moins vite peut etre?
  62.   float deltay=((float)(ptOld.y - pt.y))/2;
  63.   float angleradiansx;
  64.   float angleradiansy;
  65.   //pour la translation
  66.   anglexz=(anglexz-deltax);
  67.   angleyz=(angleyz+deltay);
  68.   // on regarde en haut ou en bas, mais on fait pas le "tour"
  69.   if (angleyz<-89.9)
  70.     angleyz=-89.9;
  71.   else if (angleyz>89.9)
  72.     angleyz=89.9;
  73.   angleradiansx = anglexz * M_PI / 180;
  74.   angleradiansy = angleyz * M_PI / 180;
  75.   viewx=ex+cos(angleradiansx)*cos(angleradiansy)*DISTANCE;
  76.   viewz=ez+sin(angleradiansx)*cos(angleradiansy)*DISTANCE;
  77.   viewy=ey+sin(angleradiansy)*DISTANCE;
  78.   SetCursorPos(ptOld.x, ptOld.y); // repositionnement du curseur - ptold est initialisé au milieu de la fenêtre
  79.   glutPostRedisplay(); // on demande une mise a jour d l'affichage
  80. }
  81. void mouse(int button, int , int x, int y)
  82. //on detecte le clic de souris pour lancer/stopper la fonction de l'animation
  83. {
  84.   //oldx=x;
  85. // oldy=y;
  86.   //on positionne le curseur au milieu
  87.   SetCursorPos(glutGet(GLUT_WINDOW_X)+(glutGet(GLUT_WINDOW_WIDTH)/2),glutGet(GLUT_WINDOW_Y)+(glutGet(GLUT_WINDOW_HEIGHT)/2));
  88.   //on enregistre sa position (au milieu)
  89.   GetCursorPos(&ptOld);
  90.   if (button == GLUT_RIGHT_BUTTON)
  91.     glutIdleFunc(motion); // on démarre la fonction idle
  92.   else
  93.     glutIdleFunc(NULL); // ou on l'arrête si c'est pas le bouton droit qui a cliquer
  94. }
  95. void reshape(int w, int h)
  96. // si on redimensionne la fenêtre, on corrige la camera
  97. {
  98.   glViewport(0, 0, (GLsizei)w, (GLsizei)h);
  99.   glMatrixMode(GL_PROJECTION);
  100.   glLoadIdentity();
  101.   //pour conserver l'aspect:
  102.   if (w <= h)
  103.       glFrustum(-1.0, 1.0,
  104.                 -1.0*(GLfloat)h/(GLfloat)w,1.0*(GLfloat)h/(GLfloat)w,
  105.                  1.0, 5000.0);
  106.    else
  107.       glFrustum(-1.0*(GLfloat)w/(GLfloat)h,1.0*(GLfloat)w/(GLfloat)h,
  108.                 -1.0, 1.0,
  109.                  1.0, 5000.0);
  110.   glMatrixMode(GL_MODELVIEW);
  111.   glLoadIdentity();
  112. }
  113. int _tmain(int argc, _TCHAR* argv[])
  114. {
  115.   glutInit(&argc, argv);
  116.   glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  117.   glutInitWindowSize(500, 500);
  118.   glutInitWindowPosition(100, 100);
  119.   glutCreateWindow(argv[0]);
  120.   init();
  121.   glutDisplayFunc(display);
  122.   glutReshapeFunc(reshape);
  123. ...
  124.   glutMouseFunc(mouse); //pour détecter clic de souris  
  125.   glutMainLoop();
  126.   return 0;
  127. }


Message édité par breizhbugs le 08-04-2010 à 16:11:15
Reply

Marsh Posté le 13-04-2010 à 15:00:48    

merci pour ta réponse, je suis sur mac osx mais je sais pas a priori sur quel système le soft va être utilisé donc il doit impérativement être multiplateforme, d'où l'utilisation de Qt.

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed