340f4f7be689d7a9789a976126e6ec87765d53a5
[tar-legacy.git] / MCDV / Camera.hpp
1 #pragma once
2
3 #include <GLFW\glfw3.h>
4
5 #include <glm\glm.hpp>
6 #include <glm\gtc\matrix_transform.hpp>
7 #include <glm\gtc\type_ptr.hpp>
8
9 #include "GLFWUtil.hpp"
10
11 #include <iostream>
12
13
14 class Camera
15 {
16 private:
17 bool firstMouse = true;
18
19 bool lastStatus = false;
20
21 double lastX = 400;
22 double lastY = 300;
23
24
25
26
27 //Used for true fps control
28 glm::vec3 travelFront = glm::vec3(0.0f, 0.0f, 1.0f);
29
30
31
32 util_keyHandler* keyHandler;
33 public:
34 glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, 1.0f);
35 glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f);
36 glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, -16.0f);
37
38 float yaw = 90.0f;
39 float pitch = 0.0f;
40
41 float sensitivity = 0.05f;
42 float speed = 2.5f;
43 float fov = 90.0f;
44
45 float near_z = 0.1f;
46 float far_z = 1000.0f;
47
48 float pitch_max = 89.0f;
49 float pitch_min = -89.0f;
50
51 int window_width = 800;
52 int window_height = 600;
53
54 bool isNoclip = true;
55
56 void handleInput(float deltaTime);
57
58 void mouseUpdate(double xpos, double ypos, bool isClicking = true);
59
60 glm::mat4 getViewMatrix();
61 glm::mat4 getProjectionMatrix();
62
63 glm::vec3 getViewRay(double xpos, double ypos, int viewWidth, int viewHeight);
64
65 Camera(util_keyHandler* keyHandler);
66 Camera();
67 ~Camera();
68 };
69
70 glm::vec2 getNormalizedDeviceCoords(double xpos, double ypos, int viewWidth, int viewHeight) {
71 float x = (2.0f * xpos) / viewWidth - 1.0f;
72 float y = (2.0f * ypos) / viewHeight - 1.0f;
73
74 return glm::vec2(x, -y);
75 }
76
77 glm::vec4 calculateViewCoords(glm::vec4 clipCoords, glm::mat4 projectionMatrix)
78 {
79 glm::mat4 inverted = glm::inverse(projectionMatrix);
80 glm::vec4 viewCoords = inverted * clipCoords;
81 return glm::vec4(viewCoords.x, viewCoords.y, -1.0f, 0.0f);
82 }
83
84 glm::vec3 calculateWorldVector(glm::vec4 viewCoords, glm::mat4 viewMatrix)
85 {
86 glm::mat4 inverted = glm::inverse(viewMatrix);
87 glm::vec4 worldCoord = inverted * viewCoords;
88 glm::vec3 mouseRay = glm::vec3(worldCoord.x, worldCoord.y, worldCoord.z);
89 mouseRay = glm::normalize(mouseRay);
90 return mouseRay;
91 }
92
93 glm::vec3 calculateMouseRay(double xpos, double ypos, int viewWidth, int viewHeight, glm::mat4 projectionMatrix, glm::mat4 viewMatrix) {
94 glm::vec2 normalizedCoords = getNormalizedDeviceCoords(xpos, ypos, viewWidth, viewHeight);
95 glm::vec4 clipCoords = glm::vec4(normalizedCoords.x, normalizedCoords.y, -1.0f, 1.0f);
96 glm::vec4 viewCoords = calculateViewCoords(clipCoords, projectionMatrix);
97 glm::vec3 worldRay = calculateWorldVector(viewCoords, viewMatrix);
98 return worldRay;
99 }
100
101 glm::vec3 Camera::getViewRay(double xpos, double ypos, int viewWidth, int viewHeight)
102 {
103 return calculateMouseRay(xpos, ypos, viewWidth, viewHeight, this->getProjectionMatrix(), this->getViewMatrix());
104 }
105
106
107 Camera::Camera()
108 {
109
110 }
111
112 void Camera::handleInput(float deltaTime)
113 {
114 glm::vec3 travelDir = cameraFront;
115
116 if (!isNoclip)
117 travelDir = this->travelFront;
118
119 if (keyHandler->getKeyDown(GLFW_KEY_LEFT_SHIFT))
120 this->speed = 20.0f;
121 else
122 this->speed = 2.5f;
123
124 if (keyHandler->getKeyDown(GLFW_KEY_W))
125 cameraPos += speed * travelDir * deltaTime;
126
127 if (keyHandler->getKeyDown(GLFW_KEY_S))
128 cameraPos -= speed * travelDir * deltaTime;
129
130 if (keyHandler->getKeyDown(GLFW_KEY_A))
131 cameraPos -= glm::normalize(glm::cross(travelDir, cameraUp)) * speed * deltaTime;
132
133 if (keyHandler->getKeyDown(GLFW_KEY_D))
134 cameraPos += glm::normalize(glm::cross(travelDir, cameraUp)) * speed * deltaTime;
135 }
136
137 void Camera::mouseUpdate(double xpos, double ypos, bool isClicking)
138 {
139 if (isClicking && (isClicking != this->lastStatus)) {
140 lastX = xpos;
141 lastY = ypos;
142 }
143
144 this->lastStatus = isClicking;
145
146 if (!isClicking)
147 return;
148
149 //Removes first movement skips
150 if (firstMouse)
151 {
152 lastX = xpos;
153 lastY = ypos;
154
155 firstMouse = false;
156 }
157
158 float xoffset = xpos - lastX;
159 float yoffset = lastY - ypos;
160
161 lastX = xpos;
162 lastY = ypos;
163
164 xoffset *= (fov / 90.0f) * this->sensitivity;
165 yoffset *= (fov / 90.0f) * this->sensitivity;
166
167 this->yaw = glm::mod(this->yaw + xoffset, 360.0f);
168 this->pitch = glm::clamp(this->pitch + yoffset, this->pitch_min, this->pitch_max);
169
170 //Front facing vector
171 glm::vec3 front;
172 front.x = cos(glm::radians(this->pitch)) * cos(glm::radians(this->yaw));
173 front.y = sin(glm::radians(this->pitch));
174 front.z = cos(glm::radians(this->pitch)) * sin(glm::radians(this->yaw));
175
176 //Used for fps movement
177 glm::vec3 tFront;
178 tFront.x = cos(glm::radians(this->yaw));
179 tFront.z = sin(glm::radians(this->yaw));
180 tFront.y = 0;
181
182 //Update class vectors
183 this->cameraFront = glm::normalize(front);
184 this->travelFront = glm::normalize(tFront);
185 }
186
187 glm::mat4 Camera::getViewMatrix()
188 {
189 //return glm::lookAt(glm::vec3(0, 0, 10), glm::vec3(0, 0, 10) + glm::vec3(0, 0, -1), glm::vec3(1, 0, 0));
190 return glm::lookAt(this->cameraPos, this->cameraPos + this->cameraFront, this->cameraUp);
191 }
192
193 glm::mat4 Camera::getProjectionMatrix()
194 {
195 //return glm::ortho(-20.0f, 20.0f, -20.0f, 20.0f, 0.1f, 100.0f);
196 return glm::perspective(glm::radians(fov / 2), (float)window_width / (float)window_height, near_z, far_z);
197 }
198
199 Camera::Camera(util_keyHandler* keyHandler)
200 {
201 this->keyHandler = keyHandler;
202 }
203
204 Camera::~Camera()
205 {
206 }
207
208