gluUnProject 尝试将鼠标坐标转换为 opengl 坐标的奇怪行为

Posted

技术标签:

【中文标题】gluUnProject 尝试将鼠标坐标转换为 opengl 坐标的奇怪行为【英文标题】:Strange behaviour of gluUnProject trying to convert mouse coords to opengl coords 【发布时间】:2013-07-10 12:24:47 【问题描述】:

我尝试将鼠标坐标转换为 opengl 坐标。实际上它似乎有效,但是当我取消注释我刚刚为测试而编写的 cout 行时,它会将我的 vars 设置为不是数字-nan。 它是如何发生的?我该如何解决?

//global:
GLdouble mouseOgl[3] = 0.0,0.0,0.0;
//handle click events of the mouse
void myMouse(int button, int state, int x, int y)

    //mouse coords to gl coords


    switch (button)
    
        case GLUT_LEFT_BUTTON:
            if(state == GLUT_UP)   //on release left mouse button
                std::cout << x << " * "<< y << std::endl;
                GetOGLPos(x, y);
                std::cout
                    << mouseOgl[0] << " # "
                    << mouseOgl[1] << " # "
                    << mouseOgl[2] << " # "
                    << std::endl;   
                glutPostRedisplay();            
                
        break;
    

这里的完整代码:

#include <iostream>
#include <stdlib.h>
#include <string>
#include <fstream>
#include <math.h>
#include <time.h> 
#include <GL/glut.h>

const GLint nNumPoints = 5;

GLfloat ctrlpoints[5][3] = 
         -4.0, -4.0, 0.0,  -2.0, 4.0, 0.0, 
        2.0, -4.0, 0.0, 4.0, 4.0, 0.0, 6.0, 2.0, 0.0;
GLdouble mouseOgl[3] = 0.0,0.0,0.0;

void GetOGLPos(int x, int y);

void init(void)

   glClearColor(1.0, 1.0, 1.0, 0.0);
   glShadeModel(GL_FLAT);
   glMap1f(GL_MAP1_VERTEX_3,    // Type of data generated
    0.0f,           // Lower u range
    1.0f,           // Upper u range
    3,              // Distance between points in the data
    nNumPoints,         // number of control points
    &ctrlpoints[0][0]);     // array of control points
    // Enable the evaluator
    glEnable(GL_MAP1_VERTEX_3);
    glEnable(GL_DEPTH);


void display(void)

   int i;
   glClear(GL_COLOR_BUFFER_BIT);
   glColor3f(0.0, 0.0, 1.0);
   glBegin(GL_LINE_STRIP);
      for (i = 0; i <= 30; i++) 
         glEvalCoord1f((GLfloat) i/30.0);
   glEnd();
   //Kontrollpunkte:
   glPointSize(5.0);
   glColor3f(1.0, 0.0, 0.0);
   glBegin(GL_POINTS);
      for (i = 0; i < nNumPoints; i++) 
         glVertex3fv(&ctrlpoints[i][0]);
   glEnd();
   glColor3f(0.0, 1.0, 0.0);
   glBegin(GL_LINE_STRIP);
        for (i = 0; i < nNumPoints; i++) 
            glVertex3fv(&ctrlpoints[i][0]);
   glEnd();
   glFlush();


void reshape(int w, int h)

   glViewport(0, 0, (GLsizei) w, (GLsizei) h);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   //keep aspect ratio:
   if (w <= h)
      glOrtho(-10.0, 10.0, -10.0*(GLfloat)h/(GLfloat)w, 
               10.0*(GLfloat)h/(GLfloat)w, -10.0, 10.0);
   else
      glOrtho(-10.0*(GLfloat)w/(GLfloat)h, 
               10.0*(GLfloat)w/(GLfloat)h, -10.0, 10.0, -10.0, 10.0);
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();


//handle click events of the mouse
void myMouse(int button, int state, int x, int y)

    //mouse coords to gl coords


    switch (button)
    
        case GLUT_LEFT_BUTTON:
            if(state == GLUT_UP)   //on release left mouse button
                std::cout << x << " * "<< y << std::endl;
                GetOGLPos(x, y);
                std::cout
                    << mouseOgl[0] << " # "
                    << mouseOgl[1] << " # "
                    << mouseOgl[2] << " # "
                    << std::endl;   
                glutPostRedisplay();            
                
        break;
    

// detailed information: 
// http://nehe.gamedev.net/article/using_gluunproject/16013/
void GetOGLPos(int x, int y)

    //init vars:
    GLint viewport[4];          
    GLdouble modelview[16];     
    GLdouble projection[16];    
    GLfloat winX, winY, winZ;   
    GLdouble posX, posY, posZ;
    //get gl specs
    glGetDoublev( GL_MODELVIEW_MATRIX, modelview ); //get Modelmatrix   
    glGetDoublev( GL_PROJECTION_MATRIX, projection );   //get projection matrix
    glGetIntegerv( GL_VIEWPORT, viewport );     //get viewport values
    //calculate the gl mouseposition
    winX = (float)x;
    winY = (float)viewport[3] - (float)y;
    glReadPixels( x, int(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ );

    gluUnProject( winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ);
/*
    following line needed to run the program propper?!?!
*/
    std::cout << "positions:" << posX << " | " << posY << " | " << posZ << std::endl;
    mouseOgl[0] = posX;
    mouseOgl[1] = posY;
    mouseOgl[2] = posZ;


int main(int argc, char** argv)

   glutInit(&argc, argv);
   glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
   glutInitWindowSize (600, 600);
   glutInitWindowPosition (100, 100);
   glutCreateWindow (argv[0]);
   init ();
   glutDisplayFunc(display);
   glutReshapeFunc(reshape);
   glutMouseFunc(myMouse);
   glutMainLoop();
   return 0;

【问题讨论】:

【参考方案1】:

鼠标回调可以在任何时候被调用,所以当你在那个回调中时你不确定你的渲染代码的正确的状态是什么......

我认为您应该在此回调中标记鼠标已被按下(将其保存到某个变量wasMousePressed = true;),然后在您的 OnRender 函数中检查鼠标点击。这样它将与opengl同步。然后检查您的cout 代码是否正常工作。

onMouse() 
    if (...)
        mousePressed = true;
    else
        mousePressed = false;


onRender() 
  clearBuffer();

  setupCameraAndProjection();

   if (mousePressed)
     checkOGLState();

   render...

【讨论】:

谢谢,这解决了问题。但是你知道为什么它在'gluUnProject();'之后使用'cout'命令工作吗? ? 不是真的,但我知道你的代码应该设计不同......也许是某种调试模式?也许通过该更改更改了与opengl代码的同步。没有进一步调查就很难说。

以上是关于gluUnProject 尝试将鼠标坐标转换为 opengl 坐标的奇怪行为的主要内容,如果未能解决你的问题,请参考以下文章

Android 上的 Opengl ES:如何使用 gluUnProject?

[转]gluProject 和 gluUnproject 的详解

OpenGL坐标转换场景到世界

将 Glut 鼠标坐标转换为 opengl

当涉及旋转时,将鼠标坐标转换为 OpenGL 中的模型坐标

将鼠标坐标转换为世界空间坐标