在OpenGL中从上方移动相机
Posted
技术标签:
【中文标题】在OpenGL中从上方移动相机【英文标题】:Moving camera from above in OpenGL 【发布时间】:2021-09-16 17:18:35 【问题描述】:我正在使用来自https://learnopengl.com/Getting-started/Camera 的Camera 类(您可以找到代码here)。
我想让相机看向 y 轴的负方向(从上方)。
但是,简单地将默认音高更改为 -90 并相应地更改它的约束值并不能解决问题。它改变了相机的方向,但它的运动完全被破坏了。
我想我需要更改updateCameraVectors()
中的数学;有人可以帮帮我吗?
#pragma once
//camera class from learnopengl.com
#include <GL/glew.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <vector>
// 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 = -90.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;
// Constructor with vectors
Camera(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)
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 xoffset, float yoffset, GLboolean constrainPitch = true)
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 > -1.0f)
Pitch = -1.0f;
if (Pitch < -179.0f)
Pitch = -179.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)
if (Zoom >= 1.0f && Zoom <= 45.0f)
Zoom -= yoffset;
if (Zoom <= 1.0f)
Zoom = 1.0f;
if (Zoom >= 90.0f)
Zoom = 90.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));
;
【问题讨论】:
【参考方案1】:Right = glm::normalize(glm::cross(Front, WorldUp));
Up = glm::normalize(glm::cross(Right, Front));
这是一种非常“懒惰”的方式来确定右向量和上向量。它做了一堆假设,包括一个你永远不会直视或直视的假设。
想一想:如果我们通过将“前进”与世界上的“向上”概念进行比较来计算“右”是什么,那么当“前进”指向直上或直下时,“右”应该是什么?
一个更简洁的方法是:
-
从 Pitch 和 Yaw 创建一个变换矩阵
将该矩阵应用于所有三个参考轴。
(可选)使用叉积重新正交化生成的三个向量。
【讨论】:
您能详细说明一下这些步骤吗?以上是关于在OpenGL中从上方移动相机的主要内容,如果未能解决你的问题,请参考以下文章