From 1c5b887de173b339826154ed5728d4268d07b39a Mon Sep 17 00:00:00 2001 From: iridiumR Date: Thu, 25 May 2023 16:55:12 +0800 Subject: [PATCH] feat(OpenGL-hello): camera --- OpenGL/hello/Makefile | 4 +- OpenGL/hello/include/camera.h | 148 ++++++++++++++++++++++++++++++++++ OpenGL/hello/include/source.h | 52 ++++++++++++ OpenGL/hello/src/main.cpp | 90 +++++++++------------ 4 files changed, 242 insertions(+), 52 deletions(-) create mode 100644 OpenGL/hello/include/camera.h create mode 100644 OpenGL/hello/include/source.h diff --git a/OpenGL/hello/Makefile b/OpenGL/hello/Makefile index ef54f9f..4f90704 100644 --- a/OpenGL/hello/Makefile +++ b/OpenGL/hello/Makefile @@ -11,7 +11,7 @@ LDFLAGS := $(shell pkg-config --static --libs glfw3) #编译工具链 CC := g++ #输出文件命名 -OUT := $(OUT_DIR)/lab1 +OUT := $(OUT_DIR)/hello #增加所有头文件所在的目录 # INC_DIR += ./include/glad @@ -55,6 +55,8 @@ nv:$(OUT) run:$(OUT) ./$(OUT) +all:$(OUT) + .PHONY:clean clean: rm -rf ./${OUT_DIR}/* diff --git a/OpenGL/hello/include/camera.h b/OpenGL/hello/include/camera.h new file mode 100644 index 0000000..928caac --- /dev/null +++ b/OpenGL/hello/include/camera.h @@ -0,0 +1,148 @@ +#ifndef CAMERA_H +#define CAMERA_H + +#include "glad/glad.h" +#include +#include +#include +#include + +// Defines several possible options for camera movement. Used as abstraction to +// stay away from window-system specific input methods +enum Camera_Movement { FORWARD, BACKWARD, LEFT, RIGHT }; + +// Default camera values +const float YAW = -90.0f; +const float PITCH = 0.0f; +const float SPEED = 2.5f; +const float SENSITIVITY = 0.1f; +const float ZOOM = 45.0f; + +// An abstract camera class that processes input and calculates the +// corresponding Euler Angles, Vectors and Matrices for use in OpenGL +class Camera { +public: + // camera Attributes + glm::vec3 Position; + glm::vec3 Front; + glm::vec3 Up; + glm::vec3 Right; + glm::vec3 WorldUp; + // euler Angles + float Yaw; + float Pitch; + // camera options + float MovementSpeed; + float MouseSensitivity; + float Zoom; + + bool firstMouse; + float lastX, lastY; + + // constructor with vectors + Camera(float X, float Y, glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f), + glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f), float yaw = YAW, + float pitch = PITCH) + : Front(glm::vec3(0.0f, 0.0f, -1.0f)), MovementSpeed(SPEED), + MouseSensitivity(SENSITIVITY), Zoom(ZOOM) { + lastX = X; + lastY = Y; + Position = position; + WorldUp = up; + Yaw = yaw; + Pitch = pitch; + updateCameraVectors(); + } + // constructor with scalar values + Camera(float posX, float posY, float posZ, float upX, float upY, float upZ, + float yaw, float pitch) + : Front(glm::vec3(0.0f, 0.0f, -1.0f)), MovementSpeed(SPEED), + MouseSensitivity(SENSITIVITY), Zoom(ZOOM) { + Position = glm::vec3(posX, posY, posZ); + WorldUp = glm::vec3(upX, upY, upZ); + Yaw = yaw; + Pitch = pitch; + updateCameraVectors(); + } + + // returns the view matrix calculated using Euler Angles and the LookAt Matrix + glm::mat4 GetViewMatrix() { + return glm::lookAt(Position, Position + Front, Up); + } + + // processes input received from any keyboard-like input system. Accepts input + // parameter in the form of camera defined ENUM (to abstract it from windowing + // systems) + void ProcessKeyboard(Camera_Movement direction, float deltaTime) { + float velocity = MovementSpeed * deltaTime; + if (direction == FORWARD) + Position += Front * velocity; + if (direction == BACKWARD) + Position -= Front * velocity; + if (direction == LEFT) + Position -= Right * velocity; + if (direction == RIGHT) + Position += Right * velocity; + } + + // processes input received from a mouse input system. Expects the offset + // value in both the x and y direction. + void ProcessMouseMovement(float xpos, float ypos, + GLboolean constrainPitch = true) { + if (firstMouse) { + lastX = xpos; + lastY = ypos; + firstMouse = false; + } + + float xoffset = xpos - lastX; + float yoffset = lastY - ypos; + lastX = xpos; + lastY = ypos; + + xoffset *= MouseSensitivity; + yoffset *= MouseSensitivity; + + Yaw += xoffset; + Pitch += yoffset; + + // make sure that when pitch is out of bounds, screen doesn't get flipped + if (constrainPitch) { + if (Pitch > 89.0f) + Pitch = 89.0f; + if (Pitch < -89.0f) + Pitch = -89.0f; + } + + // update Front, Right and Up Vectors using the updated Euler angles + updateCameraVectors(); + } + + // processes input received from a mouse scroll-wheel event. Only requires + // input on the vertical wheel-axis + void ProcessMouseScroll(float yoffset) { + Zoom -= (float)yoffset; + if (Zoom < 1.0f) + Zoom = 1.0f; + if (Zoom > 45.0f) + Zoom = 45.0f; + } + +private: + // calculates the front vector from the Camera's (updated) Euler Angles + void updateCameraVectors() { + // calculate the new Front vector + 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); + // also re-calculate the Right and Up vector + Right = glm::normalize(glm::cross( + Front, WorldUp)); // normalize the vectors, because their length gets + // closer to 0 the more you look up or down which + // results in slower movement. + Up = glm::normalize(glm::cross(Right, Front)); + } +}; +#endif \ No newline at end of file diff --git a/OpenGL/hello/include/source.h b/OpenGL/hello/include/source.h new file mode 100644 index 0000000..a657f15 --- /dev/null +++ b/OpenGL/hello/include/source.h @@ -0,0 +1,52 @@ +#include "camera.h" +#include "glad/glad.h" +#include "shader.h" +#include "stb_image.h" +#include +#include +#include +#include +#include +#include + +float vertices[] = { + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, + + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, + + -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, + 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, -0.5f, 1.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, + + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f}; + +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)}; + +float deltaTime = 0.0f; // 当前帧与上一帧的时间差 +float lastFrame = 0.0f; // 上一帧的时间 + +// settings +const unsigned int SCR_WIDTH = 800; +const unsigned int SCR_HEIGHT = 800; + +// 创建摄像机 +Camera camera = Camera(SCR_HEIGHT / 2.0f, SCR_HEIGHT / 2.0f); diff --git a/OpenGL/hello/src/main.cpp b/OpenGL/hello/src/main.cpp index be3dd31..14af8cf 100644 --- a/OpenGL/hello/src/main.cpp +++ b/OpenGL/hello/src/main.cpp @@ -1,51 +1,9 @@ -#include "glad/glad.h" -#include "shader.h" -#include "stb_image.h" -#include -#include -#include -#include -#include -#include - -float vertices[] = { - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, - - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, - - -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, - 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, -0.5f, 1.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, - - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f}; - -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)}; +#include "source.h" void framebuffer_size_callback(GLFWwindow *window, int width, int height); void processInput(GLFWwindow *window); - -// settings -const unsigned int SCR_WIDTH = 600; -const unsigned int SCR_HEIGHT = 600; +void mouse_callback(GLFWwindow *window, double xpos, double ypos); +void scroll_callback(GLFWwindow *window, double xoffset, double yoffset); int main() { @@ -73,7 +31,10 @@ int main() { } // 设置视口 + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); + glfwSetCursorPosCallback(window, mouse_callback); + glfwSetScrollCallback(window, scroll_callback); // 创建着色器程序 Shader shader = Shader("src/tex.vs", "src/tex.fs"); @@ -158,19 +119,23 @@ int main() { shader.setInt("texture2", 1); // create transformations - glm::mat4 view = glm::mat4(1.0f); + glm::mat4 view = + glm::lookAt(glm::vec3(0.0f, 0.0f, 3.0f), glm::vec3(0.0f, 0.0f, 0.0f), + glm::vec3(0.0f, 1.0f, 0.0f)); glm::mat4 projection = glm::mat4(1.0f); view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f)); - projection = glm::perspective( - glm::radians(45.0f), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f); - shader.setMat4("view", view); - shader.setMat4("projection", projection); // 开启深度测试 glEnable(GL_DEPTH_TEST); // 循环渲染 while (!glfwWindowShouldClose(window)) { + + // 计算帧时间差 + float currentFrame = glfwGetTime(); + deltaTime = currentFrame - lastFrame; + lastFrame = currentFrame; + // 处理输入 processInput(window); @@ -196,7 +161,7 @@ int main() { for (unsigned int i = 0; i < 10; i++) { glm::mat4 model(1.0f); model = glm::translate(model, cubePositions[i]); - float angle = 20.0f * i; + float angle = 20.0f * i + 50.0f; model = glm::rotate(model, glm::radians(angle), glm::vec3(1.0f, 0.3f, 0.5f)); shader.setMat4("model", model); @@ -204,6 +169,13 @@ int main() { glDrawArrays(GL_TRIANGLES, 0, 36); } + float radius = 10.0f; + view = camera.GetViewMatrix(); + shader.setMat4("view", view); + + projection = glm::perspective( + glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f); + shader.setMat4("projection", projection); // 检查并调用事件,交换缓冲 glfwSwapBuffers(window); glfwPollEvents(); @@ -218,9 +190,25 @@ int main() { void processInput(GLFWwindow *window) { if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true); + if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) + camera.ProcessKeyboard(FORWARD, deltaTime); + if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) + camera.ProcessKeyboard(BACKWARD, deltaTime); + if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) + camera.ProcessKeyboard(LEFT, deltaTime); + if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) + camera.ProcessKeyboard(RIGHT, deltaTime); } // 窗口大小改变时回调该函数 void framebuffer_size_callback(GLFWwindow *window, int width, int height) { glViewport(0, 0, width, height); +} + +void mouse_callback(GLFWwindow *window, double xpos, double ypos) { + camera.ProcessMouseMovement(xpos, ypos); +} + +void scroll_callback(GLFWwindow *window, double xoffset, double yoffset) { + camera.ProcessMouseScroll(yoffset); } \ No newline at end of file