TPSCamera.h#
↰ Parent directory (cameras
)
A class representing a Third person camera and functionality to manipulate it.
Includes#
PVRCore/glm.h
Namespaces#
Classes#
Defines#
Source Code#
#pragma once
#include "PVRCore/glm.h"
// Third persorn camera
namespace pvr {
class TPSCamera
{
public:
TPSCamera() : _azimuth(0.0f), offsetY(0.0f), offsetZ(0.0f), _targetPos(0.0f), _updatePosition(true), _updateView(false) {}
void setHeight(float height)
{
offsetY = height;
_updatePosition = true;
_updateView = true;
}
void setDistanceFromTarget(const float dist)
{
offsetZ = dist;
_updatePosition = true;
_updateView = true;
}
void setTargetPosition(const glm::vec3& targetPos)
{
_targetPos = glm::vec3(0.f);
updateTargetPosition(targetPos);
}
const glm::vec3& getTargetPosition() { return _targetPos; }
void updateTargetPosition(const glm::vec3& pos)
{
_targetPos += pos;
_updatePosition = true;
_updateView = true;
}
void updateTargetLookAngle(float angleDeg)
{
_azimuth += angleDeg;
_updatePosition = true;
_updateView = true;
}
void setTargetLookAngle(float angleDeg)
{
_azimuth = 0.0f;
updateTargetLookAngle(angleDeg);
}
float getTargetLookAngle() { return _azimuth; }
const glm::mat4& getViewMatrix() const
{
const glm::vec3& cameraPos = getCameraPosition();
// Construct the matrix and return
if (_updateView)
{
_updateView = false;
// rotate the position of the camera in
_viewX = glm::lookAt(cameraPos, _targetPos, glm::vec3(0.0f, 1.0f, 0.0f));
}
return _viewX;
}
const glm::vec3& getCameraPosition() const
{
// Construct the matrix and return
if (_updatePosition)
{
_updatePosition = false;
_updateView = true;
// this makes the camera aligned behind the target and offset it by 90 degree because our initial axis start from north.
float rotation = _azimuth + 180.f + 90.f;
glm::vec3 dir = glm::mat3(glm::rotate(glm::radians(rotation), glm::vec3(0.0, 1.f, 0.0))) * glm::vec3(1.0f, 0.0f, 0.0f);
_cameraPos = dir * offsetZ + _targetPos;
_cameraPos.y = offsetY;
}
return _cameraPos;
}
private:
float _azimuth;
float offsetY, offsetZ; // Camera offset
glm::vec3 _targetPos; // Character
mutable glm::vec3 _cameraPos;
mutable glm::mat4 _viewX;
mutable bool _updatePosition, _updateView;
};
class TPSOrbitCamera
{
#define epsilon 1e-5f
public:
TPSOrbitCamera() : _azimuth(0.0f), _inclination(0.0f), _targetPos(0.0f), _updatePosition(true), _updateView(false) {}
float getAzimuth() const { return _azimuth; }
void setAzimuth(float azimuth)
{
while (azimuth < -180.f) { azimuth += 360.f; }
while (azimuth > 180.f) { azimuth -= 360.f; }
_azimuth = azimuth;
_updatePosition = true;
_updateView = true;
}
void addAzimuth(float deltaAzimuth) { setAzimuth(_azimuth + deltaAzimuth); }
float getInclination() const { return _inclination; }
void setInclination(float inclination)
{
if (inclination > 90 - epsilon) { inclination = 90 - epsilon; }
if (inclination < -90 + epsilon) { inclination = -90 + epsilon; }
_inclination = inclination;
_updatePosition = true;
_updateView = true;
}
void addInclination(float deltaInclination) { setInclination(_inclination + deltaInclination); }
float getDistanceFromTarget() const { return _distance; }
void setDistanceFromTarget(float distance)
{
if (distance < epsilon) { distance = epsilon; }
_distance = distance;
_updatePosition = true;
_updateView = true;
}
void addDistanceFromTarget(float deltaDistance) { setDistanceFromTarget(_distance + deltaDistance); }
void setTargetPosition(const glm::vec3& targetPos)
{
_targetPos = targetPos;
_updatePosition = true;
_updateView = true;
}
const glm::vec3& getTargetPosition() const { return _targetPos; }
void addTargetPosition(const glm::vec3& pos) { setTargetPosition(_targetPos + pos); }
const glm::mat4& getViewMatrix() const
{
const glm::vec3& cameraPos = getCameraPosition();
// Construct the matrix and return
if (_updateView)
{
_updateView = false;
// rotate the position of the camera in
_viewX = glm::lookAt(cameraPos, _targetPos, glm::vec3(0.0f, 1.0f, 0.0f));
}
return _viewX;
}
const glm::vec3& getCameraPosition() const
{
// Construct the matrix and return
if (_updatePosition)
{
_updatePosition = false;
_updateView = true;
// this makes the camera aligned behind the target and offset it by 90 degree because our initial axis start from north.
float r = _distance;
float sinphi = glm::sin(glm::radians(_azimuth));
float cosphi = glm::cos(glm::radians(_azimuth));
float sintheta = glm::sin(glm::radians(_inclination));
float costheta = glm::cos(glm::radians(_inclination));
_cameraPos.x = r * costheta * cosphi;
_cameraPos.y = r * sintheta;
_cameraPos.z = r * costheta * sinphi;
}
return _cameraPos;
}
private:
float _azimuth, _inclination, _distance;
glm::vec3 _targetPos; // Character
mutable glm::vec3 _cameraPos;
mutable glm::mat4 _viewX;
mutable bool _updatePosition, _updateView;
};
#undef epsilon
} // namespace pvr