如何使用鼠标更改OpenGL相机

Sch*_*ges 3 opengl mouse shader camera matrix

我正在尝试在OpenGL中设置一个摄像头来查看三维中的一些点.要做到这一点,我不希望使用旧的,固定功能的风格(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";
Run Code Online (Sandbox Code Playgroud)

我将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);
Run Code Online (Sandbox Code Playgroud)

现在我的问题是如何调整"运动"和"鼠标"这两个函数,到目前为止只有一些代码来自前面的例子,其中使用了不推荐使用的样式:

// 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;
}
Run Code Online (Sandbox Code Playgroud)

dat*_*olf 6

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

使用GLM没有任何问题,因为GLM只是一个处理矩阵的数学库.你想学习基础知识是一件非常好的事情.这些天来很少看到一个特质.在进行高级OpenGL时,了解这些内容是非常宝贵的.

好的,有三件事需要你学习:

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

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

  3. 了解同质坐标.

(4.如果你想调整一下,学习四元数,那些东西摇滚!)

在第3步之后,您已准备好编写自己的线性数学代码.即使你还不知道同质坐标.只要写它就可以有效地处理尺寸为4×4的矩阵和尺寸为4的向量.

一旦掌握了同质坐标,就可以了解OpenGL实际上做了什么.然后:删除编写自己的线性数学库的第一个编码步骤.为什么?因为它会充满bug.我维持的一个小林is充满了它们; 每当我在一个新项目中使用它时,我会修复它们中的一些.因此,我建议您使用经过良好测试的东西,如GLM或Eigen.

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

您应该将这些分为3个矩阵:模型,视图和投影.在着色器中,您应该有两个,Modelview和Projection.即你将投影原样传递给着色器,但计算Model · View = Modelview一个单独制服传递的复合矩阵.

要移动"相机",请修改View矩阵.

现在我的问题是如何调整"运动"和"鼠标"这两个函数,到目前为止只有一些代码来自前面的例子,其中使用了不推荐使用的样式:

大多数代码保持不变,因为它不接触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
Run Code Online (Sandbox Code Playgroud)

好吧,所有的魔力似乎都在于这个功能make_rotation_matrix.那一个怎么样.好吧,因为你正在学习线性代数,这对你来说是一个很好的练习.找到R具有以下属性的矩阵:

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

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

既然你可能只想完成这件事,你也可以选择OpenGL-1.1规范,该规范在关于glRotatef的部分中记录了这个矩阵.

glRotate OpenGL-2规范

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

现在,不要使用glMatrixMode选择隐藏状态变量,而是让矩阵数学库直接在您定义和提供的矩阵变量上运行.在你的情况下View.而类似你做ProjectionModel.然后在渲染时,将Model和View收缩到已经提到的化合物中.这样做的原因是,通常您需要将顶点位置置于眼睛空间(Modelview * position对于片段着色器)的中间结果.确定矩阵值后,绑定程序(glUseProgram)并设置统一值,然后渲染几何体.(glDraw ...)