观察空间(View Space)
Direction
相机方向 = 相机位置 - 相机目标位置
Right
右轴 = 上向量 x 相机方向
Up
上轴 = 相机方向 x 右轴
LookAt
其中R是右向量,U是上向量,D是方向向量P是摄像机位置向量。
glm::mat4 view;
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));
相机移动
deltaTime
在每帧中计算deltaTime
float currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
键盘输入改变位置
通过键盘的输入,来改变相机的位置
void processInput(GLFWwindow *window)
{
float cameraSpeed = 2.5f * deltaTime;
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
cameraPos += cameraSpeed * cameraFront;
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
cameraPos -= cameraSpeed * cameraFront;
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
cameraPos -= glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
cameraPos += glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed;
}
视角移动
欧拉角
欧拉角(Euler Angle)是可以表示3D空间中任何旋转的3个值,一共有3种欧拉角:俯仰角(Pitch)、偏航角(Yaw)和滚转角(Roll)。
---
direction.x = cos(glm::radians(pitch)) * cos(glm::radians(yaw));
direction.y = sin(glm::radians(pitch));
direction.z = cos(glm::radians(pitch)) * sin(glm::radians(yaw));
鼠标回调函数
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
glfwSetCursorPosCallback(window, mouse_callback);
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
- 计算鼠标距上一帧的偏移量。
- 把偏移量添加到摄像机的俯仰角和偏航角中。
- 对偏航角和俯仰角进行最大和最小值的限制。
- 计算方向向量。
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
{
float xoffset = xpos - lastX;
float yoffset = lastY - ypos;
lastX = xpos;
lastY = ypos;
float sensitivity = 0.05; //灵敏度
xoffset *= sensitivity;
yoffset *= sensitivity;
yaw += xoffset;
pitch += yoffset;
//在90度时视角会发生逆转,所以我们把89度作为极限
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));
front.y = sin(glm::radians(pitch));
front.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));
cameraFront = glm::normalize(front);
}
相机缩放
鼠标滚轮回调函数
glfwSetScrollCallback(window, scroll_callback);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
if(fov >= 1.0f && fov <= 45.0f)
fov -= yoffset;
if(fov <= 1.0f)
fov = 1.0f;
if(fov >= 45.0f)
fov = 45.0f;
}
projection = glm::perspective(glm::radians(fov), WIDTH / HEIGHT, 0.1f, 100.0f);
摄像机类
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
enum Camera_Movement {
FORWARD,
BACKWARD,
LEFT,
RIGHT
};
#pragma once
class Camera
{
public :
Camera(glm::vec3 position, glm::vec3 worldup, float yaw, float pitch);
~Camera();
glm::mat4 GetViewMatrix();
void ProcessMouseScroll(float yoffset);
void ProcessMouseMovement(float xoffset, float yoffset, bool constrainPitch);
void ProcessKeyboard(Camera_Movement direction, float deltaTime);
glm::vec3 Position = glm::vec3(0.0f, 0.0f, 0.0f);
glm::vec3 Up;
glm::vec3 Right;
glm::vec3 Front;
glm::vec3 WorldUp;
float Pitch;
float Yaw;
float Fov;
float MovementSpeed;
float MouseSensitivity;
private :
void UpdateCameraVectors();
};
#include "Camera.h"
//偏航角
const float YAW = -90.0f;
//俯仰角
const float PITCH = 0.0f;
//视野(Field of View)
const float FOV = 45.0f;
//移动速度
const float SPEED = 5.0f;
//鼠标灵敏度
const float SENSITIVITY = 0.1f;
Camera::Camera(glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3 worldup = 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), Fov(FOV)
{
Position = position;
Yaw = yaw;
Pitch = pitch;
WorldUp = worldup;
UpdateCameraVectors();
}
Camera::~Camera()
{
}
glm::mat4 Camera::GetViewMatrix()
{
return glm::lookAt(Position, Position + Front, Up);
}
void Camera::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;
}
void Camera::ProcessMouseScroll(float yoffset)
{
Fov -= yoffset;
if (Fov < 1.0f)
Fov = 1.0f;
if (Fov > 45.0f)
Fov = 45.0f;
}
void Camera::ProcessMouseMovement(float xoffset, float yoffset, bool 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::UpdateCameraVectors()
{
glm::vec3 front = glm::vec3(0);
front.x = glm::cos(glm::radians(Yaw)) * glm::cos(glm::radians(Pitch));
front.y = glm::sin(glm::radians(Pitch));
front.z = glm::sin(glm::radians(Yaw)) * glm::cos(glm::radians(Pitch));
Front = glm::normalize(front);
Right = glm::normalize(glm::cross(Front, WorldUp));
Up = glm::normalize(glm::cross(Front, Right));
}
完整工程代码Github:
[github repo="acgloby/LearnOpenGL"]
Comments NOTHING