FPSCamera.h#
↰ Parent directory (cameras
)
A class representing a First person camera and functionality to manipulate it.
Includes#
PVRCore/glm.h
Namespaces#
Classes#
Source Code#
#pragma once
#include "PVRCore/glm.h"
namespace pvr {
class FPSCamera
{
public:
FPSCamera() : _yaw(0.f), _pos(0.f), _isPosDirty(true), _isOrientationDirty(true), _moveZ(0.f), _moveX(0.f), _pitch(0.f)
{
_right = glm::vec3(1.f, 0.0f, 0.0f);
_up = glm::vec3(0.f, 1.0f, 0.0f);
_look = glm::vec3(0.f, 0.0f, -1.0f);
}
void moveZ(float z)
{
_moveZ += z;
_isPosDirty = true;
}
void moveX(float x)
{
_moveX += x;
_isPosDirty = true;
}
void set(const glm::vec3& camPos, float yaw, float pitch)
{
setPosition(camPos);
setOrientation(yaw, pitch);
}
void setPosition(const glm::vec3& camPos)
{
_pos = camPos;
_isPosDirty = true;
}
void setOrientation(float yaw, float pitch)
{
_yaw = _pitch = 0.f;
orientate(yaw, pitch);
}
void yaw(float yaw)
{
_yaw += yaw;
if (_yaw <= -180.f) { _yaw += 360.f; }
if (_yaw > 180.f) { _yaw -= 360.f; }
_isOrientationDirty = true;
}
void reset(const glm::vec3& pos, float yaw, float pitch)
{
_pos = pos;
_isPosDirty = true;
_pitch = 0.0f;
_yaw = 0.0f;
orientate(yaw, pitch);
}
void pitch(float pitch)
{
_pitch += pitch;
_pitch = glm::clamp(_pitch, -90.f, 90.f);
_isOrientationDirty = true;
}
void orientate(float yaw, float pitch)
{
_isOrientationDirty = true;
_pitch += pitch;
_pitch = glm::clamp(_pitch, -90.f, 90.f);
this->yaw(yaw);
}
const glm::vec3& getPosition()
{
updateRUL();
updatePos();
return _pos;
}
glm::mat4 getViewMatrix() const
{
updateRUL();
updatePos();
// Create a 4x4 view matrix from the right, up, forward and eye position vectors
glm::mat4 viewMatrix = { glm::vec4(_right.x, _up.x, _look.x, 0), glm::vec4(_right.y, _up.y, _look.y, 0), glm::vec4(_right.z, _up.z, _look.z, 0),
glm::vec4(-glm::dot(_right, _pos), -glm::dot(_up, _pos), -glm::dot(_look, _pos), 1) };
return viewMatrix;
}
private:
void updateRUL() const
{
if (_isOrientationDirty)
{
// If the pitch and yaw angles are in degrees,
// they need to be converted to radians. Here
// I assume the values are already converted to radians.
const float cosPitch = cos(glm::radians(_pitch));
const float sinPitch = sin(glm::radians(_pitch));
const float cosYaw = cos(glm::radians(_yaw));
const float sinYaw = sin(glm::radians(_yaw));
_right = { cosYaw, 0, -sinYaw };
_up = { sinYaw * sinPitch, cosPitch, cosYaw * sinPitch };
_look = { sinYaw * cosPitch, -sinPitch, cosPitch * cosYaw };
_isOrientationDirty = false;
}
}
void updatePos() const
{
if (_isPosDirty)
{
_pos += _moveZ * _look;
_isPosDirty = false;
_moveZ = 0.0f;
}
}
mutable glm::vec3 _pos;
mutable float _moveZ, _moveX;
float _yaw, _pitch;
mutable glm::vec3 _right, _look, _up;
mutable glm::mat4 _viewX;
mutable bool _isPosDirty;
mutable bool _isOrientationDirty;
};
} // namespace pvr