zoukankan      html  css  js  c++  java
  • [LearnOpenGL]照相机的变换、坐标系、摄像机

    前言

    跟着LearnOpenGL上学着做项目,的确对于知识掌握得更清晰一些了。

    第一个项目

    第一个项目,是关于简单的熟悉矩阵变换的,创建了10个立方体,代码如下。

     // 视图矩阵,看作是一个照相机
    glm::mat4 view;
    view = glm::translate(view, glm::vec3(0.0f, 0.0f, -6.0f));
    view = glm::rotate(view, glm::radians(15.0f), glm::vec3(0.0f, 0.0f, 1.0f));
    
    // 模型矩阵
    glm::mat4 projection;
    projection = glm::perspective(glm::radians(45.0f), static_cast<GLfloat>(WIDTH) / static_cast<GLfloat>(HEIGHT), 0.001f, 100.0f);
    
    glUniformMatrix4fv(glGetUniformLocation(shader.program, "view"), 1, GL_FALSE, glm::value_ptr(view));
    glUniformMatrix4fv(glGetUniformLocation(shader.program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
    
    while (!glfwWindowShouldClose(window))
    {
        glfwPollEvents();
        
        // 因为已经涉及到了3d,所以需要开启深度测试,并且要每一帧都要清除颜色缓存和深度缓存
        
        glClearColor(0.298f, 0.451f, 0.773f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        
        glBindVertexArray(VAO);
        
        // 创建10个正方体
        for (GLuint i = 0; i < 10; ++i) {
            glm::mat4 model;
            model = glm::translate(model, cubePositions[i]);
            
            if (i % 2) {
                // 固定的旋转的角度
                model = glm::rotate(model, glm::radians(20.0f * i), glm::vec3(0.0f, 0.3f, 0.5f));
            }
            else {
                // 随时间旋转的角度
                model = glm::rotate(model, glm::radians<GLfloat>(glfwGetTime() * 20.0f), glm::vec3(0.0f, 1.0f, 0.5f));
            }
            
            glUniformMatrix4fv(glGetUniformLocation(shader.program, "model"), 1, GL_FALSE, glm::value_ptr(model));
            
            // 一个四边形由两个三角形组成,两个三角形则包括了6个索引,所以6个面则需要36个索引
            glDrawArrays(GL_TRIANGLES, 0, 36);
        }
        
        glBindVertexArray(0);
    
        glfwSwapBuffers(window);
    }
     
    

    第二个项目

    这个项目稍微复杂,涉及到了坐标系,摄像机的知识。

    #include <iostream>
    #define GLEW_STATIC
    #include <GL/glew.h>
    #include <GLFW/glfw3.h>
    #include "SOIL.h"
    #include "Shader.h"
    
    #include <glm/glm.hpp>
    #include <glm/gtc/matrix_transform.hpp>
    #include <glm/gtc/type_ptr.hpp>
    
    const GLuint WIDTH = 800, HEIGHT = 600;
    GLfloat mixValue = 0.2f;
    
    //------------------------------------2.----------------------------------
    glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 3.0f);
    // 为什么是负的呢,因为要知道摄像机指向的是z轴的负方向
    glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f);
    glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);
    
    //------------------------------------3.----------------------------------
    bool keys[1024];//用来存储哪些按键被按下
    
    //------------------------------------4.----------------------------------
    GLfloat deltaTime = 0.0f; //当前帧和上一帧的时间差
    GLfloat lastFrame  = 0.0f; //上一帧时间
    
    //------------------------------------5.----------------------------------
    GLfloat yaw   = -90.0f;	// Yaw is initialized to -90.0 degrees since a yaw of 0.0 results in a direction vector pointing to the right (due to how Eular angles work) so we initially rotate a bit to the left.
    //为偏航角
    GLfloat pitch =   0.0f; //为俯仰角
    GLfloat lastX =  WIDTH  / 2.0;
    GLfloat lastY =  HEIGHT / 2.0;
    bool firstMouse = true;
    
    GLfloat fov = 1.0f;
    
    void isDoMovement() {
        //------------------------------------3.----------------------------------
    //    GLfloat speed = 0.2f;
        
        //------------------------------------4.----------------------------------
        GLfloat speed = 5.0f * deltaTime;
        
        // 照相机向z轴负方向移动
        if (keys[GLFW_KEY_W]) {
            cameraPos += cameraFront * speed;
        }
        // 照相机向z轴正方向移动
        else if (keys[GLFW_KEY_S]) {
            cameraPos -= cameraFront * speed;
        }
        // 照相机向x轴负方向
        else if (keys[GLFW_KEY_A]) {
            //cross表示叉乘,求出对于参数中的两个向量都垂直的向量,求完了以后还需要进行归一化得到向量
            cameraPos -= glm::normalize(glm::cross(cameraFront, cameraUp)) * speed;
        }
        // 照相机向x轴正方向
        else if (keys[GLFW_KEY_D]) {
            cameraPos += glm::normalize(glm::cross(cameraFront, cameraUp)) * speed;
        }
    }
    
    void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) {
        if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
    		glfwSetWindowShouldClose(window, GL_TRUE);
        }
        
    //	if (key == GLFW_KEY_UP && action == GLFW_PRESS)
    //	{
    //		mixValue += 0.1f;
    //		if (mixValue >= 1.0f)
    //			mixValue = 1.0f;
    //	}
    //	if (key == GLFW_KEY_DOWN && action == GLFW_PRESS)
    //	{
    //		mixValue -= 0.1f;
    //		if (mixValue <= 0.0f)
    //			mixValue = 0.0f;
    //	}
        
        //------------------------------------2.----------------------------------
    //    GLfloat speed = 0.2f;
    //    
    //    // 照相机向z轴负方向移动
    //    if (key == GLFW_KEY_W) {
    //        cameraPos += cameraFront * speed;
    //    }
    //    // 照相机向z轴正方向移动
    //    else if (key == GLFW_KEY_S) {
    //        cameraPos -= cameraFront * speed;
    //    }
    //    // 照相机向x轴负方向
    //    else if (key == GLFW_KEY_A) {
    //        //cross表示叉乘,求出对于参数中的两个向量都垂直的向量,求完了以后还需要进行归一化得到向量
    //        cameraPos -= glm::normalize(glm::cross(cameraFront, cameraUp)) * speed;
    //    }
    //    // 照相机向x轴正方向
    //    else if (key == GLFW_KEY_D) {
    //        cameraPos += glm::normalize(glm::cross(cameraFront, cameraUp)) * speed;
    //    }
        
    
        //------------------------------------3.----------------------------------
        // 在第三种方法中,这个函数用来监听
        // 先判断有没有按下,不再按下的时候,把该按下的按键进行重置
        if(action == GLFW_PRESS) {
            // 照相机向z轴负方向移动
            if (key == GLFW_KEY_W) {
                keys[key] = true;
            }
        // 照相机向z轴正方向移动
            else if (key == GLFW_KEY_S) {
                keys[key] = true;
            }
        // 照相机向x轴负方向
            else if (key == GLFW_KEY_A) {
                //cross表示叉乘,求出对于参数中的两个向量都垂直的向量,求完了以后还需要进行归一化得到向量
                keys[key] = true;
            }
        // 照相机向x轴正方向
            else if (key == GLFW_KEY_D) {
                keys[key] = true;
            }
        }
        else if(action == GLFW_RELEASE) {
            keys[key] = false;
        }
    }
    
    //------------------------------------5.----------------------------------
    // 其中的xpos和ypos代表的是鼠标x和y的位置,摄像头上下左右指向
    void mouse_callback(GLFWwindow* window, double xpos, double ypos) {
        // 第一次移动鼠标
        if(firstMouse)
        {
            //对上一帧x和y的方向上的位置进行赋值
            lastX = xpos;
            lastY = ypos;
            firstMouse = false;
        }
        
        GLfloat xoffset = xpos - lastX;//计算x轴上的偏移量
        GLfloat yoffset = lastY - ypos;//计算y轴上的偏移量
        lastX = xpos;
        lastY = ypos;
        
        GLfloat sensitivity = 0.05;
        xoffset *= sensitivity;
        yoffset *= sensitivity;
        
        yaw   += xoffset;
        pitch += yoffset;
        
        if(pitch > 89.0f)
            pitch = 89.0f;
        if(pitch < -89.0f)
            pitch = -89.0f;
        
        glm::vec3 front;
        front.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));//同求z的原理
        front.y = sin(glm::radians(pitch)); // 以xz作为一个平面,y轴向上,形成一个三角形,可以用sin求出俯仰角的移动
        front.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));// cos则可以求出xz平面,其中xz平面,z轴向上,x轴向右,可以根据sin偏航角计算出z
        cameraFront = glm::normalize(front); //归一化
    }
    
    //摄像头靠近或者进行远离
    void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
    {
        if(fov >= 1.0f && fov <= 45.0f)
            fov -= yoffset * 0.05f; //如果在规定的fov范围,可以进行减小,超过则进行重置
        if(fov <= 1.0f)
            fov = 1.0f;
        if(fov >= 45.0f)
            fov = 45.0f;
    }
    
    
    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* window = glfwCreateWindow(WIDTH, HEIGHT, "OpenGL", nullptr, nullptr);
    	if (window == nullptr)
    	{
    		std::cout << "Failed to create GLFW window" << std::endl;
    		glfwTerminate();
    		return -1;
    	}
    	glfwMakeContextCurrent(window);
    
    	glfwSetKeyCallback(window, key_callback);
        
        glfwSetCursorPosCallback(window, mouse_callback);
        glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
        glfwSetScrollCallback(window, scroll_callback);
    
    	glewExperimental = GL_TRUE;
    	if (glewInit() != GLEW_OK)
    	{
    		std::cout << "Failed to initialize GLEW" << std::endl;
    		return -1;
    	}
    
    	glViewport(0, 0, WIDTH, HEIGHT);
    
    	// ¯ÂȉÂ˚
    	Shader shader("/Users/staff/Desktop/practise/fgh/fgh/vertexShader.vsh", "/Users/staff/Desktop/practise/fgh/fgh/fragmentShader.fsh");
    
    	// ÚÂÍÒÚÛ‡ 1
    	GLuint texture1;
    	glGenTextures(1, &texture1);
    	glBindTexture(GL_TEXTURE_2D, texture1);
    
    	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    
    	int width, height;
    	unsigned char* image = SOIL_load_image("/Users/staff/Desktop/practise/fgh/fgh/wall.jpg", &width, &height, 0, SOIL_LOAD_RGB);
    	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
    	glGenerateMipmap(GL_TEXTURE_2D);
    	SOIL_free_image_data(image);
    	glBindTexture(GL_TEXTURE_2D, 0);
    
    	// ÚÂÍÒÚÛ‡ 2
    	GLuint texture2;
    	glGenTextures(1, &texture2);
    	glBindTexture(GL_TEXTURE_2D, texture2);
    
    	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
    
    	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    
    	image = SOIL_load_image("/Users/staff/Desktop/practise/fgh/fgh/awesomeface.png", &width, &height, 0, SOIL_LOAD_RGBA);
    	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
    	glGenerateMipmap(GL_TEXTURE_2D);
    	SOIL_free_image_data(image);
    	glBindTexture(GL_TEXTURE_2D, 0);
    
        // 6个面上的顶点信息
        GLfloat vertices[] = {
            // Positions          // Texture Coords    //colors
            -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,     1.0f, 1.0f, 1.0f,
            0.5f, -0.5f, -0.5f,  1.0f, 0.0f,      1.0f, 1.0f, 1.0f,
            0.5f,  0.5f, -0.5f,  1.0f, 1.0f,      1.0f, 1.0f, 1.0f,
            0.5f,  0.5f, -0.5f,  1.0f, 1.0f,      1.0f, 1.0f, 1.0f,
            -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,     1.0f, 1.0f, 1.0f,
            -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,     1.0f, 1.0f, 1.0f,
            
            -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,     1.0f, 1.0f, 1.0f,
            0.5f, -0.5f,  0.5f,  1.0f, 0.0f,      1.0f, 1.0f, 1.0f,
            0.5f,  0.5f,  0.5f,  1.0f, 1.0f,      1.0f, 1.0f, 1.0f,
            0.5f,  0.5f,  0.5f,  1.0f, 1.0f,      1.0f, 1.0f, 1.0f,
            -0.5f,  0.5f,  0.5f,  0.0f, 1.0f,     1.0f, 1.0f, 1.0f,
            -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,     1.0f, 1.0f, 1.0f,
            
            -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,     1.0f, 1.0f, 1.0f,
            -0.5f,  0.5f, -0.5f,  1.0f, 1.0f,     1.0f, 1.0f, 1.0f,
            -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,     1.0f, 1.0f, 1.0f,
            -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,     1.0f, 1.0f, 1.0f,
            -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,     1.0f, 1.0f, 1.0f,
            -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,     1.0f, 1.0f, 1.0f,
            
            0.5f,  0.5f,  0.5f,  1.0f, 0.0f,      1.0f, 1.0f, 1.0f,
            0.5f,  0.5f, -0.5f,  1.0f, 1.0f,      1.0f, 1.0f, 1.0f,
            0.5f, -0.5f, -0.5f,  0.0f, 1.0f,      1.0f, 1.0f, 1.0f,
            0.5f, -0.5f, -0.5f,  0.0f, 1.0f,      1.0f, 1.0f, 1.0f,
            0.5f, -0.5f,  0.5f,  0.0f, 0.0f,      1.0f, 1.0f, 1.0f,
            0.5f,  0.5f,  0.5f,  1.0f, 0.0f,      1.0f, 1.0f, 1.0f,
            
            -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,     1.0f, 1.0f, 1.0f,
            0.5f, -0.5f, -0.5f,  1.0f, 1.0f,      1.0f, 1.0f, 1.0f,
            0.5f, -0.5f,  0.5f,  1.0f, 0.0f,      1.0f, 1.0f, 1.0f,
            0.5f, -0.5f,  0.5f,  1.0f, 0.0f,      1.0f, 1.0f, 1.0f,
            -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,     1.0f, 1.0f, 1.0f,
            -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,     1.0f, 1.0f, 1.0f,
            
            -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,     1.0f, 1.0f, 1.0f,
            0.5f,  0.5f, -0.5f,  1.0f, 1.0f,      1.0f, 1.0f, 1.0f,
            0.5f,  0.5f,  0.5f,  1.0f, 0.0f,      1.0f, 1.0f, 1.0f,
            0.5f,  0.5f,  0.5f,  1.0f, 0.0f,      1.0f, 1.0f, 1.0f,
            -0.5f,  0.5f,  0.5f,  0.0f, 0.0f,     1.0f, 1.0f, 1.0f,
            -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,     1.0f, 1.0f, 1.0f
        };
    
        
    	GLuint VBO, VAO, EBO;
    	glGenVertexArrays(1, &VAO);
    	glGenBuffers(1, &VBO);
    	glGenBuffers(1, &EBO);
    
    	glBindVertexArray(VAO);
    
    	glBindBuffer(GL_ARRAY_BUFFER, VBO);
    	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    
        GLuint _positionSlot = glGetAttribLocation(shader.program, "position");
        GLuint _colorSlot = glGetAttribLocation(shader.program, "color");
        GLuint _textureCoordsSlot = glGetAttribLocation(shader.program, "texCoord");
        //GLuint _textureSlot = glGetUniformLocation(shader.program, "ourTexture");
        
    	glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
    	glEnableVertexAttribArray(_positionSlot);
    
        glVertexAttribPointer(_textureCoordsSlot, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
        glEnableVertexAttribArray(_textureCoordsSlot);
        
        glVertexAttribPointer(_colorSlot, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
        glEnableVertexAttribArray(_colorSlot);
        
    	glBindVertexArray(0);
        
        // 10个立方体的位置
        glm::vec3 cubePositions[] = {
            glm::vec3(0.0f,  0.0f,  0.0f),
            glm::vec3(2.0f,  5.0f, -15.0f),
            glm::vec3(-1.5f, -2.2f, -2.5f),
            glm::vec3(-3.8f, -2.0f, -12.3f),
            glm::vec3(2.4f, -0.4f, -3.5f),
            glm::vec3(-1.7f,  3.0f, -7.5f),
            glm::vec3(1.3f, -2.0f, -2.5f),
            glm::vec3(1.5f,  2.0f, -2.5f),
            glm::vec3(1.5f,  0.2f, -1.5f),
            glm::vec3(-1.3f,  1.0f, -1.5f)
        };
    
    	while (!glfwWindowShouldClose(window))
    	{
    		glfwPollEvents();
            //------------------------------------4.----------------------------------
            GLfloat curTime = glfwGetTime();
            deltaTime = curTime - lastFrame;
            lastFrame = curTime;
            
            //------------------------------------3.----------------------------------
            isDoMovement();
            
            // 因为已经涉及到了3d,所以需要开启深度测试,并且要每一帧都要清除颜色缓存和深度缓存
            
    		glClearColor(0.298f, 0.451f, 0.773f, 1.0f);
    		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
            
            shader.use();
            
            glEnable(GL_DEPTH_TEST);
            glEnable(GL_BLEND);
            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
            
            glActiveTexture(GL_TEXTURE0);
            glBindTexture(GL_TEXTURE_2D, texture1);
            glUniform1i(glGetUniformLocation(shader.program, "ourTexture1"), 0);
            glActiveTexture(GL_TEXTURE1);
            glBindTexture(GL_TEXTURE_2D, texture2);
            glUniform1i(glGetUniformLocation(shader.program, "ourTexture2"), 1);
            glUniform1f(glGetUniformLocation(shader.program, "mixValue"), mixValue);
            
            //----------------------------------------1.-------------------------------------------
            glm::mat4 view;
            // 照相机向量
    //        GLfloat radius = 20.0f;
    //        GLfloat camX = sinf(glfwGetTime()) * radius;
    //        GLfloat camZ = cosf(glfwGetTime()) * radius;
    //        // 首先要知道lookAt函数的参数的意思,分别是eye,center,up,分别代表的是摄像机的位置向量,目标,上向量
    //        // 这里实现的是照相机绕着顶点(0,0,0)进行旋转
    //        view = glm::lookAt(glm::vec3(camX, 0.0f, camZ), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
            
            //----------------------------------------2.-------------------------------------------
            //view = glm::lookAt(cameraPos, glm::vec3(0.0f, 0.0f, 0.0f), cameraUp);
            
            //----------------------------------------5.-------------------------------------------
            view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);
            
            // 模型矩阵
            glm::mat4 projection;
            
            
    //        projection = glm::perspective(glm::radians(45.0f), static_cast<GLfloat>(WIDTH) / static_cast<GLfloat>(HEIGHT), 0.001f, 100.0f);
            
            //----------------------------------------5.-------------------------------------------
            projection = glm::perspective(fov, (GLfloat)WIDTH/(GLfloat)HEIGHT, 0.1f, 100.0f);
            
            glUniformMatrix4fv(glGetUniformLocation(shader.program, "view"), 1, GL_FALSE, glm::value_ptr(view));
            glUniformMatrix4fv(glGetUniformLocation(shader.program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
            
            glBindVertexArray(VAO);
            // 创建10个正方体
            for (GLuint i = 0; i < 10; ++i) {
                glm::mat4 model;
                model = glm::translate(model, cubePositions[i]);
                
                if (i % 2) {
                    // 固定的旋转的角度
                    model = glm::rotate(model, glm::radians(20.0f * i), glm::vec3(0.0f, 0.3f, 0.5f));
                }
                else {
                    // 随时间旋转的角度
                    model = glm::rotate(model, glm::radians<GLfloat>(glfwGetTime() * 20.0f), glm::vec3(0.0f, 1.0f, 0.5f));
                }
                
                glUniformMatrix4fv(glGetUniformLocation(shader.program, "model"), 1, GL_FALSE, glm::value_ptr(model));
                
                // 一个四边形由两个三角形组成,两个三角形则包括了6个索引,所以6个面则需要36个索引
                glDrawArrays(GL_TRIANGLES, 0, 36);
            }
            
    		glBindVertexArray(0);
    
    		glfwSwapBuffers(window);
    	}
    
    	// Û‰‡ÎˇÂÏ, Á‡‚Â¯‡ÂÏ
    	glDeleteVertexArrays(1, &VAO);
    	glDeleteBuffers(1, &VBO);
    	glDeleteBuffers(1, &EBO);
    
    	glfwTerminate();
    
    	return 0;
    }
    
    

    这里面的1,2,3,4,5分别是版本的演化;

    1. 其中1是最开始的版本:增加了照相机向量,不过是固定的;
    2. 其中2是增加了摄像机移动的功能;
    3. 其中3是因为2无法实现同时按下两个按键进行移动的功能,因为用数组进行记录,最后统一处理;
    4. 其中4是因为3中的移动距离在每个机器上都不太一样,有的会在同一时间段内比其他人绘制更多帧,导致运动速度会变得大,造成效果不好,因此,增加时间差,记录时间差,乘以固定的值,如果时间差变大时,意味着上一帧渲染时间多,那就会得到更高的移动速度,否之,则相反。这样就会和上一帧平衡了。这就好比走路和跑步,跑步的移动速度肯定是要高于走路,总不能要求走路和跑步的移动速度是一样的吧。
    5. 其中5则在之前的基础上增加了上下左右移动摄像机,以及通过滚轮实现靠近和远离的功能。这里面涉及到了许多的数学知识,不过不是很难,仔细看看教程还是能看懂的。

    教程地址

    第二个项目的延伸

    之所以说是延伸是因为,第二个项目所有东西都堆在了一起,耦合程度高,因此教程把这些都封装了起来。

    .h文件

    #pragma once
    #include <vector>
    #include <GL/glew.h>
    #include <glm/glm.hpp>
    #include <glm/gtc/matrix_transform.hpp>
    
    enum Camera_Movement {
    	FORWARD,
    	BACKWARD,
    	LEFT,
    	RIGHT
    };
    
    const GLfloat YAW = -90.0f;
    const GLfloat PITCH = 0.0f;
    const GLfloat SPEED = 3.0f;
    const GLfloat SENSITIVTY = 0.25f;
    const GLfloat ZOOM = 45.0f;
    
    class Camera {
    public:
    	glm::vec3 Position;
    	glm::vec3 Front;
    	glm::vec3 Up;
    	glm::vec3 Right;
    	glm::vec3 WorldUp;
    	GLfloat Yaw;
    	GLfloat Pitch;
    	GLfloat MovementSpeed;
    	GLfloat MouseSensitivity;
    	GLfloat Zoom;
    
    	Camera(glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f), GLfloat yaw = YAW, GLfloat pitch = PITCH);
    	Camera(GLfloat posX, GLfloat posY, GLfloat posZ, GLfloat upX, GLfloat upY, GLfloat upZ, GLfloat yaw, GLfloat pitch);
    	glm::mat4 GetViewMatrix();
    	// 处理按键事件
    	void ProcessKeyboard(Camera_Movement direction, GLfloat deltaTime);
    	// 处理鼠标移动事件
    	void ProcessMouseMovement(GLfloat xoffset, GLfloat yoffset, GLboolean constrainPitch = true);
    	// 处理鼠标滚动事件
    	void ProcessMouseScroll(GLfloat yoffset);
    private:
    	void updateCameraVectors();
    };
    
    

    .cpp文件

    #include "Camera.h"
    
    Camera::Camera(glm::vec3 position, glm::vec3 up, GLfloat yaw, GLfloat pitch)
    	: Front(glm::vec3(0.0f, 0.0f, -1.0f))
    	, MovementSpeed(SPEED)
    	, MouseSensitivity(SENSITIVTY)
    	, Zoom(ZOOM)
    {
    	Position = position;
    	WorldUp = up;
    	Yaw = yaw;
    	Pitch = pitch;
    	updateCameraVectors();
    }
    
    Camera::Camera(GLfloat posX, GLfloat posY, GLfloat posZ, GLfloat upX, GLfloat upY, GLfloat upZ, GLfloat yaw, GLfloat pitch) : Front(glm::vec3(0.0f, 0.0f, -1.0f)), MovementSpeed(SPEED), MouseSensitivity(SENSITIVTY), Zoom(ZOOM)
    {
    	Position = glm::vec3(posX, posY, posZ);
    	WorldUp = glm::vec3(upX, upY, upZ);
    	Yaw = yaw;
    	Pitch = pitch;
    	updateCameraVectors();
    }
    
    glm::mat4 Camera::GetViewMatrix() {
    	return glm::lookAt(Position, Position + Front, Up);
    }
    
    void Camera::ProcessKeyboard(Camera_Movement direction, GLfloat deltaTime) {
    	GLfloat velocity = MovementSpeed * deltaTime;
    	if (direction == FORWARD)
    		Position += glm::normalize(glm::cross(WorldUp, Right)) * velocity;
    	if (direction == BACKWARD)
    		Position -= glm::normalize(glm::cross(WorldUp, Right)) * velocity;
    	if (direction == LEFT)
    		Position -= Right * velocity;
    	if (direction == RIGHT)
    		Position += Right * velocity;
    }
    
    void Camera::ProcessMouseMovement(GLfloat xoffset, GLfloat yoffset, GLboolean constrainPitch) {
    	xoffset *= MouseSensitivity;
    	yoffset *= MouseSensitivity;
    
    	Yaw += xoffset;
    	Pitch += yoffset;
    
    	if (constrainPitch) {
    		if (Pitch > 89.0f)
    			Pitch = 89.0f;
    		if (Pitch < -89.0f)
    			Pitch = -89.0f;
    	}
    
    	updateCameraVectors();
    }
    
    void Camera::ProcessMouseScroll(GLfloat yoffset) {
    	if (Zoom >= 1.0f && Zoom <= 45.0f)
    		Zoom -= yoffset;
    	if (Zoom <= 1.0f)
    		Zoom = 1.0f;
    	if (Zoom >= 45.0f)
    		Zoom = 45.0f;
    }
    
    void Camera::updateCameraVectors() {
    	glm::vec3 front;
    	front.x = cos(glm::radians(Yaw)) * cos(glm::radians(Pitch));
    	front.y = sin(glm::radians(Pitch));
    	front.z = sin(glm::radians(Yaw)) * cos(glm::radians(Pitch));
    	Front = glm::normalize(front);
    	Right = glm::normalize(glm::cross(Front, WorldUp));
    	Up = glm::normalize(glm::cross(Right, Front));
    }
    
    
  • 相关阅读:
    zendstuido10 配置spket插件
    Extjs各版本的下载链接
    主题:Android、iPhone和Java三个平台一致的加密工具
    TestDisk 恢复rm -rf 的文件
    java实现定时任务的三种方法
    mac 下安装 lua5.3 + cjson
    Mac OS X 上Lua的安装方法
    Channel States
    JSON常见操作
    微信小程序——获取元素的宽高等属性
  • 原文地址:https://www.cnblogs.com/George1994/p/6391282.html
Copyright © 2011-2022 走看看