//***************************************************************************************** // Truevision - a 3d modeler for gnome and povray // // sphere.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/sphere.h" #include "include/viewmanager.h" #include "include/objectlist.h" #include "include/tvio.h" #include "include/preferences.h" #include "include/utils3d.h" #include //************************************** // Constructeur //************************************** Sphere::Sphere( app_objs *appref ) : Object3D_with_material( appref ) { type = TV_OBJ3D_SPHERE; category = TV_OBJ3D_OBJECTS; set_name( "Sphere" ); // Base location = new ObjParam_point( N_("Location"), "LOC", NULL, app_ref, true ); location->set( 0, 0, 0 ); size = new ObjParam_scale( N_("Scale"), "SIZE", NULL, app_ref, true ); size->set( 0.2, 0.2, 0.2 ); rotation = new ObjParam_rotation( N_("Rotation"), "ROT", NULL, app_ref, true ); rotation->set( 0, 0, 0 ); radius = new ObjParam_float( N_("Radius"), "RADIUS", NULL, app_ref, true, 1 ); radius->set_range( 50, -50, 0.01, 4 ); } Sphere::Sphere( Sphere & ref ) : Object3D_with_material( ref ) { location = new ObjParam_point( *ref.location ); size = new ObjParam_scale( *ref.size ); rotation = new ObjParam_rotation( *ref.rotation ); radius = new ObjParam_float( *ref.radius ); } Sphere::~Sphere() { delete location; delete size; delete rotation; delete radius; } //************************************** // Display // Dessin de la sphere //************************************** void Sphere::display( glview *view, bool set_col ) { if ( hidden->value() ) return; if ( location->changed() || size->changed() || rotation->changed() || radius->changed() ) list.invalidate(); Object3D::display( view ); if ( set_col ) set_color(); if ( ! list.exec() ) { // mise à zero des parametres location->unchange(); size->unchange(); rotation->unchange(); radius->unchange(); // creation de la liste si necessaire list.begin(); glPushMatrix(); // Position et direction gfloat x, y, z; location->get( x, y, z ); glTranslatef( x, y, z ); rotation->gl_rotate(); size->get( x, y, z ); glScalef( x, y, z ); PREF_DEF int quality = 6 + pref->preview_quality->value()*6; GLUquadricObj *quadobj = gluNewQuadric(); if ( !quadobj ) { app_warning( _("Out of memory" ) ); return; } gluQuadricDrawStyle( quadobj, GLU_FILL ); //gluQuadricNormals( quadobj, GLU_SMOOTH ); //gluQuadricOrientation( quadobj, GLU_OUTSIDE ); gluSphere(quadobj, radius->value() , quality, quality ); //gdk_gl_draw_sphere( TRUE, 1, 10, 10 ); glEnd(); glPopMatrix(); list.end(); } } //*********************************************** // Edit //*********************************************** void Sphere::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"), 4 ); location->get_widget( table, tt, 1 ); radius->get_widget( table, tt, 2 ); size->get_widget( table, tt, 3 ); rotation->get_widget( table, tt, 4 ); get_texture_widgets( edit_cont, tt ); gtk_widget_show_all( wid ); } //*********************************************** // Mouse drag //*********************************************** void Sphere::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_SCALE: { size->mouse_drag( drag ); } break; case TV_PMODE_ROTATE: { rotation->mouse_drag( drag ); break; } case TV_PMODE_CUSTOM: ((ObjParam_point*)(objlist->get_current_param()))->mouse_drag( drag ); break; default: break; } } //*********************************************** // Pref_changed //*********************************************** void Sphere::pref_changed() { Object3D::pref_changed(); location->pref_changed(); size->pref_changed(); rotation->pref_changed(); radius->pref_changed(); } //*********************************************** // Destroy editor //*********************************************** void Sphere::destroy_editor() { Object3D::destroy_editor(); location->clear_widget(); size->clear_widget(); texture->clear_widget(); rotation->clear_widget(); radius->clear_widget(); } //*********************************************** // Output to povray //*********************************************** void Sphere::output_to_povray_pass1( ofstream & file ) { file << "\n\n// Sphere : " << name->value(); file << "\n#declare "; get_underscore_name( file ); file << " ="; file << "\nsphere {\n\t<0,0,0>, "; file << radius->value() << " \n\t"; 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 ); location->get( x, y, z ); file << "\n\ttranslate <" << x << "," << y << "," << -z << ">"; file << "\n}"; } void Sphere::save( ofstream & file ) { file << "\nSPHERE{\n"; save_basics( file ); size->save( file ); rotation->save( file ); location->save( file ); texture->save( file ); radius->save( file ); file << "\n}"; } bool Sphere::load( ifstream & file, char *ltag ) { if ( strcmp( ltag, "SPHERE" ) ) 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 ( size->load( file, tag ) ) continue; if ( rotation->load( file, tag ) ) continue; if ( radius->load( file, tag ) ) continue; tvio_skip_section(file ); } while ( tag != NULL ); return true; } //************************************** // Constructeur //************************************** BlobSphere::BlobSphere( app_objs *appref ) : Sphere( appref ) { type = TV_OBJ3D_BLOBSPHERE; category = TV_OBJ3D_OBJECTS; set_name( "Blob Sphere" ); strength = new ObjParam_float( N_("Strength"), "STRENGTH", NULL, app_ref, true, 1 ); strength->set_range( 100, -100, 0.1, 3 ); } BlobSphere::BlobSphere( BlobSphere & ref ) : Sphere( ref ) { type = TV_OBJ3D_BLOBSPHERE; strength = new ObjParam_float( *ref.strength ); } BlobSphere::~BlobSphere() { delete strength; } //*********************************************** // Edit //*********************************************** void BlobSphere::edit_widget( GtkWidget *wid ) { bool tt = true; // Options communes Object3D::edit_widget( wid ); // Options de geometrie new_frame( edit_cont, _("General settings") ); strength->get_widget( frame, tt ); location->get_widget( frame, tt ); radius->get_widget( frame, tt ); size->get_widget( frame, tt ); rotation->get_widget( frame, tt ); gtk_widget_show_all( wid ); } //*********************************************** // Pref_changed //*********************************************** void BlobSphere::pref_changed() { Sphere::pref_changed(); strength->pref_changed(); } //*********************************************** // Destroy editor //*********************************************** void BlobSphere::destroy_editor() { Sphere::destroy_editor(); strength->clear_widget(); } //*********************************************** // Output to povray //*********************************************** void BlobSphere::output_to_povray_pass1( ofstream & file ) { if ( !render->value() ) return; file << "\n\tsphere {\n\t<0,0,0>, "; file << radius->value() << ", strength " << strength->value() << "\n\t"; Object3D::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 ); location->get( x, y, z ); file << "\n\ttranslate <" << x << "," << y << "," << -z << ">"; file << "\n}"; } void BlobSphere::save( ofstream & file ) { file << "\nBLOBSPHERE{\n"; save_basics( file ); size->save( file ); rotation->save( file ); location->save( file ); strength->save( file ); radius->save( file ); file << "\n}"; } bool BlobSphere::load( ifstream & file, char *ltag ) { if ( strcmp( ltag, "BLOBSPHERE" ) ) 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 ( size->load( file, tag ) ) continue; if ( rotation->load( file, tag ) ) continue; if ( strength->load( file, tag ) ) continue; if ( radius->load( file, tag ) ) continue; tvio_skip_section(file ); } while ( tag != NULL ); return true; } float BlobSphere::get_strength_radius() { float val = 0; float *rad = size->get(); float stren = strength->value(); if ( stren > 1 ) stren = 1; for ( int i = 0 ; i < 3 ; i++ ) { float test = stren*rad[i]; if ( test > val ) val = test; } val *= radius->value(); return val; } float BlobSphere::get_strength( float x, float y, float z ) { float density = 0; float a, b, c; location->get( a, b, c ); float ux = x-a; float uy = y-b; float uz = z-c; float angles[3], cosa[3], sina[3]; rotation->get_as_radian( angles[0], angles[1], angles[2] ); for ( int i = 0 ; i < 3 ; i++ ) { cosa[i] = cos( angles[i] ); sina[i] = sin( angles[i] ); } // X rotate float tux = ux; float tuy = cosa[0]*uy - sina[0]*uz; float tuz = cosa[0]*uz + sina[0]*uy; // Y rotate ux = tuz*sina[1] + tux*cosa[1]; uy = tuy; uz = tuz*cosa[1] - tux*sina[1]; // Z rotate tux = cosa[2]*ux - sina[2]*uy; tuy = cosa[2]*uy + sina[2]*ux; tuz = uz; size->get( a, b, c ); float rad = radius->value(); ux = tux/a/rad; uy = tuy/b/rad; uz = tuz/c/rad; //cout << "\nvect2 <" << ux << ", " << uy << ", " << uz << ">"; cout.flush(); //size->get( a, b, c ); //ux = tux/a; uy = tuy/b; uz = tuz/c; float distance = ( ux*ux + uy*uy + uz*uz ); if ( distance > 1 ) return 0; density = strength->value() * square( 1 - (distance) ); return density; }