]> git.tdb.fi Git - libs/gl.git/blob - source/camera.cpp
Drop Id tags and copyright notices from files
[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(M_PI/4),
10         aspect(4.0/3.0),
11         clip_near(0.1),
12         clip_far(10),
13         position(0, 0, 0),
14         look_dir(0, 0, -1),
15         up_dir(0, 1, 0)
16 { }
17
18 void Camera::set_field_of_view(float f)
19 {
20         fov = f;
21 }
22
23 void Camera::set_aspect(float a)
24 {
25         aspect = a;
26 }
27
28 void Camera::set_depth_clip(float n, float f)
29 {
30         clip_near = n;
31         clip_far = f;
32 }
33
34 void Camera::set_position(const Vector3 &p)
35 {
36         position = p;
37         compute_matrix();
38 }
39
40 void Camera::set_up_direction(const Vector3 &u)
41 {
42         float len = sqrt(u.x*u.x+u.y*u.y+u.z*u.z);
43
44         up_dir.x = u.x/len;
45         up_dir.y = u.y/len;
46         up_dir.z = u.z/len;
47
48         compute_matrix();
49 }
50
51 void Camera::set_look_direction(const Vector3 &l)
52 {
53         float len = sqrt(l.x*l.x+l.y*l.y+l.z*l.z);
54
55         look_dir.x = l.x/len;
56         look_dir.y = l.y/len;
57         look_dir.z = l.z/len;
58
59         compute_matrix();
60 }
61
62 void Camera::look_at(const Vector3 &p)
63 {
64         set_look_direction(Vector3(p.x-position.x, p.y-position.y, p.z-position.z));
65 }
66
67 Vector3 Camera::project(const Vector4 &p) const
68 {
69         float frustum_h = tan(fov/2);
70         float frustum_w = frustum_h*aspect;
71         float z_range = clip_far-clip_near;
72
73         float eye_x = matrix[0]*p.x+matrix[4]*p.y+matrix[8]*p.z+matrix[12]*p.w;
74         float eye_y = matrix[1]*p.x+matrix[5]*p.y+matrix[9]*p.z+matrix[13]*p.w;
75         float eye_z = matrix[2]*p.x+matrix[6]*p.y+matrix[10]*p.z+matrix[14]*p.w;
76
77         return Vector3(eye_x/frustum_w/-eye_z, eye_y/frustum_h/-eye_z,
78                 (clip_far+clip_near)/z_range+2*clip_far*clip_near/(eye_z*z_range));
79 }
80
81 Vector4 Camera::unproject(const Vector4 &p) const
82 {
83         float frustum_h = tan(fov/2);
84         float frustum_w = frustum_h*aspect;
85         float z_range = clip_far-clip_near;
86
87         float z = (2*clip_far*clip_near)/(p.z*z_range-(clip_far+clip_near))-matrix[14]*p.w;
88         float x = p.x*-z*frustum_w-matrix[12]*p.w;
89         float y = p.y*-z*frustum_h-matrix[13]*p.w;
90
91         return Vector4(matrix[0]*x+matrix[1]*y+matrix[2]*z,
92                 matrix[4]*x+matrix[5]*y+matrix[6]*z,
93                 matrix[8]*x+matrix[9]*y+matrix[10]*z,
94                 p.w);
95 }
96
97 void Camera::apply() const
98 {
99         MatrixStack::projection() = Matrix::perspective(fov, aspect, clip_near, clip_far);
100         MatrixStack::modelview() = matrix;
101 }
102
103 void Camera::compute_matrix()
104 {
105         float x = look_dir.y*up_dir.z-look_dir.z*up_dir.y;
106         float y = look_dir.z*up_dir.x-look_dir.x*up_dir.z;
107         float z = look_dir.x*up_dir.y-look_dir.y*up_dir.x;
108         float len = sqrt(x*x+y*y+z*z);
109         double mdata[16];
110
111         mdata[0] = x/len;
112         mdata[4] = y/len;
113         mdata[8] = z/len;
114
115         mdata[1] = mdata[4]*look_dir.z-mdata[8]*look_dir.y;
116         mdata[5] = mdata[8]*look_dir.x-mdata[0]*look_dir.z;
117         mdata[9] = mdata[0]*look_dir.y-mdata[4]*look_dir.x;
118
119         mdata[2] = -look_dir.x;
120         mdata[6] = -look_dir.y;
121         mdata[10] = -look_dir.z;
122
123         mdata[12] = -position.x*mdata[0]-position.y*mdata[4]-position.z*mdata[8];
124         mdata[13] = -position.x*mdata[1]-position.y*mdata[5]-position.z*mdata[9];
125         mdata[14] = -position.x*mdata[2]-position.y*mdata[6]-position.z*mdata[10];
126
127         mdata[3] = 0;
128         mdata[7] = 0;
129         mdata[11] = 0;
130         mdata[15] = 1;
131
132         matrix = mdata;
133 }
134
135 } // namespace GL
136 } // namespace Msp