-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcamera.cpp
More file actions
91 lines (78 loc) · 2.38 KB
/
Copy pathcamera.cpp
File metadata and controls
91 lines (78 loc) · 2.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include "camera.h"
Camera::Camera(QObject *parent)
: QObject(parent)
{
updateViewMatrix();
}
Camera::~Camera() = default;
void Camera::setPosition(const QVector3D &position)
{
if (position == m_position)
return;
m_position = position;
updateViewMatrix();
}
void Camera::setUpVector(const QVector3D &upVector)
{
if (upVector == m_upVector)
return;
m_upVector = upVector;
updateViewMatrix();
}
void Camera::setViewCenter(const QVector3D &viewCenter)
{
if (viewCenter == m_viewCenter)
return;
m_viewCenter = viewCenter;
updateViewMatrix();
}
void Camera::panAboutViewCenter(float angle)
{
rotate(angle, m_upVector);
}
void Camera::tiltAboutViewCenter(float angle)
{
const auto viewVector = (m_viewCenter - m_position).normalized();
const auto axis = QVector3D::crossProduct(m_upVector, viewVector).normalized();
rotate(angle, axis);
}
void Camera::zoom(float dz)
{
constexpr auto MinDistance = 1.0f;
constexpr auto MaxDistance = 20.0f;
const auto toCenter = m_position - m_viewCenter;
auto distance = toCenter.length();
distance -= distance * dz;
distance = std::clamp(distance, MinDistance, MaxDistance);
setPosition(m_viewCenter + toCenter.normalized() * distance);
}
void Camera::translate(const QVector3D &localOffset)
{
const auto worldOffset = localToWorld(localOffset);
setPosition(m_position + worldOffset);
setViewCenter(m_viewCenter + worldOffset);
}
QVector3D Camera::localToWorld(const QVector3D &v) const
{
const auto viewVector = m_viewCenter - m_position;
if (viewVector.isNull())
return {};
const auto xBasis = QVector3D::crossProduct(viewVector, m_upVector).normalized();
const auto yBasis = QVector3D::crossProduct(xBasis, viewVector).normalized();
return v.x() * xBasis + v.y() * yBasis + v.z() * viewVector.normalized();
}
void Camera::rotate(float angle, const QVector3D &axis)
{
const auto q = QQuaternion::fromAxisAndAngle(axis, angle);
setUpVector(q * m_upVector);
const auto viewVector = m_viewCenter - m_position;
const auto cameraToCenter = q * viewVector;
setPosition(viewCenter() - cameraToCenter);
setViewCenter(position() + cameraToCenter);
}
void Camera::updateViewMatrix()
{
m_viewMatrix.setToIdentity();
m_viewMatrix.lookAt(m_position, m_viewCenter, m_upVector);
emit viewMatrixChanged(m_viewMatrix);
}