2015-07-26 21:39:49 +00:00
|
|
|
#include "CCamera.h"
|
|
|
|
#include "CGraphics.h"
|
|
|
|
#include <Common/CQuaternion.h>
|
2015-09-01 17:05:48 +00:00
|
|
|
#include <Common/Math.h>
|
2015-07-26 21:39:49 +00:00
|
|
|
#include <gtc/matrix_transform.hpp>
|
|
|
|
|
|
|
|
CCamera::CCamera()
|
|
|
|
{
|
|
|
|
mMode = eFreeCamera;
|
|
|
|
mPosition = CVector3f(0);
|
|
|
|
mAspectRatio = 1.7777777f;
|
|
|
|
|
2015-09-01 23:21:10 +00:00
|
|
|
mYaw = -Math::skHalfPi;
|
2015-07-26 21:39:49 +00:00
|
|
|
mPitch = 0.0f;
|
2015-11-26 07:47:02 +00:00
|
|
|
SetOrbit(CVector3f(0), 5.f);
|
|
|
|
Update();
|
2015-07-26 21:39:49 +00:00
|
|
|
|
2015-11-26 07:47:02 +00:00
|
|
|
mMoveSpeed = 1.f;
|
|
|
|
mLookSpeed = 1.f;
|
2015-07-26 21:39:49 +00:00
|
|
|
mViewOutdated = true;
|
|
|
|
mProjectionOutdated = true;
|
2015-09-27 22:02:53 +00:00
|
|
|
mFrustumPlanesOutdated = true;
|
2015-07-26 21:39:49 +00:00
|
|
|
}
|
|
|
|
|
2015-11-26 07:47:02 +00:00
|
|
|
CCamera::CCamera(CVector3f Position, CVector3f /*Target*/)
|
2015-07-26 21:39:49 +00:00
|
|
|
{
|
|
|
|
// todo: make it actually look at the target!
|
|
|
|
mMode = eFreeCamera;
|
2015-11-26 07:47:02 +00:00
|
|
|
mMoveSpeed = 1.f;
|
|
|
|
mLookSpeed = 1.f;
|
2015-07-26 21:39:49 +00:00
|
|
|
mPosition = Position;
|
2015-09-01 23:21:10 +00:00
|
|
|
mYaw = -Math::skHalfPi;
|
2015-07-26 21:39:49 +00:00
|
|
|
mPitch = 0.0f;
|
2015-11-26 07:47:02 +00:00
|
|
|
Update();
|
2015-07-26 21:39:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CCamera::Pan(float XAmount, float YAmount)
|
|
|
|
{
|
2015-11-26 07:47:02 +00:00
|
|
|
if (mMode == eFreeCamera)
|
2015-07-26 21:39:49 +00:00
|
|
|
{
|
2015-11-26 07:47:02 +00:00
|
|
|
Update();
|
|
|
|
mPosition += mRightVector * (XAmount * mMoveSpeed);
|
|
|
|
mPosition += mUpVector * (YAmount * mMoveSpeed);
|
2015-07-26 21:39:49 +00:00
|
|
|
mViewOutdated = true;
|
2015-09-27 22:02:53 +00:00
|
|
|
mFrustumPlanesOutdated = true;
|
2015-07-26 21:39:49 +00:00
|
|
|
}
|
|
|
|
|
2015-11-26 07:47:02 +00:00
|
|
|
else
|
|
|
|
Rotate(-XAmount * 0.3f, YAmount * 0.3f);
|
2015-07-26 21:39:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CCamera::Rotate(float XAmount, float YAmount)
|
|
|
|
{
|
2015-11-26 07:47:02 +00:00
|
|
|
mYaw -= (XAmount * mLookSpeed * 0.3f);
|
|
|
|
mPitch -= (YAmount * mLookSpeed * 0.3f);
|
|
|
|
|
|
|
|
mViewOutdated = true;
|
|
|
|
mFrustumPlanesOutdated = true;
|
2015-07-26 21:39:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CCamera::Zoom(float Amount)
|
|
|
|
{
|
2015-11-26 07:47:02 +00:00
|
|
|
if (mMode == eFreeCamera)
|
|
|
|
{
|
|
|
|
Update();
|
2015-11-27 12:26:32 +00:00
|
|
|
mPosition += mDirection * (Amount * mMoveSpeed);
|
2015-11-26 07:47:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
else
|
2015-11-27 12:26:32 +00:00
|
|
|
mOrbitDistance -= Amount * mMoveSpeed;
|
2015-11-26 07:47:02 +00:00
|
|
|
|
2015-07-26 21:39:49 +00:00
|
|
|
mViewOutdated = true;
|
2015-09-27 22:02:53 +00:00
|
|
|
mFrustumPlanesOutdated = true;
|
2015-07-26 21:39:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CCamera::Snap(CVector3f Position)
|
|
|
|
{
|
|
|
|
mPosition = Position;
|
2015-09-01 23:21:10 +00:00
|
|
|
mYaw = -Math::skHalfPi;
|
2015-07-26 21:39:49 +00:00
|
|
|
mPitch = 0.0f;
|
|
|
|
mViewOutdated = true;
|
2015-09-27 22:02:53 +00:00
|
|
|
mFrustumPlanesOutdated = true;
|
2015-11-26 07:47:02 +00:00
|
|
|
Update();
|
2015-07-26 21:39:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CCamera::ProcessKeyInput(EKeyInputs KeyFlags, double DeltaTime)
|
|
|
|
{
|
|
|
|
float FDeltaTime = (float) DeltaTime;
|
2015-11-26 07:47:02 +00:00
|
|
|
|
2015-11-27 12:26:32 +00:00
|
|
|
if (KeyFlags & eWKey) Zoom(FDeltaTime * 25.f);
|
|
|
|
if (KeyFlags & eSKey) Zoom(-FDeltaTime * 25.f);
|
2015-11-26 07:47:02 +00:00
|
|
|
if (KeyFlags & eQKey) Pan(0, -FDeltaTime * 25.f);
|
|
|
|
if (KeyFlags & eEKey) Pan(0, FDeltaTime * 25.f);
|
|
|
|
if (KeyFlags & eAKey) Pan(-FDeltaTime * 25.f, 0);
|
|
|
|
if (KeyFlags & eDKey) Pan(FDeltaTime * 25.f, 0);
|
2015-07-26 21:39:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CCamera::ProcessMouseInput(EKeyInputs KeyFlags, EMouseInputs MouseFlags, float XMovement, float YMovement)
|
|
|
|
{
|
|
|
|
// Free Camera
|
|
|
|
if (mMode == eFreeCamera)
|
|
|
|
{
|
|
|
|
if (MouseFlags & eMiddleButton)
|
|
|
|
{
|
|
|
|
if (KeyFlags & eCtrlKey) Zoom(-YMovement * 0.2f);
|
|
|
|
else Pan(-XMovement, YMovement);
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (MouseFlags & eRightButton) Rotate(XMovement, YMovement);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Orbit Camera
|
|
|
|
else if (mMode == eOrbitCamera)
|
|
|
|
{
|
2015-11-26 07:47:02 +00:00
|
|
|
if ((MouseFlags & eMiddleButton) || (MouseFlags & eRightButton))
|
|
|
|
Pan(-XMovement, YMovement);
|
2015-07-26 21:39:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CRay CCamera::CastRay(CVector2f DeviceCoords)
|
|
|
|
{
|
|
|
|
CMatrix4f InverseVP = (ViewMatrix().Transpose() * ProjectionMatrix().Transpose()).Inverse();
|
|
|
|
|
|
|
|
CVector3f RayOrigin = CVector3f(DeviceCoords.x, DeviceCoords.y, -1.f) * InverseVP;
|
|
|
|
CVector3f RayTarget = CVector3f(DeviceCoords.x, DeviceCoords.y, 0.f) * InverseVP;
|
|
|
|
CVector3f RayDir = (RayTarget - RayOrigin).Normalized();
|
|
|
|
|
|
|
|
CRay Ray;
|
|
|
|
Ray.SetOrigin(RayOrigin);
|
|
|
|
Ray.SetDirection(RayDir);
|
|
|
|
return Ray;
|
|
|
|
}
|
|
|
|
|
2015-11-26 07:47:02 +00:00
|
|
|
void CCamera::SetMoveMode(ECameraMoveMode Mode)
|
|
|
|
{
|
|
|
|
mMode = Mode;
|
|
|
|
mViewOutdated = true;
|
|
|
|
mFrustumPlanesOutdated = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCamera::SetOrbit(const CVector3f& OrbitTarget, float Distance)
|
|
|
|
{
|
|
|
|
mOrbitTarget = OrbitTarget;
|
|
|
|
mOrbitDistance = Distance;
|
|
|
|
|
|
|
|
if (mMode == eOrbitCamera)
|
|
|
|
{
|
|
|
|
mViewOutdated = true;
|
|
|
|
mFrustumPlanesOutdated = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCamera::SetOrbit(const CAABox& OrbitTarget, float DistScale /*= 2.5f*/)
|
|
|
|
{
|
|
|
|
CVector3f Min = OrbitTarget.Min();
|
|
|
|
CVector3f Max = OrbitTarget.Max();
|
|
|
|
|
|
|
|
mOrbitTarget = OrbitTarget.Center();
|
|
|
|
mOrbitDistance = ((Max.x - Min.x) + (Max.y - Min.y) + (Max.z - Min.z)) / 3.f;
|
|
|
|
mOrbitDistance *= DistScale;
|
|
|
|
|
|
|
|
if (mMode == eOrbitCamera)
|
|
|
|
{
|
|
|
|
mViewOutdated = true;
|
|
|
|
mFrustumPlanesOutdated = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCamera::SetOrbitDistance(float Distance)
|
|
|
|
{
|
|
|
|
mOrbitDistance = Distance;
|
|
|
|
|
|
|
|
if (mMode == eOrbitCamera)
|
|
|
|
{
|
|
|
|
mViewOutdated = true;
|
|
|
|
mFrustumPlanesOutdated = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-26 21:39:49 +00:00
|
|
|
void CCamera::LoadMatrices()
|
|
|
|
{
|
|
|
|
CGraphics::sMVPBlock.ViewMatrix = ViewMatrix();
|
2015-08-24 01:02:14 +00:00
|
|
|
CGraphics::sMVPBlock.ProjectionMatrix = ProjectionMatrix();
|
|
|
|
CGraphics::UpdateMVPBlock();
|
|
|
|
}
|
|
|
|
|
2015-07-26 21:39:49 +00:00
|
|
|
// ************ GETTERS ************
|
|
|
|
CVector3f CCamera::Position() const
|
|
|
|
{
|
|
|
|
return mPosition;
|
|
|
|
}
|
|
|
|
|
2015-09-01 17:05:48 +00:00
|
|
|
CVector3f CCamera::Direction() const
|
2015-07-26 21:39:49 +00:00
|
|
|
{
|
|
|
|
return mDirection;
|
|
|
|
}
|
|
|
|
|
2015-11-25 21:37:34 +00:00
|
|
|
CVector3f CCamera::UpVector() const
|
|
|
|
{
|
|
|
|
return mUpVector;
|
|
|
|
}
|
|
|
|
|
|
|
|
CVector3f CCamera::RightVector() const
|
|
|
|
{
|
|
|
|
return mRightVector;
|
|
|
|
}
|
|
|
|
|
2015-09-01 17:05:48 +00:00
|
|
|
float CCamera::Yaw() const
|
2015-07-26 21:39:49 +00:00
|
|
|
{
|
|
|
|
return mYaw;
|
|
|
|
}
|
|
|
|
|
2015-09-01 17:05:48 +00:00
|
|
|
float CCamera::Pitch() const
|
2015-07-26 21:39:49 +00:00
|
|
|
{
|
|
|
|
return mPitch;
|
|
|
|
}
|
|
|
|
|
2015-09-01 17:05:48 +00:00
|
|
|
float CCamera::FieldOfView() const
|
|
|
|
{
|
|
|
|
return 55.f;
|
|
|
|
}
|
2015-07-26 21:39:49 +00:00
|
|
|
|
2015-11-26 07:47:02 +00:00
|
|
|
ECameraMoveMode CCamera::MoveMode() const
|
|
|
|
{
|
|
|
|
return mMode;
|
|
|
|
}
|
|
|
|
|
2015-07-26 21:39:49 +00:00
|
|
|
const CMatrix4f& CCamera::ViewMatrix()
|
|
|
|
{
|
|
|
|
if (mViewOutdated)
|
2015-11-26 07:47:02 +00:00
|
|
|
UpdateView();
|
2015-07-26 21:39:49 +00:00
|
|
|
|
|
|
|
return mCachedViewMatrix;
|
|
|
|
}
|
|
|
|
|
|
|
|
const CMatrix4f& CCamera::ProjectionMatrix()
|
|
|
|
{
|
|
|
|
if (mProjectionOutdated)
|
2015-11-26 07:47:02 +00:00
|
|
|
UpdateProjection();
|
2015-07-26 21:39:49 +00:00
|
|
|
|
|
|
|
return mCachedProjectionMatrix;
|
|
|
|
}
|
|
|
|
|
2015-09-27 22:02:53 +00:00
|
|
|
const CFrustumPlanes& CCamera::FrustumPlanes()
|
|
|
|
{
|
|
|
|
if (mFrustumPlanesOutdated)
|
2015-11-26 07:47:02 +00:00
|
|
|
UpdateFrustum();
|
2015-09-27 22:02:53 +00:00
|
|
|
|
|
|
|
return mCachedFrustumPlanes;
|
|
|
|
}
|
|
|
|
|
2015-07-26 21:39:49 +00:00
|
|
|
// ************ SETTERS ************
|
|
|
|
void CCamera::SetPosition(CVector3f Position)
|
|
|
|
{
|
|
|
|
mPosition = Position;
|
|
|
|
mViewOutdated = true;
|
2015-09-27 22:02:53 +00:00
|
|
|
mFrustumPlanesOutdated = true;
|
2015-07-26 21:39:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CCamera::SetDirection(CVector3f Direction)
|
|
|
|
{
|
|
|
|
mDirection = Direction;
|
|
|
|
mViewOutdated = true;
|
2015-09-27 22:02:53 +00:00
|
|
|
mFrustumPlanesOutdated = true;
|
2015-07-26 21:39:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CCamera::SetYaw(float Yaw)
|
|
|
|
{
|
|
|
|
mYaw = Yaw;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCamera::SetPitch(float Pitch)
|
|
|
|
{
|
|
|
|
mPitch = Pitch;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCamera::SetMoveSpeed(float MoveSpeed)
|
|
|
|
{
|
|
|
|
mMoveSpeed = MoveSpeed;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCamera::SetLookSpeed(float LookSpeed)
|
|
|
|
{
|
|
|
|
mLookSpeed = LookSpeed;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCamera::SetAspectRatio(float AspectRatio)
|
|
|
|
{
|
|
|
|
mAspectRatio = AspectRatio;
|
|
|
|
mProjectionOutdated = true;
|
2015-09-27 22:02:53 +00:00
|
|
|
mFrustumPlanesOutdated = true;
|
2015-07-26 21:39:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ************ PRIVATE ************
|
2015-11-26 07:47:02 +00:00
|
|
|
void CCamera::Update()
|
2015-07-26 21:39:49 +00:00
|
|
|
{
|
2015-11-26 07:47:02 +00:00
|
|
|
// Update direction
|
2015-09-01 23:21:10 +00:00
|
|
|
if (mPitch > Math::skHalfPi) mPitch = Math::skHalfPi;
|
|
|
|
if (mPitch < -Math::skHalfPi) mPitch = -Math::skHalfPi;
|
2015-07-26 21:39:49 +00:00
|
|
|
|
|
|
|
mDirection = CVector3f(
|
|
|
|
cos(mPitch) * cos(mYaw),
|
|
|
|
cos(mPitch) * sin(mYaw),
|
|
|
|
sin(mPitch)
|
|
|
|
);
|
|
|
|
|
2015-11-25 21:37:34 +00:00
|
|
|
mRightVector = CVector3f(
|
2015-09-01 23:21:10 +00:00
|
|
|
cos(mYaw - Math::skHalfPi),
|
|
|
|
sin(mYaw - Math::skHalfPi),
|
2015-07-26 21:39:49 +00:00
|
|
|
0
|
|
|
|
);
|
|
|
|
|
2015-11-25 21:37:34 +00:00
|
|
|
mUpVector = mRightVector.Cross(mDirection);
|
2015-11-26 07:47:02 +00:00
|
|
|
|
|
|
|
// Update position
|
|
|
|
if (mMode == eOrbitCamera)
|
|
|
|
{
|
|
|
|
if (mOrbitDistance < 1.f) mOrbitDistance = 1.f;
|
|
|
|
mPosition = mOrbitTarget + (mDirection * -mOrbitDistance);
|
|
|
|
}
|
|
|
|
|
|
|
|
mViewOutdated = true;
|
|
|
|
mFrustumPlanesOutdated = true;
|
2015-11-25 21:37:34 +00:00
|
|
|
}
|
|
|
|
|
2015-11-26 07:47:02 +00:00
|
|
|
void CCamera::UpdateView()
|
2015-11-25 21:37:34 +00:00
|
|
|
{
|
|
|
|
// todo: don't use glm
|
2015-11-26 07:47:02 +00:00
|
|
|
Update();
|
2015-07-26 21:39:49 +00:00
|
|
|
|
|
|
|
glm::vec3 glmpos(mPosition.x, mPosition.y, mPosition.z);
|
|
|
|
glm::vec3 glmdir(mDirection.x, mDirection.y, mDirection.z);
|
2015-11-25 21:37:34 +00:00
|
|
|
glm::vec3 glmup(mUpVector.x, mUpVector.y, mUpVector.z);
|
2015-07-26 21:39:49 +00:00
|
|
|
mCachedViewMatrix = CMatrix4f::FromGlmMat4(glm::lookAt(glmpos, glmpos + glmdir, glmup)).Transpose();
|
|
|
|
mViewOutdated = false;
|
|
|
|
}
|
|
|
|
|
2015-11-26 07:47:02 +00:00
|
|
|
void CCamera::UpdateProjection()
|
2015-07-26 21:39:49 +00:00
|
|
|
{
|
2015-09-01 17:05:48 +00:00
|
|
|
mCachedProjectionMatrix = Math::PerspectiveMatrix(55.f, mAspectRatio, 0.1f, 4096.f);
|
2015-07-26 21:39:49 +00:00
|
|
|
mProjectionOutdated = false;
|
|
|
|
}
|
2015-09-27 22:02:53 +00:00
|
|
|
|
2015-11-26 07:47:02 +00:00
|
|
|
void CCamera::UpdateFrustum()
|
2015-09-27 22:02:53 +00:00
|
|
|
{
|
|
|
|
mCachedFrustumPlanes.SetPlanes(mPosition, mDirection, 55.f, mAspectRatio, 0.1f, 4096.f);
|
|
|
|
mFrustumPlanesOutdated = false;
|
|
|
|
}
|