added 3dengfx into the repo, probably not the correct version for this
[summerhack] / src / 3dengfx / src / gfx / base_cam.cpp
1 /*
2 This file is part of the graphics core library.
3
4 Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
5
6 the graphics core library is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 the graphics core library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with the graphics core library; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21 #include "3dengfx_config.h"
22
23 #include "base_cam.hpp"
24
25 #ifdef USING_3DENGFX
26 #include "3dengfx/3denginefx.hpp"
27 #endif  // USING_3DENGFX
28
29 FrustumPlane::FrustumPlane() {
30         a = b = c = d = 0;
31 }
32
33 FrustumPlane::FrustumPlane(scalar_t a, scalar_t b, scalar_t c, scalar_t d) {
34         this->a = a;
35         this->b = b;
36         this->c = c;
37         this->d = d;
38 }
39
40 // frustum plane extraction from a projection (or mvp) matrix
41 FrustumPlane::FrustumPlane(const Matrix4x4 &mat, int plane) {
42         int i = plane / 2;
43         int neg = plane % 2;
44
45         a = mat[3][0] + (neg ? -mat[i][0] : mat[i][0]);
46         b = mat[3][1] + (neg ? -mat[i][1] : mat[i][1]);
47         c = mat[3][2] + (neg ? -mat[i][2] : mat[i][2]);
48         d = mat[3][3] + (neg ? -mat[i][3] : mat[i][3]);
49
50         // normalize plane equation
51         scalar_t len = Vector3(a, b, c).length();
52         a /= len;
53         b /= len;
54         c /= len;
55         d /= len;
56 }
57
58 BaseCamera::BaseCamera(const Vector3 &trans, const Quaternion &rot) {
59         set_position(trans);
60         set_rotation(rot);
61         up = Vector3(0, 1, 0);
62         fov = quarter_pi;
63         near_clip = 1.0;
64         far_clip = 10000.0;
65         aspect = 1.33333;
66         flip_view.x = flip_view.y = flip_view.z = false;
67 }
68
69 BaseCamera::~BaseCamera() {}
70
71 void BaseCamera::setup_frustum(const Matrix4x4 &m) {
72         for(int i=0; i<6; i++) {
73                 frustum[i] = FrustumPlane(m, i);
74         }
75 }
76
77 void BaseCamera::set_up_vector(const Vector3 &up) {
78         this->up = up;
79 }
80
81 void BaseCamera::set_fov(scalar_t angle) {
82         fov = angle;
83 }
84
85 scalar_t BaseCamera::get_fov() const {
86         return fov;
87 }
88
89 void BaseCamera::set_aspect(scalar_t aspect) {
90         this->aspect = aspect;
91 }
92
93 scalar_t BaseCamera::get_aspect() const {
94         return aspect;
95 }
96
97 void BaseCamera::set_clipping_planes(scalar_t near_clip, scalar_t far_clip) {
98         this->near_clip = near_clip;
99         this->far_clip = far_clip;
100 }
101
102 void BaseCamera::set_clipping_plane(scalar_t val, ClipPlane which) {
103         if(which == CLIP_NEAR) {
104                 near_clip = val;
105         } else {
106                 far_clip = val;
107         }
108 }
109
110 scalar_t BaseCamera::get_clipping_plane(ClipPlane which) const {
111         return which == CLIP_NEAR ? near_clip : far_clip;
112 }
113
114
115 void BaseCamera::zoom(scalar_t zoom_factor, unsigned long msec) {
116         Vector3 zoom_dir(0, 0, zoom_factor);
117         PRS prs = get_prs(msec);
118
119         zoom_dir.transform(prs.rotation.inverse());
120         translate(zoom_dir, msec);
121 }
122
123 void BaseCamera::pan(const Vector2 &dir, unsigned long msec) {
124         Vector3 i(1, 0, 0), j(0, 1, 0);
125         
126         PRS prs = get_prs(msec);
127         
128         i.transform(prs.rotation.inverse());
129         j.transform(prs.rotation.inverse());
130         
131         translate(i * dir.x);
132         translate(j * dir.y);
133 }
134
135 void BaseCamera::roll(scalar_t angle, unsigned long msec) {
136         Vector3 dir(0, 0, 1);
137         dir.transform(get_prs(msec).rotation);
138
139         Quaternion q(dir, angle);
140         up = Vector3(0, 1, 0);
141         up.transform(q);
142 }
143
144 void BaseCamera::flip(bool x, bool y, bool z) {
145         flip_view.x = x;
146         flip_view.y = y;
147         flip_view.z = z;
148 }
149
150 const FrustumPlane *BaseCamera::get_frustum() const {
151         return frustum;
152 }
153
154 Matrix4x4 BaseCamera::get_projection_matrix() const {
155 #ifdef USING_3DENGFX
156         return create_projection_matrix(fov, aspect, near_clip, far_clip);
157 #else
158         return Matrix4x4::identity_matrix;
159 #endif  // USING_3DENGFX
160 }
161
162 void BaseCamera::activate(unsigned long msec) const {
163 #ifdef USING_3DENGFX
164         set_matrix(XFORM_VIEW, get_camera_matrix(msec));
165
166         Matrix4x4 proj = get_projection_matrix();
167         set_matrix(XFORM_PROJECTION, proj);
168
169         engfx_state::view_mat_camera = (const Camera*)this;
170         const_cast<BaseCamera*>(this)->setup_frustum(proj * engfx_state::view_matrix);
171 #endif  // USING_3DENGFX
172 }