2013-01-05 25 views
3

我想在OpenGL中设置相机以查看三维中的某些点。为了实现这一点,我不想使用旧的固定功能样式(glMatrixMode(),glTranslate等),而是自己设置模型视图投影矩阵,并在我的顶点着色器中使用它。正射投影就足够了。如何使用鼠标更改OpenGL相机

很多关于这个的教程似乎都使用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); 

现在的问题是如何将两个功能“运动”和“鼠标”,这在这一点上只有一些代码从前面的例子中,在利用这样的过时的风格适应:

// 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; 
} 

回答

6

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

使用GLM没有什么错,因为GLM只是一个数学库来处理矩阵。你想学习非常基础知识是一件非常好的事情。这些日子里很少见到这种特质。了解这些东西在进行高级OpenGL时是非常宝贵的。

好,三米要学的东西给你:

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

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

  3. 了解同质坐标。

(4.如果你想香料的东西,学习四元数,这些东西岩!)

第3步后,您就可以编写自己的线性数学代码。即使你还不知道同质坐标。只需写出它与4×4矩阵和4维向量处理效率高。

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

我成立了MVP的初始值是在我的着色单位矩阵设置方法,它给了我我的观点的正确的2D表示:

您应该将这些分成3点矩阵:模型,视图和投影。在着色器中,应该有两个,Modelview和Projection。即您将投影传递给着色器,但是会计算一个单独制服中传递的复合矩阵。

要移动“相机”,请修改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 

好了,所有的魔法似乎在于功能make_rotation_matrix内。那是怎么看的。那么既然你正在学习线性代数,这对你来说是一个很好的练习。找到矩阵R具有以下属性:

l a = R·a,其中一个是旋转

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

因为你很可能只是想这件事做的角度的轴线,你可以和诉诸寻找到了OpenGL的1.1规范,其中记录这个矩阵中的部分约glRotatef

glRotate OpenGL-2 spec

就在它们旁边,您可以找到所有其他矩阵处理函数的规格。

现在,您不需要对使用glMatrixMode选择的某个隐藏状态变量进行操作,而是让您的矩阵数学库直接在您定义和提供的矩阵变量上进行操作。在你的情况下View。而且你可以使用ProjectionModel。然后,在渲染时,将模型和视图合并到已经提到的化合物中。原因是,你经常需要将顶点位置放入眼睛空间的中间结果(片段着色器的Modelview * position)。在确定矩阵值后,你绑定程序(glUseProgram)并设置统一值,然后渲染你的几何图形。 (glDraw ...)