-
Notifications
You must be signed in to change notification settings - Fork 1
/
Camera.cpp
126 lines (105 loc) · 4.51 KB
/
Camera.cpp
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
#include <SDL2/SDL.h>
#include <SDL2/SDL_opengl.h>
#include <math.h>
#include "Camera.h"
#include "App.h"
#define GLM_FORCE_RADIANS
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
namespace typing
{
Camera::Camera(const juzutil::Vector3& origin, const juzutil::Vector3& lookat)
: m_origin(origin), m_lookat(lookat)
{
m_forward = (lookat - origin);
m_forward.Normalize();
if (m_forward[0] == 1.0f || m_forward[0] == -1.0f) {
m_right.Set(0.0f, -m_forward[0], 0.0f);
} else if (m_forward[1] == 1.0f || m_forward[1] == -1.0f) {
m_right.Set(0.0f, m_forward[1], 0.0f);
} else if(m_forward[2] == 1.0f || m_forward[2] == -1.0f) {
m_right.Set(1.0f, 0.0f, 0.0f);
} else {
m_right = m_forward.GetMajorAxis() % m_forward;
m_right.Normalize();
}
m_up = m_forward % m_right;
m_up.Normalize();
}
void Camera::ApplyPerspective()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glm::mat4 projection = glm::perspective(
1.30899694f, 4.0f/3.0f, 0.1f, 10000.0f);
glLoadMatrixf(glm::value_ptr(projection));
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glm::vec3 origin(m_origin[0], m_origin[1], m_origin[2]);
glm::vec3 center(m_lookat[0], m_lookat[1], m_lookat[2]);
glm::vec3 up(m_up[0], m_up[1], m_up[2]);
glm::mat4 lookat = glm::lookAt(origin, center, up);
glLoadMatrixf(glm::value_ptr(lookat));
glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *)&m_modelview);
glGetFloatv(GL_PROJECTION_MATRIX, (GLfloat *)&m_projection);
}
const juzutil::Vector2 Camera::PerspectiveProject(
const juzutil::Vector3& worldCoords) const
{
int view[4];
glGetIntegerv(GL_VIEWPORT, view);
glm::vec3 obj(worldCoords[0], worldCoords[1], worldCoords[2]);
glm::vec3 coords = glm::project(obj,
m_modelview,
m_projection,
glm::vec4(view[0],
view[1],
view[2],
view[3]));
return juzutil::Vector2(
coords.x, static_cast<float>(APP.GetScreenHeight()) - coords.y);
}
const juzutil::Vector3 Camera::UnPerspectiveProject(
const juzutil::Vector2& screenCoords,
const float worldCoordsZ) const
{
int view[4];
glGetIntegerv(GL_VIEWPORT, view);
// Unproject to the near and far clip plane and use the two values to
// work out how much to adjust the result by to end up at the required
// Z value in world coords.
glm::vec3 worldCoordsNear =
glm::unProject(
glm::vec3(screenCoords[0],
static_cast<float>(APP.GetScreenHeight()) -
screenCoords[1],
0.0f),
m_modelview,
m_projection,
glm::vec4(view[0], view[1], view[2], view[3]));
glm::vec3 worldCoordsFar =
glm::unProject(
glm::vec3(screenCoords[0],
static_cast<float>(APP.GetScreenHeight()) -
screenCoords[1],
1.0f),
m_modelview,
m_projection,
glm::vec4(view[0], view[1], view[2], view[3]));
glm::vec3 nearToFar = worldCoordsFar - worldCoordsNear;
float ratio = (0.0f - worldCoordsNear.z) / nearToFar.z;
glm::vec3 worldCoords(worldCoordsNear.x + (worldCoordsFar.x - worldCoordsNear.x) * ratio,
worldCoordsNear.y + (worldCoordsFar.y - worldCoordsNear.y) * ratio,
worldCoordsNear.z + (worldCoordsFar.z - worldCoordsNear.z) * ratio);
return juzutil::Vector3(worldCoords.x, worldCoords.y, worldCoords.z);
}
void Camera::ApplyOrtho() const
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, APP.GetScreenWidth(), APP.GetScreenHeight(),
0, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW_MATRIX);
}
}