]> git.tdb.fi Git - libs/gl.git/blob - source/render/camera.cpp
Check the flat qualifier from the correct member
[libs/gl.git] / source / render / camera.cpp
1 #include <cmath>
2 #include "camera.h"
3 #include "matrix.h"
4
5 using namespace std;
6
7 namespace Msp {
8 namespace GL {
9
10 Camera::Camera()
11 {
12         update_projection_matrix();
13         update_object_matrix();
14 }
15
16 void Camera::copy_parameters(const Camera &source)
17 {
18         fov = source.fov;
19         height = source.height;
20         aspect = source.aspect;
21         clip_near = source.clip_near;
22         clip_far = source.clip_far;
23         frustum_x = source.frustum_x;
24         frustum_y = source.frustum_y;
25         rotate = source.rotate;
26         position = source.position;
27         look_dir = source.look_dir;
28         up_dir = source.up_dir;
29         update_projection_matrix();
30         update_object_matrix();
31 }
32
33 void Camera::set_field_of_view(const Geometry::Angle<float> &f)
34 {
35         fov = f;
36         update_projection_matrix();
37 }
38
39 void Camera::set_orthographic(float w, float h)
40 {
41         fov = Geometry::Angle<float>::zero();
42         height = h;
43         if(w)
44                 aspect = w/h;
45         update_projection_matrix();
46 }
47
48 void Camera::set_aspect_ratio(float a)
49 {
50         aspect = a;
51         update_projection_matrix();
52 }
53
54 void Camera::set_depth_clip(float n, float f)
55 {
56         clip_near = n;
57         clip_far = f;
58         update_projection_matrix();
59 }
60
61 void Camera::set_frustum_axis(float x, float y)
62 {
63         frustum_x = x;
64         frustum_y = y;
65         update_projection_matrix();
66 }
67
68 void Camera::set_frustum_rotation(const Geometry::Angle<float> &r)
69 {
70         rotate = r;
71         update_projection_matrix();
72 }
73
74 void Camera::set_position(const Vector3 &p)
75 {
76         position = p;
77         update_object_matrix();
78 }
79
80 void Camera::set_look_direction(const Vector3 &l)
81 {
82         look_dir = normalize(l);
83         update_object_matrix();
84 }
85
86 void Camera::look_at(const Vector3 &p)
87 {
88         set_look_direction(p-position);
89 }
90
91 void Camera::set_up_direction(const Vector3 &u)
92 {
93         up_dir = normalize(u);
94         update_object_matrix();
95 }
96
97 void Camera::set_object_matrix(const Matrix &m)
98 {
99         position = m.column(3).slice<3>(0);
100         look_dir = normalize(-m.column(2).slice<3>(0));
101         up_dir = normalize(m.column(1).slice<3>(0));
102         update_object_matrix();
103 }
104
105 Vector3 Camera::project(const Vector4 &p) const
106 {
107         Vector4 r = proj_matrix*(view_matrix*p);
108         return r.slice<3>(0)/r.w;
109 }
110
111 Vector3 Camera::project(const Vector3 &p) const
112 {
113         return project(Vector4(p.x, p.y, p.z, 1.0));
114 }
115
116 Vector4 Camera::unproject(const Vector4 &p) const
117 {
118         Vector4 r = invert(proj_matrix)*Vector4(p.x, p.y, p.z, 1.0f);
119         r = matrix*Vector4(r.x/r.w, r.y/r.w, r.z/r.w, p.w);
120         return r;
121 }
122
123 Vector3 Camera::unproject(const Vector3 &p) const
124 {
125         return unproject(Vector4(p.x, p.y, p.z, 1.0f)).slice<3>(0);
126 }
127
128 void Camera::update_projection_matrix()
129 {
130         float frustum_h = (fov!=Geometry::Angle<float>::zero() ? tan(fov/2.0f)*clip_near : height/2);
131         float frustum_w = frustum_h*aspect;
132         float left = frustum_w*(frustum_x-1.0f);
133         float right = frustum_w*(frustum_x+1.0f);
134         float bottom = frustum_h*(frustum_y-1.0f);
135         float top = frustum_h*(frustum_y+1.0f);
136         if(fov>Geometry::Angle<float>::zero())
137                 proj_matrix = Matrix::frustum(left, right, bottom, top, clip_near, clip_far);
138         else
139                 proj_matrix = Matrix::ortho(left, right, bottom, top, clip_near, clip_far);
140         proj_matrix = Matrix::rotation(rotate, Vector3(0, 0, 1))*proj_matrix;
141
142         adjust_projection_matrix(proj_matrix);
143
144         shdata.uniform("clip_eye_matrix", proj_matrix);
145         shdata.uniform("eye_clip_matrix", invert(proj_matrix));
146 }
147
148 void Camera::update_object_matrix()
149 {
150         Vector3 right_dir = normalize(cross(look_dir, up_dir));
151         Vector4 columns[4];
152         columns[0] = compose(right_dir, 0.0f);
153         columns[1] = compose(cross(right_dir, look_dir), 0.0f);
154         columns[2] = compose(-look_dir, 0.0f);
155         columns[3] = compose(position, 1.0f);
156         matrix = Matrix::from_columns(columns);
157         view_matrix = invert(matrix);
158
159         shdata.uniform("world_eye_matrix", matrix);
160         shdata.uniform("eye_world_matrix", view_matrix);
161 }
162
163 void Camera::set_debug_name(const string &name)
164 {
165 #ifdef DEBUG
166         shdata.set_debug_name(name+" [UBO]");
167 #else
168         (void)name;
169 #endif
170 }
171
172
173 Camera::Loader::Loader(Camera &c):
174         DataFile::ObjectLoader<Camera>(c)
175 {
176         add("aspect_ratio", &Loader::aspect_ratio);
177         add("depth_clip", &Loader::depth_clip);
178         add("field_of_view", &Loader::field_of_view);
179         add("look_at", &Loader::look_at);
180         add("look_direction", &Loader::look_direction);
181         add("orthographic", &Loader::orthographic);
182         add("position", &Loader::position);
183         add("up_direction", &Loader::up_direction);
184 }
185
186 void Camera::Loader::aspect_ratio(float a)
187 {
188         obj.set_aspect_ratio(a);
189 }
190
191 void Camera::Loader::depth_clip(float n, float f)
192 {
193         obj.set_depth_clip(n, f);
194 }
195
196 void Camera::Loader::field_of_view(float a)
197 {
198         obj.set_field_of_view(Geometry::Angle<float>::from_degrees(a));
199 }
200
201 void Camera::Loader::look_at(float x, float y, float z)
202 {
203         obj.look_at(Vector3(x, y, z));
204 }
205
206 void Camera::Loader::look_direction(float x, float y, float z)
207 {
208         obj.set_look_direction(Vector3(x, y, z));
209 }
210
211 void Camera::Loader::orthographic(float w, float h)
212 {
213         obj.set_orthographic(w, h);
214 }
215
216 void Camera::Loader::position(float x, float y, float z)
217 {
218         obj.set_position(Vector3(x, y, z));
219 }
220
221 void Camera::Loader::up_direction(float x, float y, float z)
222 {
223         obj.set_up_direction(Vector3(x, y, z));
224 }
225
226 } // namespace GL
227 } // namespace Msp