|
@@ -6,9 +6,13 @@
|
6
|
6
|
* \author xythobuz
|
7
|
7
|
*/
|
8
|
8
|
|
|
9
|
+#include <limits>
|
|
10
|
+#include <glm/gtc/epsilon.hpp>
|
9
|
11
|
#include <glm/gtc/matrix_transform.hpp>
|
|
12
|
+#include <glm/gtx/quaternion.hpp>
|
10
|
13
|
|
11
|
14
|
#include "global.h"
|
|
15
|
+#include "RunTime.h"
|
12
|
16
|
#include "system/Window.h"
|
13
|
17
|
#include "Camera.h"
|
14
|
18
|
|
|
@@ -28,153 +32,160 @@
|
28
|
32
|
#define FBR 6
|
29
|
33
|
#define FTR 7
|
30
|
34
|
|
31
|
|
-class Plane {
|
32
|
|
- public:
|
33
|
|
- Plane() : normal(glm::vec3(0.0f, 0.0f, 0.0f)), d(0.0f) { }
|
34
|
|
- void set(glm::vec3 v1, glm::vec3 v2, glm::vec3 v3) {
|
35
|
|
- normal = glm::normalize(glm::cross(v3 - v2, v1 - v2));
|
36
|
|
- d = -glm::dot(normal, v2);
|
37
|
|
- }
|
38
|
|
- float distance(glm::vec3 p) {
|
39
|
|
- return d + glm::dot(normal, p);
|
40
|
|
- }
|
41
|
|
- private:
|
42
|
|
- glm::vec3 normal;
|
43
|
|
- float d;
|
44
|
|
-};
|
45
|
|
-
|
46
|
|
-// ----------------------------------------------------------------------------
|
47
|
|
-
|
48
|
35
|
const static float fov = 45.0f;
|
49
|
36
|
const static float nearDist = 0.1f;
|
50
|
37
|
const static float farDist = 75000.0f;
|
51
|
|
-const static float freeCameraStep = 256.0f;
|
|
38
|
+const static float maxSpeed = 2048.0f;
|
|
39
|
+const static float controllerViewFactor = 384.0f;
|
|
40
|
+
|
|
41
|
+const static glm::vec3 rightUnit(1.0f, 0.0f, 0.0f);
|
|
42
|
+const static glm::vec3 upUnit(0.0f, 1.0f, 0.0f);
|
|
43
|
+const static glm::vec3 dirUnit(0.0f, 0.0f, -1.0f);
|
52
|
44
|
|
53
|
45
|
glm::vec3 Camera::pos(0.0f, 0.0f, 0.0f);
|
54
|
|
-glm::vec2 Camera::rot(0.0f, 0.0f);
|
55
|
|
-glm::vec3 Camera::lastPos(1.0f, 0.0f, 0.0f);
|
56
|
|
-glm::vec2 Camera::lastRot(1.0f, 0.0f);
|
|
46
|
+glm::quat Camera::quaternion(glm::vec3(0.0f, 0.0f, 0.0f));
|
|
47
|
+glm::vec3 Camera::posSpeed(0.0f, 0.0f, 0.0f);
|
|
48
|
+glm::vec2 Camera::rotSpeed(0.0f, 0.0f);
|
57
|
49
|
glm::vec2 Camera::lastSize(0.0f, 0.0f);
|
58
|
50
|
glm::mat4 Camera::projection(1.0f);
|
59
|
51
|
glm::mat4 Camera::view(1.0f);
|
60
|
52
|
float Camera::rotationDeltaX = 0.75f;
|
61
|
53
|
float Camera::rotationDeltaY = 0.75f;
|
62
|
54
|
bool Camera::updateViewFrustum = true;
|
63
|
|
-static Plane planes[6];
|
64
|
|
-
|
65
|
|
-static glm::vec3 frustumColors[6] = {
|
66
|
|
- glm::vec3(1.0f, 0.0f, 0.0f), // NEAR, red
|
67
|
|
- glm::vec3(0.0f, 1.0f, 0.0f), // FAR, green
|
68
|
|
- glm::vec3(0.0f, 0.0f, 1.0f), // TOP, blue
|
69
|
|
- glm::vec3(1.0f, 1.0f, 0.0f), // BOTTOM, yellow
|
70
|
|
- glm::vec3(0.0f, 1.0f, 1.0f), // LEFT, light-blue
|
71
|
|
- glm::vec3(1.0f, 0.0f, 1.0f) // RIGHT, pink
|
72
|
|
-};
|
73
|
|
-static glm::vec3 frustumVertices[8];
|
74
|
55
|
|
75
|
56
|
void Camera::reset() {
|
76
|
57
|
pos = glm::vec3(0.0f, 0.0f, 0.0f);
|
77
|
|
- rot = glm::vec2(0.0f, 0.0f);
|
78
|
|
- lastPos = glm::vec3(1.0f, 0.0f, 0.0f);
|
79
|
|
- lastRot = glm::vec2(1.0f, 0.0f);
|
|
58
|
+ quaternion = glm::quat(glm::vec3(0.0f, 0.0f, 0.0f));
|
|
59
|
+ posSpeed = glm::vec3(0.0f, 0.0f, 0.0f);
|
|
60
|
+ rotSpeed = glm::vec2(0.0f, 0.0f);
|
80
|
61
|
lastSize = glm::vec2(0.0f, 0.0f);
|
81
|
62
|
projection = glm::mat4(1.0f);
|
82
|
63
|
view = glm::mat4(1.0f);
|
83
|
64
|
}
|
84
|
65
|
|
85
|
66
|
void Camera::handleAction(ActionEvents action, bool isFinished) {
|
|
67
|
+ float factor = 1.0f;
|
86
|
68
|
if (isFinished)
|
87
|
|
- return;
|
88
|
|
-
|
89
|
|
- glm::vec3 dir(
|
90
|
|
- glm::cos(rot.y) * glm::sin(rot.x),
|
91
|
|
- glm::sin(rot.y),
|
92
|
|
- glm::cos(rot.y) * glm::cos(rot.x)
|
93
|
|
- );
|
94
|
|
- glm::vec3 right(
|
95
|
|
- glm::sin(rot.x - glm::pi<float>() / 2.0f),
|
96
|
|
- 0.0f,
|
97
|
|
- glm::cos(rot.x - glm::pi<float>() / 2.0f)
|
98
|
|
- );
|
99
|
|
- glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f);
|
|
69
|
+ factor = -1.0f;
|
100
|
70
|
|
101
|
71
|
if (action == forwardAction) {
|
102
|
|
- pos += dir * freeCameraStep;
|
|
72
|
+ posSpeed += dirUnit * maxSpeed * factor;
|
103
|
73
|
} else if (action == backwardAction) {
|
104
|
|
- pos -= dir * freeCameraStep;
|
|
74
|
+ posSpeed -= dirUnit * maxSpeed * factor;
|
105
|
75
|
} else if (action == leftAction) {
|
106
|
|
- pos += right * freeCameraStep;
|
|
76
|
+ posSpeed += rightUnit * maxSpeed * factor;
|
107
|
77
|
} else if (action == rightAction) {
|
108
|
|
- pos -= right * freeCameraStep;
|
|
78
|
+ posSpeed -= rightUnit * maxSpeed * factor;
|
109
|
79
|
} else if (action == jumpAction) {
|
110
|
|
- pos += up * freeCameraStep;
|
|
80
|
+ posSpeed += upUnit * maxSpeed * factor;
|
111
|
81
|
} else if (action == crouchAction) {
|
112
|
|
- pos -= up * freeCameraStep;
|
113
|
|
- } else if (action == useAction) {
|
114
|
|
- } else if (action == holsterAction) {
|
115
|
|
- } else if (action == walkAction) {
|
|
82
|
+ posSpeed -= upUnit * maxSpeed * factor;
|
116
|
83
|
}
|
117
|
84
|
}
|
118
|
85
|
|
119
|
86
|
void Camera::handleMouseMotion(int x, int y) {
|
120
|
|
- while (x > 0) {
|
121
|
|
- rot.x += rotationDeltaX;
|
122
|
|
- x--;
|
123
|
|
- }
|
124
|
|
- while (x < 0) {
|
125
|
|
- rot.x -= rotationDeltaX;
|
126
|
|
- x++;
|
127
|
|
- }
|
128
|
|
- while (y > 0) {
|
129
|
|
- if (rot.y > -(glm::pi<float>() / 2.0f)) {
|
130
|
|
- rot.y -= rotationDeltaY;
|
131
|
|
- }
|
132
|
|
- y--;
|
133
|
|
- }
|
134
|
|
- while (y < 0) {
|
135
|
|
- if (rot.y < (glm::pi<float>() / 2.0f)) {
|
136
|
|
- rot.y += rotationDeltaY;
|
137
|
|
- }
|
138
|
|
- y++;
|
139
|
|
- }
|
|
87
|
+ if (x != 0)
|
|
88
|
+ quaternion = glm::quat(upUnit * rotationDeltaX * float(x)) * quaternion;
|
140
|
89
|
|
141
|
|
- while (rot.x > (glm::pi<float>() * 2.0f))
|
142
|
|
- rot.x -= glm::pi<float>() * 2.0f;
|
|
90
|
+ if (y != 0)
|
|
91
|
+ quaternion = glm::quat(quaternion * -rightUnit * rotationDeltaY * float(y)) * quaternion;
|
|
92
|
+}
|
|
93
|
+
|
|
94
|
+void Camera::handleControllerAxis(float value, KeyboardButton axis) {
|
|
95
|
+ if (glm::epsilonEqual(value, 0.0f, 0.01f))
|
|
96
|
+ value = 0.0f;
|
|
97
|
+
|
|
98
|
+ if (axis == leftXAxis) {
|
|
99
|
+ posSpeed.x = -maxSpeed * value;
|
|
100
|
+ } else if (axis == leftYAxis) {
|
|
101
|
+ posSpeed.z = maxSpeed * value;
|
|
102
|
+ } else if (axis == rightXAxis) {
|
|
103
|
+ rotSpeed.x = controllerViewFactor * value;
|
|
104
|
+ } else if (axis == rightYAxis) {
|
|
105
|
+ rotSpeed.y = controllerViewFactor * value;
|
|
106
|
+ }
|
|
107
|
+}
|
143
|
108
|
|
144
|
|
- while (rot.x < -(glm::pi<float>() * 2.0f))
|
145
|
|
- rot.x += glm::pi<float>() * 2.0f;
|
|
109
|
+void Camera::handleControllerButton(KeyboardButton button, bool released) {
|
|
110
|
+ if (button == aButton) {
|
|
111
|
+ handleAction(jumpAction, released);
|
|
112
|
+ } else if (button == bButton) {
|
|
113
|
+ handleAction(crouchAction, released);
|
|
114
|
+ } else if (button == padUp) {
|
|
115
|
+ handleAction(forwardAction, released);
|
|
116
|
+ } else if (button == padDown) {
|
|
117
|
+ handleAction(backwardAction, released);
|
|
118
|
+ } else if (button == padLeft) {
|
|
119
|
+ handleAction(leftAction, released);
|
|
120
|
+ } else if (button == padRight) {
|
|
121
|
+ handleAction(rightAction, released);
|
|
122
|
+ }
|
146
|
123
|
}
|
147
|
124
|
|
148
|
125
|
bool Camera::update() {
|
149
|
126
|
glm::vec2 size(getWindow().getWidth(), getWindow().getHeight());
|
150
|
127
|
|
151
|
|
- if ((lastPos == pos) && (lastRot == rot) && (lastSize == size))
|
152
|
|
- return false;
|
153
|
|
-
|
154
|
128
|
if (lastSize != size) {
|
155
|
|
- //! \fixme TODO instead of mirroring the axes in the shader, scale here
|
|
129
|
+ //! \fixme TODO instead of mirroring the Y axis in the shader, scale with -1 here
|
156
|
130
|
projection = glm::perspective(fov, size.x / size.y, nearDist, farDist);
|
157
|
131
|
lastSize = size;
|
158
|
132
|
}
|
159
|
133
|
|
160
|
|
- glm::vec3 dir(
|
161
|
|
- glm::cos(rot.y) * glm::sin(rot.x),
|
162
|
|
- glm::sin(rot.y),
|
163
|
|
- glm::cos(rot.y) * glm::cos(rot.x)
|
164
|
|
- );
|
|
134
|
+ float dT = getRunTime().getLastFrameTime();
|
|
135
|
+ pos += quaternion * posSpeed * dT;
|
|
136
|
+
|
|
137
|
+ if (glm::epsilonNotEqual(rotSpeed.x, 0.0f, 0.01f))
|
|
138
|
+ quaternion = glm::quat(upUnit * rotationDeltaX * rotSpeed.x * dT) * quaternion;
|
|
139
|
+
|
|
140
|
+ if (glm::epsilonNotEqual(rotSpeed.y, 0.0f, 0.01f))
|
|
141
|
+ quaternion = glm::quat(quaternion * -rightUnit * rotationDeltaY * rotSpeed.y * dT) * quaternion;
|
|
142
|
+
|
|
143
|
+ glm::mat4 translate = glm::translate(glm::mat4(1.0f), pos);
|
|
144
|
+ glm::mat4 rotate = glm::toMat4(quaternion);
|
|
145
|
+ view = glm::inverse(translate * rotate);
|
|
146
|
+
|
|
147
|
+ if (updateViewFrustum)
|
|
148
|
+ calculateFrustumPlanes();
|
|
149
|
+
|
|
150
|
+ return updateViewFrustum;
|
|
151
|
+}
|
|
152
|
+
|
|
153
|
+glm::vec2 Camera::getRotation() {
|
|
154
|
+ glm::vec3 euler = glm::eulerAngles(quaternion);
|
|
155
|
+ return glm::vec2(euler.y, euler.x);
|
|
156
|
+}
|
|
157
|
+
|
|
158
|
+// ----------------------------------------------------------------------------
|
165
|
159
|
|
166
|
|
- glm::vec3 right(
|
167
|
|
- glm::sin(rot.x - glm::pi<float>() / 2.0f),
|
168
|
|
- 0.0f,
|
169
|
|
- glm::cos(rot.x - glm::pi<float>() / 2.0f)
|
170
|
|
- );
|
|
160
|
+class FrustumPlane {
|
|
161
|
+ public:
|
|
162
|
+ FrustumPlane() : normal(glm::vec3(0.0f, 0.0f, 0.0f)), d(0.0f) { }
|
|
163
|
+ void set(glm::vec3 v1, glm::vec3 v2, glm::vec3 v3) {
|
|
164
|
+ normal = glm::normalize(glm::cross(v3 - v2, v1 - v2));
|
|
165
|
+ d = -glm::dot(normal, v2);
|
|
166
|
+ }
|
|
167
|
+ float distance(glm::vec3 p) {
|
|
168
|
+ return d + glm::dot(normal, p);
|
|
169
|
+ }
|
|
170
|
+ private:
|
|
171
|
+ glm::vec3 normal;
|
|
172
|
+ float d;
|
|
173
|
+};
|
171
|
174
|
|
172
|
|
- glm::vec3 up = glm::cross(right, dir);
|
173
|
|
- view = glm::lookAt(pos, pos + dir, up);
|
|
175
|
+// ----------------------------------------------------------------------------
|
174
|
176
|
|
175
|
|
- if (!updateViewFrustum)
|
176
|
|
- return false;
|
|
177
|
+static FrustumPlane planes[6];
|
|
178
|
+static glm::vec3 frustumColors[6] = {
|
|
179
|
+ glm::vec3(1.0f, 0.0f, 0.0f), // NEAR, red
|
|
180
|
+ glm::vec3(0.0f, 1.0f, 0.0f), // FAR, green
|
|
181
|
+ glm::vec3(0.0f, 0.0f, 1.0f), // TOP, blue
|
|
182
|
+ glm::vec3(1.0f, 1.0f, 0.0f), // BOTTOM, yellow
|
|
183
|
+ glm::vec3(0.0f, 1.0f, 1.0f), // LEFT, light-blue
|
|
184
|
+ glm::vec3(1.0f, 0.0f, 1.0f) // RIGHT, pink
|
|
185
|
+};
|
|
186
|
+static glm::vec3 frustumVertices[8];
|
177
|
187
|
|
|
188
|
+void Camera::calculateFrustumPlanes() {
|
178
|
189
|
glm::mat4 combo = projection * view;
|
179
|
190
|
|
180
|
191
|
// Calculate frustum corners to display them
|
|
@@ -200,10 +211,6 @@ bool Camera::update() {
|
200
|
211
|
planes[RIGHT].set(frustumVertices[NBR], frustumVertices[NTR], frustumVertices[FBR]);
|
201
|
212
|
planes[NEAR].set(frustumVertices[NTL], frustumVertices[NTR], frustumVertices[NBR]);
|
202
|
213
|
planes[FAR].set(frustumVertices[FTR], frustumVertices[FTL], frustumVertices[FBL]);
|
203
|
|
-
|
204
|
|
- lastPos = pos;
|
205
|
|
- lastRot = rot;
|
206
|
|
- return true;
|
207
|
214
|
}
|
208
|
215
|
|
209
|
216
|
bool Camera::boxInFrustum(BoundingBox b) {
|