Kukatz 3D  0.1
Török Attila szakdolgozata
projects/Kukatz 3D/src/camera.cpp
00001 /*
00002  * camera.cpp - Kukatz 3D
00003  * Copyright (c) 2010, 2011 - TÖRÖK Attila (torokati44@gmail.com)
00004  *
00005  * This software is provided 'as-is', without any express or implied
00006  * warranty. In no event will the authors be held liable for any damages
00007  * arising from the use of this software.
00008  *
00009  * Permission is granted to anyone to use this software for any purpose,
00010  * including commercial applications, and to alter it and redistribute it
00011  * freely, subject to the following restrictions:
00012  *
00013  *       1. The origin of this software must not be misrepresented; you must not
00014  *                      claim that you wrote the original software. If you use this software
00015  *                      in a product, an acknowledgment in the product documentation would be
00016  *                      appreciated but is not required.
00017  *
00018  *       2. Altered source versions must be plainly marked as such, and must not be
00019  *                      misrepresented as being the original software.
00020  *
00021  *       3. This notice may not be removed or altered from any source
00022  *                      distribution.
00023  */
00024 
00025 #include "camera.hpp"
00026 
00027 #include "followercamera.hpp"
00028 
00029 #include <iostream>
00030 
00031 #include "opengl.hpp"
00032 #include "misc.hpp"
00033 
00034 //unsigned long int Camera::culled[7];
00035 Camera* Camera::current_cam = 0;
00036 
00037 Camera::Camera(const sf::Vector3f& p, const sf::Vector3f& c,
00038                 const sf::Vector3f& u, const sf::Vector2i& offs, const sf::Vector2i& s,
00039                 float f, float zn, float zf):
00040         Viewport(offs, s, zn, zf),
00041         pos(p), center(c), up(u),
00042         object(new StaticObject("CAMERA", "ATLAS_1")),
00043         fov(f), eye_distance(0.05f), screen_distance(5.0f)
00044 {
00045         update_object();
00046         /*
00047         for (unsigned int i = 0; i < 7; ++i)
00048         {
00049                 culled[i] = 0;
00050         }
00051         */
00052         current_cam = this;
00053         get_corners(0.0f);
00054 }
00055 
00056 void Camera::update_object()
00057 {
00058         object->set_position(pos);
00059         
00060         object->set_x_axis(normalize(center - pos));
00061         object->set_y_axis(normalize(crossprod(up, center - pos)));
00062         object->set_z_axis();
00063 }
00064 
00065 /*
00066 void Camera::get_matrices()
00067 {
00068         glGetDoublev(GL_PROJECTION_MATRIX, projection_matrix);
00069         glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix);
00070         glGetIntegerv(GL_VIEWPORT, viewport);
00071 }
00072 */
00073 
00074 void Camera::get_corners(float d)
00075 {
00076         float near_half_height = z_near * tan(fov * 0.5f * M_PI / 180.0f);
00077         float near_half_width  = near_half_height * (float)size.x / (float)size.y;
00078         
00079         float far_half_height = z_far * tan(fov * 0.5f * M_PI / 180.0f);
00080         float far_half_width  = far_half_height * (float)size.x / (float)size.y;
00081         
00082         sf::Vector3f forward_normal = normalize(center - pos);
00083         sf::Vector3f left = normalize(crossprod(up, forward_normal));
00084         sf::Vector3f up = normalize(crossprod(-left, forward_normal));
00085         
00086         
00087         bln = pos + forward_normal * z_near + left * (near_half_width - d * (eye_distance / 2.0f) * (z_near / screen_distance)) - up * near_half_height;
00088         blf = pos + forward_normal * z_far  + left * (far_half_width  - d * (eye_distance / 2.0f) * (z_far  / screen_distance))  - up * far_half_height;
00089         brn = pos + forward_normal * z_near - left * (near_half_width + d * (eye_distance / 2.0f) * (z_near / screen_distance)) - up * near_half_height;
00090         brf = pos + forward_normal * z_far  - left * (far_half_width  + d * (eye_distance / 2.0f) * (z_far  / screen_distance))  - up * far_half_height;
00091         
00092         tln = pos + forward_normal * z_near + left * (near_half_width - d * (eye_distance / 2.0f) * (z_near / screen_distance)) + up * near_half_height;
00093         tlf = pos + forward_normal * z_far  + left * (far_half_width  - d * (eye_distance / 2.0f) * (z_far  / screen_distance)) + up * far_half_height;
00094         trn = pos + forward_normal * z_near - left * (near_half_width + d * (eye_distance / 2.0f) * (z_near / screen_distance)) + up * near_half_height;
00095         trf = pos + forward_normal * z_far  - left * (far_half_width  + d * (eye_distance / 2.0f) * (z_far  / screen_distance)) + up * far_half_height;
00096 }
00097 
00098 void Camera::get_planes()
00099 {
00100         sf::Vector3f forward_normal = normalize(center - pos);
00101         sf::Vector3f bottom_normal  = normalize(crossprod(brn - bln, blf - bln));
00102         sf::Vector3f left_normal    = normalize(crossprod(blf - bln, tln - bln));
00103         sf::Vector3f top_normal     = normalize(crossprod(tln - trn, trf - trn));
00104         sf::Vector3f right_normal   = normalize(crossprod(trn - brn, brf - brn));
00105         
00106         //BOTTOM
00107         planes[0].point = bln;
00108         planes[0].normal = bottom_normal;
00109         
00110         //NEAR
00111         planes[1].point = bln;
00112         planes[1].normal = forward_normal;
00113         
00114         //LEFT
00115         planes[2].point = bln;
00116         planes[2].normal = left_normal;
00117         
00118         //RIGHT
00119         planes[3].point = brn;
00120         planes[3].normal = right_normal;
00121         
00122         //TOP
00123         planes[4].point = tln;
00124         planes[4].normal = top_normal;
00125         
00126         //FAR
00127         planes[5].point = blf;
00128         planes[5].normal = -forward_normal;
00129         
00130         //bln += up * 0.001f;
00131         /*
00132         glPointSize(20.0);
00133         Texture::unbind();
00134         glColor4ub(255,0, 0, 255);
00135         glBegin(GL_POINTS);
00136         glVertex3f(bln.x, bln.y, bln.z);
00137         bln += bottom_normal * 0.1f;
00138         glVertex3f(bln.x, bln.y, bln.z);
00139         glEnd();
00140         glColor4ub(255, 255, 255, 255);*/
00141 }
00142 
00143 void Camera::render()
00144 {
00145         object->render();
00146         
00147         Texture::unbind();
00148         
00149 #define VERTEX(P) glVertex3f((P).x, (P).y, (P).z);
00150         
00151         glBegin(GL_LINES);
00152         
00153         VERTEX(bln);
00154         VERTEX(brn);
00155         
00156         VERTEX(tln);
00157         VERTEX(trn);
00158         
00159         VERTEX(bln);
00160         VERTEX(tln);
00161         
00162         VERTEX(brn);
00163         VERTEX(trn);
00164         
00165         VERTEX(bln);
00166         VERTEX(blf);
00167         
00168         VERTEX(brn);
00169         VERTEX(brf);
00170         
00171         VERTEX(tln);
00172         VERTEX(tlf);
00173         
00174         VERTEX(trn);
00175         VERTEX(trf);
00176         
00177         glEnd();
00178 }
00179 
00180 void Camera::set_pos(const sf::Vector3f& p, const sf::Vector3f& c,
00181         const sf::Vector3f& u)
00182 {
00183         pos = p;
00184         center = c;
00185         up = u;
00186 }
00187 
00188 
00189 const sf::Vector3f& Camera::get_pos()
00190 {
00191         return pos;
00192 }
00193 
00194 const sf::Vector3f& Camera::get_center()
00195 {
00196         return center;
00197 }
00198 
00199 const sf::Vector3f& Camera::get_up()
00200 {
00201         return up;
00202 }
00203 
00204 Camera& Camera::get_current()
00205 {
00206         return *current_cam;
00207 }
00208 
00209 bool Camera::sees(const sf::Vector3f& p, float r)
00210 {
00211         for (unsigned int i = 0; i < 6; ++i)
00212         {
00213                 if (dotprod(planes[i].normal, normalize((p + planes[i].normal * r) - planes[i].point)) < 0)
00214                 {
00215                         //++culled[i];
00216                         return false;
00217                 }
00218         }
00219         
00220         //++culled[6];
00221         
00222         return true;
00223 }
00224 
00225 void Camera::look_3d(float d)
00226 {
00227         glMatrixMode(GL_PROJECTION);
00228         glLoadIdentity();
00229         
00230         float half_height = z_near * tan(fov * 0.5f * M_PI / 180.f);
00231         float half_width  = half_height * (float)size.x / (float) size.y;
00232         
00233         glFrustum(-half_width - d * ((eye_distance / 2.0f) * (z_near / screen_distance)),
00234                 half_width - d * ((eye_distance / 2.0f) * (z_near / screen_distance)),
00235                 -half_height, half_height, z_near, z_far);
00236         
00237         glMatrixMode(GL_MODELVIEW);
00238         glLoadIdentity();
00239         
00240         sf::Vector3f right = normalize(crossprod(center - pos, up)) / 2.0f;
00241         // eye distance is halved by the coefficient above... so it's a half-normal
00242         
00243         gluLookAt(
00244                         pos.x + right.x * eye_distance * d,
00245                         pos.y + right.y * eye_distance * d,
00246                         pos.z + right.z * eye_distance * d,
00247                         
00248                         center.x + right.x * eye_distance * d,
00249                         center.y + right.y * eye_distance * d,
00250                         center.z + right.z * eye_distance * d,
00251                         
00252                 up.x,     up.y,     up.z);
00253         
00254         glViewport(offset.x, offset.y, size.x, size.y);
00255         
00256         current_cam = this;
00257         
00258         get_corners(d);
00259         get_planes();
00260 }
00261 
00262 Camera::~Camera()
00263 {
00264         /*
00265         for (unsigned int i = 0; i < 7; ++i)
00266         {
00267                 std::cout << i << ".: " << culled[i] << "\n";
00268         }
00269         */
00270         delete object;
00271 }
 Összes Osztályok