Opengl 鼠标点击矩形

Posted

技术标签:

【中文标题】Opengl 鼠标点击矩形【英文标题】:Opengl Mouse click on rectangle 【发布时间】:2016-02-11 09:18:43 【问题描述】:

伙计们,我在使用 glut 鼠标功能时遇到了这个程序的问题。我在做什么 在屏幕上绘制一个矩形,在鼠标功能中,我将像素坐标转换为宽度为 600 和高度为 500 的世界坐标如何确定鼠标点击这些矩形。 代码:

#include <cstdlib>
#include<GL\freeglut.h>
#include <iostream>
using namespace std;

    float xWorldCoordinate = 0.0f;
    float yWorldCoordinate = 0.0f;
    float r = 0.0f;
    float g = 0.0f;
    float b = 0.0f;
    float r1 = 0.0f;
    float g1 = 0.0f;
    float b1 = 0.0f;
    bool isRed = false;

    void init(void) 

        glClearColor(31.0f / 255, 28.0f / 255, 44.0f / 255, 0.0f);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
    

    void MouseButton(int button, int action, int xPixel, int yPixel) 

        if (button == GLUT_LEFT_BUTTON && action == GLUT_DOWN) 
            yPixel = 500 - yPixel;
            xWorldCoordinate = (xPixel / 600.0f) * 2;
            yWorldCoordinate = (yPixel / 400.0f) * 2;
            xWorldCoordinate = -1 + xWorldCoordinate;
            yWorldCoordinate = -1 + yWorldCoordinate;

            int index1 = 0;
            int index2 = 0;
            //Index1
            glReadPixels(xPixel, yPixel, 1, 1, GL_STENCIL_INDEX, GL_UNSIGNED_INT, &index1);// Read pixel under mouse's cursor and read information from stencil buffer to index when it rectangle index should be equal to 1


            if (index1 == 1) 
                isRed = !isRed;
                if (isRed) 
                    r = 0.0f;

                
                else 
                    r = 1.0f;
                


                //Index 2
            //  glReadPixels(xPixel, yPixel, 1, 1, GL_STENCIL_INDEX, GL_UNSIGNED_INT, &index2);
            
        

        glutPostRedisplay();
    

    void Rectangles(void) 

        glStencilFunc(GL_ALWAYS, 1, -1); //set front and back function and reference value for stencil testing
        glBegin(GL_POLYGON);

        glColor3f(r, g, b);
        glVertex2f(-0.1f, 0.1f);
        glVertex2f(-0.1f, -0.1f);
        glVertex2f(0.1f, -0.1f);
        glVertex2f(0.1f, 0.1f);
        glEnd();

        //2nd Rectangle
        glStencilFunc(GL_ALWAYS, 2, -1);
        glBegin(GL_POLYGON);
        glColor3f(r1, g1, b1);
        glVertex2f(0.66f, 0.84f);
        glVertex2f(0.87f, 0.84f);
        glVertex2f(0.87f, 0.66f);
        glVertex2f(0.66f, 0.66f);
        glEnd();
    
    void Display(void) 
        glClearStencil(0); // specifies the index used by glClear to clear the stencil buffer
        glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
        glEnable(GL_STENCIL_TEST);
        glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        Rectangles();
        glFlush();
    

    int main(int argc, char **argv) 

        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_STENCIL); //Bit mask to select a window with a stencil buffer.
        glutInitWindowSize(600, 500);
        glutInitWindowPosition(100, 100);
        glutCreateWindow("Mouse");
        init();
        glutDisplayFunc(&Display);
        glutMouseFunc(&MouseButton);
        glutMainLoop();

        return EXIT_SUCCESS;
    

【问题讨论】:

您试图确定单击时是否单击了矩形,我说得对吗? @segevara 是的,正是点击它改变颜色 【参考方案1】:

我想你可以通过这个来使用 GLUT_STENCIL 你可以通过索引来指示你场景中的所有对象

 #if defined(__APPLE__) || defined(MACOSX)
  #include <GLUT/glut.h>
#else
  #include <GL\freeglut.h>
#endif
#include <cstdlib>
#include <iostream>
using namespace std;

using namespace std;

    float xWorldCoordinate = 0.0f;
    float yWorldCoordinate = 0.0f;
    float r = 0.0f;
    float g = 0.0f;
    float b = 0.0f;
    float r1 = 0.0f;
    float g1 = 0.0f;
    float b1 = 0.0f;
    bool isRed = false;
    bool isBlue = false;
    void init(void) 

        glClearColor(31.0f / 255, 28.0f / 255, 44.0f / 255, 0.0f);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
    

    void MouseButton(int button, int action, int xPixel, int yPixel) 

        if (button == GLUT_LEFT_BUTTON && action == GLUT_DOWN) 
            yPixel = glutGet(GLUT_WINDOW_HEIGHT) - yPixel;

            int * index = new int[1];
            //Index1
            glReadPixels(xPixel, yPixel, 1, 1, GL_STENCIL_INDEX, GL_UNSIGNED_INT, index);// Read pixel under mouse's cursor and read information from stencil buffer to index when it rectangle index should be equal to 1


            if (index[0] == 1) 
                isRed = !isRed;
                if (isRed) 
                    r = 1.0f;

                
                else 
                    r = 0.0f;
                
                //Index 2
            //  glReadPixels(xPixel, yPixel, 1, 1, GL_STENCIL_INDEX, GL_UNSIGNED_INT, &index2);
          else if(index[0] == 2)
            isBlue = !isBlue;
            if (isBlue) 
                b1 = 1.0f;

            
            else 
                b1 = 0.0f;
            
          
          delete index;
        

        glutPostRedisplay();
    

    void Rectangles(void) 

        glStencilFunc(GL_ALWAYS, 1, -1); //set front and back function and reference value for stencil testing
        glBegin(GL_POLYGON);

        glColor3f(r, g, b);
        glVertex2f(-0.1f, 0.1f);
        glVertex2f(-0.1f, -0.1f);
        glVertex2f(0.1f, -0.1f);
        glVertex2f(0.1f, 0.1f);
        glEnd();

        //2nd Rectangle
        glStencilFunc(GL_ALWAYS, 2, -1);
        glBegin(GL_POLYGON);
        glColor3f(r1, g1, b1);
        glVertex2f(0.66f, 0.84f);
        glVertex2f(0.87f, 0.84f);
        glVertex2f(0.87f, 0.66f);
        glVertex2f(0.66f, 0.66f);
        glEnd();
    
    void Display(void) 
        glClearStencil(0); // specifies the index used by glClear to clear the stencil buffer
        glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
        glEnable(GL_STENCIL_TEST);
        glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        Rectangles();
        glFlush();
    

    int main(int argc, char **argv) 

        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_STENCIL); //Bit mask to select a window with a stencil buffer.
        glutInitWindowSize(600, 500);
        glutInitWindowPosition(100, 100);
        glutCreateWindow("Mouse");
        init();
        glutDisplayFunc(&Display);
        glutMouseFunc(&MouseButton);
        glutMainLoop();

        return EXIT_SUCCESS;
    

它适用于我在 Mac 上,但我认为也应该适用于 freeglut

【讨论】:

感谢您的回答,它有效,您能帮我解决这个问题吗***.com/questions/35310028/… 我不明白这段代码是如何工作的 glReadPixels(xPixel, yPixel - 1, 1, 1, GL_STENCIL_INDEX,GL_UNSIGNED_INT, &amp;index) 。我知道这个函数的参数,但在 y 坐标中你为什么写 yPixel - 1 。你也可以只写yPixel 为什么你写-1,你如何写宽度和高度1。在最后一个参数data 之后,你写了&amp;index 它如何自动将值初始化为 1 并返回地址 1 你能解释一下吗?我在这一行很困惑 我编辑了我的问题代码,如果我现在制作两个矩形而不是它应该如何工作,你能帮我吗.. @hamel123 实际上你是对的,-1 不需要 yPixel。 glReadPixels 可以从一组像素中读取信息,在我们的例子中,我们希望只从一个像素中读取信息,因此我们希望只从一个像素中读取信息,因此您可以通过有趣的矩形来指示这些像素组中的信息 (x,y) 和适当的高度和宽度,因此 height and width 是 1。glReadPixels 还读取缓冲区中的信息,您在我们的例子中的参数中指示我们只需要一个数字情况,我们只读取一个像素,所以我给 glReadPixels 变量的地址,我需要它从模板缓冲区中放置信息。 @hamel123 我刚刚编辑了两个矩形的代码,如果它适合你,请告诉我

以上是关于Opengl 鼠标点击矩形的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL - 在鼠标点击时绘制多边形,多边形总是在右边

鼠标点击开始动画 OpenGL/GLUT C++

OpenGL用鼠标拖动绘制矩形?

OpenGL / C++ - 如何在鼠标点击时填充一个点周围的区域?

OpenGL随机大小矩形代码更改绘制的矩形

如何通过鼠标点击获得鼠标点的三维世界坐标呢?OPENGL