//***************************************************************************************** // Truevision - a 3d modeler for gnome and povray // // camera.cc // // Vincent LE PRINCE // Copyright (C) 2000-2005 Vincent LE PRINCE // This file is part of the TRUEVISION Package // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ //******************************************************************************************* #include "include/camera.h" #include "include/viewmanager.h" #include "include/objectlist.h" #include "include/tvio.h" #include #include #include "include/matpov.h" #include "include/preferences.h" /* Some files do not define M_PI... */ #ifndef M_PI #define M_PI 3.14159265358979323846 #endif //************************************** // Définitions // parametres du dessin //************************************** //const float pi = 3.141592654; const float hauteur = 0.02; const float largeur = 0.02; const float longeur = 0.05; const float longueur_sky = 0.1; const float cam_poly[4][2] = { {-largeur,hauteur},{largeur,hauteur},{largeur,-hauteur},{-largeur,-hauteur} }; // Type de camera const int cam_mode_num = 11; const gchar * cam_mode_list[cam_mode_num] = { N_("Perspective"), N_("Orthographic"), N_("Fisheye"), N_("Ultrawide projection"), N_("Omnimax"), N_("Panoramic"), N_("Cylindrical, vertical fixed"), N_("Cylindrical, horizontal fixed"),N_("Cylindrical, vertical unfixed"),N_("Cylindrical, horizontal unfixed"), N_("Spherical")}; const char * cam_modes_output[cam_mode_num] = { "perspective", "orthographic", "fisheye", "ultra_wide_angle", "omnimax", "panoramic", "cylinder 1", "cylinder 2", "cylinder 3", "cylinder 4", "spherical" }; //************************************** // Constructeur //************************************** Camera::Camera( app_objs *appref ) : Object3D( appref ) { type = TV_OBJ3D_CAMERA; category = TV_OBJ3D_NOCAT; set_name( "Camera" ); location = new ObjParam_point( N_("Location"), "LOC", _("Coordinates of the point where the camera is installed"), app_ref, true ); location->set( 1, 1, 1 ); look_at = new ObjParam_point( N_("Look at"), "LOOKAT", _("Coordinates of the point the camera is looking at"), app_ref, true ); look_at->set( 0, 0, 0 ); frustum = new ObjParam_bool( N_("Show frustum"), "FRUSTUM", _("Show camera angle of view representation"), app_ref, true, true ); roll = new ObjParam_float_angle( N_("Roll"), "ROLL", _("Rotate the camera around its axis"), app_ref, true, 0 ); roll->set_range( 360, 0, 1 ); angle = new ObjParam_float( N_("Angle"), "ANGLE", NULL, app_ref, true, 40 ); angle->set_range( 360, 0, 1 ); aratio = new ObjParam_float( N_("Aspect ratio"), "ARATIO", NULL, appref, true, 1.33 ); aratio->set_range( 10, 0.01, 0.1 ); cam_mode = new ObjParam_option_combo( N_("Mode"), "MODE", NULL, app_ref, false ); cam_mode->set_list( cam_mode_list, cam_mode_num, 0 ); // Blur blur = new ObjParam_bool_activator( N_("Use focal blur"), "BLUR_USED", NULL, app_ref, false, false ); blur_sample = new ObjParam_int( N_("Blur sample"), "BLUR_SAMP", NULL, app_ref, false, 7 ); blur_sample->set_range( 100, 1, 1 ); aperture = new ObjParam_float( N_("Aperture"), "BLUR_APERT", NULL, app_ref, false, 1 ); aperture->set_range( 3, 0, 0.1 ); focal_point = new ObjParam_point_virtual( N_("Focal point"), "BLUR_FPOINT", NULL, app_ref, true ); focal_point->set( 0, 0, 0 ); confidence = new ObjParam_float( N_("Confidence"), "BLUR_CONF", NULL, app_ref, false, 0.5 ); confidence->set_range( 1, 0, 0.01 ); variance = new ObjParam_float( N_("Variance"), "BLUR_VAR", NULL, app_ref, false, 0.02 ); variance->set_range( 1, 0, 0.01 ); normal = new ObjParam_texref( N_("Normal"), "NORM", NULL, app_ref, false ); h_angle = new ObjParam_float( N_("Horiz. angle"), "H_ANG", NULL, app_ref, false, 180.0 ); h_angle->set_range( 360, -360, 0.1, 6 ); v_angle = new ObjParam_float( N_("Vert. angle"), "V_ANG", NULL, app_ref, false, 180.0 ); v_angle->set_range( 360, -360, 0.1, 6 ); } //************************************** // Display // Dessin de la camera //************************************** void Camera::display( glview *view, bool set_col ) { if ( hidden->value() ) return; // Rappel de liste deja calculee if ( frustum->changed() || location->changed() || look_at->changed() || roll->changed() || angle->changed() || aratio->changed() ) list.invalidate(); Object3D::display( view ); set_color(); if ( ! list.exec() ) { // mise à zero des parametres frustum->unchange(); location->unchange(); look_at->unchange(); roll->unchange(); angle->unchange(); aratio->unchange(); // creation de la liste si necessaire list.begin(); // Position et direction gfloat x, y, z, a, b, c; location->get( x, y, z ); look_at->get( a, b, c ); gfloat xoffset = x-a, yoffset = y-b, zoffset = z-c; gfloat xoffset2= xoffset*xoffset; gfloat zoffset2=zoffset*zoffset; glPushMatrix(); // Translation glTranslatef( x, y, z ); // Rotation float gamma = atan2( xoffset, zoffset ) * 180.0 / M_PI; float beta = - atan2( yoffset, sqrt( zoffset2 + xoffset2 ) ) * 180.0 / M_PI; glRotatef( gamma, 0, 1, 0 ); glRotatef( beta, 1, 0, 0 ); glRotatef( roll->value(), 0, 0, 1 ); // Boite de la camera for ( float offset = 0 ; offset < longeur*4 ; offset += 2*longeur ) { glBegin( GL_LINE_LOOP ); for ( int i = 0 ; i < 4 ; i++ ) glVertex3f( cam_poly[i][0], cam_poly[i][1], offset ); glEnd(); } glBegin( GL_LINES ); for ( int i = 0 ; i < 4 ; i++ ) { glVertex3f( cam_poly[i][0], cam_poly[i][1], 0 /*longeur*/ ); glVertex3f( cam_poly[i][0], cam_poly[i][1], 2*longeur ); } glEnd(); // Frustum if ( frustum->value() ) { // Distance au point focal const float dist = - sqrt( xoffset2 + yoffset*yoffset + zoffset2 ); // Limites du champs const float right = dist * tan( angle->value() / 360.0 * M_PI ); const float up = right / aratio->value(); const float champ[4][2] = { {-right,up}, {right,up}, {right,-up}, {-right,-up} }; glBegin( GL_LINES ); // Rayon principal glVertex3f( 0, 0, 0 ); glVertex3f( 0, 0, dist ); // Sky glVertex3f( 0, 0, 0 ); glVertex3f( 0, longueur_sky, 0 ); glVertex3f( 0, longueur_sky, 0 ); glVertex3f( longueur_sky/4, 2*longueur_sky/3, 0 ); glVertex3f( 0, longueur_sky, 0 ); glVertex3f( -longueur_sky/4, 2*longueur_sky/3, 0 ); // Enveloppe for ( int i = 0 ; i < 4 ; i++ ) { glVertex3f( 0, 0, 0 ); glVertex3f( champ[i][0], champ[i][1], dist ); } glEnd(); glBegin( GL_LINE_LOOP ); for ( int i = 0 ; i < 4 ; i++ ) glVertex3f( champ[i][0], champ[i][1], dist ); glEnd(); } glPopMatrix(); list.end(); } } //*********************************************** // Edit //*********************************************** void Camera::edit_widget( GtkWidget *wid ) { PREF_DEF bool tt = pref->tooltips->value(); // Options communes Object3D::edit_widget( wid, false ); //hollow->unget_widget(); frustum->get_widget( edit_cont, tt ); // Options de geometrie new_table( edit_cont,_("General settings"), 6 ); cam_mode->get_widget( table, tt, 1 ); location->get_widget( table, tt, 2 ); look_at->get_widget( table, tt, 3 ); roll->get_widget( table, tt, 4 ); angle->get_widget( table, tt, 5 ); aratio->get_widget( table, tt, 6 ); new_table( edit_cont, N_("Spherical settings"), 2 ); h_angle->get_widget( table, tt, 1 ); v_angle->get_widget( table, tt, 2 ); mode_changed(); // Focal blur new_frame( edit_cont, N_("Focal blur") ); GtkWidget *box = gtk_vbox_new( FALSE, 0 ); blur->get_widget( frame, tt, box ); gtk_box_pack_start( GTK_BOX(frame), box, TRUE, TRUE, 3 ); new_table_no_frame( box, 5 ); blur_sample->get_widget( table, tt, 1 ); aperture->get_widget( table, tt, 2 ); focal_point->get_widget( table, tt, 3 ); confidence->get_widget( table, tt, 4 ); variance->get_widget( table, tt, 5 ); // Camera ray perturbation new_table( edit_cont, N_("Ray perturbation"), 1 ); normal->get_widget( table, tt, 1 ); gtk_widget_show_all( wid ); cam_mode->connect_signal( GTK_SIGNAL_FUNC(sign_camera_mode), this ); } void Camera::mode_changed() { //cam_mode->flush(); //cout << "\nCamera mode changed to : " << cam_mode->value(); //cout.flush(); if ( cam_mode->value() == 10 ) { h_angle->set_widget_active(); v_angle->set_widget_active(); } else { h_angle->set_widget_inactive(); v_angle->set_widget_inactive(); } } //*********************************************** // Pref_changed //*********************************************** void Camera::pref_changed() { Object3D::pref_changed(); cam_mode->pref_changed(); frustum->pref_changed(); location->pref_changed(); look_at->pref_changed(); roll->pref_changed(); angle->pref_changed(); aratio->pref_changed(); blur->pref_changed(); blur_sample->pref_changed(); focal_point->pref_changed(); aperture->pref_changed(); confidence->pref_changed(); variance->pref_changed(); normal->pref_changed(); h_angle->pref_changed(); v_angle->pref_changed(); } //*********************************************** // Pref_changed //*********************************************** void Camera::destroy_editor() { Object3D::destroy_editor(); cam_mode->clear_widget(); frustum->clear_widget(); location->clear_widget(); look_at->clear_widget(); roll->clear_widget(); angle->clear_widget(); aratio->clear_widget(); blur->clear_widget(); blur_sample->clear_widget(); focal_point->clear_widget(); aperture->clear_widget(); confidence->clear_widget(); variance->clear_widget(); normal->clear_widget(); v_angle->clear_widget(); h_angle->clear_widget(); } //*********************************************** // Mouse drag //*********************************************** void Camera::mouse_drag( struct drag_info *drag ) { VMAN_DEF OBJLIST_DEF switch( vmanager->get_pointer_mode() ) { case TV_PMODE_SELECT: case TV_PMODE_TRANSLATE: location->mouse_drag( drag ); break; case TV_PMODE_ROTATE: { roll->mouse_drag( drag ); break; } case TV_PMODE_CUSTOM: ((ObjParam_point*)(objlist->get_current_param()))->mouse_drag( drag ); break; default: break; } } //*********************************************** // Output to povray //*********************************************** void Camera::output_to_povray_pass2( ofstream & file ) { file << "\n\n// Camera : " << name->value(); file << "\n\ncamera {\n\t"; file << cam_modes_output[cam_mode->value()]; file << "\n\tlocation "; location->output_to_povray(file); if ( cam_mode->value() == 10 ) { file << "\n\tangle "; h_angle->output_to_povray(file); file << "\t"; v_angle->output_to_povray(file); } else { file << "\n\tangle "; angle->output_to_povray(file); } file << "\n\tup <0,1,0>\n\tright <"; aratio->output_to_povray(file); gfloat x, y, z, a, b, c; location->get( x, y, z ); look_at->get( a, b, c ); gfloat xoffset = x-a, yoffset = y-b, zoffset = z-c; gfloat xoffset2= xoffset*xoffset; gfloat zoffset2=zoffset*zoffset; float gamma = atan2( xoffset, zoffset ); float beta = - atan2( yoffset, sqrt( zoffset2 + xoffset2 ) ); float rolla = roll->value() /180.0 * M_PI; float upx = sin(beta)*sin(gamma)*cos(rolla) - cos(gamma)*sin(rolla); float upy = cos(beta)*cos(rolla); float upz = cos(rolla)*sin(beta)*cos(gamma) + sin(rolla)*sin(gamma); file << ",0,0>\n\tsky < " << upx << ", " << upy << ", " << -upz << " >"; /*file << cos( roll->value() / 180.0 * M_PI ); file << ','; file << sin( roll->value() / 180.0 * M_PI ); file << '>';*/ file << "\n\tlook_at "; look_at->output_to_povray(file); if ( blur->value() ) { file << "\n\taperture "; aperture->output_to_povray(file); file << "\n\tfocal_point "; focal_point->output_to_povray(file); file << "\n\tblur_samples "; blur_sample->output_to_povray(file); file << "\n\tconfidence "; confidence->output_to_povray(file); file << "\n\tvariance "; variance->output_to_povray(file); } PovMaterial *mat = ((PovMaterial*)normal->get_current()); if ( mat != NULL ) if ( mat->has_normal() ) mat->output_to_povray_normal( file ); file << "\n}"; } void Camera::save( ofstream & file ) { file << "\nCAMERA{\n"; save_basics( file ); cam_mode->save( file ); frustum->save( file ); location->save( file ); look_at->save( file ); roll->save( file ); angle->save( file ); aratio->save( file ); blur->save( file ); blur_sample->save( file ); focal_point->save( file ); aperture->save( file ); confidence->save( file ); variance->save( file ); h_angle->save( file ); v_angle->save( file ); file << "\n}"; } bool Camera::load( ifstream & file, char *ltag ) { if ( strcmp( ltag, "CAMERA" ) ) return false; set_load_progress( file ); char * tag = NULL; do { tag = tvio_get_next_tag( file ); if ( tag == NULL ) break; if ( load_basics( file, tag ) ) continue; if ( location->load( file, tag ) ) continue; if ( cam_mode->load( file, tag ) ) continue; if ( frustum->load( file, tag ) ) continue; if ( look_at->load( file, tag ) ) continue; if ( roll->load( file, tag ) ) continue; if ( angle->load( file, tag ) ) continue; if ( aratio->load( file, tag ) ) continue; if ( blur->load( file, tag ) ) continue; if ( blur_sample->load( file, tag ) ) continue; if ( focal_point->load( file, tag ) ) continue; if ( aperture->load( file, tag ) ) continue; if ( confidence->load( file, tag ) ) continue; if ( variance->load( file, tag ) ) continue; if ( h_angle->load( file, tag ) ) continue; if ( v_angle->load( file, tag ) ) continue; tvio_skip_section(file ); } while ( tag != NULL ); return true; }