//***************************************************************************************** // Truevision - a 3d modeler for gnome and povray // // media.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/media.h" #include "include/dlgutils.h" #include "include/tvio.h" #include "include/matlist.h" #include "include/preferences.h" //************************************** // Définitions //************************************** const int sampling_type_num = 3; const char *sampling_type_list[sampling_type_num] = { N_("Monte Carlo integration"), N_("Distributive sampling"), N_("Adaptative sampling"), }; int PovTexMedia::count=0; PovTexMedia::PovTexMedia( app_objs *appref, char *tagname, void (*asuicidal_func)(gpointer, gpointer), gpointer amother ) : MaterialItem( app_ref, tagname ) { num = ++count; char text[25]; sprintf( text, "Media #%u", num ); set_name( text ); item_type = TV_MITEM_MEDIA; suicidal_func = asuicidal_func; mother = amother; tree_store = NULL; intervals = new TvWidget_int( N_("Intervals"), "INTERV", NULL, app_ref, 10 ); intervals->set_range( 1000, 1, 1 ); sample_min = new TvWidget_int( N_("min sample"), "SAMPMIN", NULL, app_ref, 1 ); sample_min->set_range( 1000, 1, 1 ); sample_max = new TvWidget_int( N_("max sample"), "SAMPMAX", NULL, app_ref, 1 ); sample_max->set_range( 1000, 1, 1 ); confidence = new TvWidget_float( N_("Confidence"), "CONF", NULL, app_ref, 0.9 ); confidence->set_range( 0.9999, 0.0001, 0.1, 4 ); variance = new TvWidget_float( N_("Variance"), "VAR", NULL, app_ref, 0.00782 ); variance->set_range( 1, 0.0001, 0.1, 5 ); ratio = new TvWidget_float( N_("Ratio"), "RATIO", NULL, app_ref, 1 ); ratio->set_range( 1, 0, 0.1, 3 ); jitter = new TvWidget_float( N_("Jitter"), "JITTER", NULL, app_ref, 0 ); jitter->set_range( 100, 0, 0.1, 3 ); aa_level = new TvWidget_int( N_("Antialiasing level"), "AALEVEL", NULL, app_ref, 4 ); aa_level->set_range( 100, 1, 1 ); aa_threshold = new TvWidget_float( N_("Antialiasing threshold"), "AATHRES", NULL, app_ref, 0.1 ); aa_threshold->set_range( 100, 0, 0.1, 3 ); sampling_method = new TvWidget_option_combo( N_("Sampling method"), "METHOD", NULL, app_ref ); sampling_method->set_list( sampling_type_list, sampling_type_num, 0 ); absorption = new TvWidget_pigment_rb( N_("Absorption"), "ABSORP", NULL, app_ref ); absorption->set( 0, 0, 0, 0 ); emission = new TvWidget_pigment_rb( N_("Emission"), "EMIT", NULL, app_ref ); emission->set( 0, 0, 0, 0 ); scattering = new TvWidget_scattering_rb( N_("Scattering"), "SCATTER", NULL, app_ref ); transfo = new TvWidget_transformation_rb( N_("Transformation"), "TRANSFO", NULL, app_ref ); } PovTexMedia::PovTexMedia( PovTexMedia & ref ) : MaterialItem( ref ) { set_name( ref.get_name() ); item_type = TV_MITEM_MEDIA; intervals = new TvWidget_int( *ref.intervals ); sample_min = new TvWidget_int( *ref.sample_min ); sample_max = new TvWidget_int( *ref.sample_max ); confidence = new TvWidget_float( *ref.confidence ); variance = new TvWidget_float( *ref.variance ); ratio = new TvWidget_float( *ref.ratio ); sampling_method = new TvWidget_option_combo( *ref.sampling_method ); jitter = new TvWidget_float( *ref.jitter ); aa_level = new TvWidget_int( *ref.aa_level ); aa_threshold = new TvWidget_float( *ref.aa_threshold ); absorption = new TvWidget_pigment_rb( *ref.absorption ); emission = new TvWidget_pigment_rb( *ref.emission ); scattering = new TvWidget_scattering_rb( *ref.scattering ); transfo = new TvWidget_transformation_rb( *ref.transfo ); for ( unsigned int i = 0 ; i < ref.density_liste.size() ; i++ ) { PovTexDensity *item = new PovTexDensity( *ref.density_liste[i] ); density_liste.push_back( item ); } } PovTexMedia::~PovTexMedia() { delete intervals; delete sample_min; delete sample_max; delete confidence; delete variance; delete ratio; delete sampling_method; delete jitter; delete aa_level; delete aa_threshold; delete absorption; delete emission; delete scattering; delete transfo; for ( unsigned int i = 0 ; i < density_liste.size() ; i++ ) delete density_liste[i]; } void PovTexMedia::add_to_tree( GtkTreeView *view, GtkTreeStore *store, GtkTreeSelection *selection, GtkTreeIter *parent, GtkTreeIter *sibling ) { MaterialItem::add_to_tree( view, store, selection, parent, sibling ); for ( unsigned int i = 0 ; i < density_liste.size() ; i++ ) density_liste[i]->add_to_tree( view, store, selection, &node_iter ); } void PovTexMedia::remove_from_tree() { for ( unsigned int i = 0 ; i < density_liste.size() ; i++ ) density_liste[i]->remove_from_tree(); MaterialItem::remove_from_tree(); } void PovTexMedia::save_node_state() { MaterialItem::save_node_state(); for ( unsigned int i = 0 ; i < density_liste.size() ; i++ ) density_liste[i]->save_node_state(); } void PovTexMedia::edit_widget( GtkWidget *box ) { PREF_DEF bool tt = pref->tooltips->value(); MaterialItem::edit_widget( box, _("Media") ); GtkWidget *vbox = gtk_vbox_new( FALSE, 0 ); gtk_box_pack_start( GTK_BOX(edit_cont), vbox, TRUE, TRUE, 0 ); GtkWidget *frame_box = new_table( vbox, _("General"), 10 ); sampling_method->get_widget( frame_box, tt, 1 ); intervals->get_widget( frame_box, tt, 2 ); sample_min->get_widget( frame_box, tt, 3 ); sample_max->get_widget( frame_box, tt, 4 ); confidence->get_widget( frame_box, tt, 5 ); variance->get_widget( frame_box, tt, 6 ); ratio->get_widget( frame_box, tt, 7 ); jitter->get_widget( frame_box, tt, 8 ); aa_level->get_widget( frame_box, tt, 9 ); aa_threshold->get_widget( frame_box, tt, 10 ); absorption->get_widget_rb( vbox, tt ); emission->get_widget_rb( vbox, tt ); scattering->get_widget_rb( vbox, tt ); transfo->get_widget_rb( vbox, tt ); GtkWidget *del_button = gtk_button_new_with_label( _("Delete this media") ); gtk_box_pack_start( GTK_BOX(vbox), del_button, FALSE, TRUE, 2 ); gtk_signal_connect( GTK_OBJECT(del_button), "clicked", GTK_SIGNAL_FUNC(sign_media_delete), this ); GtkWidget *add_button = gtk_button_new_with_label( _("Add density") ); gtk_box_pack_start( GTK_BOX(vbox), add_button, FALSE, TRUE, 2 ); gtk_signal_connect( GTK_OBJECT(add_button), "clicked", GTK_SIGNAL_FUNC(sign_media_add_density), this ); gtk_widget_show_all( widget ); } void PovTexMedia::destroy_widget() { MaterialItem::destroy_widget(); intervals->clear_widget(); sample_min->clear_widget(); sample_max->clear_widget(); confidence->clear_widget(); variance->clear_widget(); ratio->clear_widget(); sampling_method->clear_widget(); jitter->clear_widget(); aa_level->clear_widget(); aa_threshold->clear_widget(); absorption->clear_widget(); emission->clear_widget(); scattering->clear_widget(); transfo->clear_widget(); } void PovTexMedia::flush() { intervals->flush(); sample_min->flush(); sample_max->flush(); confidence->flush(); variance->flush(); ratio->flush(); sampling_method->flush(); jitter->flush(); aa_level->flush(); aa_threshold->flush(); absorption->flush(); emission->flush(); scattering->flush(); transfo->flush(); } void PovTexMedia::output_to_povray( ofstream & file ) { file << "\n\t\tmedia {"; file << "\n\t\t\tintervals "; intervals->output_to_povray( file ); file << "\n\t\t\tsamples "; sample_min->output_to_povray( file ); file << ", "; sample_max->output_to_povray( file ); file << "\n\t\t\tconfidence "; confidence->output_to_povray( file ); file << "\n\t\t\tvariance "; variance->output_to_povray( file ); file << "\n\t\t\tratio "; ratio->output_to_povray( file ); file << "\n\t\t\tmethod " << sampling_method->value() + 1; file << "\n\t\t\tjitter "; jitter->output_to_povray( file ); file << "\n\t\t\taa_level "; aa_level->output_to_povray( file ); file << "\n\t\t\taa_threshold "; aa_threshold->output_to_povray( file ); file << "\n\t\t\tabsorption "; absorption->output_to_povray( file ); file << "\n\t\t\temission "; emission->output_to_povray( file ); scattering->output_to_povray( file ); for ( unsigned int i = 0 ; i < density_liste.size() ; i ++ ) density_liste[i]->output_to_povray( file ); transfo->output_to_povray( file ); file << "\n\t\t}"; } void PovTexMedia::save( ofstream & file ) { file << "\nMEDIA{"; name->save( file ); expand->save( file ); intervals->save( file ); sample_min->save( file ); sample_max->save( file ); confidence->save( file ); variance->save( file ); ratio->save( file ); sampling_method->save( file ); jitter->save( file ); aa_level->save( file ); aa_threshold->save( file ); absorption->save( file ); emission->save( file ); scattering->save( file ); for ( unsigned int i = 0 ; i < density_liste.size() ; i ++ ) density_liste[i]->save( file ); transfo->save( file ); file << "} "; } bool PovTexMedia::load( ifstream & file, char * ltag ) { if ( strcmp( "MEDIA", ltag ) ) return false; char * tag = NULL; do { tag = tvio_get_next_tag( file ); if ( tag == NULL ) break; if (name->load( file , tag ) ) continue; if (expand->load( file , tag ) ) continue; if (intervals->load( file , tag ) ) continue; if (sample_min->load( file , tag ) ) continue; if (sample_max->load( file , tag ) ) continue; if (confidence->load( file , tag ) ) continue; if (variance->load( file , tag ) ) continue; if (ratio->load( file , tag ) ) continue; if (sampling_method->load( file , tag ) ) continue; if (jitter->load( file , tag ) ) continue; if (aa_level->load( file , tag ) ) continue; if (aa_threshold->load( file , tag ) ) continue; if (absorption->load( file , tag ) ) continue; if (emission->load( file , tag ) ) continue; if (scattering->load( file , tag ) ) continue; if (transfo->load( file , tag ) ) continue; if ( ! strcmp( "DENSITY", tag ) ) { PovTexDensity *newone = new PovTexDensity( app_ref, "DENSITY", sign_media_density_suicide, (gpointer)this ); newone->load( file, tag ); density_liste.push_back( newone ); continue; } tvio_skip_section( file ); } while( tag != NULL ); return true; } void PovTexMedia::add_density() { PovTexDensity *newone = new PovTexDensity( app_ref, "DENSITY", sign_media_density_suicide, (gpointer)this ); density_liste.push_back( newone ); newone->add_to_tree( tree_view, tree_store, tree_selection, &node_iter ); } void PovTexMedia::delete_density( PovTexDensity * density ) { vector::iterator it = density_liste.begin(); while ( it != density_liste.end() ) { if ( *it == density ) { //gtk_ctree_select( ctree, ctree_node ); select_tree_row(); density->remove_from_tree(); density_liste.erase( it ); delete density; break; } it++; } } bool PovTexMedia::paste( MaterialItem *item ) { switch ( item->get_type() ) { default : return false; break; case TV_MITEM_DENSITY: { PovTexDensity *dens = new PovTexDensity( *(PovTexDensity*)item ); density_liste.push_back( dens ); dens->set_params( sign_media_density_suicide, (gpointer)this ); dens->add_to_tree( tree_view, tree_store, tree_selection, &node_iter ); } break; case TV_MITEM_MEDIA: { PovTexMedia *med = (PovTexMedia*)item; for ( unsigned int i = 0 ; i < density_liste.size() ; i ++ ) delete density_liste[i]; density_liste.clear(); for ( unsigned int i = 0 ; i < med->density_liste.size() ; i++ ) { PovTexDensity *it = new PovTexDensity( *(med->density_liste[i]) ); it->set_params( sign_media_density_suicide, (gpointer)this ); density_liste.push_back( it ); } if ( GTK_IS_WIDGET(widget) ) { gtk_widget_destroy( edit_cont ); intervals->clear_widget(); sample_min->clear_widget(); sample_max->clear_widget(); confidence->clear_widget(); variance->clear_widget(); ratio->clear_widget(); sampling_method->clear_widget(); jitter->clear_widget(); aa_level->clear_widget(); aa_threshold->clear_widget(); absorption->clear_widget(); emission->clear_widget(); scattering->clear_widget(); transfo->clear_widget(); } intervals->copy( med->intervals ); sample_min->copy( med->sample_min ); sample_max->copy( med->sample_max ); confidence->copy(med->confidence ); variance->copy( med->variance ); ratio->copy( med->ratio ); sampling_method->copy( med->ratio ); jitter->copy( med->ratio ); aa_level->copy( med->ratio ); aa_threshold->copy( med->ratio ); absorption->copy( med->absorption ); emission->copy( med->emission ); scattering->copy( med->scattering ); transfo->copy( med->transfo ); GtkTreeIter *old_node = gtk_tree_iter_copy( &(med->node_iter) ); add_to_tree( tree_view, tree_store, tree_selection, tree_node_parent, old_node ); gtk_tree_selection_unselect_iter( tree_selection, &node_iter ); select_tree_row(); gtk_tree_iter_free( old_node ); } break; } return true; } //************************************** // Scattering //************************************** const int scattering_type_num = 5; const char *scattering_type_name[scattering_type_num] = { N_("Isotropic"), N_("Mie hazy"), N_("Mie murky"), N_("Rayleigh"), N_("Henyey-Greenstein") }; TvWidget_scattering::TvWidget_scattering( const char *name, const char *sname, const char *tooltip, app_objs *appref ) : TvWidget( name, sname, tooltip, appref ) { use_scattering = new TvWidget_bool_activator( _("Use scattering"), "USED", NULL, app_ref, false ); color = new TvWidget_pigment( _("Color"), "COLOR", NULL, app_ref ); color->set( 0, 0, 0, 0, 0 ); type = new TvWidget_option_combo( _("Type"), "TYPE", NULL, app_ref ); type->set_list( scattering_type_name, scattering_type_num, 0 ); eccentricity = new TvWidget_float( _("Eccentricity"), "ECCENT", NULL, app_ref, 0.0 ); eccentricity->set_range( 1000, -1000, 0.1, 3 ); extinction = new TvWidget_float( _("Extinction"), "EXTINCT", NULL, app_ref, 1.0 ); extinction->set_range( 5.0, 0, 0.01, 3 ); } TvWidget_scattering::TvWidget_scattering( TvWidget_scattering & ref ) : TvWidget( ref ) { use_scattering = new TvWidget_bool_activator( *ref.use_scattering ); color = new TvWidget_pigment( *ref.color ); type = new TvWidget_option_combo( *ref.type ); eccentricity = new TvWidget_float( *ref.eccentricity ); extinction = new TvWidget_float( *ref.extinction ); } TvWidget_scattering::~TvWidget_scattering() { delete use_scattering; delete color; delete type; delete eccentricity; delete extinction; } void TvWidget_scattering::get_widget_wnframe( GtkWidget *box, bool tt, bool frame ) { if ( frame ) widget = dlg_simple_box_frame( name, box ); else { widget = gtk_vbox_new( FALSE, 0 ); gtk_box_pack_start( GTK_BOX(box), widget, FALSE, TRUE, 2 ); } use_scattering->get_widget_no_toggle( widget, tt ); GtkWidget *activated_box = gtk_vbox_new( FALSE, 0 ); gtk_box_pack_start( GTK_BOX(widget), activated_box, FALSE, FALSE, 0 ); use_scattering->set_target( activated_box ); color->get_widget( activated_box, tt ); GtkWidget *table = new_table_no_frame( activated_box, 3 ); type->get_widget( table, tt, 5 ); eccentricity->get_widget( table, tt, 4 ); extinction ->get_widget( table, tt,3 ); use_scattering->update_widget(); } void TvWidget_scattering::clear_widget() { widget = NULL; use_scattering->clear_widget(); color->clear_widget(); type->clear_widget(); eccentricity->clear_widget(); extinction->clear_widget(); } void TvWidget_scattering::flush() { if ( !GTK_IS_WIDGET(widget) ) return; use_scattering->flush(); color->flush(); type->flush(); eccentricity->flush(); extinction->flush(); } void TvWidget_scattering::output_to_povray( ofstream & file ) { file << "\n\t\t\tscattering {\n\t\t\t\t"; file << type->value() + 1 << ", "; color->output_to_povray( file ); if ( type->value() == 4 ) { file << "\n\t\t\t\teccentricity "; eccentricity->output_to_povray( file ); } file << "\n\t\t\t\textinction "; extinction->output_to_povray( file ); file << "\n\t\t\t}"; } void TvWidget_scattering::save( ofstream & file ) { TvWidget::save( file ); use_scattering->save( file ); type->save( file ); color->save( file ); eccentricity->save( file ); extinction->save( file ); file << "} "; } bool TvWidget_scattering::load( ifstream & file, char * ltag ) { if ( strcmp( sname, ltag ) ) return false; char * tag = NULL; do { tag = tvio_get_next_tag( file ); if ( tag == NULL ) break; if ( use_scattering->load( file , tag ) ) continue; if ( type->load( file , tag ) ) continue; if ( color->load( file , tag ) ) continue; if ( eccentricity->load( file , tag ) ) continue; if ( extinction->load( file , tag ) ) continue; tvio_skip_section( file ); } while( tag != NULL ); return true; }