【问题标题】:How to use mouse to change OpenGL camera如何使用鼠标改变OpenGL相机
【发布时间】:2013-01-05 13:43:03
【问题描述】:

我正在尝试在 OpenGL 中设置一个摄像头来查看 3 维中的一些点。 为了实现这一点,我不想使用旧的、固定的功能样式(glMatrixMode()、glTranslate 等),而是自己设置模型视图投影矩阵并在我的顶点着色器中使用它。一个正交投影就足够了。

很多关于这方面的教程似乎都使用了 glm 库,但由于我对 OpenGL 完全陌生,我想以正确的方式学习它,然后使用一些第三方库。此外,大多数教程都没有描述如何使用 glMotionFunc() 和 glMouseFunc() 将相机定位在空间中。

所以,我想我正在寻找一些示例代码和指导如何在 3D 中查看我的观点。这是我写的顶点着色器:

const GLchar *vertex_shader =   // Vertex Shader
"#version 330\n"
"layout (location = 0) in vec4 in_position;"
"layout (location = 1) in vec4 in_color;"
"uniform float myPointSize;"
"uniform mat4 myMVP;"
"out vec4 color;"  
"void main()"  
"{"
"   color = in_color;"
"   gl_Position = in_position * myMVP;"
"   gl_PointSize = myPointSize;"
"}\0";

我将 MVP 的初始值设置为我的着色器设置方法中的单位矩阵,它为我的点提供了正确的 2D 表示:

// Set up initial values for uniform variables
glUseProgram(shader_program);

location_pointSize = glGetUniformLocation(shader_program, "myPointSize");
glUniform1f(location_pointSize, 25.0f);

location_mvp = glGetUniformLocation(shader_program, "myMVP");
float mvp_array[16] = {1.0f, 0.0f, 0.0f, 0.0f,  // 1st column
                       0.0f, 1.0f, 0.0f, 0.0f,  // 2nd column
                       0.0f, 0.0f, 1.0f, 0.0f,  // 3rd column
                       0.0f, 0.0f, 0.0f, 1.0f   // 4th column
                      };
glUniformMatrix4fv(location_mvp, 1, GL_FALSE, mvp_array);

glUseProgram(0);

现在我的问题是如何调整“motion”和“mouse”这两个函数,到目前为止,这两个函数只有前一个示例中的一些代码,其中使用了已弃用的执行方式:

// OLD, UNUSED VARIABLES
int mouse_old_x;
int mouse_old_y;
int mouse_buttons = 0;
float rotate_x = 0.0;
float rotate_y = 0.0;
float translate_z = -3.0;

...
// set view matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, translate_z);
glRotatef(rotate_x, 1.0, 0.0, 0.0);
glRotatef(rotate_y, 0.0, 1.0, 0.0);
...

// OLD, UNUSED FUNCTIONS
void mouse(int button, int state, int x, int y)
{
    if (state == GLUT_DOWN)
    {
        mouse_buttons |= 1<<button;
    }
    else if (state == GLUT_UP)
    {
        mouse_buttons = 0;
    }

    mouse_old_x = x;
    mouse_old_y = y;
}

void motion(int x, int y)
{
    float dx, dy;
    dx = (float)(x - mouse_old_x);
    dy = (float)(y - mouse_old_y);

    if (mouse_buttons & 1)
    {
        rotate_x += dy * 0.2f;
        rotate_y += dx * 0.2f;
    }
    else if (mouse_buttons & 4)
    {
        translate_z += dy * 0.01f;
    }

    mouse_old_x = x;
    mouse_old_y = y;
}

【问题讨论】:

    标签: opengl matrix camera mouse shader


    【解决方案1】:

    我想以正确的方式学习它,然后使用一些第三方库。

    使用 GLM 并没有错,因为 GLM 只是一个处理矩阵的数学库。您想学习非常基础的知识是一件非常好的事情。这些天很少见的特征。在进行高级 OpenGL 时,了解这些内容非常宝贵。

    好的,为你学习三件事:

    1. 基本离散线性代数,即如何处理具有离散元素的矩阵和向量。标量和复杂的元素暂时就足够了。

    2. 一点点数字。您必须能够编写执行基本线性代数运算的代码:缩放和添加向量,执行向量的内积和外积。执行矩阵向量和矩阵矩阵乘法。反转矩阵。

    3. 了解齐次坐标。

    (4. 如果你想增加趣味,学习四元数,那些东西很摇滚!)

    在第 3 步之后,您就可以编写自己的线性数学代码了。即使你还不知道齐次坐标。只需编写它就可以有效地处理 4×4 维矩阵和 4 维向量。

    一旦你掌握了齐次坐标,你就会明白 OpenGL 的实际作用。然后:在编写自己的线性数学库时放弃最初的编码步骤。 为什么?因为它会充满错误。我维护的一个小 linmath.h 充满了它们;每次我在一个新项目中使用它时,我都会修复其中的一些。因此,我建议您使用经过良好测试的东西,例如 GLM 或 Eigen。

    我在我的着色器设置方法中将 MVP 的初始值设置为单位矩阵,它为我的点提供了正确的 2D 表示:

    您应该将它们分成 3 个矩阵:模型、视图和投影。在您的着色器中,您应该有两个模型视图和投影。 IE。您将投影按原样传递给着色器,但计算以单独统一传递的复合 Model · View = Modelview 矩阵。

    要移动“相机”,您需要修改View 矩阵。

    现在我的问题是如何调整“motion”和“mouse”这两个函数,到目前为止,这两个函数只有前一个示例中的一些代码,其中使用了已弃用的执行方式:

    大部分代码保持不变,因为它不涉及 OpenGL。您需要替换的是那些 glRotate 和 glTranslate 调用。

    如前所述,您正在处理View 矩阵。首先让我们看看 glRotate 做了什么。在固定函数 OpenGL 中有一个内部别名,我们称之为M,它设置为使用 glMatrixMode 选择的任何矩阵。然后我们可以将glRotate用伪代码写成

    proc glRotate(angle, vec_x, vec_y, vec_z):
        mat4x4 R = make_rotation_matrix(angle, vec_x, vec_y, vec_z)
        M = M · R
    

    好的,所有的魔法似乎都在函数make_rotation_matrix 中。那个看起来怎么样。好吧,既然你正在学习线性代数,这对你来说是一个很好的练习。找到具有以下属性的矩阵R

    l a = R·a,其中 a 是旋转轴

    cos(phi) = b·c &amp;&amp; b·a = 0 &amp;&amp; b·c = 0,其中 phi 是旋转角度

    由于您可能只是想完成这件事,您也可以求助于 OpenGL-1.1 规范,该规范在其关于 glRotatef 的部分中记录了该矩阵

    您可以在它们旁边找到所有其他矩阵操作函数的规范。

    现在,您无需对使用 glMatrixMode 选择的某些隐藏状态变量进行操作,而是让您的矩阵数学库直接对您定义和提供的矩阵变量进行操作。在你的情况下View。与ProjectionModel 类似。然后在渲染时,将模型和视图收缩到已经提到的复合体中。这样做的原因是,您通常想要将顶点位置带入眼睛空间的中间结果(片段着色器的Modelview * position)。确定矩阵值后,您绑定程序 (glUseProgram) 并设置统一值,然后渲染您的几何图形。 (glDraw…)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多