//***************************************************************************************** // Truevision - a 3d modeler for gnome and povray // // lights.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/lights.h" #include "include/viewmanager.h" #include "include/objectlist.h" #include "include/tvio.h" #include #include "include/preferences.h" //******************************************************************************************** // POINTLIGHT //******************************************************************************************** //************************************** // Constructeur //************************************** PointLight::PointLight( app_objs *appref ) : Object3D( appref ) { type = TV_OBJ3D_POINTLIGHT; category = TV_OBJ3D_LIGHTS; set_name( "Point light" ); OBJLIST_DEF light_id = objlist->light_request(); // Base location = new ObjParam_point( N_("Location"), "LOC", NULL, app_ref, true ); location->set( 0.6, 0.6, 0.6 ); color = new ObjParam_color( N_("Color"), "COL", NULL, app_ref, true ); color->set( 255, 255, 255, 255 ); media_attenuation = new ObjParam_bool( N_("Media attenuation"), "MED_ATT", NULL, app_ref, false, false ); media_interaction = new ObjParam_bool( N_("Media interaction"), "MED_INT", NULL, app_ref, false, false ); parallel = new ObjParam_bool( N_("Parallel"), "PARA", NULL, app_ref, false, false ); look_like = new ObjParam_objref( N_("Looks like"), "LLIKE", NULL, app_ref, false ); projected_through = new ObjParam_objref( N_("Projected through"), "PROJT", NULL, app_ref, false ); // Fade fade = new ObjParam_bool_activator( N_("Use fading"), "FADE_USED", NULL, app_ref, false, false ); fade_power = new ObjParam_float( N_("Fade power"), "FADE_POW", NULL, app_ref, false, 0 ); fade_power->set_range( 10, 0, 0.1, 6 ); fade_distance = new ObjParam_float( N_("Fade distance"), "FADE_DIST", NULL, appref, false, 2 ); fade_distance->set_range( 10, 0, 0.1, 6 ); // Photons refraction = new ObjParam_bool( N_("Refraction"), "PREFRAC", NULL, app_ref, false, false ); reflection = new ObjParam_bool( N_("Reflection"), "PREFLEC", NULL, app_ref, false, false ); area = new ObjParam_bool( N_("Area light"), "PAREA", NULL, app_ref, false, false ); } PointLight::PointLight( PointLight & ref ) : Object3D( ref ) { OBJLIST_DEF light_id = objlist->light_request(); location = new ObjParam_point( *ref.location ); color = new ObjParam_color( *ref.color ); media_attenuation = new ObjParam_bool( *ref.media_attenuation ); media_interaction = new ObjParam_bool( *ref.media_interaction ); fade = new ObjParam_bool_activator( *ref.fade ); fade_power = new ObjParam_float( *ref.fade_power ); fade_distance = new ObjParam_float( *ref.fade_distance ); parallel = new ObjParam_bool( *ref.parallel ); refraction = new ObjParam_bool( *ref.refraction ); reflection = new ObjParam_bool( *ref.reflection ); area = new ObjParam_bool( *ref.area ); look_like = new ObjParam_objref( *ref.look_like ); projected_through = new ObjParam_objref( *ref.projected_through ); } PointLight::~PointLight() { OBJLIST_DEF objlist->light_release( light_id ); delete location; delete color; delete media_attenuation; delete media_interaction; delete fade; delete fade_power; delete fade_distance; delete parallel; delete refraction; delete reflection; delete area; delete look_like; delete projected_through; } //************************************** // Display // Dessin de la lampe //************************************** void PointLight::display( glview *view, bool set_col ) { OBJLIST_DEF if ( hidden->value() ) { objlist->light_disable( light_id ); //cout << "\nLight is hidden !"; cout.flush(); return; } // Rappel de liste deja calculee if ( location->changed() || color->changed() ) list.invalidate(); Object3D::display( view ); if ( set_col ) set_color(); if ( look_like->get_current() != NULL ) { glPushMatrix(); gfloat x, y, z; location->get( x, y, z ); glTranslatef( x, y, z ); look_like->get_current()->display( view ); glPopMatrix(); } if ( projected_through->get_current() != NULL ) { glPushMatrix(); gfloat x, y, z; location->get( x, y, z ); glTranslatef( x, y, z ); projected_through->get_current()->display( view ); glPopMatrix(); } if ( ! list.exec() ) { // mise à zero des parametres location->unchange(); color->unchange(); // creation de la liste si necessaire //cout << " & Creating light !"; cout.flush(); list.begin(); //glPushMatrix(); //glLoadIdentity(); objlist->light_disable( light_id ); GLfloat coldef[4]; color->gl_array( coldef ); //cout << "\n\tcolor = "; //for ( int i = 0 ;i < 4 ; i++ ) cout << coldef[i] << " - "; //cout.flush(); float a, b, c; float loc[3]; location->get( a, b, c ); loc[0] = a; loc[1] = b; loc[2] = c; //cout << "\n\tposition = " << a << " - " << b << " - " << c; //cout << "\n\tligh id = " << light_id; //cout.flush(); objlist->light_set_properties( light_id, loc, coldef ); objlist->light_enable( light_id ); // Position et direction gfloat x, y, z; const float lof = 0.025; location->get( x, y, z ); glBegin( GL_LINES ); glVertex3f( x-lof, y, z ); glVertex3f( x+lof, y, z ); glVertex3f( x, y-lof, z ); glVertex3f( x, y+lof, z ); glVertex3f( x, y, z-lof ); glVertex3f( x, y, z+lof ); glVertex3f( x-lof, y+lof, z ); glVertex3f( x+lof, y-lof, z ); glVertex3f( x+lof, y+lof, z ); glVertex3f( x-lof, y-lof, z ); glVertex3f( x-lof, y, z-lof ); glVertex3f( x+lof, y, z+lof ); glVertex3f( x+lof, y, z-lof ); glVertex3f( x-lof, y, z+lof ); glVertex3f( x, y+lof, z+lof ); glVertex3f( x, y-lof, z-lof ); glVertex3f( x, y+lof, z-lof ); glVertex3f( x, y-lof, z+lof ); glEnd(); //glPopMatrix(); list.end(); } } //*********************************************** // Edit //*********************************************** void PointLight::edit_widget( GtkWidget *wid ) { PREF_DEF bool tt = pref->tooltips->value(); // Options communes Object3D::edit_widget( wid ); // Options de geometrie new_table( edit_cont, _("General settings"), 7 ); location->get_widget( table, tt, 1 ); color->get_widget( table, tt, 2 ); media_interaction->get_widget( table, tt, 3 ); media_attenuation->get_widget( table, tt ,4 ); parallel->get_widget( table, tt ,5 ); look_like->get_widget( table, tt, 6 ); projected_through->get_widget( table, tt, 7 ); // Fade new_frame( edit_cont, _("Light fading") ); GtkWidget *box = gtk_vbox_new( FALSE, 0 ); fade->get_widget( frame, tt, box ); gtk_box_pack_start( GTK_BOX(frame), box, TRUE, TRUE, 3 ); new_table_no_frame( box, 2 ); fade_power->get_widget( table, tt, 1 ); fade_distance->get_widget( table, tt, 2 ); // Photons new_frame( edit_cont, _("Photons") ); refraction->get_widget( frame, tt ); reflection->get_widget( frame, tt ); area->get_widget( frame, tt ); gtk_widget_show_all( wid ); } //*********************************************** // Mouse drag //*********************************************** void PointLight::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_CUSTOM: ((ObjParam_point*)(objlist->get_current_param()))->mouse_drag( drag ); break; default: break; } } //*********************************************** // Pref_changed //*********************************************** void PointLight::pref_changed() { Object3D::pref_changed(); location->pref_changed(); color->pref_changed(); media_attenuation->pref_changed(); media_interaction->pref_changed(); fade->pref_changed(); fade_power->pref_changed(); fade_distance->pref_changed(); parallel->pref_changed(); refraction->pref_changed(); reflection->pref_changed(); area->pref_changed(); look_like->pref_changed(); projected_through->pref_changed(); } //*********************************************** // Destroy editor //*********************************************** void PointLight::destroy_editor() { Object3D::destroy_editor(); location->clear_widget(); color->clear_widget(); media_attenuation->clear_widget(); media_interaction->clear_widget(); fade->clear_widget(); fade_power->clear_widget(); fade_distance->clear_widget(); parallel->clear_widget(); refraction->clear_widget(); reflection->clear_widget(); area->clear_widget(); look_like->clear_widget(); projected_through->clear_widget(); } //*********************************************** // Output to povray //*********************************************** void PointLight::output_to_povray_pass1( ofstream & file ) { if ( look_like->get_current() != NULL ) look_like->get_current()->output_to_povray_pass1( file ); if ( projected_through->get_current() != NULL ) projected_through->get_current()->output_to_povray_pass1( file ); file << "\n\n// Point light : " << name->value(); file << "\n#declare "; get_underscore_name( file ); file << " ="; file << "\n\nlight_source {\n\t"; location->output_to_povray(file); file << "\n\tcolor "; color->output_to_povray(file); if ( media_attenuation->value() ) file << "\n\tmedia_attenuation "; if ( media_interaction->value() ) file << "\n\tmedia_interaction "; if ( no_shadow->value() ) file << "\n\tshadowless"; if ( parallel->value() ) file << "\n\tparallel"; if ( fade->value() ) { file << "\n\tfade_distance "; fade_distance->output_to_povray(file); file << "\n\tfade_power "; fade_power->output_to_povray(file); } if ( look_like->get_current() != NULL ) { file << "\n\tlooks_like { object { "; look_like->get_current()->get_underscore_name( file ); file << " } }"; } if ( projected_through->get_current() != NULL ) { file << "\n\tprojected_through { object { "; projected_through->get_current()->get_underscore_name( file ); file << " } }"; } file << "\n\tphotons {"; file << "\n\t\trefraction " << ( refraction->value() ? "on" : "off" ); file << "\n\t\treflection " << ( reflection->value() ? "on" : "off" ); if ( area->value() ) file << "\n\t\tarea_light"; file << "\n\t}"; file << "\n}"; } void PointLight::save( ofstream & file ) { file << "\nPOINTLIGHT{\n"; save_basics( file ); location->save( file ); color->save( file ); media_attenuation->save( file ); media_interaction->save( file ); fade->save( file ); fade_distance->save( file ); fade_power->save( file ); parallel->save( file ); refraction->save( file ); reflection->save( file ); area->save( file ); look_like->save( file ); projected_through->save( file ); file << "\n}"; } bool PointLight::load( ifstream & file, char *ltag ) { if ( strcmp( ltag, "POINTLIGHT" ) ) 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 ( color->load( file, tag ) ) continue; if ( media_interaction->load( file, tag ) ) continue; if ( media_attenuation->load( file, tag ) ) continue; if ( fade->load( file, tag ) ) continue; if ( fade_distance->load( file, tag ) ) continue; if ( fade_power->load( file, tag ) ) continue; if ( parallel->load( file, tag ) ) continue; if ( refraction->load( file, tag ) ) continue; if ( reflection->load( file, tag ) ) continue; if ( area->load( file, tag ) ) continue; if ( look_like->load( file, tag ) ) continue; if ( projected_through->load( file, tag ) ) continue; tvio_skip_section(file ); } while ( tag != NULL ); return true; } //******************************************************************************************** // AREALIGHT //******************************************************************************************** //************************************** // Constructeur //************************************** AreaLight::AreaLight( app_objs *appref ) : PointLight( appref ) { type = TV_OBJ3D_AREALIGHT; category = TV_OBJ3D_LIGHTS; set_name( "Area light" ); OBJLIST_DEF light_id = objlist->light_request(); // Base size = new ObjParam_point( N_("Size"), "SIZE", NULL, app_ref, true ); size->set( 0.1, 0, 0.1 ); rotation = new ObjParam_rotation( N_("Rotation"), "ROT", NULL, app_ref, true ); rotation->set( 0, 0, 0 ); sizex = new ObjParam_int( N_("X density"), "XDENS", NULL, app_ref, true, 2 ); sizex->set_range( 100, 1, 1 ); sizez = new ObjParam_int( N_("Z density"), "ZDENS", NULL, app_ref, true, 2 ); sizez->set_range( 100, 1, 1 ); jitter = new ObjParam_bool( N_("Jitter"), "JITTER", NULL, app_ref, false, false ); adaptive = new ObjParam_int( N_("Adaptive"), "ADAPT", NULL, app_ref, false, 0 ); adaptive->set_range( 10, 0, 1 ); circular = new ObjParam_bool( N_("Circular"), "CIRC", NULL, app_ref, false ); orient = new ObjParam_bool( N_("Orient"), "ORIENT", NULL, app_ref, false ); parallel = new ObjParam_bool( N_("Parallel"), "PARA", NULL, app_ref, false ); } AreaLight::AreaLight( AreaLight & ref ) : PointLight( ref ) { size = new ObjParam_point( *ref.size ); rotation = new ObjParam_rotation( *ref.rotation ); sizex = new ObjParam_int( *ref.sizex ); sizez = new ObjParam_int( *ref.sizez ); jitter = new ObjParam_bool( *ref.jitter ); adaptive = new ObjParam_int( *ref.adaptive ); circular = new ObjParam_bool( *ref.circular ); orient = new ObjParam_bool( *ref.orient ); parallel = new ObjParam_bool( *ref.parallel ); } AreaLight::~AreaLight() { delete size; delete rotation; delete sizex; delete sizez; delete jitter; delete adaptive; delete circular; delete orient; delete parallel; } //************************************** // Display // Dessin de la lampe //************************************** void AreaLight::display( glview *view, bool set_col ) { OBJLIST_DEF if ( hidden->value() ) { objlist->light_disable( light_id ); return; } // Rappel de liste deja calculee if ( location->changed() || color->changed() || size->changed() || rotation->changed() || sizez->changed() || sizex->changed() ) list.invalidate(); Object3D::display( view ); set_color(); if ( ! list.exec() ) { // mise à zero des parametres location->unchange(); color->unchange(); rotation->unchange(); size->unchange(); sizez->unchange(); sizex->unchange(); // creation de la liste si necessaire list.begin(); glPushMatrix(); objlist->light_enable( light_id ); GLfloat coldef[4]; color->gl_array( coldef ); objlist->light_set_properties( light_id, location->get(), coldef ); gfloat x, y, z; location->get( x, y, z ); glTranslatef( x, y, z ); if ( projected_through->get_current() != NULL ) { glPushMatrix(); gfloat x, y, z; location->get( x, y, z ); glTranslatef( x, y, z ); projected_through->get_current()->display( view ); glPopMatrix(); } if ( look_like->get_current() != NULL ) { glPushMatrix(); gfloat x, y, z; location->get( x, y, z ); glTranslatef( x, y, z ); look_like->get_current()->display( view ); glPopMatrix(); } rotation->gl_rotate(); size->get( x, y, z ); glBegin( GL_LINE_LOOP ); glVertex3f( 0, 0, 0 ); glVertex3f( x, 0, 0 ); glVertex3f( x, 0, z ); glVertex3f( 0, 0, z ); glEnd(); glPointSize( 4 ); float xoffset = x / ( sizex->value() - 1 ); float zoffset = z / ( sizez->value() - 1 ); x += 0.0001; z += 0.0001; if ( xoffset == 0 ) xoffset = 0.0001; if ( zoffset == 0 ) zoffset = 0.0001; glBegin( GL_POINTS ); for ( float i = 0 ; i <= x ; i += xoffset ) for ( float j = 0 ; j <= z ; j += zoffset ) glVertex3f( i, 0, j ); glEnd(); glPopMatrix(); list.end(); } } //*********************************************** // Edit //*********************************************** void AreaLight::edit_widget( GtkWidget *wid ) { PREF_DEF bool tt = pref->tooltips->value(); // Options communes Object3D::edit_widget( wid ); // Options de geometrie new_table( edit_cont, _("General settings"), 15 ); location->get_widget( table, tt, 1 ); size->get_widget( table, tt ,2 ); rotation->get_widget( table, tt, 3 ); sizex->get_widget( table, tt, 4 ); sizez->get_widget( table, tt, 5 ); circular->get_widget( table, tt, 6 ); orient->get_widget( table, tt, 7 ); color->get_widget( table, tt, 8 ); look_like->get_widget( table, tt, 9 ); projected_through->get_widget( table, tt, 10 ); media_interaction->get_widget( table, tt, 11 ); media_attenuation->get_widget( table, tt, 12 ); parallel->get_widget( table, tt, 13 ); adaptive->get_widget( table, tt, 14 ); jitter->get_widget( table, tt, 15 ); // Fade new_frame( edit_cont, _("Light fading") ); GtkWidget *box = gtk_vbox_new( FALSE, 0 ); fade->get_widget( frame, tt, box ); gtk_box_pack_start( GTK_BOX(frame), box, TRUE, TRUE, 3 ); new_table_no_frame( box, 2 ); fade_power->get_widget( table, tt, 1 ); fade_distance->get_widget( table, tt, 2 ); // Photons new_frame( edit_cont, _("Photons") ); refraction->get_widget( frame, tt ); reflection->get_widget( frame, tt ); area->get_widget( frame, tt ); gtk_widget_show_all( wid ); } //*********************************************** // Mouse drag //*********************************************** void AreaLight::mouse_drag( struct drag_info *drag ) { VMAN_DEF OBJLIST_DEF switch ( vmanager->get_pointer_mode() ) { case TV_PMODE_ROTATE: rotation->mouse_drag( drag ); break; case TV_PMODE_SCALE: size->mouse_drag( drag ); break; case TV_PMODE_SELECT: case TV_PMODE_TRANSLATE: location->mouse_drag( drag ); break; case TV_PMODE_CUSTOM: ((ObjParam_point*)(objlist->get_current_param()))->mouse_drag( drag ); break; default: break; } } //*********************************************** // Pref_changed //*********************************************** void AreaLight::pref_changed() { PointLight::pref_changed(); size->pref_changed(); rotation->pref_changed(); sizex->pref_changed(); sizez->pref_changed(); jitter->pref_changed(); adaptive->pref_changed(); circular->pref_changed(); orient->pref_changed(); parallel->pref_changed(); } //*********************************************** // Destroy editor //*********************************************** void AreaLight::destroy_editor() { PointLight::destroy_editor(); size->clear_widget(); rotation->clear_widget(); sizex->clear_widget(); sizez->clear_widget(); jitter->clear_widget(); adaptive->clear_widget(); circular->clear_widget(); orient->clear_widget(); parallel->clear_widget(); } //*********************************************** // Output to povray //*********************************************** void AreaLight::output_to_povray_pass1( ofstream & file ) { if ( circular->value() == TRUE ) { if ( sizex->value() == 1 ) sizex->set( 2 ); if ( sizez->value() == 1 ) sizez->set( 2 ); } if ( look_like->get_current() != NULL ) look_like->get_current()->output_to_povray_pass1( file ); if ( projected_through->get_current() != NULL ) projected_through->get_current()->output_to_povray_pass1( file ); file << "\n\n// Area light : " << name->value(); file << "\n#declare "; get_underscore_name( file ); file << " ="; file << "\n\nlight_source { <0, 0, 0>\n\t"; file << "\n\tcolor "; color->output_to_povray(file); file <<"\n\tarea_light <0.1,0,0>, <0,0,0.1>, "; file << sizex->value() << ", " << sizez->value(); float x, y, z; size->get( x, y, z ); file << "\n\tscale <" << x << ",1," << -z << "> \n\t"; rotation->output_to_povray( file ); location->get( x, y, z ); file << "\n\ttranslate <" << x << "," << y << "," << -z << "> \n\t"; if ( media_attenuation->value() ) file << "\n\tmedia_attenuation "; if ( media_interaction->value() ) file << "\n\tmedia_interaction "; if ( no_shadow->value() ) file << "\n\tshadowless"; if ( jitter->value() ) file << "\n\tjitter"; if ( circular->value() ) file << "\n\tcircular"; if ( orient->value() ) file << "\n\torient"; if ( parallel->value() ) file << "\n\tparallel"; if ( adaptive->value() > 0 ) file << "\n\tadaptive " << adaptive->value(); if ( fade->value() ) { file << "\n\tfade_distance "; fade_distance->output_to_povray(file); file << "\n\tfade_power "; fade_power->output_to_povray(file); } if ( look_like->get_current() != NULL ) { file << "\n\tlooks_like { object { "; look_like->get_current()->get_underscore_name( file ); file << " } }"; } if ( projected_through->get_current() != NULL ) { file << "\n\tprojected_through { object { "; projected_through->get_current()->get_underscore_name( file ); file << " } }"; } file << "\n\tphotons {"; file << "\n\t\trefraction " << ( refraction->value() ? "on" : "off" ); file << "\n\t\treflection " << ( reflection->value() ? "on" : "off" ); if ( area->value() ) file << "\n\t\tarea_light"; file << "\n\t}"; file << "\n}"; } void AreaLight::save( ofstream & file ) { file << "\nAREALIGHT{\n"; save_basics( file ); location->save( file ); color->save( file ); media_interaction->save( file ); media_attenuation->save( file ); fade->save( file ); fade_distance->save( file ); fade_power->save( file ); size->save( file ); rotation->save( file ); sizex->save( file ); sizez->save( file ); jitter->save( file ); adaptive->save( file ); circular->save( file ); orient->save( file ); parallel->save( file ); refraction->save( file ); reflection->save( file ); area->save( file ); look_like->save( file ); projected_through->save( file ); file << "\n}"; } bool AreaLight::load( ifstream & file, char *ltag ) { if ( strcmp( ltag, "AREALIGHT" ) ) 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 ( color->load( file, tag ) ) continue; if ( media_interaction->load( file, tag ) ) continue; if ( media_attenuation->load( file, tag ) ) continue; if ( fade->load( file, tag ) ) continue; if ( fade_distance->load( file, tag ) ) continue; if ( fade_power->load( file, tag ) ) continue; if ( size->load( file, tag ) ) continue; if ( rotation->load( file, tag ) ) continue; if ( sizex->load( file, tag ) ) continue; if ( sizez->load( file, tag ) ) continue; if ( jitter->load( file, tag ) ) continue; if ( adaptive->load( file, tag ) ) continue; if ( circular->load( file, tag ) ) continue; if ( orient->load( file, tag ) ) continue; if ( parallel->load( file, tag ) ) continue; if ( refraction->load( file, tag ) ) continue; if ( reflection->load( file, tag ) ) continue; if ( area->load( file, tag ) ) continue; if ( look_like->load( file, tag ) ) continue; if ( projected_through->load( file, tag ) ) continue; tvio_skip_section(file ); } while ( tag != NULL ); return true; } //*********************************************************************************************** // SPOTLIGHT //*********************************************************************************************** //************************************** // Constructeur //************************************** SpotLight::SpotLight( app_objs *appref ) : Object3D( appref ) { type = TV_OBJ3D_SPOTLIGHT; category = TV_OBJ3D_LIGHTS; set_name( "Spot light" ); OBJLIST_DEF light_id = objlist->light_request(); // Base location = new ObjParam_point( N_("Location"), "LOC", NULL, app_ref, true ); location->set( 0.6, 0.6, 0.6 ); pointat = new ObjParam_point( N_("Point at"), "AT", NULL, app_ref, true ); pointat->set( 0, 0, 0 ); radius = new ObjParam_float( N_("Radius"), "RAD", NULL, app_ref, 30, true ); radius->set( 70 ); radius->set_range( 360, 0, 1, 3 ); falloff = new ObjParam_float( N_("Falloff"), "FOFF", NULL, app_ref, 45, true ); falloff->set( 70 ); falloff->set_range( 360, 0, 1, 3 ); tightness = new ObjParam_int( N_("Tightness"), "TNESS", NULL, app_ref, 0, true ); tightness->set_range( 100, 1, 1 ); frustum = new ObjParam_bool( N_("Show frutum"), "FRUS", NULL, app_ref, true, true ); color = new ObjParam_color( N_("Color"), "COL", NULL, app_ref, true ); color->set( 255, 255, 255, 255 ); media_attenuation = new ObjParam_bool( N_("Media attenuation"), "MED_ATT", NULL, app_ref, false, false ); media_interaction = new ObjParam_bool( N_("Media interaction"), "MED_INT", NULL, app_ref, false, false ); parallel = new ObjParam_bool( N_("Parallel"), "PARA", NULL, app_ref, false, false ); look_like = new ObjParam_objref( N_("Looks like"), "LLIKE", NULL, app_ref, false ); projected_through = new ObjParam_objref( N_("Projected through"), "PROJT", NULL, app_ref, false ); // Fade fade = new ObjParam_bool_activator( N_("Use fading"), "FADE_USED", NULL, app_ref, false, false ); fade_power = new ObjParam_float( N_("Fade power"), "FADE_POW", NULL, app_ref, false, 0 ); fade_power->set_range( 10, 0, 0.1 ); fade_distance = new ObjParam_float( N_("Fade distance"), "FADE_DIST", NULL, appref, false, 2 ); fade_distance->set_range( 10, 0, 0.1 ); // Photons refraction = new ObjParam_bool( N_("Refraction"), "PREFRAC", NULL, app_ref, false, false ); reflection = new ObjParam_bool( N_("Reflection"), "PREFLEC", NULL, app_ref, false, false ); area = new ObjParam_bool( N_("Area light"), "PAREA", NULL, app_ref, false, false ); } SpotLight::SpotLight( SpotLight & ref ) : Object3D( ref ) { OBJLIST_DEF light_id = objlist->light_request(); location = new ObjParam_point( *ref.location ); pointat = new ObjParam_point( *ref.pointat ); radius = new ObjParam_float( *ref.radius ); falloff = new ObjParam_float( *ref.falloff ); tightness = new ObjParam_int( *ref.tightness ); frustum = new ObjParam_bool( *ref.frustum ); color = new ObjParam_color( *ref.color ); media_attenuation = new ObjParam_bool( *ref.media_attenuation ); media_interaction = new ObjParam_bool( *ref.media_interaction ); fade = new ObjParam_bool_activator( *ref.fade ); fade_power = new ObjParam_float( *ref.fade_power ); fade_distance = new ObjParam_float( *ref.fade_distance ); parallel = new ObjParam_bool( *ref.parallel ); refraction = new ObjParam_bool( *ref.refraction ); reflection = new ObjParam_bool( *ref.reflection ); area = new ObjParam_bool( *ref.area ); look_like = new ObjParam_objref( *ref.look_like ); projected_through = new ObjParam_objref( *ref.projected_through ); } SpotLight::~SpotLight() { OBJLIST_DEF objlist->light_release( light_id ); delete location; delete pointat; delete radius; delete falloff; delete tightness; delete frustum; delete color; delete media_attenuation; delete media_interaction; delete fade; delete fade_power; delete fade_distance; delete parallel; delete refraction; delete reflection; delete area; delete look_like; delete projected_through; } //************************************** // Display // Dessin de la lampe //************************************** void SpotLight::display( glview *view, bool set_col ) { OBJLIST_DEF if ( hidden->value() ) { objlist->light_disable( light_id ); return; } // Rappel de liste deja calculee if ( location->changed() || color->changed() || pointat->changed() || radius->changed() || frustum->changed() ) list.invalidate(); GLint polymode; glGetIntegerv( GL_POLYGON_MODE, &polymode ); glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); Object3D::display( view ); set_color(); if ( ! list.exec() ) { // mise à zero des parametres location->unchange(); pointat->unchange(); frustum->unchange(); radius->unchange(); color->unchange(); // creation de la liste si necessaire list.begin(); if ( look_like->get_current() != NULL ) { glPushMatrix(); gfloat x, y, z; location->get( x, y, z ); glTranslatef( x, y, z ); look_like->get_current()->display( view ); glPopMatrix(); } if ( projected_through->get_current() != NULL ) { glPushMatrix(); gfloat x, y, z; location->get( x, y, z ); glTranslatef( x, y, z ); projected_through->get_current()->display( view ); glPopMatrix(); } glPushMatrix(); objlist->light_enable( light_id ); GLfloat coldef[4]; color->gl_array( coldef ); objlist->light_set_properties( light_id, location->get(), pointat->get(), radius->value(), coldef ); // Position et direction const float lof = 0.025; float x, y, z, a, b, c; location->get( x, y, z ); pointat->get( a, b, c ); glTranslatef( x, y, z ); glRotatef( atan2( a-x, c-z )*180/3.1415, 0, 1, 0 ); glRotatef( -atan2( b-y, sqrt( (c-z)*(c-z) + (a-x)*(a-x) ) )*180/3.1415, 1, 0, 0 ); glBegin( GL_LINES ); glVertex3f( -lof, 0, 0 ); glVertex3f( +lof, 0, 0 ); glVertex3f( 0, -lof, 0 ); glVertex3f( 0, +lof, 0 ); glVertex3f( 0, 0, -lof ); glVertex3f( 0, 0, +lof ); glVertex3f( -lof, +lof, 0 ); glVertex3f( +lof, -lof, 0 ); glVertex3f( +lof, +lof, 0 ); glVertex3f( -lof, -lof, 0 ); glVertex3f( -lof, 0, -lof ); glVertex3f( +lof, 0, +lof ); glVertex3f( +lof, 0, -lof ); glVertex3f( -lof, 0, +lof ); glVertex3f( 0, +lof, +lof ); glVertex3f( 0, -lof, -lof ); glVertex3f( 0, +lof, -lof ); glVertex3f( 0, -lof, +lof ); glEnd(); if ( frustum->value() ) { float dist = sqrt( (x-a)*(x-a) + (y-b)*(y-b) + (z-c)*(z-c) ); GLUquadricObj *quadobj = gluNewQuadric(); if ( !quadobj ) { app_warning( N_("Out of memory" ) ); return; } gluCylinder(quadobj, 0, sin(radius->value() *3.1415 / 360 )*dist*2, dist, 12, 12 ); } glPopMatrix(); list.end(); } glPolygonMode( static_cast(GL_FRONT_AND_BACK), static_cast(polymode) ); } //*********************************************** // Edit //*********************************************** void SpotLight::edit_widget( GtkWidget *wid ) { PREF_DEF bool tt = pref->tooltips->value(); edit_widget_base( wid ); hidden->get_widget( edit_cont, tt ); hidden->connect_signal( GTK_SIGNAL_FUNC(sign_hidden_changed), this ); render->get_widget( edit_cont, tt ); frustum->get_widget( edit_cont, tt ); // Options de geometrie new_table( edit_cont, _("General settings"), 11 ); location->get_widget( table, tt, 1 ); pointat->get_widget( table, tt, 2 ); radius->get_widget( table, tt, 3 ); falloff->get_widget( table, tt, 4 ); tightness->get_widget( table, tt, 5 ); color->get_widget( table, tt, 6 ); media_interaction->get_widget( table, tt, 7 ); media_attenuation->get_widget( table, tt, 8 ); parallel->get_widget( table, tt, 9 ); look_like->get_widget( table, tt, 10 ); projected_through->get_widget( table, tt, 11 ); // Fade new_frame( edit_cont, _("Light fading") ); GtkWidget *box = gtk_vbox_new( FALSE, 0 ); fade->get_widget( frame, tt, box ); gtk_box_pack_start( GTK_BOX(frame), box, TRUE, TRUE, 3 ); new_table_no_frame( box, 2 ); fade_power->get_widget( table, tt, 1 ); fade_distance->get_widget( table, tt, 2 ); // Photons new_frame( edit_cont, _("Photons") ); refraction->get_widget( frame, tt ); reflection->get_widget( frame, tt ); area->get_widget( frame, tt ); gtk_widget_show_all( wid ); } //*********************************************** // Mouse drag //*********************************************** void SpotLight::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_CUSTOM: ((ObjParam_point*)(objlist->get_current_param()))->mouse_drag( drag ); break; default: break; } } //*********************************************** // Pref_changed //*********************************************** void SpotLight::pref_changed() { Object3D::pref_changed(); location->pref_changed(); pointat->pref_changed(); radius->pref_changed(); falloff->pref_changed(); tightness->pref_changed(); frustum->pref_changed(); color->pref_changed(); media_attenuation->pref_changed(); media_interaction->pref_changed(); fade->pref_changed(); fade_power->pref_changed(); fade_distance->pref_changed(); parallel->pref_changed(); refraction->pref_changed(); reflection->pref_changed(); area->pref_changed(); look_like->pref_changed(); projected_through->pref_changed(); } //*********************************************** // Destroy editor //*********************************************** void SpotLight::destroy_editor() { Object3D::destroy_editor(); location->clear_widget(); pointat->clear_widget(); radius->clear_widget(); falloff->clear_widget(); tightness->clear_widget(); frustum->clear_widget(); color->clear_widget(); media_attenuation->clear_widget(); media_interaction->clear_widget(); fade->clear_widget(); fade_power->clear_widget(); fade_distance->clear_widget(); parallel->clear_widget(); refraction->clear_widget(); reflection->clear_widget(); area->clear_widget(); look_like->clear_widget(); projected_through->clear_widget(); } //*********************************************** // Output to povray //*********************************************** void SpotLight::output_to_povray_pass1( ofstream & file ) { if ( look_like->get_current() != NULL ) look_like->get_current()->output_to_povray_pass1( file ); if ( projected_through->get_current() != NULL ) projected_through->get_current()->output_to_povray_pass1( file ); file << "\n\n// Spotlight : " << name->value(); file << "\n#declare "; get_underscore_name( file ); file << " ="; file << "\n\nlight_source {\n\t"; location->output_to_povray(file); file << "\n\tcolor "; color->output_to_povray(file); file << "\n\tspotlight"; file << "\n\tradius "; radius->output_to_povray(file); file << "\n\tfalloff "; falloff->output_to_povray(file); file << "\n\tpoint_at "; pointat->output_to_povray(file); file << "\n\ttightness "; tightness->output_to_povray(file); if ( media_attenuation->value() ) file << "\n\tmedia_attenuation "; if ( media_interaction->value() ) file << "\n\tmedia_interaction "; if ( parallel->value() ) file << "\n\tparallel "; if ( fade->value() ) { file << "\n\tfade_distance "; fade_distance->output_to_povray(file); file << "\n\tfade_power "; fade_power->output_to_povray(file); } if ( look_like->get_current() != NULL ) { file << "\n\tlooks_like { object { "; look_like->get_current()->get_underscore_name( file ); file << " } }"; } if ( projected_through->get_current() != NULL ) { file << "\n\tprojected_through { object { "; projected_through->get_current()->get_underscore_name( file ); file << " } }"; } file << "\n\tphotons {"; file << "\n\t\trefraction " << ( refraction->value() ? "on" : "off" ); file << "\n\t\treflection " << ( reflection->value() ? "on" : "off" ); if ( area->value() ) file << "\n\t\tarea_light"; file << "\n\t}"; file << "\n}"; } void SpotLight::save( ofstream & file ) { file << "\nSPOTLIGHT{\n"; save_basics( file ); location->save( file ); color->save( file ); radius->save( file ); falloff->save( file ); pointat->save( file ); tightness->save( file ); media_interaction->save( file ); media_attenuation->save( file ); fade->save( file ); fade_distance->save( file ); fade_power->save( file ); parallel->save( file ); refraction->save( file ); reflection->save( file ); area->save( file ); look_like->save( file ); projected_through->save( file ); file << "\n}"; } bool SpotLight::load( ifstream & file, char *ltag ) { if ( strcmp( ltag, "SPOTLIGHT" ) ) 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 ( color->load( file, tag ) ) continue; if ( media_interaction->load( file, tag ) ) continue; if ( media_attenuation->load( file, tag ) ) continue; if ( fade->load( file, tag ) ) continue; if ( fade_distance->load( file, tag ) ) continue; if ( fade_power->load( file, tag ) ) continue; if ( radius->load( file, tag ) ) continue; if ( falloff->load( file, tag ) ) continue; if ( pointat->load( file, tag ) ) continue; if ( tightness->load( file, tag ) ) continue; if ( parallel->load( file, tag ) ) continue; if ( area->load( file, tag ) ) continue; if ( refraction->load( file, tag ) ) continue; if ( reflection->load( file, tag ) ) continue; if ( look_like->load( file, tag ) ) continue; if ( projected_through->load( file, tag ) ) continue; tvio_skip_section(file ); } while ( tag != NULL ); return true; } //***************************************************** // CylindricalLight //***************************************************** CylindricalLight::CylindricalLight( app_objs *app_ref ) : SpotLight( app_ref ) { type = TV_OBJ3D_CYLLIGHT; category = TV_OBJ3D_LIGHTS; set_name( "Cylindrical light" ); } //************************************** // Display // Dessin de la lampe //************************************** void CylindricalLight::display( glview *view, bool set_col ) { OBJLIST_DEF if ( hidden->value() ) { objlist->light_disable( light_id ); return; } // Rappel de liste deja calculee if ( location->changed() || color->changed() || pointat->changed() || radius->changed() || frustum->changed() ) list.invalidate(); GLint polymode; glGetIntegerv( GL_POLYGON_MODE, &polymode ); glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); Object3D::display( view ); set_color(); if ( ! list.exec() ) { // mise à zero des parametres location->unchange(); pointat->unchange(); frustum->unchange(); radius->unchange(); color->unchange(); // creation de la liste si necessaire list.begin(); if ( look_like->get_current() != NULL ) { glPushMatrix(); gfloat x, y, z; location->get( x, y, z ); glTranslatef( x, y, z ); look_like->get_current()->display( view ); glPopMatrix(); } if ( projected_through->get_current() != NULL ) { glPushMatrix(); gfloat x, y, z; location->get( x, y, z ); glTranslatef( x, y, z ); projected_through->get_current()->display( view ); glPopMatrix(); } glPushMatrix(); objlist->light_enable( light_id ); GLfloat coldef[4]; color->gl_array( coldef ); objlist->light_set_properties( light_id, location->get(), pointat->get(), radius->value(), coldef ); // Position et direction const float lof = 0.025; float x, y, z, a, b, c; location->get( x, y, z ); pointat->get( a, b, c ); glTranslatef( x, y, z ); glRotatef( atan2( a-x, c-z )*180/3.1415, 0, 1, 0 ); glRotatef( -atan2( b-y, sqrt( (c-z)*(c-z) + (a-x)*(a-x) ) )*180/3.1415, 1, 0, 0 ); glBegin( GL_LINES ); glVertex3f( -lof, 0, 0 ); glVertex3f( +lof, 0, 0 ); glVertex3f( 0, -lof, 0 ); glVertex3f( 0, +lof, 0 ); glVertex3f( 0, 0, -lof ); glVertex3f( 0, 0, +lof ); glVertex3f( -lof, +lof, 0 ); glVertex3f( +lof, -lof, 0 ); glVertex3f( +lof, +lof, 0 ); glVertex3f( -lof, -lof, 0 ); glVertex3f( -lof, 0, -lof ); glVertex3f( +lof, 0, +lof ); glVertex3f( +lof, 0, -lof ); glVertex3f( -lof, 0, +lof ); glVertex3f( 0, +lof, +lof ); glVertex3f( 0, -lof, -lof ); glVertex3f( 0, +lof, -lof ); glVertex3f( 0, -lof, +lof ); glEnd(); if ( frustum->value() ) { float dist = sqrt( (x-a)*(x-a) + (y-b)*(y-b) + (z-c)*(z-c) ); float rad = sin(radius->value() *3.1415 / 360 )*dist*2; GLUquadricObj *quadobj = gluNewQuadric(); if ( !quadobj ) { app_warning( N_("Out of memory" ) ); return; } gluCylinder(quadobj, rad, rad, dist, 12, 12 ); } glPopMatrix(); list.end(); } glPolygonMode( static_cast(GL_FRONT_AND_BACK), static_cast(polymode) ); } //*********************************************** // Output to povray //*********************************************** void CylindricalLight::output_to_povray_pass1( ofstream & file ) { if ( look_like->get_current() != NULL ) look_like->get_current()->output_to_povray_pass1( file ); if ( projected_through->get_current() != NULL ) projected_through->get_current()->output_to_povray_pass1( file ); file << "\n\n// Cylindrical light : " << name->value(); file << "\n#declare "; get_underscore_name( file ); file << " ="; file << "\n\nlight_source {\n\t"; location->output_to_povray(file); file << "\n\tcolor "; color->output_to_povray(file); file << "\n\tcylinder"; file << "\n\tradius "; radius->output_to_povray(file); file << "\n\tfalloff "; falloff->output_to_povray(file); file << "\n\tpoint_at "; pointat->output_to_povray(file); file << "\n\ttightness "; tightness->output_to_povray(file); if ( media_attenuation->value() ) file << "\n\tmedia_attenuation "; if ( media_interaction->value() ) file << "\n\tmedia_interaction "; if ( parallel->value() ) file << "\n\tparallel "; if ( fade->value() ) { file << "\n\tfade_distance "; fade_distance->output_to_povray(file); file << "\n\tfade_power "; fade_power->output_to_povray(file); } if ( look_like->get_current() != NULL ) { file << "\n\tlooks_like { object { "; look_like->get_current()->get_underscore_name( file ); file << " } }"; } if ( projected_through->get_current() != NULL ) { file << "\n\tprojected_through { object { "; projected_through->get_current()->get_underscore_name( file ); file << " } }"; } file << "\n\tphotons {"; file << "\n\t\trefraction " << ( refraction->value() ? "on" : "off" ); file << "\n\t\treflection " << ( reflection->value() ? "on" : "off" ); if ( area->value() ) file << "\n\t\tarea_light"; file << "\n\t}"; file << "\n}"; } void CylindricalLight::save( ofstream & file ) { file << "\nCYLINDERLIGHT{\n"; save_basics( file ); location->save( file ); color->save( file ); radius->save( file ); falloff->save( file ); pointat->save( file ); tightness->save( file ); media_interaction->save( file ); media_attenuation->save( file ); fade->save( file ); fade_distance->save( file ); fade_power->save( file ); parallel->save( file ); refraction->save( file ); reflection->save( file ); area->save( file ); look_like->save( file ); projected_through->save( file ); file << "\n}"; } bool CylindricalLight::load( ifstream & file, char *ltag ) { if ( strcmp( ltag, "CYLINDERLIGHT" ) ) 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 ( color->load( file, tag ) ) continue; if ( media_interaction->load( file, tag ) ) continue; if ( media_attenuation->load( file, tag ) ) continue; if ( fade->load( file, tag ) ) continue; if ( fade_distance->load( file, tag ) ) continue; if ( fade_power->load( file, tag ) ) continue; if ( radius->load( file, tag ) ) continue; if ( falloff->load( file, tag ) ) continue; if ( pointat->load( file, tag ) ) continue; if ( tightness->load( file, tag ) ) continue; if ( parallel->load( file, tag ) ) continue; if ( refraction->load( file, tag ) ) continue; if ( reflection->load( file, tag ) ) continue; if ( area->load( file, tag ) ) continue; if ( look_like->load( file, tag ) ) continue; if ( projected_through->load( file, tag ) ) continue; tvio_skip_section(file ); } while ( tag != NULL ); return true; }