首页 > 解决方案 > 用鼠标单击 OpenGL 拖动 3d 对象

问题描述

我试图左键单击并拖动任何 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();
}

标签: c++openglglut

解决方案


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

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

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

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

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


推荐阅读