OpenGL / GLUT中的鼠标拖动对象[关闭]

Posted

技术标签:

【中文标题】OpenGL / GLUT中的鼠标拖动对象[关闭]【英文标题】:Mouse-drag object in OpenGL/GLUT [closed] 【发布时间】:2013-11-29 15:19:23 【问题描述】:

我整天都在寻找简单程序的教程或示例代码 - 单击对象(例如 2D 矩形),然后当您按住并移动鼠标时,对象跟随鼠标,然后在鼠标释放对象保留在新位置。换句话说,我想了解如何使用鼠标事件拖放对象。

谁能帮我指出与此问题相关的任何有用信息来源的正确方向?

【问题讨论】:

***.com/questions/19884182/… 【参考方案1】:

感谢到目前为止的所有回复。

我已经想出了怎么做,所以我会继续回答我自己的问题。

我正在使用 GLUT 作为鼠标处理程序:

    当鼠标被点击并移动(glutMotionFunc)时,拖动函数被调用。

    在拖动函数中,鼠标坐标 (x,y) 在转换为窗口坐标的同时转换为 Points 结构。

    如果鼠标在方块内,则通过更改坐标拖动方块并重新显示。

我对 OpenGL 和 C++ 还是很陌生,所以我为混乱的编码表示歉意。这样做我有点沮丧,因为重新绘制的正方形使光标看起来像中心一样。我欢迎这个问题的替代解决方案和对我的代码的批评,用于学习目的。

代码(包括过剩和使用命名空间标准):

// points structure made of two coordinates; x and y
struct Points

    float x,y;  // initializor
    Points()  x = 0.0; y = 0.0;  // constructor

    Points(float _x, float _y) : x(_x), y(_y) 
;

// square made of 4 points
class Square

public:
    Points pts[4]; // square structure
    Square(); // initialize constructor

    void draw(Square *sqr); // draw square
    Points mouse(int x, int y); // get mouse coordintaes
    Square* drag(Square *sqr, Points *mouse); // change points of sqr
;

// square constructor
Square::Square()

    pts[0] = Points(0.2,0.2);
    pts[1] = Points(0.4,0.2);
    pts[2] = Points(0.4,0.4);
    pts[3] = Points(0.2,0.4);
;

// draw function
void Square::draw(Square *sqr)

    // draw square fill
    int i;
    glColor3f(0.2, 0.2, 0.2);
    glBegin(GL_QUADS);
    for (i = 0; i < 4; ++i)
    
        glVertex2f(sqr->pts[i].x, sqr->pts[i].y);
    
    glEnd();
    // draw square points
    i = 0;

    glColor3f(1.0, 1.0, 1.0);
    glBegin(GL_POINTS);
    for (i = 0; i < 4; ++i)
    
        glVertex2f(sqr->pts[i].x, sqr->pts[i].y);
    
    glEnd();


// mouse function
Points Square::mouse(int x, int y)

    int windowWidth = 400, windowHeight = 400;
    return Points(float(x)/windowWidth, 1.0 - float(y)/windowHeight);


// drag function
Square* Square::drag(Square *sqr, Points *mouse)

    sqr->pts[0].x = mouse->x - 0.1;
    sqr->pts[0].y = mouse->y - 0.1;
    sqr->pts[1].x = mouse->x + 0.1;
    sqr->pts[1].y = mouse->y - 0.1;

    sqr->pts[3].x = mouse->x - 0.1;
    sqr->pts[3].y = mouse->y + 0.1;

    sqr->pts[2].x = mouse->x + 0.1;
    sqr->pts[2].y = mouse->y + 0.1;

    return sqr;


// GLOBAL

// create square object
Square* sqr = new Square;


// display at start
void display() 
    glClear(GL_COLOR_BUFFER_BIT);
    sqr->draw(sqr);
    glFlush();


// drag function
void drag (int x, int y)

    // int x and y of mouse converts to screen coordinates
    // returns the point as mousePt
    Points mousePt = sqr->mouse(x,y);
    //create pointer to window point coordinates
    Points* mouse = &mousePt;

    // if the mouse is within the square
    if (mouse->x > sqr->pts[0].x && mouse->y > sqr->pts[0].y)
           
        if (mouse->x < sqr->pts[2].x && mouse->y < sqr->pts[2].y)
        
            // then drag by chaning square coordinates relative to mouse
            sqr->drag(sqr,mouse);
            glutPostRedisplay();
        
    



void Initialize() 
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);


int main(int iArgc, char** cppArgv) 

    glutInit(&iArgc, cppArgv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutInitWindowSize(400, 400);
    glutInitWindowPosition(200, 200);
    glutCreateWindow("Move Box");


    glutMotionFunc(drag);

    Initialize();
    glutDisplayFunc(display);
    glutMainLoop();
    return 0;

【讨论】:

【参考方案2】:

OpenGL 只关心绘图过程。其他一切(鼠标输入、对象拾取、场景管理/更改等)完全由您来实现。

这是一个粗略的大纲:

    安装鼠标点击事件处理程序(具体使用方法取决于使用的框架和/或操作系统)

    在鼠标单击事件处理程序中执行拾取操作。这通常涉及将鼠标窗口位置取消投影到世界空间中(请参阅 gluUnproject),从而产生一条射线。测试场景中的每个对象是否与射线相交;您必须自己实现,因为 OpenGL 只是绘制事物(OpenGL 中没有“场景”之类的东西)。

    如果一个对象已被拾取,请将其注册到鼠标拖动处理程序中

    每次发生鼠标拖动事件时,调整对象的位置数据并触发 OpenGL 显示(您总是在 OpenGL 中重绘整个事物)。

    释放鼠标时,从拖动处理程序中取消注册对象。

【讨论】:

感谢您的指导。我想我将使用 GLUT 进行事件处理。问题似乎比我想象的要复杂一些。【参考方案3】:

正如其他人所提到的,OpenGL 不处理用户输入。你想为此使用一个库。如果您想要更全面的解决方案,您甚至可以使用更完整的渲染或物理引擎。

对于简单的用户输入,您可以使用SDL(例如this 用于鼠标输入)。

对于更完整的 2D 内容,您可以使用 Box2D。 Here 是一大堆教程。

重量级解决方案是完整的渲染引擎,例如Ogre3D 或CrystalSpace。

【讨论】:

【参考方案4】:

正如其他人所说,您需要先获取鼠标处理程序才能获取鼠标位置。然后你需要一种方法来选择一个对象。您有几个选项可以在 OpenGL 中进行挑选。

    如果您使用的是经典 OpenGL,则可以使用选择缓冲区。以下链接是一个很好的教程 http://www.lighthouse3d.com/opengl/picking/index.php3?openglway 如果您使用的是基于着色器的现代 opengl,则可以使用基于 FBO 的拾取。 http://ogldev.atspace.co.uk/www/tutorial29/tutorial29.html 在这两种情况下,您始终可以自己实现光线跟踪拾取。 gluUnproject 对实现有很大帮助。 http://schabby.de/picking-opengl-ray-tracing/

之后,您只需要根据鼠标移动或加速度更新对象位置即可。

【讨论】:

以上是关于OpenGL / GLUT中的鼠标拖动对象[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

Mac 上的 OpenGL/GLUT 应用程序无法获得焦点 [关闭]

用鼠标单击 OpenGL 拖动 3d 对象

用鼠标在 OpenGL GLUT 中绘制多边形

如何在OpenGL中实现按住鼠标左键就可以旋转图形的功能

将 Glut 鼠标坐标转换为 opengl

如何在 OpenGL/Glut 中更改鼠标光标的位置?