如何使用鼠标更改OpenGL相机 [英] How to use mouse to change OpenGL camera

查看:75
本文介绍了如何使用鼠标更改OpenGL相机的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在OpenGL中设置相机以查看3维的一些点. 为此,我不想使用旧的固定功能样式(glMatrixMode(),glTranslate等),而是自己设置模型视图投影矩阵并在我的顶点着色器中使用它.正交投影就足够了.

I'm trying to set up a camera in OpenGL to view some points in 3 dimensions. To achieve this, I don't want to use the old, fixed functionality style (glMatrixMode(), glTranslate, etc.) but rather set up the Model View Projection matrix myself and use it in my vertex shader. An orthographic projection is sufficient.

与此相关的许多教程似乎都使用glm库,但是由于我是OpenGL的新手,所以我想以正确的方式学习它,然后再使用一些第三方库.此外,大多数教程都没有描述如何使用glMotionFunc()和glMouseFunc()在空间中定位相机.

A lot of tutorials on this seem to use the glm library for this, but since I'm completely new to OpenGL, I'd like to learn it the right way and afterwards use some third party libraries. Additionally, most tutorials don't describe how to use the glMotionFunc() and glMouseFunc() to position the camera in space.

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

So, I guess I'm looking for some sample code and guidance how to see my points in 3D. Here's the vertex shader I've written:

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表示:

I set up the initial value of the MVP to be the identity matrix in my shader set up method which gives me the correct 2D representation of my points:

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

现在我的问题是如何适应运动"和鼠标"这两个功能,到目前为止,这两个功能仅来自上一个示例,其中使用了不赞成使用的样式:

Now my question is how to adapt the two functions "motion" and "mouse", which to this point only have some code from a previous example, where the deprecated style of doing this was used:

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

推荐答案

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

I'd like to learn it the right way and afterwards use some third party libraries.

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

There's nothing wrong in using GLM, as GLM is just a math library to deal with matrices. It's a very good thing that you want to learn the very basics. A trait only seldomly seen these days. Knowing these things is invaluable when doing advanced OpenGL.

好的,为您学习三件事:

Okay, three things to learn for you:

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

  1. Basic discrete linear algebra, i.e. how to deal with matrices and vectors with discrete elements. Scalar and complex elements will suffice for the time being.

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

A little bit of numerics. You must be able to write code performing the elementary linear algebra operations: Scaling, and adding vectors, performing an inner and and outer product of vectors. Perform matrix-vector and matrix-matrix multiplication. Inverting a matrix.

了解同质坐标.

(4.如果您想使事情变得有趣,请学习四元数,那些事情会摇动!)

( 4. if you want to spice things up, learn quaternions, those things rock! )

在第3步之后,您就可以编写自己的线性数学代码了.即使您还不知道同构坐标.只需编写即可有效处理尺寸为4×4的矩阵和尺寸为4的向量.

After Step 3 you're ready to write your own linear math code. Even if you don't know about homogenous coordinates yet. Just write it do deal efficiently with matrices of dimension 4×4 and vectors of dimension 4.

掌握了同类坐标后,您就会了解OpenGL的实际作用.然后:放弃那些最初的编码步骤来编写自己的线性数学库.为什么?因为它将充满错误.我维护的那条小灵长鱼被他们迷住了.每当我在新项目中使用它时,我都会修复许多问题.因此,我建议您使用经过良好测试的东西,例如GLM或Eigen.

Once you mastered homogenous coordinates you understand what OpenGL actually does. And then: Drop those first coding steps in writing your own linear math library. Why? Because it will be full of bugs. The one small linmath.h I maintain is riddled with them; everytime I use it in a new project I fix a number of them. Hence I recommend you use something well tested, like GLM, or Eigen.

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

I set up the initial value of the MVP to be the identity matrix in my shader set up method which gives me the correct 2D representation of my points:

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

You should separate these into 3 matrices: Model, View and Projection. In your shader you should have two, Modelview and Projection. I.e. you pass the projection to the shader as it is, but calculate a compound Model · View = Modelview matrix passed in a separate uniform.

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

To move the "camera" you modify the View matrix.

现在我的问题是如何适应运动"和鼠标"这两个功能,到目前为止,这两个功能仅来自上一个示例,其中使用了不赞成使用的样式:

Now my question is how to adapt the two functions "motion" and "mouse", which to this point only have some code from a previous example, where the deprecated style of doing this was used:

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

Most of this code remains the same, as it doesn't touch OpenGL. What you have to replace is those glRotate and glTranslate calls.

您已经在说View矩阵.首先让我们看一下glRotate的功能.在固定功能的OpenGL中,有一个内部别名,我们称之为M,该别名设置为使用glMatrixMode选择的任何矩阵.然后我们可以用伪代码将glRotate编写为

You're working on the View matrix, as already told. First lets look what glRotate does. In fixed function OpenGL there's an internal alias, let's call it M, that is set to whatever matrix is selected with glMatrixMode. Then we can write glRotate in pseudocode as

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:

Okay, all the magic seems to lie within the function make_rotation_matrix. How that that one look. Well since you're learning linear algebra this is a great exercise for you. Find the matrix R with the following properties:

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

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

cos(phi) = b·c && b·a = 0 && b·c = 0, where phi is the angle of rotation

由于您可能只想完成此事情,因此您也可以研究OpenGL-1.1规范,该规范在有关glRotatef的部分中介绍了此矩阵.

Since you probably just want to get this thing done, you can as well resort to look into the OpenGL-1.1 specification, which documents this matrix in its section about glRotatef

在它们旁边,您可以找到所有其他矩阵处理功能的规格.

Right beside them you can find the specs for all the other matrix manipulation functions.

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

Now instead of operating on some hidden state variable you select with glMatrixMode you let your matrix math library operate directly on the matrix variable you define and supply. In your case View. And similar you do with Projection and Model. Then when you're rendering, you contract Model and View into the compound already mentioned. The reason for this is, that often you want the intermediate result of bringing the vertex position into eyespace (Modelview * position for the fragment shader). After determining the matrix values you bind the program (glUseProgram) and set the uniform values, then render your geometry. (glDraw…)

这篇关于如何使用鼠标更改OpenGL相机的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆