OpenGL视角LooAt及Perspective理解

来源:互联网 发布:矩阵制组织结构的特点 编辑:程序博客网 时间:2024/06/10 10:11

在:
http://blog.csdn.net/yulinxx/article/details/59538755
的基础上,修改 main.cpp

理解 glm::perspective 和 glm::lookAt


相机竖立在50米开外, 用90度的视角去看0,0,0点的位置,

那么50米外原点中,高度为50的物体,正好看到, 超过50则会被截断!

这里写图片描述

void
gluLookAt(GLdouble eyeX, GLdouble eyeY, GLdouble eyeZ,
GLdouble centerX, GLdouble centerY, GLdouble centerZ,
GLdouble upX, GLdouble upY, GLdouble upZ);

glm::mat4 projection =
glm::perspective(fovyInRadians, aspect, zNear, zFar);

相机视角,以侧视图观察, 在此处以90度为 fovyInRadians 值,
在图中,以45度角进行半分开来,予以剖析

相机离原点为50, 则原点处Y最大能显示为50, z=-50处Y最大能显示为100
若在原点绘图,
我们绘制一个 98*98的正方形,则在视图中,几乎填满视图 (X Y 值分别从-49 到 +49)
为显示边框,所以绘制一个稍小于100的正方形
这里写图片描述
glm::lookAt 用于相机定位

glm::perspective用于相机视角设置

#define GLEW_STATIC#include <GL/glew.h>#include <GLFW/glfw3.h>#include <glm/glm.hpp>#include <glm/gtc/matrix_transform.hpp>#include <glm/gtc/type_ptr.hpp>#include <SOIL/SOIL.h>#include "Shader.h"#include <stdio.h>#include <Windows.h>#include <math.h>#pragma comment(lib, "SOIL.lib")#pragma comment (lib, "opengl32.lib")#pragma comment (lib, "glew32s.lib")#pragma comment (lib, "glfw3.lib") #pragma comment (lib, "glfw3dll.lib") #pragma comment (lib, "glew32mxs.lib")#pragma comment (lib, "assimp.lib")#define  WIDTH 500#define  HEIGH 500glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 50.0f); // 相机距离原点50glm::vec3 cameraTarg = glm::vec3(0.0f, 0.0f, 0.0f);glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);glm::vec4  mousePos;GLfloat fRotateAngle = 0.0f;void keyFun(GLFWwindow* pWnd, int nKey, int nScanCode, int nAction, int nMode);void mouseFun(GLFWwindow* pWnd, int, int, int);void cursorFun(GLFWwindow* window, double x, double y);//////////////////////////////////int main(){    glfwInit();    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);    GLFWwindow* pWnd = glfwCreateWindow(WIDTH, HEIGH, "OGL Geometry Shader", nullptr, nullptr);    glfwMakeContextCurrent(pWnd);    glfwSetKeyCallback(pWnd, keyFun);    glfwSetCursorPosCallback(pWnd, cursorFun);    glfwSetMouseButtonCallback(pWnd, mouseFun);    glewExperimental = GL_TRUE;    glewInit();    glViewport(0, 0, WIDTH, HEIGH);#if 0    // 在原点处绘图,即离相机50, 将Y值稍微缩小,便于显示    GLfloat cube[] = {        -49.0f, -49.0f, -0.0f,   49.0f, -49.0f,-0.0f,        49.0f, -49.0f,-0.0f,     49.0f, 49.0f,-0.0f,        49.0f, 49.0f,-0.0f,     -49.0f, -49.0f, -0.0f,        -49.0f, -49.0f, -0.0f,   -49.0f, 49.0f,-0.0f,        -49.0f, 49.0f, -0.0f,   49.0f, 49.0f,-0.0f,        -49.0f, 49.0f, -0.0f,  49.0f, -49.0f, -0.0f,    };#else    // 在z -50 处绘图,即离相机100,将Y值稍微缩小,便于显示    GLfloat cube[] = {        -99.0f, -99.0f, -50.0f,   99.0f, -99.0f,-50.0f,        99.0f, -99.0f,-50.0f,    99.0f, 99.0f,-50.0f,        99.0f, 99.0f,-50.0f,        -99.0f, -99.0f, -50.0f,        -99.0f, -99.0f, -50.0f,   -99.0f, 99.0f,-50.0f,        -99.0f, 99.0f, -50.0f,   99.0f, 99.0f,-50.0f,        -99.0f, 99.0f, -50.0f,  99.0f, -99.0f, -50.0f,    };#endif    GLuint nVAO, nVBO;    glGenVertexArrays(1, &nVAO);    glBindVertexArray(nVAO);    {        glGenBuffers(1, &nVBO);        glBindBuffer(GL_ARRAY_BUFFER, nVBO);        {            glBufferData(GL_ARRAY_BUFFER, sizeof(cube), &cube[0], GL_STATIC_DRAW);            glEnableVertexAttribArray(0);   // vertex            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0);        }        glBindBuffer(GL_ARRAY_BUFFER, 0);    }    glBindVertexArray(0);    Shader shader("./Shader/vertex.vx", "./Shader/frag.fg");    shader.userShaderProg();    glm::mat4 model;        // 模型矩阵    glm::mat4 view;         // 视图矩阵    // 投影矩阵                 视角      宽高比                     近        远截面    // 侧视图    glm::mat4 proj = glm::perspective(3.141592f/2.0f, GLfloat(WIDTH / HEIGH), 1.0f, 200.0f);    GLint nModelLoc = glGetUniformLocation(shader.getProg(), "model");    GLint nViewLoc = glGetUniformLocation(shader.getProg(), "view");    GLint nProjLoc = glGetUniformLocation(shader.getProg(), "projection");    // 将矩阵传至Shader    glUniformMatrix4fv(nModelLoc, 1, GL_FALSE, glm::value_ptr(model));    glUniformMatrix4fv(nViewLoc, 1, GL_FALSE, glm::value_ptr(view));    glUniformMatrix4fv(nProjLoc, 1, GL_FALSE, glm::value_ptr(proj));    while (!glfwWindowShouldClose(pWnd))    {        glfwPollEvents();        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);        glClear(GL_COLOR_BUFFER_BIT);        view = glm::lookAt(cameraPos, cameraTarg, cameraUp);        glUniformMatrix4fv(nViewLoc, 1, GL_FALSE, glm::value_ptr(view));        glBindVertexArray(nVAO);        {            glDrawArrays(GL_LINES, 0, sizeof(cube)/sizeof(GLfloat)/3);        }        glBindVertexArray(0);        glfwSwapBuffers(pWnd);    }    return 0;}void keyFun(GLFWwindow* pWnd, int nKey, int nScanCode, int nAction, int nMode){    if (nAction == GLFW_PRESS)    {        if (nKey == GLFW_KEY_W)        {            // 物体到相机的单位向量            glm::vec3 direction = glm::normalize(cameraTarg - cameraPos);            direction *= 0.1;   // 移动0.1个单位向量            cameraPos += direction;        }        else if (nKey == GLFW_KEY_S)        {            glm::vec3 direction = glm::normalize(cameraTarg - cameraPos);            direction *= 0.1;            cameraPos -= direction;        }        else if (nKey == GLFW_KEY_A)        {            // 物体到相机的单位向量            glm::vec3 direction = glm::normalize(cameraTarg - cameraPos);            // 物体到相机的单位向量 与 相机的向上向量相乘,得到垂直向量,即平移向量            glm::vec3 vertical = glm::normalize(glm::cross(direction, cameraUp));            vertical *= 0.1;            cameraPos += vertical;  // 移动相机位置            cameraTarg += vertical; //相机的指向位置也一起平衡(不平移则以原来的目标转圈)        }        else if (nKey == GLFW_KEY_D)        {            glm::vec3 direction = glm::normalize(cameraTarg - cameraPos);            glm::vec3 vertical = glm::normalize(glm::cross(direction, cameraUp));            vertical *= 0.1;            cameraPos -= vertical;            cameraTarg -= vertical;        }        else if (nKey == GLFW_KEY_Q)        {            GLfloat radius = glm::distance(cameraPos, cameraTarg);            fRotateAngle += 0.1;            GLfloat camX = sin(fRotateAngle) * radius + cameraTarg.x;            GLfloat camZ = cos(fRotateAngle) * radius + cameraTarg.z;            cameraPos = glm::vec3(camX, 0.0, camZ);        }        else if (nKey == GLFW_KEY_E)        {            GLfloat radius = glm::distance(cameraPos, cameraTarg);            fRotateAngle -= 0.1;            GLfloat camX = sin(fRotateAngle) * radius + cameraTarg.x;            GLfloat camZ = cos(fRotateAngle) * radius + cameraTarg.z;            cameraPos = glm::vec3(camX, 0.0, camZ);        }        else if (nKey == GLFW_KEY_X)    // 还原视图        {            cameraPos = glm::vec3(0.0f, 0.0f, 5.0f);            cameraTarg = glm::vec3(0.0f, 0.0f, 0.0f);        }    }}void mouseFun(GLFWwindow* window, int button, int action, int mods){    if (action == GLFW_PRESS)    {        switch (button)        {        case GLFW_MOUSE_BUTTON_LEFT:        {            //printf("Screen X:%.3f Y:%.3f\t\tOGL X:%.3f, Y:%.3f\t\t\tLeft button clicked!\n", mousePos.x, mousePos.y, mousePos.z, mousePos.w);            float mouseX = mousePos.x / (WIDTH  * 0.5f) - 1.0f;            float mouseY = mousePos.y / (HEIGH * 0.5f) - 1.0f;            //mouseX = mousePos.z;            //mouseY = -mousePos.w;            //printf("mouse X:%.3f mouseY:%.3f \n", mouseX, mouseY);            glm::mat4 proj = glm::perspective(45.0f, GLfloat(WIDTH / HEIGH), 1.0f, -100.0f);            glm::mat4 view = glm::lookAt(cameraPos, cameraTarg, cameraUp);            glm::mat4 invVP = glm::inverse(proj * view);            glm::vec4 screenPos = glm::vec4(mouseX, -mouseY, 1.0f, 1.0f);            glm::vec4 worldPos = invVP * screenPos;            glm::vec3 dir = glm::normalize(glm::vec3(worldPos));            printf("dir X:%.3f dir:%.3f dir:%.3f\n", dir.x, dir.y, dir.z);        }        break;        case GLFW_MOUSE_BUTTON_MIDDLE:            printf("Middle button clicked!\n");            break;        case GLFW_MOUSE_BUTTON_RIGHT:            system("cls");            printf("Right button clicked!\n");            break;        default:            printf("Default \n");            return;        }    }    return;}void cursorFun(GLFWwindow* window, double x, double y){    float xpos = float((x - WIDTH / 2) / WIDTH) * 2;    float ypos = float(0 - (y - HEIGH / 2) / HEIGH) * 2;    //printf("Mouse position move to [ %.3f : %.3f ]\n", xpos, ypos);    mousePos = glm::vec4(x, y, xpos, ypos);    return;}

源码:
http://download.csdn.net/download/yulinxx/9975863

原创粉丝点击