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