]> git.tdb.fi Git - libs/gl.git/blob - source/render/camera.cpp
Add validation for mapping buffers
[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         shdata.uniform("clip_eye_matrix", proj_matrix);
143         shdata.uniform("eye_clip_matrix", invert(proj_matrix));
144 }
145
146 void Camera::update_object_matrix()
147 {
148         Vector3 right_dir = normalize(cross(look_dir, up_dir));
149         Vector4 columns[4];
150         columns[0] = compose(right_dir, 0.0f);
151         columns[1] = compose(cross(right_dir, look_dir), 0.0f);
152         columns[2] = compose(-look_dir, 0.0f);
153         columns[3] = compose(position, 1.0f);
154         matrix = Matrix::from_columns(columns);
155         view_matrix = invert(matrix);
156
157         shdata.uniform("world_eye_matrix", matrix);
158         shdata.uniform("eye_world_matrix", view_matrix);
159 }
160
161 void Camera::set_debug_name(const string &name)
162 {
163 #ifdef DEBUG
164         shdata.set_debug_name(name+" [UBO]");
165 #else
166         (void)name;
167 #endif
168 }
169
170
171 Camera::Loader::Loader(Camera &c):
172         DataFile::ObjectLoader<Camera>(c)
173 {
174         add("aspect_ratio", &Loader::aspect_ratio);
175         add("depth_clip", &Loader::depth_clip);
176         add("field_of_view", &Loader::field_of_view);
177         add("look_at", &Loader::look_at);
178         add("look_direction", &Loader::look_direction);
179         add("orthographic", &Loader::orthographic);
180         add("position", &Loader::position);
181         add("up_direction", &Loader::up_direction);
182 }
183
184 void Camera::Loader::aspect_ratio(float a)
185 {
186         obj.set_aspect_ratio(a);
187 }
188
189 void Camera::Loader::depth_clip(float n, float f)
190 {
191         obj.set_depth_clip(n, f);
192 }
193
194 void Camera::Loader::field_of_view(float a)
195 {
196         obj.set_field_of_view(Geometry::Angle<float>::from_degrees(a));
197 }
198
199 void Camera::Loader::look_at(float x, float y, float z)
200 {
201         obj.look_at(Vector3(x, y, z));
202 }
203
204 void Camera::Loader::look_direction(float x, float y, float z)
205 {
206         obj.set_look_direction(Vector3(x, y, z));
207 }
208
209 void Camera::Loader::orthographic(float w, float h)
210 {
211         obj.set_orthographic(w, h);
212 }
213
214 void Camera::Loader::position(float x, float y, float z)
215 {
216         obj.set_position(Vector3(x, y, z));
217 }
218
219 void Camera::Loader::up_direction(float x, float y, float z)
220 {
221         obj.set_up_direction(Vector3(x, y, z));
222 }
223
224 } // namespace GL
225 } // namespace Msp