-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcamera.cpp
More file actions
142 lines (112 loc) · 4.19 KB
/
camera.cpp
File metadata and controls
142 lines (112 loc) · 4.19 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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//
// Created by Molom on 2022-02-27.
//
#include "camera.h"
using namespace DirectX;
Camera::Camera() {
calculateProjection(1);
calculateView();
}
XMMATRIX Camera::viewMatrix() const {
return XMLoadFloat4x4(&view.value());
}
XMMATRIX Camera::projectionMatrix() const {
return XMLoadFloat4x4(&projection.value());
}
XMMATRIX Camera::cameraMatrix() const {
return XMLoadFloat4x4(&view.value()) * XMLoadFloat4x4(&projection.value());
}
DirectX::XMFLOAT3 Camera::position() const {
XMFLOAT3 position{};
XMStoreFloat3(&position, XMVectorAdd(XMLoadFloat3(&_center),
XMVectorScale(XMLoadFloat3(&_direction), distance * zoom)));
return position;
}
void Camera::resize(QSizeF newSize) {
viewportSize = newSize;
calculateProjection(newSize.width() / newSize.height());
}
void Camera::changeZoom(float delta) {
if (delta <= 0) {
zoom *= STEP;
} else {
zoom /= STEP;
}
calculateView();
}
void Camera::rotate(QPointF angle) {
auto rotate = angle * SENSITIVITY;
yaw += static_cast<float>(rotate.x());
pitch = std::clamp<float>(pitch + static_cast<float>(rotate.y()), MIN_ANGLE, MAX_ANGLE);
_direction = {
cos(yaw) * cos(pitch),
sin(pitch),
sin(yaw) * cos(pitch),
};
XMStoreFloat3(&_direction, XMVector3Normalize(XMLoadFloat3(&_direction)));
XMStoreFloat3(&_right, XMVector3Normalize(
XMVector3Cross(
XMLoadFloat3(&worldUp),
XMLoadFloat3(&_direction)
)
));
XMStoreFloat3(&_up, XMVector3Normalize(
XMVector3Cross(
XMLoadFloat3(&_direction),
XMLoadFloat3(&_right)
)
));
calculateView();
}
void Camera::move(QPointF offset) {
auto moveRight = XMVectorScale(XMLoadFloat3(&_right), SPEED * offset.x());
auto moveUp = XMVectorScale(XMLoadFloat3(&_up), -SPEED * offset.y());
auto move = XMVectorAdd(moveRight, moveUp);
XMStoreFloat3(&_center, XMVectorAdd(XMLoadFloat3(&_center), move));
calculateView();
}
void Camera::moveTo(DirectX::XMFLOAT3 position) {
_center = position;
calculateView();
}
void Camera::calculateView() {
auto centerVector = XMLoadFloat3(&_center);
auto fromCenterVector = XMVectorScale(XMLoadFloat3(&_direction), distance * zoom);
XMFLOAT4X4 v{};
XMStoreFloat4x4(&v, XMMatrixLookAtRH(
XMVectorAdd(centerVector, fromCenterVector),
centerVector,
XMLoadFloat3(&_up)));
view.setValue(v);
}
void Camera::calculateProjection(float aspectRatio) {
_aspectRatio = aspectRatio;
XMFLOAT4X4 proj{};
XMStoreFloat4x4(&proj, XMMatrixPerspectiveFovRH(
XMConvertToRadians(FOV),
_aspectRatio, _near, _far));
projection.setValue(proj);
// _z = ((viewportSize.height() / 2.0f) / tan(FOV / 2.0f)) / viewport().height();
_z = 1.0f / tan(XMConvertToRadians(FOV) / 2.0f);
}
std::tuple<XMMATRIX, XMMATRIX> Camera::stereoscopicViewMatrix() const {
auto center = XMLoadFloat3(&_center);
auto position = XMVectorAdd(center, XMVectorScale(
XMLoadFloat3(&_direction), distance * zoom));
auto shift = XMVectorScale(XMLoadFloat3(&_right), _eyesDistance / 2.0f);
auto viewLeft = XMMatrixLookAtRH(XMVectorSubtract(position, shift),
XMVectorSubtract(center, shift), XMLoadFloat3(&_up));
auto viewRight = XMMatrixLookAtRH(XMVectorAdd(position, shift),
XMVectorAdd(center, shift), XMLoadFloat3(&_up));
return std::make_tuple(viewLeft, viewRight);
}
std::tuple<XMMATRIX, XMMATRIX> Camera::stereoscopicProjectionMatrix() const {
float shift = (_eyesDistance / 2.0f) * _near / _focusDistance;
float top = tan(XMConvertToRadians(FOV) / 2.0f) * _near;
float right = _aspectRatio * top;
auto projLeft = XMMatrixPerspectiveOffCenterRH(-right + shift, right + shift,
-top, top, _near, _far);
auto projRight = XMMatrixPerspectiveOffCenterRH(-right - shift, right - shift,
-top, top, _near, _far);
return std::make_tuple(projLeft, projRight);
}