]> git.tdb.fi Git - libs/gl.git/blob - source/camera.cpp
Add orthographic mode to Camera
[libs/gl.git] / source / camera.cpp
1 #include <cmath>
2 #include "camera.h"
3 #include "matrix.h"
4
5 namespace Msp {
6 namespace GL {
7
8 Camera::Camera():
9         fov(Geometry::Angle<float>::from_turns(0.125)),
10         height(0),
11         aspect(4.0/3.0),
12         clip_near(0.1),
13         clip_far(10),
14         frustum_x(0),
15         frustum_y(0),
16         position(0, 0, 0),
17         look_dir(0, 0, -1),
18         up_dir(0, 1, 0)
19 {
20         update_projection_matrix();
21         update_object_matrix();
22 }
23
24 void Camera::set_field_of_view(const Geometry::Angle<float> &f)
25 {
26         fov = f;
27         update_projection_matrix();
28 }
29
30 void Camera::set_orthographic(float w, float h)
31 {
32         fov = Geometry::Angle<float>::zero();
33         height = h;
34         if(w)
35                 aspect = w/h;
36         update_projection_matrix();
37 }
38
39 void Camera::set_aspect(float a)
40 {
41         aspect = a;
42         update_projection_matrix();
43 }
44
45 void Camera::set_depth_clip(float n, float f)
46 {
47         clip_near = n;
48         clip_far = f;
49         update_projection_matrix();
50 }
51
52 void Camera::set_frustum_axis(float x, float y)
53 {
54         frustum_x = x;
55         frustum_y = y;
56         update_projection_matrix();
57 }
58
59 void Camera::set_position(const Vector3 &p)
60 {
61         position = p;
62         update_object_matrix();
63 }
64
65 void Camera::set_up_direction(const Vector3 &u)
66 {
67         up_dir = normalize(u);
68         update_object_matrix();
69 }
70
71 void Camera::set_look_direction(const Vector3 &l)
72 {
73         look_dir = normalize(l);
74         update_object_matrix();
75 }
76
77 void Camera::look_at(const Vector3 &p)
78 {
79         set_look_direction(p-position);
80 }
81
82 Vector3 Camera::project(const Vector4 &p) const
83 {
84         Vector4 r = proj_matrix*(view_matrix*p);
85         return Vector3(r)/r.w;
86 }
87
88 Vector3 Camera::project(const Vector3 &p) const
89 {
90         return project(Vector4(p.x, p.y, p.z, 1.0));
91 }
92
93 Vector4 Camera::unproject(const Vector4 &p) const
94 {
95         Vector4 r = invert(proj_matrix)*Vector4(p.x, p.y, p.z, 1.0f);
96         r = object_matrix*Vector4(r.x, r.y, r.z, p.w);
97         return r;
98 }
99
100 void Camera::apply() const
101 {
102         MatrixStack::projection() = proj_matrix;
103         MatrixStack::modelview() = view_matrix;
104 }
105
106 void Camera::update_projection_matrix()
107 {
108         float frustum_h = tan(fov/2.0f)*clip_near;
109         float frustum_w = frustum_h*aspect;
110         float left = frustum_w*(frustum_x-1.0f);
111         float right = frustum_w*(frustum_x+1.0f);
112         float bottom = frustum_h*(frustum_y-1.0f);
113         float top = frustum_h*(frustum_y+1.0f);
114         if(fov>Geometry::Angle<float>::zero())
115                 proj_matrix = Matrix::frustum(left, right, bottom, top, clip_near, clip_far);
116         else
117                 proj_matrix = Matrix::ortho(left, right, bottom, top, clip_near, clip_far);
118 }
119
120 void Camera::update_object_matrix()
121 {
122         Vector3 right_dir = normalize(cross(look_dir, up_dir));
123         Vector4 columns[4];
124         columns[0] = Vector4(right_dir, 0.0f);
125         columns[1] = Vector4(cross(right_dir, look_dir), 0.0f);
126         columns[2] = Vector4(-look_dir, 0.0f);
127         columns[3] = Vector4(position, 1.0f);
128         object_matrix = Matrix::from_columns(columns);
129         view_matrix = invert(object_matrix);
130 }
131
132 } // namespace GL
133 } // namespace Msp