//***************************************************************************************** // Truevision - a 3d modeler for gnome and povray // // superellipsoid.cc // // Christian Spoer // // Vincent LE PRINCE // Christian Spoer // Copyright (C) 2000-2005 Vincent LE PRINCE // This file is part of the TRUEVISION Package // // Some of the code comes from the GIRAM-Project. // // 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/superellipsoid.h" #include "include/viewmanager.h" #include "include/objectlist.h" #include "include/tvio.h" #include "include/preferences.h" /* Some files do not define M_PI... */ #ifndef M_PI #define M_PI 3.14159265358979323846 #endif //************************************** // Constructeur //************************************** Superellipsoid::Superellipsoid( app_objs *appref ) : Object3D_with_material( appref ) { type = TV_OBJ3D_SUPERELLIPSOID; category = TV_OBJ3D_OBJECTS; set_name( "Superellipsoid" ); // Base location = new ObjParam_point( _("Location"), "LOC", NULL, app_ref, true ); location->set( 0, 0, 0 ); scale = new ObjParam_scale( _("Scale"), "SIZE", NULL, app_ref, true ); scale->set( 0.2, 0.2, 0.2 ); east = new ObjParam_float( _("\"East\"-Value"), "EAST", NULL, app_ref, true, 0.5 ); east->set_range( 1.0, 0.001, 0.01, 3 ); north = new ObjParam_float( _("\"North\"-Value"), "NORTH", NULL, app_ref, true, 0.5 ); north->set_range( 1.0, 0.001, 0.01, 3 ); rotation = new ObjParam_rotation( _("Rotation"), "ROT", NULL, app_ref, true ); rotation->set( 0, 0, 0 ); } Superellipsoid::Superellipsoid( Superellipsoid & ref ) : Object3D_with_material( ref ) { location = new ObjParam_point( *ref.location ); scale = new ObjParam_scale( *ref.scale ); rotation = new ObjParam_rotation( *ref.rotation ); east = new ObjParam_float( *ref.east ); north = new ObjParam_float( *ref.north ); } Superellipsoid::~Superellipsoid() { delete location; delete scale; delete rotation; delete east; delete north; } //************************************** // Display //************************************** void Superellipsoid::display( glview *view, bool set_col ) { if ( hidden->value() ) return; if ( location->changed() || scale->changed() || rotation->changed() || east->changed() || north->changed() ) list.invalidate(); Object3D::display( view ); if ( set_col ) set_color(); if ( ! list.exec() ) { // mise à zero des parametres location->unchange(); scale->unchange(); rotation->unchange(); east->unchange(); north->unchange(); // creation de la liste si necessaire list.begin(); glPushMatrix(); // Position et direction gfloat a, b, c; location->get( a, b, c ); glTranslatef( a, b, c ); rotation->gl_rotate(); scale->get( a, b, c ); glScalef( a, b, c ); const int numt = 10; gdouble s1,s2,c1,c2,t1,t2; gint i,j; gdouble east_v = east->value(); gdouble north_v = north->value(); // The North-Pole glBegin( GL_TRIANGLE_FAN ); glNormal3f( 0, 0, 1 ); glVertex3f(0.0, 0.0, 1.0); for ( i = 0 ; i < numt ; i++) { t1 = M_PI / numt; if (sin(t1) >= 0.0) s1 = pow( sin(t1), north_v); else s1 = -pow(-sin(t1), north_v); if (cos(t1) >= 0.0) c1 = pow( cos(t1), north_v); else c1 = -pow(-cos(t1), north_v); t2 = i * 2.0 * M_PI / numt; if (sin(t2) >= 0.0) s2 = pow( sin(t2), east_v); else s2 = -pow(-sin(t2), east_v); if (cos(t2) >= 0.0) c2 = pow( cos(t2), east_v); else c2 = -pow(-cos(t2), east_v); glVertex3f(s1*c2, s1*s2, c1); t2 = (i+1) * 2.0 * M_PI / numt; if (sin(t2) >= 0.0) s2 = pow( sin(t2), east_v); else s2 = -pow(-sin(t2), east_v); if (cos(t2) >= 0.0) c2 = pow( cos(t2), east_v); else c2 = -pow(-cos(t2), east_v); glNormal3f( s1*c2, s1*s2, c1); glVertex3f(s1*c2, s1*s2, c1); } glEnd(); // Then the Mid Zone glBegin( GL_TRIANGLE_STRIP ); for (i = 1 ; i < numt-1 ; i++) { for (j = 0 ; j < numt ; j++) { t1 = i * M_PI / numt; if (sin(t1) >= 0.0) s1 = pow( sin(t1), north_v); else s1 = -pow(-sin(t1), north_v); if (cos(t1) >= 0.0) c1 = pow( cos(t1), north_v); else c1 = -pow(-cos(t1), north_v); t2 = j * 2.0 * M_PI / numt; if (sin(t2) >= 0.0) s2 = pow( sin(t2), east_v); else s2 = -pow(-sin(t2), east_v); if (cos(t2) >= 0.0) c2 = pow( cos(t2), east_v); else c2 = -pow(-cos(t2), east_v); glNormal3f(s1*c2, s1*s2, c1); glVertex3f(s1*c2, s1*s2, c1); t1 = (i+1) * M_PI / numt; if (sin(t1) >= 0.0) s1 = pow( sin(t1), north_v); else s1 = -pow(-sin(t1), north_v); if (cos(t1) >= 0.0) c1 = pow( cos(t1), north_v); else c1 = -pow(-cos(t1), north_v); t2 = j * 2.0 * M_PI / numt; if (sin(t2) >= 0.0) s2 = pow( sin(t2), east_v); else s2 = -pow(-sin(t2), east_v); if (cos(t2) >= 0.0) c2 = pow( cos(t2), east_v); else c2 = -pow(-cos(t2), east_v); glNormal3f(s1*c2, s1*s2, c1); glVertex3f(s1*c2, s1*s2, c1); t1 = i * M_PI / numt; if (sin(t1) >= 0.0) s1 = pow( sin(t1), north_v); else s1 = -pow(-sin(t1), north_v); if (cos(t1) >= 0.0) c1 = pow( cos(t1), north_v); else c1 = -pow(-cos(t1), north_v); t2 = (j+1) * 2.0 * M_PI / numt; if (sin(t2) >= 0.0) s2 = pow( sin(t2), east_v); else s2 = -pow(-sin(t2), east_v); if (cos(t2) >= 0.0) c2 = pow( cos(t2), east_v); else c2 = -pow(-cos(t2), east_v); glNormal3f(s1*c2, s1*s2, c1); glVertex3f(s1*c2, s1*s2, c1); t1 = (i+1) * M_PI / numt; if (sin(t1) >= 0.0) s1 = pow( sin(t1), north_v); else s1 = -pow(-sin(t1), north_v); if (cos(t1) >= 0.0) c1 = pow( cos(t1), north_v); else c1 = -pow(-cos(t1), north_v); t2 = (j+1) * 2.0 * M_PI / numt; if (sin(t2) >= 0.0) s2 = pow( sin(t2), east_v); else s2 = -pow(-sin(t2), east_v); if (cos(t2) >= 0.0) c2 = pow( cos(t2), east_v); else c2 = -pow(-cos(t2), east_v); glNormal3f( s1*c2, s1*s2, c1); glVertex3f( s1*c2, s1*s2, c1); } } glEnd(); // And the South Pole glBegin( GL_TRIANGLE_FAN ); glNormal3f(0.0, 0.0, -1.0); glVertex3f(0.0, 0.0, -1.0); for (i=0 ; i= 0.0) s1 = pow( sin(t1), north_v); else s1 = -pow(-sin(t1), north_v); if (cos(t1) >= 0.0) c1 = pow( cos(t1), north_v); else c1 = -pow(-cos(t1), north_v); t2 = i * 2.0 * M_PI / numt; if (sin(t2) >= 0.0) s2 = pow( sin(t2), east_v); else s2 = -pow(-sin(t2), east_v); if (cos(t2) >= 0.0) c2 = pow( cos(t2), east_v); else c2 = -pow(-cos(t2), east_v); glVertex3f(s1*c2, s1*s2, c1); t2 = (i+1) * 2.0 * M_PI / numt; if (sin(t2) >= 0.0) s2 = pow( sin(t2), east_v); else s2 = -pow(-sin(t2), east_v); if (cos(t2) >= 0.0) c2 = pow( cos(t2), east_v); else c2 = -pow(-cos(t2), east_v); glNormal3f(s1*c2, s1*s2, c1); glVertex3f(s1*c2, s1*s2, c1); } glEnd(); glPopMatrix(); list.end(); } } //*********************************************** // Edit //*********************************************** void Superellipsoid::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"), 5 ); location->get_widget( table, tt, 1 ); north->get_widget( table, tt, 2 ); east->get_widget( table, tt, 3 ); scale->get_widget( table, tt, 4 ); rotation->get_widget( table, tt, 5 ); get_texture_widgets( edit_cont, tt ); gtk_widget_show_all( wid ); } //*********************************************** // Mouse drag //*********************************************** void Superellipsoid::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: { scale->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 Superellipsoid::pref_changed() { Object3D::pref_changed(); location->pref_changed(); scale->pref_changed(); rotation->pref_changed(); east->pref_changed(); north->pref_changed(); } //*********************************************** // Destroy editor //*********************************************** void Superellipsoid::destroy_editor() { Object3D::destroy_editor(); location->clear_widget(); scale->clear_widget(); texture->clear_widget(); rotation->clear_widget(); east->clear_widget(); north->clear_widget(); } //*********************************************** // Output to povray //*********************************************** void Superellipsoid::output_to_povray_pass1( ofstream & file ) { file << "\n\n// Superellipsoid : " << name->value(); file << "\n#declare "; get_underscore_name( file ); file << " ="; float x, y, z; // Check if the north and the east-values are valid if ( north->value() > 1.0) north->set( 1.0 ); if ( north->value() <= 0.0) north->set( 0.0001 ); if ( east->value() > 1.0) east->set( 1.0 ); if ( east->value() <= 0.0) east->set( 0.0001 ); file << "\n\n//Superellipsoid " << name->value(); file << "\nsuperellipsoid {\n\t"; file << "<" << east->value() << ", " << north->value() << ">"; Object3D_with_material::output_to_povray_pass1( file ); scale->get( x, y, z ); file << "\n\tscale <" << x << ", " << y << ", " << z << ">"; rotation->output_to_povray( file ); location->get( x, y, z ); file << "\n\ttranslate <" << x << "," << y << "," << -z << "> \n\t"; file << "\n}"; } void Superellipsoid::save( ofstream & file ) { file << "\nSUPERELLIPSOID{\n"; save_basics( file ); location->save( file ); scale->save( file ); rotation->save( file ); east->save( file ); north->save( file ); texture->save( file ); file << "\n}"; } bool Superellipsoid::load( ifstream & file, char *ltag ) { if ( strcmp( ltag, "SUPERELLIPSOID" ) ) 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 ( scale->load( file, tag ) ) continue; if ( rotation->load( file, tag ) ) continue; if ( east->load( file, tag ) ) continue; if ( north->load( file, tag ) ) continue; tvio_skip_section(file ); } while ( tag != NULL ); return true; } void Superellipsoid::set_east(float e) { printf("Setting East Value to: %f\n", e);fflush(stdout); if (e < 0.001) east->set(0.0001); else if (e > 1.0) east->set(1.0); else east->set(e); } void Superellipsoid::set_north(float n) { printf("Setting North Value to: %f\n", n);fflush(stdout); if (n < 0.0) north->set(0.0001); else if (n > 1.0) north->set(1.0); else north->set(n); }