OpenGL键盘 WSADQE进行旋转缩放平移简单操作

http://blog.csdn.net/yulinxx/article/details/59538755

在上篇的基础上,添加键盘的控制,实现物体的缩放,平移,旋转操作

这里写图片描述

这里写图片描述
分析:
放大: 当摄像机沿Z轴靠近物体,则物体显示会变大,反之则小
左右平移: 摄像机往左移,则看到的物体往右移
旋转: 以相机到物体的距离为半径进行旋转
当旋转后,再平移,比如相机到了b位置,再平移,以绿线为向量进行平移. 已知相机到物体的向量,已知相机的向上up向量0,1,0,可以叉乘得到垂直的绿线向量,再以此向量进行平移即可.
旋转后的放大缩小,则以相机到物体的向量进行平移.
代码如下:
定义两个全局变量:
glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 3.0f); // 相机位置
glm::vec3 cameraTarg = glm::vec3(0.0f, 0.0f, 0.0f); // 物体位置

WSAD移动相机, QE旋转相机,X还原视图

这里写图片描述

#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"

#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 800
#define  HEIGH 600


GLfloat g_nX = 0;
GLfloat g_nY = 0;
GLfloat g_nZ = 0;

glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 3.0f);
glm::vec3 cameraTarg = glm::vec3(0.0f, 0.0f, 0.0f);

//glm::mat4 view;           // 视图矩阵
GLfloat fRotateAngle = 0.0f;

void keyFun(GLFWwindow* pWnd, int nKey, int nScanCode, int nAction, int nMode);

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

    glewExperimental = GL_TRUE;

    glewInit();

    glViewport(0, 0, WIDTH, HEIGH); 

    GLfloat fPoint[] = {
        0.0f, 0.0f, 0.0f,       1.0f, 0.0f, 0.0f,
        0.5f, -0.6f, 0.0f,      0.0f, 1.0f, 0.0f,
        0.5f, 0.5f, 0.0f,       0.0f, 0.0f, 1.0f,
        -0.5f, 0.6f, 0.0f,      0.0f, 1.0f, 1.0f,
        -0.2f, -0.5f, 0.0f, 0.0f, 0.4f, 1.0f,
        - 0.8f, 0.3f, 0.0f,     1.0f, 0.30f, 1.0f   };

    GLuint nVAO, nVBO;
    glGenVertexArrays(1, &nVAO);
    glBindVertexArray(nVAO);
    {
        glGenBuffers(1, &nVBO);
        glBindBuffer(GL_ARRAY_BUFFER, nVBO);
        {
            glBufferData(GL_ARRAY_BUFFER, sizeof(fPoint), fPoint, GL_STATIC_DRAW);

            glEnableVertexAttribArray(0);   // vertex
            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6* sizeof(GLfloat), (GLvoid*)0);

            glEnableVertexAttribArray(1);   // color
            glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6* sizeof(GLfloat), (GLvoid*)(3 * sizeof(GL_FLOAT)));
        }
        glBindBuffer(GL_ARRAY_BUFFER, 0);
    }
    glBindVertexArray(0);

    glEnable(GL_PROGRAM_POINT_SIZE);

    //Shader shader("./Shader/vertex.vx", "./Shader/geo.geo", "./Shader/frag.fg");
    Shader shader("./Shader/vertex.vx", "./Shader/frag.fg");
    shader.userShaderProg();

    glm::mat4 model;        // 模型矩阵
    glm::mat4 view;         // 视图矩阵
    // 后移(观察点与物体在同一平面)  否则无法显示物体
    view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));

    // 投影矩阵                 视角      宽高比                     近        远截面
    glm::mat4 proj = glm::perspective(45.0f, GLfloat(WIDTH / HEIGH), 0.1f, 100.0f);

    // 获取Shader中 uniform 变量位置
    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));

    GLfloat radius = 6.0f;

    while (!glfwWindowShouldClose(pWnd))
    {
        glfwPollEvents();

        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        GLfloat camX = sin(glfwGetTime()) * radius;
        GLfloat camZ = cos(glfwGetTime()) * radius;

        view = glm::lookAt(cameraPos, cameraTarg, glm::vec3(0.0, 1.0, 0.0));
        glUniformMatrix4fv(nViewLoc, 1, GL_FALSE, glm::value_ptr(view));

        glBindVertexArray(nVAO);
        {
            //glDrawArrays(GL_TRIANGLES, 0, sizeof(fPoint) / sizeof(GLfloat) / 6);
            //glDrawArrays(GL_POINTS, 0, sizeof(fPoint) / sizeof(GLfloat) / 6);
            glDrawArrays(GL_LINE_STRIP, 0, sizeof(fPoint) / sizeof(GLfloat) / 6);
        }
        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.2;   // 移动0.2个单位向量
            cameraPos += direction;
        }
        else if (nKey == GLFW_KEY_S)
        {
            glm::vec3 direction = glm::normalize(cameraTarg - cameraPos);
            direction *= 0.2;
            cameraPos -= direction;
        }
        else if (nKey == GLFW_KEY_A)
        {
            // 物体到相机的单位向量
            glm::vec3 direction = glm::normalize(cameraTarg - cameraPos);
            // 物体到相机的单位向量 与 相机的向上向量相乘,得到垂直向量,即平移向量
            glm::vec3 vertical = glm::normalize(glm::cross(direction, glm::vec3(0.0f, 1.0f, 0.0f)));
            vertical *= 0.2;
            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, glm::vec3(0.0f, 1.0f, 0.0f)));
            vertical *= 0.2;
            cameraPos -= vertical;
            cameraTarg -= vertical;
        }
        else if (nKey == GLFW_KEY_Q)
        {
            GLfloat radius = glm::distance(cameraPos, cameraTarg);
            fRotateAngle += 0.2;

            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.2;

            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, 3.0f);
            cameraTarg = glm::vec3(0.0f, 0.0f, 0.0f);
        }
    }
}

这里写图片描述

源码下载:
http://download.csdn.net/detail/yulinxx/9769945

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值