-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathcamera.cpp
More file actions
246 lines (190 loc) · 7.19 KB
/
camera.cpp
File metadata and controls
246 lines (190 loc) · 7.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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
//Ripped and converted from http://r3dux.org/2012/12/a-c-camera-class-for-simple-opengl-fps-controls/
#include "Camera.h"
const double Camera::TO_RADS = 3.141592654 / 180.0; // The value of 1 degree in radians
Camera::Camera(GLFWwindow* thewindow, float theWindowWidth, float theWindowHeight)
{
initCamera();
window = thewindow;
windowWidth = theWindowWidth;
windowHeight = theWindowHeight;
// Calculate the middle of the window
windowMidX = windowWidth / 2.0f;
windowMidY = windowHeight / 2.0f;
glfwSetCursorPos(window, windowMidX, windowMidY);
}
Camera::~Camera()
{
// Nothing to do here - we don't need to free memory as all member variables
// were declared on the stack.
}
void Camera::initCamera()
{
// Set position, rotation and speed values to a default value, note rotation should be nonzero.
position = { 2,2,1 };
rotation = { 0,0,0 };
speed = { 0,0,0 };
// How fast we move (higher values mean we move and strafe faster)
movementSpeedFactor = 5;
pitchSensitivity = 0.05; // How sensitive mouse movements affect looking up and down
yawSensitivity = 0.05; // How sensitive mouse movements affect looking left and right
// To begin with, we aren't holding down any keys
holdingForward = false;
holdingBackward = false;
holdingLeftStrafe = false;
holdingRightStrafe = false;
altLock = true;
}
// Function to convert degrees to radians
const double Camera::toRads(const double &theAngleInDegrees) const
{
return theAngleInDegrees * TO_RADS;
}
// Function to deal with mouse position changes
void Camera::handleMouseMove(GLFWwindow* window, int mouseX, int mouseY)
{
// Calculate our horizontal and vertical mouse movement from middle of the window
double horizMovement = (mouseX - windowMidX) * yawSensitivity;
double vertMovement = (mouseY - windowMidY) * pitchSensitivity;
//std::cout << "Mid window values: " << windowMidX << "\t" << windowMidY << std::endl;
//std::cout << "Mouse values : " << mouseX << "\t" << mouseY << std::endl;
//std::cout << horizMovement << "\t" << vertMovement << std::endl << std::endl;
// Apply the mouse movement to our rotation vector. The vertical (look up and down)
// movement is applied on the X axis, and the horizontal (look left and right)
// movement is applied on the Y Axis
rotation.x += vertMovement;
rotation.y += horizMovement;
// Limit looking up to vertically up minus a bit
if (rotation.x < -89.9f) { rotation.x = -89.9f; }
// Limit looking down to vertically down minus a bit
if (rotation.x > 89.9f) { rotation.x = 89.9f; }
// If you prefer to keep the angles in the range -180 to +180 use this code
// and comment out the 0 to 360 code below.
//
// Looking left and right. Keep the angles in the range -180.0f (anticlockwise turn looking behind) to 180.0f (clockwise turn looking behind)
/*if (yRot < -180.0f)
{
yRot += 360.0f;
}
if (yRot > 180.0f)
{
yRot -= 360.0f;
}*/
// Looking left and right - keep angles in the range 0.0 to 360.0
// 0 degrees is looking directly down the negative Z axis "North", 90 degrees is "East", 180 degrees is "South", 270 degrees is "West"
// We can also do this so that our 360 degrees goes -180 through +180 and it works the same, but it's probably best to keep our
// range to 0 through 360 instead of -180 through +180.
if (rotation.y < 0.0f) { rotation.y += 360.0f; }
if (rotation.y > 360.0f) { rotation.y -= 360.0f; }
if (mouseX != windowMidX || mouseY != windowMidY) { glfwSetCursorPos(window, windowMidX, windowMidY); }
}
// Function to calculate which direction we need to move the camera and by what amount
void Camera::move(double deltaTime)
{
// Vector to break up our movement into components along the X, Y and Z axis
glm::vec3 movement = { 0,0,0 };
//Following section has questionable use
// Get the sine and cosine of our X and Y axis rotation
double sinXRot = sin(toRads(rotation.x));
double cosXRot = cos(toRads(rotation.x));
double sinYRot = sin(toRads(rotation.y));
double cosYRot = cos(toRads(rotation.y));
double pitchLimitFactor = cosXRot; // This cancels out moving on the Z axis when we're looking up or down
if (holdingForward)
{
movement += glm::vec3(cosYRot, -sinYRot, -sinXRot * (altLock ? 0.0 : 1.0));
}
if (holdingBackward)
{
movement -= glm::vec3(cosYRot, -sinYRot, -sinXRot * (altLock ? 0.0 : 1.0));
}
if (holdingLeftStrafe)
{
movement += glm::vec3(sinYRot, cosYRot, 0.0f);
}
if (holdingRightStrafe)
{
movement -= glm::vec3(sinYRot, cosYRot, 0.0f);
}
// Normalise our movement vector, but ONLY if it's non-zero! Normalising a vector of zero length
// leads to the new vector having a length of NaN (Not a Number) because of the divide by zero.
// Note: Using '>= 0.0f' rather than '!= 0.0f' avoids the compiler float comparison warning - we could
// instead use '>= std::epsilon()' from the limit.h header, but I think that would be overkill.
// Further reading: http://www.cplusplus.com/reference/limits/numeric_limits/
if (glm::length(movement) > 0.0f)
{
movement = glm::normalize(movement);
}
// Calculate our value to keep the movement the same speed regardless of the framerate...
double framerateIndependentFactor = movementSpeedFactor * deltaTime;
// .. and then apply it to our movement vector.
movement *= framerateIndependentFactor;
// Finally, apply the movement to our position
position += movement;
}
void Camera::handleKeypress(GLint key, GLint action)
{
// If a key is pressed, toggle the relevant key-press flag
if (action == GLFW_PRESS || action == GLFW_REPEAT)
{
//cout << "Got keypress: " << key << "\t" << action << endl;
switch (key)
{
case 87: // 'w'
//std::cout << "forward key down!" << std::endl;
holdingForward = true;
break;
case 83: // 's'
//std::cout << "backward key down!" << std::endl;
holdingBackward = true;
break;
case 65: // 'a'
//std::cout << "left strafe key down!" << std::endl;
holdingLeftStrafe = true;
break;
case 68: // 'd'
//std::cout << "right strafe key down!" << std::endl;
holdingRightStrafe = true;
break;
default:
// Do nothing...
break;
}
}
else // If a key is released, toggle the relevant key-release flag
{
switch (key)
{
case 87: // 'w'
//std::cout << "forward key up!" << std::endl;
holdingForward = false;
break;
case 83: // 's'
holdingBackward = false;
break;
case 65: // 'a'
holdingLeftStrafe = false;
break;
case 68: // 'd'
holdingRightStrafe = false;
break;
default:
// Do nothing...
break;
} // End of switch block
} // End of else GLFW_RELEASE block
}
glm::vec3 Camera::getRotVec()
{
//Manually convert xyz rotations to a unit vector for camera pointing.
double x, y, z;
x = cos(toRads(rotation.y))*cos(toRads(rotation.x));
y = -sin(toRads(rotation.y))*cos(toRads(rotation.x));
z = -sin(toRads(rotation.x));
glm::vec3 rotVec = { x,y,z };
glm::normalize(rotVec);
return rotVec;
}
glm::vec3 Camera::getUpVec()
{
return glm::vec3(0, 0, 1); //TEMPORARY, BUT THIS WORKS. DON'T MESS WITH IT UNLESS YOU WANT TO MESS WITH getRotVec.
}