13 glm::vec3 eyePos{ 0,0,0 };
14 glm::vec3 aimPos{ 0,0,0 };
15 glm::vec3 upDir{0,-1,0};
16 float zFar = 1000000.0f;
18 ViewMode currentViewMode = ViewMode::Y_UP;
22 _projectionMatrix(1.0f),
29 eyePos = glm::vec3(0.f, 0.f, -770.0f);
30 aimPos = glm::vec3(0.f, 0.f, 0.f);
44 void init()
override {
45 _projectionMatrix = glm::perspective(glm::radians(45.0f), (
float)_screenWidth / (
float)_screenHeight, 0.1f, zFar);
46 updateCameraOrientation();
48 _cameraMatrix = glm::mat4(1.0f);
50 glm::vec3 scale(_scale, _scale, 1.0f);
51 _cameraMatrix = glm::scale(_cameraMatrix, scale);
54 glm::vec3 translate(-_position.x, -_position.y, 0.0f);
55 _cameraMatrix = glm::translate(_cameraMatrix, translate);
57 _cameraMatrix = _projectionMatrix * _viewMatrix * _cameraMatrix;
61 void update()
override {
63 updateCameraOrientation();
65 _cameraMatrix = glm::mat4(1.0f);
68 glm::vec3 translate(-_position.x, -_position.y, 0.0f);
69 _cameraMatrix = glm::translate(_cameraMatrix, translate);
71 glm::vec3 scale(_scale, _scale, 1.0f);
72 _cameraMatrix = glm::scale(_cameraMatrix, scale);
75 _cameraMatrix = _projectionMatrix * _viewMatrix * _cameraMatrix;
81 void updateCameraOrientation() {
82 if (currentViewMode == ViewMode::Y_UP) {
83 upDir = glm::vec3(0.0f, -1.0f, 0.0f);
90 upDir = glm::vec3(0.0f, 0.0f, -1.0f);
98 void setOrientation(glm::vec3 eye, glm::vec3 target, glm::vec3 up) {
99 _viewMatrix = glm::lookAt(eye, target, up);
102 glm::vec2 convertScreenToWorld(glm::vec2 screenCoords)
const override {
103 SDL_FRect cameraRect = getCameraRect();
105 glm::vec2 worldCoords;
107 worldCoords = screenCoords;
108 worldCoords /= _scale;
110 worldCoords.x = worldCoords.x + cameraRect.x;
111 worldCoords.y = worldCoords.y + cameraRect.y;
118 void setPosition(
const glm::vec3 newPosition)
override {
119 eyePos = newPosition;
120 _cameraChange =
true;
123 void setPosition_X(
const float newPosition)
override {
124 eyePos.x = newPosition;
125 _cameraChange =
true;
128 void setPosition_Y(
const float newPosition)
override {
129 eyePos.y = newPosition;
130 _cameraChange =
true;
133 void setPosition_Z(
const float newPosition)
override {
134 eyePos.z = newPosition;
135 _cameraChange =
true;
138 void movePosition_Hor(
const float step) {
139 glm::vec3 direction = glm::normalize(aimPos - eyePos);
142 glm::vec3 right = glm::normalize(glm::cross(direction, upDir));
145 eyePos += right * step;
146 aimPos += right * step;
147 _cameraChange =
true;
149 void movePosition_Vert(
const float step) {
150 glm::vec3 direction = glm::normalize(aimPos - eyePos);
153 eyePos += upDir * step;
154 aimPos += upDir * step;
155 _cameraChange =
true;
158 void movePosition_Forward(
const float step) {
159 glm::vec3 direction = glm::normalize(aimPos - eyePos);
160 eyePos += direction * step;
161 aimPos += direction * step;
162 _cameraChange =
true;
165 void setAimPos(
const glm::vec3 newAimPos) {
167 _cameraChange =
true;
170 void moveAimPos(glm::vec3 startingAimPos,
const glm::vec2 distance) {
171 aimPos = startingAimPos;
172 const float sensitivity = 0.0001f;
174 float yaw = distance.x * sensitivity;
175 float pitch = distance.y * sensitivity;
177 glm::vec3 direction = glm::normalize(aimPos - eyePos);
179 direction = glm::rotate(direction, yaw, upDir);
181 glm::vec3 right = glm::normalize(glm::cross(direction, upDir));
183 direction = glm::rotate(direction, pitch, right);
186 aimPos = eyePos + direction;
187 _cameraChange =
true;
190 glm::vec3 getEulerAnglesFromDirection(glm::vec3 direction) {
191 float yaw = glm::atan(direction.x, direction.z);
192 float pitch = glm::asin(-direction.y);
195 return glm::vec3(glm::degrees(pitch), glm::degrees(yaw), glm::degrees(roll));
203 glm::vec3 getAimPos() {
207 void setScale(
float newScale)
override {
209 _cameraChange =
true;
213 glm::vec3 getPosition()
const override {
217 float getScale()
const override {
221 glm::mat4 getCameraMatrix()
const override {
222 return _cameraMatrix;
225 glm::ivec2 getCameraDimensions()
const override {
226 glm::vec2 cameraDimensions = { _screenWidth, _screenHeight };
227 return cameraDimensions;
230 SDL_FRect getCameraRect()
const override {
231 float cameraWidth = getCameraDimensions().x / getScale();
232 float cameraHeight = getCameraDimensions().y / getScale();
234 float cameraX = _position.x - cameraWidth / 2.0f ;
235 float cameraY = _position.y - cameraHeight / 2.0f ;
237 SDL_FRect cameraRect = { cameraX , cameraY , cameraWidth, cameraHeight };
241 void setCameraMatrix(glm::mat4 newMatrix) {
242 _cameraChange =
true;
244 void resetCameraPosition() {
246 _position = glm::vec2(0.0f,0.0f);
249 eyePos = glm::vec3(0.f, 0.f, -770.0f);
250 aimPos = glm::vec3( 0,0,0 );
252 currentViewMode = ViewMode::Y_UP;
253 upDir = glm::vec3( 0,-1,0 );
257 _cameraChange =
true;
259 float getMinScale() {
263 float getMaxScale() {
268 bool isPointInCameraView(
const glm::vec4 point,
float margin)
270 glm::mat4 vpMatrix = _cameraMatrix;
272 glm::vec4 clipSpacePos = vpMatrix * point;
274 if (clipSpacePos.w != 0.0f) {
275 clipSpacePos.x /= clipSpacePos.w;
276 clipSpacePos.y /= clipSpacePos.w;
277 clipSpacePos.z /= clipSpacePos.w;
281 if (clipSpacePos.x < -1.0f - margin || clipSpacePos.x > 1.0f + margin)
return false;
282 if (clipSpacePos.y < -1.0f - margin || clipSpacePos.y > 1.0f + margin)
return false;
283 if (clipSpacePos.z < -margin || clipSpacePos.z > 1.0f + margin)
return false;
288 bool hasChanged()
override {
289 return _cameraChange;
292 void makeCameraDirty()
override {
293 _cameraChange =
true;
296 void refreshCamera()
override {
297 _cameraChange =
false;
301 glm::vec3 castRayAt(
const glm::vec2& screenPos) {
303 float x = (2.0f * screenPos.x) / _screenWidth - 1.0f;
304 float y = 1.0f - (2.0f * screenPos.y) / _screenHeight;
305 glm::vec4 clipCoords = glm::vec4(x, y, -1.0f, 1.0f);
308 glm::vec4 eyeCoords = glm::inverse(_projectionMatrix) * clipCoords;
309 eyeCoords = glm::vec4(eyeCoords.x, eyeCoords.y, -1.0f, 0.0f);
312 glm::vec3 worldRay = glm::vec3(glm::inverse(_viewMatrix) * eyeCoords);
313 worldRay = glm::normalize(worldRay);
317 glm::vec3 getPointOnRayAtZ(
const glm::vec3& rayOrigin,
const glm::vec3& rayDirection,
float desiredZ) {
319 if (rayDirection.z == 0.0f) {
321 return glm::vec3(std::numeric_limits<float>::infinity());
325 float t = (desiredZ - rayOrigin.z) / rayDirection.z;
328 glm::vec3 pointOnRay = rayOrigin + t * rayDirection;
333 glm::mat4 getViewMatrix() {
337 glm::mat4 getProjMatrix() {
342 int _screenWidth, _screenHeight;
343 float _minScale = 0.1f, _maxScale = 5.0f;
348 glm::mat4 _projectionMatrix;
349 glm::mat4 _viewMatrix;
350 glm::mat4 _cameraMatrix;