//***************************************************************************************** // Truevision - a 3d modeler for gnome and povray // // blob.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/blob.h" #include "include/viewmanager.h" #include "include/objectlist.h" #include "include/tvio.h" #include "include/sphere.h" #include "include/cylinder.h" #include "include/impsurface.h" #include "include/preferences.h" Blob::Blob( app_objs *appref ) : ObjCSG( appref ) { type = TV_OBJ3D_BLOB; category = TV_OBJ3D_OBJECTS; set_name( "Blob" ); threshold = new ObjParam_float( N_("Threshold"), "THRES", NULL,app_ref, true, 1 ); threshold->set_range( 100, 0, 0.1, 4 ); sturm = new ObjParam_bool( N_("Sturm"), "STURM", NULL, app_ref, true, false ); hierarchy = new ObjParam_bool( N_("Hieriarchy"), "HIERAR", NULL, app_ref, true, true ); evaluate = new ObjParam_bool( N_("Evaluate"), "EVAL", N_("OpenGL preview"), app_ref, true, false ); } Blob::Blob( Blob & ref ) : ObjCSG( ref ) { threshold = new ObjParam_float( *ref.threshold ); sturm = new ObjParam_bool( *ref.sturm ); hierarchy = new ObjParam_bool( *ref.hierarchy ); evaluate = new ObjParam_bool( *ref.evaluate ); } void Blob::edit_widget( GtkWidget *wid ) { PREF_DEF bool tt = pref->tooltips->value(); // Options communes Object3D_with_material::edit_widget( wid, true ); // add sphere & add cylinder buttons GtkWidget *button = gtk_button_new_with_label( N_("Add Spherical component") ); //gtk_container_set_border_width( GTK_CONTAINER(button), 1 ); gtk_signal_connect( GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(sign_blob_add_sphere), this ); gtk_box_pack_start( GTK_BOX(edit_cont), button, FALSE, FALSE, 1 ); button = gtk_button_new_with_label( N_("Add Cylindrical component") ); //gtk_container_set_border_width( GTK_CONTAINER(button), 1 ); gtk_signal_connect( GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(sign_blob_add_cylinder), this ); gtk_box_pack_start( GTK_BOX(edit_cont), button, FALSE, TRUE, 1 ); // Options de geometrie new_table( edit_cont, _("General settings"), 8 ); evaluate->get_widget( table, tt, 1 ); threshold->get_widget( table, tt, 2 ); sturm->get_widget( table, tt, 3 ); hierarchy->get_widget( table, tt, 4 ); translation->get_widget( table, tt, 5 ); size->get_widget( table, tt, 6 ); rotation->get_widget( table, tt, 7 ); get_texture_widgets( edit_cont, tt ); gtk_widget_show_all( wid ); } void Blob::destroy_editor() { Object3D_with_material::destroy_editor(); translation->clear_widget(); size->clear_widget(); rotation->clear_widget(); threshold->clear_widget(); sturm->clear_widget(); hierarchy->clear_widget(); evaluate->clear_widget(); } void Blob::pref_changed() { Object3D_with_material::pref_changed(); translation->pref_changed(); size->pref_changed(); rotation->pref_changed(); threshold->pref_changed(); sturm->pref_changed(); hierarchy->pref_changed(); evaluate->pref_changed(); } // Output to povray void Blob::output_to_povray_pass1( ofstream & file ) { file << "\n\n// Blob : " << name->value(); file << "\n#declare "; get_underscore_name( file ); file << " ="; file << "\n\nblob {"; file << "\n\tthreshold " << threshold->value(); for ( unsigned int i = 0 ; i < children.size() ; i++ ) children[i]->output_to_povray_pass1( file ); file << "\n\tsturm " << ( sturm->value() ? "on" : "off" ); file << "\n\thierarchy " << ( hierarchy->value() ? "on" : "off" ); Object3D_with_material::output_to_povray_pass1( file ); float x, y, z; size->get( x, y, z ); file << "\n\tscale <" << x << ',' << y << ',' << z << ">\n\t"; rotation->output_to_povray( file ); translation->get( x, y, z ); file << "\n\ttranslate <" << x << "," << y << "," << -z << ">"; file << "\n}"; } void Blob::save( ofstream & file ) { file << "\nBLOB{\n"; save_basics( file ); translation->save( file ); size->save( file ); rotation->save( file ); texture->save( file ); node_expanded->save( file ); threshold->save( file ); sturm->save( file ); hierarchy->save( file ); evaluate->save( file ); for ( unsigned int i = 0 ; i < children.size() ; i++ ) children[i]->save( file ); file << "\n}"; } bool Blob::load( ifstream & file, char *ltag ) { if ( strcmp( "BLOB", ltag ) ) return false; OBJLIST_DEF char * tag = NULL; do { tag = tvio_get_next_tag( file ); if ( tag == NULL ) break; if ( load_basics( file, tag ) ) continue; if ( translation->load( file, tag ) ) continue; if ( rotation->load( file, tag ) ) continue; if ( size->load( file, tag ) ) continue; if ( node_expanded->load( file, tag ) ) continue; if ( threshold->load( file, tag ) ) continue; if ( sturm->load( file, tag ) ) continue; if ( hierarchy->load( file, tag ) ) continue; if ( evaluate->load( file, tag ) ) continue; Object3D *obj = objlist->create_object( tag ); if ( obj != NULL ) { if ( obj->load( file, tag ) ) { add_object( obj ); continue; } else delete obj; } tvio_skip_section(file ); } while ( tag != NULL ); //cout << "\nblob loaded !"; cout.flush(); return true; } void Blob::add_sphere() { BlobSphere *sphere = new BlobSphere( app_ref ); add_object( sphere ); VMAN_DEF vmanager->refresh(); ((Object3D*)(sphere))->add_to_tree( tree_view, tree_store, tree_selection, &node_iter , NULL ); //((Object3D*)(sphere))->ctree_node_select(); } void Blob::add_cylinder() { BlobCylinder *cylinder = new BlobCylinder( app_ref ); add_object( cylinder ); VMAN_DEF vmanager->refresh(); ((Object3D*)(cylinder))->add_to_tree( tree_view, tree_store, tree_selection, &node_iter , NULL ); //((Object3D*)(cylinder))->ctree_node_select(); } //************************************** // Display //************************************** void Blob::display( glview *view, bool set_col ) { if ( hidden->value() ) return; if ( evaluate->value() == FALSE ) { ObjCSG::display( view ); return; } if ( translation->changed() || size->changed() || rotation->changed() || threshold->changed() ) list.invalidate(); for ( unsigned int i = 0 ; i < children.size() ; i++ ) if ( children[i]->changed() ) list.invalidate(); if ( set_col ) set_color(); Object3D::display( view ); if ( ! list.exec() ) { // mise à zero des parametres translation->unchange(); size->unchange(); rotation->unchange(); threshold->unchange(); // creation de la liste si necessaire list.begin(); glPushMatrix(); // Position et direction gfloat x, y, z; translation->get( x, y, z ); glTranslatef( x, y, z ); rotation->gl_rotate(); size->get( x, y, z ); glScalef( x, y, z ); float max[3], min[3]; for ( int i = 0 ; i < 3 ; i++ ) { min[i] = 100; max[i] = -100; } //gfloat a,b,c; for ( unsigned int i = 0 ; i < children.size() ; i++ ) { float *pos = children[i]->get_location(); float radius = children[i]->get_strength_radius(); children[i]->unchange(); for ( int i = 0 ; i < 3 ; i++ ) { float test = pos[i] + radius; if ( test > max[i] ) max[i] = test; test = pos[i] - radius; if ( test < min[i] ) min[i] = test; } for ( int i = 0 ; i < 3 ; i++ ) { float len = ( max[i] - min[i] ) / 50.0; max[i] += len; min[i] -= len; } } ImplicitSurface Preview( app_ref, BlobTestFunc, this, min, max ); glPopMatrix(); list.end(); } } bool Blob::is_inside( float x, float y, float z ) { float strength = 0; for ( unsigned int i = 0 ; i < children.size() ; i++ ) strength += children[i]->get_strength( x, y, z ); //cout << "\ndens = " << strength; cout.flush(); if ( threshold->value() < strength ) return true; else return false; }