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

Posted

技术标签:

【中文标题】用鼠标单击 OpenGL 拖动 3d 对象【英文标题】:3d Object Dragging with mouse click OpenGL 【发布时间】:2018-11-15 03:26:02 【问题描述】:

我正在尝试左键单击并拖动任何 3d 对象,如果我放开它,它应该保持在新位置,我将如何实现这一点? 3d 对象是从头文件中的绘图函数加载的。

有人说我应该使用 glutMouseFunc 或 glutMotionFunc。

void MouseClickCallbackFunction(int button, int state, int x, int y)


    if (state == GLUT_DOWN) 

    if (button == GLUT_LEFT)
    
        std::cout << "Left " << x << " " << y <<std::endl;
        leftClick.x = x;
        leftClick.y = y;
    
    else if (button == GLUT_RIGHT_BUTTON) 

        std::cout << "Right " << x << " " << y << std::endl;
        rightClick.x = x;
        rightClick.y = y;

    

    theGame->mouseClicked(button, state, x, y);
    glutPostRedisplay();



/* function MouseMotionCallbackFunction()
 * Description:
 *   - this is called when the mouse is clicked and moves
 */
void MouseMotionCallbackFunction(int x, int y)

    theGame->mouseMoved(x, y);
    glutPostRedisplay();


int main(int argc, char **argv)

    /* initialize the window and OpenGL properly */
    glutInit(&argc, argv);
    glutInitContextVersion(4, 2);
    glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
    glutCreateWindow("OpenGL Framework");

    glewExperimental = true;
    if (glewInit() != GLEW_OK)
    
        std::cout << "GLEW could not be initialized. \n";
        system("pause");
        return 0;
    

    //glewInit();

    std::cout << "OpenGL version: " << glGetString(GL_VERSION) << std::endl;

    /* set up our function callbacks */
    glutDisplayFunc(DisplayCallbackFunction);
    glutKeyboardFunc(KeyboardCallbackFunction);
    glutKeyboardUpFunc(KeyboardUpCallbackFunction);
    glutMouseFunc(MouseClickCallbackFunction);
    glutMotionFunc(MouseMotionCallbackFunction);
    glutTimerFunc(1, TimerCallbackFunction, 0);

    /* init the game */
    theGame = new Game();
    theGame->initializeGame();

    /* start the game */
    glutMainLoop();
    return 0;
         

这是绘制对象的函数

void Game::draw()

    glClearColor(0, 0, 0, 0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    PassThrough.Bind();
    PassThrough.SendUniformMat4("uModel", MonkeyTransform.data, false);
    PassThrough.SendUniformMat4("uView", CameraTransform.GetInverse().data, false);
    PassThrough.SendUniformMat4("uProj", CameraProjection.data, false);

    PassThrough.SendUniform("uTex", 0);
    PassThrough.SendUniform("LightPosition", CameraTransform.GetInverse() * vec4(4.0f,0.0f,0.0f,1.0f));
    PassThrough.SendUniform("LightAmbient", vec3(0.15f, 0.15f, 0.15f));
    PassThrough.SendUniform("LightDiffuse", vec3(0.7f,0.1f,0.2f));
    PassThrough.SendUniform("LightSpecular", vec3(0.8f,0.1f,0.1f));
    PassThrough.SendUniform("LightSpecularExponent", 50.0f);
    PassThrough.SendUniform("Attenuation_Constant", 1.0f);
    PassThrough.SendUniform("Attenuation_Linear", 0.1f);
    PassThrough.SendUniform("Attenuation_Quadratic", 0.01f);

    glBindVertexArray(Monkey.VAO);
    glDrawArrays(GL_TRIANGLES, 0, Monkey.GetNumVerticies());
    glBindVertexArray(0); 

    PassThrough.unBind();
    glutSwapBuffers();

【问题讨论】:

看看这个Compute objects moving with arrows and mouse 【参考方案1】:

这个概念叫做鼠标拾取。实现这一点的一种方法是光线投射。本质上,您要做的是将鼠标坐标映射到场景中的某个区域。在您的情况下,您想检查该位置是否在猴子内。那么就如同处理鼠标上、下、移动事件一样简单。

鼠标按下:检查对象是否被拾取。如果是,那就太好了——也许突出显示它或其他东西。将参考存储到选取的对象;存储鼠标在拾取开始时的位置(pos)

鼠标移动:鼠标按下了吗?是拾取的对象参考吗?根据鼠标移动事件中 pos 和 coord 之间的增量更新对象位置

鼠标上移:清除拾取的 obj ref、位置

此链接可能感兴趣http://antongerdelan.net/opengl/raycasting.html

【讨论】:

我将如何用代码实现这个?有什么例子吗? 我找到了另一个可能对您有帮助的答案:***.com/questions/25861374/…

以上是关于用鼠标单击 OpenGL 拖动 3d 对象的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL用鼠标拖动绘制矩形?

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

虚拟仿真Unity3D中实现鼠标的单击双击拖动的不同状态判断

单击窗口 x 轴的末端时,通过鼠标单击在 OpenGL 中创建的光线不正确?

在 OpenGL 上单击鼠标时无法旋转和更改对象的颜色

如何检查鼠标是不是在 freeglut 的三角形区域内单击?