//***************************************************************************************** // Truevision - a 3d modeler for gnome and povray // // glview.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/glview.h" #include "include/preferences.h" #include "include/viewmanager.h" #include "include/objectlist.h" #include "include/scene.h" #include drag_info glview::drag; // Drag & drop infos //******************************************* // Définition //******************************************* //int attrlist[] = { GDK_GL_RGBA, GDK_GL_DOUBLEBUFFER, GDK_GL_DEPTH_SIZE, 24, GDK_GL_ATTRIB_LIST_NONE }; const float axis_width = 2; /* Some files do not define M_PI... */ #ifndef M_PI #define M_PI 3.14159265358979323846 #endif GlDisplayList glview::grid_lists[3]; GlDisplayList glview::axis_list; app_objs *glview::app_ref = NULL; GdkGC *glview::tbar_gc = NULL; GdkGLContext *glview::glcontext = NULL; GdkGLConfig *glview::glconfig = NULL; //const float nulvect[3] = {0, 0, 0}; TvWidget_point *glview::common_lookat = NULL; gchar *glview::but_pixmaps_fnames[glview::but_pixmaps_num]; const char *but_pixmaps_path[glview::but_pixmaps_num] = { "view_menu.png", "view_rollup.png", "view_rolldown.png", "view_maximize.png", "view_restore.png" }; //******************************************* // Constructeur //******************************************* glview::glview( app_objs *appref, GtkWidget *box, GtkWidget *aframe, GtkWidget *tbframe ) { // Initialisations app_ref = appref; PREF_DEF tooltips = pref->tooltips->value(); container = box; drag.view = this; drag.rotation = &rotate; tbar_focus = false; old_zoom = 1.11; // Paramétres visible = true; local_lookat = new TvWidget_point( N_("Look at"), "LOOKA", NULL, app_ref ); local_lookat->set( 0, 0, 0 ); tv_widgets.push_back( local_lookat ); if ( common_lookat == NULL ) common_lookat = new TvWidget_point( N_("Common look at"), "CLOOKA", NULL, app_ref ); common_lookat->set( 0, 0, 0 ); tv_widgets.push_back( common_lookat ); lookat = ( pref->nav2D->value() ) ? common_lookat : local_lookat; maximized = new TvWidget_bool( N_("Maximize"), "MAXI", NULL, app_ref, false ); tv_widgets.push_back( maximized ); rolled_up = new TvWidget_bool( N_("Roll"), "ROLLU", NULL, app_ref, false ); tv_widgets.push_back( rolled_up ); gl_solid = new TvWidget_bool( N_("Solid"), "SOL", NULL, app_ref, false ); tv_widgets.push_back( gl_solid ); gl_lighting = new TvWidget_bool( N_("Lightning"), "LIGHT", NULL, app_ref, false ); tv_widgets.push_back( gl_lighting ); gl_smooth = new TvWidget_bool( N_("Smooth"), "SMOOTH", NULL, app_ref, true ); tv_widgets.push_back( gl_smooth ); axis = new TvWidget_bool( N_("Axis"), "AXIS", NULL, app_ref, false ); tv_widgets.push_back( axis ); label = new TvWidget_bool( N_("Label"), "LAB", NULL, app_ref, false ); tv_widgets.push_back( label ); grid_scale = new TvWidget_float( N_("Grid scale"), "GSCALE", NULL, app_ref, 0.4 ); tv_widgets.push_back( grid_scale ); grid_major = new TvWidget_int( N_("Major grid lines"), "GMAJOR", NULL, app_ref, 10 ); tv_widgets.push_back( grid_major ); // Test OpenGL if ( glconfig == NULL ) { if ( gdk_gl_query_extension() == FALSE ) app_fatal_err( N_("OpenGL not supported !") ); glconfig = gdk_gl_config_new_by_mode( (GdkGLConfigMode)(GDK_GL_MODE_RGB | GDK_GL_MODE_DEPTH | GDK_GL_MODE_DOUBLE) ); } // Pixmap gnomes if ( but_pixmaps_fnames[0] == NULL ) for ( register int i = 0 ; i < but_pixmaps_num ; i++ ) but_pixmaps_fnames[i] = tv_get_pixmap( (char*)but_pixmaps_path[i] ); // Barre de titre if ( tbframe == NULL ) { tframe = gtk_frame_new( NULL ); gtk_box_pack_start( GTK_BOX(container), tframe, FALSE, FALSE, 0 ); gtk_container_set_border_width( GTK_CONTAINER(tframe), 0 ); gtk_frame_set_shadow_type( GTK_FRAME(tframe), GTK_SHADOW_OUT ); gtk_widget_set_usize( tframe, -1, 20 ); } else tframe = tbframe; tbbox = gtk_hbox_new( FALSE, 0 ); gtk_container_set_border_width( GTK_CONTAINER(tbbox), 0 ); gtk_container_add( GTK_CONTAINER(tframe), tbbox ); //Menu title_bar_button_new( tbbox, 0, 0, _("Menu"), GTK_SIGNAL_FUNC(sign_pop_menu) ); // Nom de la vue tbar_focus = false; tbar_str = NULL; tbar = gtk_drawing_area_new(); gtk_widget_set_events( tbar, GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_FOCUS_CHANGE_MASK | GDK_KEY_PRESS_MASK ); gtk_box_pack_start( GTK_BOX(tbbox), tbar, TRUE, TRUE, 0 ); gtk_signal_connect( GTK_OBJECT(tbar), "expose_event", GTK_SIGNAL_FUNC(sign_glview_tbar_expose), this ); gtk_signal_connect( GTK_OBJECT(tbar), "configure_event", GTK_SIGNAL_FUNC(sign_glview_tbar_configure), this ); gtk_signal_connect( GTK_OBJECT(tbar), "button_press_event", GTK_SIGNAL_FUNC(sign_glview_tbar_mouse_click), this ); gtk_signal_connect( GTK_OBJECT(tbar), "focus_in_event", GTK_SIGNAL_FUNC(sign_glview_tbar_focus_in), this ); gtk_signal_connect( GTK_OBJECT(tbar), "focus_out_event", GTK_SIGNAL_FUNC(sign_glview_tbar_focus_out), this ); gtk_signal_connect( GTK_OBJECT(tbar), "key_press_event", GTK_SIGNAL_FUNC(sign_glview_tbar_key_press), this ); // Bouttons title_bar_button_new( tbbox, 1, 1, N_("Roll"), GTK_SIGNAL_FUNC(sign_roll) ); title_bar_button_new( tbbox, 2, 3, N_("Maximize/Restore"), GTK_SIGNAL_FUNC(sign_maximize) ); // Frame if ( aframe == NULL ) { frame = gtk_frame_new( NULL ); gtk_box_pack_start( GTK_BOX(container), frame, TRUE, TRUE, 0 ); gtk_frame_set_shadow_type( GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT ); gtk_container_set_resize_mode (GTK_CONTAINER (frame), GTK_RESIZE_IMMEDIATE); gtk_container_set_reallocate_redraws (GTK_CONTAINER (frame), TRUE); } else frame = aframe; // Aire OpenGL area = gtk_drawing_area_new(); if ( area == NULL ) app_fatal_err( N_("Can't create GtkGlExt object !") ); gtk_widget_set_events( area, GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_SCROLL_MASK ); if ( glcontext == NULL ) { gtk_widget_set_gl_capability( area, glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE ); gtk_signal_connect_after( GTK_OBJECT(area), "realize", GTK_SIGNAL_FUNC(initgl), this ); gtk_signal_connect( GTK_OBJECT(area), "configure_event", GTK_SIGNAL_FUNC(reshape), this ); gtk_signal_connect( GTK_OBJECT(area), "expose_event", GTK_SIGNAL_FUNC(display), this ); gtk_signal_connect( GTK_OBJECT(area), "button_press_event", GTK_SIGNAL_FUNC(sign_mouse_button_pressed), this ); gtk_signal_connect( GTK_OBJECT(area), "motion_notify_event", GTK_SIGNAL_FUNC(sign_mouse_moved), this ); gtk_signal_connect( GTK_OBJECT(area), "scroll_event", GTK_SIGNAL_FUNC(sign_mouse_scroll), this ); //GtkWidget *vbox2 = gtk_hbox_new( TRUE, 0 ); gtk_container_add( GTK_CONTAINER(frame), area ); //gtk_box_pack_start( GTK_BOX(frame), area, TRUE, TRUE, 0 ); gtk_widget_show( area ); gtk_widget_realize( area ); glcontext = gtk_widget_get_gl_context( area ); } else { gtk_widget_set_gl_capability( area, glconfig, glcontext, TRUE, GDK_GL_RGBA_TYPE ); gtk_signal_connect_after( GTK_OBJECT(area), "realize", GTK_SIGNAL_FUNC(initgl), this ); gtk_signal_connect( GTK_OBJECT(area), "configure_event", GTK_SIGNAL_FUNC(reshape), this ); gtk_signal_connect( GTK_OBJECT(area), "expose_event", GTK_SIGNAL_FUNC(display), this ); gtk_signal_connect( GTK_OBJECT(area), "button_press_event", GTK_SIGNAL_FUNC(sign_mouse_button_pressed), this ); gtk_signal_connect( GTK_OBJECT(area), "motion_notify_event", GTK_SIGNAL_FUNC(sign_mouse_moved), this ); gtk_signal_connect( GTK_OBJECT(area), "scroll_event", GTK_SIGNAL_FUNC(sign_mouse_scroll), this ); gtk_container_add( GTK_CONTAINER(frame), area ); gtk_widget_show( area ); } gtk_widget_show_all( frame ); gtk_widget_show_all( tframe ); } //***************************************************** // Destructeur //***************************************************** glview::~glview() { gtk_container_remove( GTK_CONTAINER(frame), area ); gtk_container_remove( GTK_CONTAINER(tframe), tbbox ); //if ( tbar_gc != NULL ) gdk_gc_unref( tbar_gc ); delete local_lookat; common_lookat->set( 0, 0, 0 ); delete maximized; delete rolled_up; delete gl_solid; delete gl_lighting; delete gl_smooth; delete axis; delete label; delete grid_scale; delete grid_major; } //***************************************************** // Titlebar Buttons //***************************************************** GtkWidget *glview::title_bar_button_new( GtkWidget *hbox, int num, int pix,const gchar *tt, GtkSignalFunc func ) { buttons_widget[num] = gtk_button_new(); gtk_button_set_relief( GTK_BUTTON(buttons_widget[num]), GTK_RELIEF_NONE ); GTK_WIDGET_UNSET_FLAGS( buttons_widget[num], GTK_CAN_FOCUS ); gtk_container_set_border_width( GTK_CONTAINER(buttons_widget[num]), 0 ); gtk_box_pack_start( GTK_BOX(hbox), buttons_widget[num], FALSE, TRUE, 0 ); if ( tt != NULL ) { buttons_tooltips[num] = gtk_tooltips_new(); gtk_tooltips_set_tip( buttons_tooltips[num], buttons_widget[num], tt, NULL ); } else buttons_tooltips[num] = NULL; if ( !tooltips ) gtk_tooltips_disable( buttons_tooltips[num] ); buttons_gpix[num] = gtk_image_new_from_file( but_pixmaps_fnames[pix] ); gtk_container_add( GTK_CONTAINER(buttons_widget[num]), buttons_gpix[num] ); gtk_signal_connect( GTK_OBJECT(buttons_widget[num]), "clicked", func, this ); return buttons_widget[num]; } void glview::tbar_expose( GdkEventExpose *ev ) { if ( tbar_str == NULL ) return; PREF_DEF GdkColor col; if ( tbar_focus ) pref->tbar_selected->gdk_col( col ); else pref->tbar_unselected->gdk_col( col ); gdk_colormap_alloc_color( gtk_widget_get_colormap( tbar ), &col, FALSE, TRUE ); gdk_gc_set_foreground( tbar_gc, &col ); gdk_draw_rectangle( tbar->window, tbar_gc, TRUE, 0, 0, tbar->allocation.width, tbar->allocation.height ); gint x = ( tbar->allocation.width - gdk_string_width( gtk_style_get_font( tbar->style ), tbar_str ) ) / 2; gint h = gdk_string_height( gtk_style_get_font( tbar->style ), tbar_str ); gint y = ( tbar->allocation.height - h ) / 2 + h; gdk_draw_string( tbar->window, gtk_style_get_font( tbar->style ), tbar->style->fg_gc[tbar->state], x, y, tbar_str ); } void glview::tbar_configure() { if ( tbar_gc == NULL ) tbar_gc = gdk_gc_new( tbar->window ); GTK_WIDGET_SET_FLAGS( tbar, GTK_CAN_FOCUS ); } void glview::tbar_mouse_click( GdkEventButton *ev ) { if ( tbar_focus ) return; gtk_widget_grab_focus( tbar ); } void glview::tbar_redraw() { GdkRectangle rect; rect.x = 0; rect.y = 0; rect.width = tbar->allocation.width; rect.height = tbar->allocation.height; gtk_widget_draw( tbar, &rect ); } //****************************************************** // Pref Changed ! //****************************************************** void glview::pref_changed() { PREF_DEF // Listes axis_list.invalidate(); for ( int i = 0 ; i < 3 ; i++ ) grid_lists[i].invalidate(); // Antialias if ( pref->line_antialias->value() ) glEnable( GL_LINE_SMOOTH ); else glDisable( GL_LINE_SMOOTH ); // Tooltips tooltips = pref->tooltips->value(); if ( tooltips ) for ( register int i = 0 ; i < buttons_num ; i++ ) gtk_tooltips_enable( buttons_tooltips[i] ); else for ( register int i = 0 ; i < buttons_num ; i++ ) gtk_tooltips_disable( buttons_tooltips[i] ); lookat = ( pref->nav2D->value() ) ? common_lookat : local_lookat; // Grid'n'Snap grid_scale->set( pref->grid_spacing->value() ); grid_major->set( pref->grid_major_lines->value() ); tbar_redraw(); } //****************************************************** // Attach Popup //****************************************************** void glview::attach_popup() { popup = gtk_menu_new(); // Rafraichir GtkWidget *item = gtk_menu_item_new_with_label( N_("Refresh") ); gtk_signal_connect( GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(sign_view_refresh), this ); gtk_menu_append( GTK_MENU(popup), item ); // Home item = gtk_menu_item_new_with_label( N_("Home") ); gtk_signal_connect( GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(sign_view_home), this ); gtk_menu_append( GTK_MENU(popup), item ); // Séparateur item = gtk_menu_item_new(); gtk_menu_append( GTK_MENU(popup), item ); // Types de Vues GSList *radio = NULL; const gchar *vlabel[view_type_num] = { N_("Top"), N_("Front"), N_("Right"), N_("Perspective"), N_("Camera") }; for ( int i = 0 ; i < view_type_num ; i++ ) { menu_view_types[i] = gtk_radio_menu_item_new_with_label( radio, vlabel[i] ); radio = gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM(menu_view_types[i]) ); gtk_menu_append( GTK_MENU(popup), menu_view_types[i] ); GTK_CHECK_MENU_ITEM(menu_view_types[i])->active = ( i == (int)type ) ? TRUE : FALSE; gtk_signal_connect( GTK_OBJECT(menu_view_types[i]), "activate", GTK_SIGNAL_FUNC(sign_change_view_type), this ); } // Parametres OpenGL item = gtk_menu_item_new(); gtk_menu_append( GTK_MENU(popup), item ); add_menu_item_bool( &menu_gl_solid, N_("Solid"), GTK_SIGNAL_FUNC(sign_toggle_solid), gl_solid->value() ); add_menu_item_bool( &menu_gl_lighting, N_("Lighting"), GTK_SIGNAL_FUNC(sign_toggle_lighting), gl_lighting->value() ); add_menu_item_bool( &menu_gl_smooth, N_("Smooth shading"), GTK_SIGNAL_FUNC(sign_toggle_smooth), gl_smooth->value() ); // Axes item = gtk_menu_item_new(); gtk_menu_append( GTK_MENU(popup), item ); add_menu_item_bool( &menu_axis, N_("Show axis"), GTK_SIGNAL_FUNC(sign_toggle_axis), axis->value() ); add_menu(); gtk_menu_attach_to_widget( GTK_MENU(popup), area, popup_detacher ); gtk_widget_show_all( popup ); } void glview::add_menu_item_bool( GtkWidget **wid, const gchar *text, GtkSignalFunc func, bool state ) { *wid = gtk_check_menu_item_new_with_label( text ); gtk_signal_connect( GTK_OBJECT(*wid), "activate", func, this ); gtk_check_menu_item_set_show_toggle( GTK_CHECK_MENU_ITEM(*wid), TRUE ); GTK_CHECK_MENU_ITEM(*wid)->active = state; gtk_menu_append( GTK_MENU(popup), *wid ); } //****************************************************** // Init //****************************************************** void glview::init_view() { //cout << "\nEnter init... "; cout.flush(); PREF_DEF if ( !gdk_gl_drawable_gl_begin( get_drawable(), get_context() ) ) return; glViewport( 0, 0, (GLint)area->allocation.width, (GLint)area->allocation.height ); if ( pref->line_antialias->value() ) glEnable( GL_LINE_SMOOTH ); //background->set_bkgd(); set_gl_variables(); gdk_gl_drawable_gl_end( get_drawable() ); } //****************************************************** // Reshape //****************************************************** void glview::reshape_view( GdkEventConfigure *ev ) { //cout << "\nEnter shape... "; cout.flush(); if ( !gdk_gl_drawable_gl_begin( get_drawable(), get_context() ) ) return; glViewport( 0, 0, (GLint)(area->allocation.width), (GLint)(area->allocation.height) ); //cout << "Done."; cout.flush(); //cout << "\n\twidth = " << (GLint)(area->allocation.width); //cout << "\n\theight = " << (GLint)(area->allocation.height); //cout.flush(); set_gl_variables(); if ( GTK_IS_WIDGET(get_drawable()) ) background->set_bkgd(); gdk_gl_drawable_gl_end( get_drawable() ); } //****************************************************** // Display //****************************************************** void glview::display_view( GdkEventExpose *event ) { if ( event != NULL ) if ( event->count > 0 ) return; refresh(); } //****************************************************** // Refresh //****************************************************** void glview::refresh() { //cout << "\nEnter refresh...glview "; cout.flush(); if ( ! GTK_WIDGET_REALIZED( area ) ) return; GdkGLDrawable *drawable = get_drawable(); if ( ! GDK_IS_GL_DRAWABLE( drawable ) ) return; if ( ! gdk_gl_drawable_gl_begin( drawable, get_context() ) ) return; background->set_bkgd(); set_gl_variables(); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT ); //cout << "Done."; cout.flush(); gdk_gl_drawable_gl_end( drawable ); } void glview::force_refresh() { OBJLIST_DEF objlist->invalidate_lists(); refresh(); } void glview::invalidate() { GdkRectangle rect; rect.x = 0; rect.y = 0; rect.width = area->allocation.width; rect.height = area->allocation.height; //cout << "\ninvalidate = " << rect.width << " - " << rect.height; cout.flush(); gdk_window_invalidate_rect( area->window, &rect, TRUE ); } //******************************************************* // Set GL Variables //******************************************************* GLfloat ambient[] = { 0.6, 0.6, 0.6, 1.0 }; void glview::set_gl_variables() { if ( gl_solid->value() == false ) glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); else glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE ); GLfloat ambient[] = { 0.2, 0.2, 0.2, 0 }; glLightModelfv( GL_LIGHT_MODEL_AMBIENT, ambient ); //glLightModeli( GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE ); if ( gl_lighting->value() ) glEnable( GL_LIGHTING ); else glDisable( GL_LIGHTING ); if ( gl_smooth->value() ) glShadeModel( GL_SMOOTH ); else glShadeModel( GL_FLAT ); glLineWidth( LINE_WIDTH ); glPointSize( POINT_SIZE ); glEnable( GL_DEPTH_TEST ); glEnable( GL_NORMALIZE ); glDisable( GL_CULL_FACE ); //glEnable( GL_BLEND ); //glBlendFunc( GL_SRC_ALPHA, GL_DST_ALPHA ); } //******************************************************* // Click //******************************************************* void glview::click( GdkEventButton *ev ) { tbar_mouse_click(NULL); VMAN_DEF drag.first_click = true; drag.view = this; drag.rotation = &rotate; switch ( ev->button ) { case 1: { GdkModifierType state; int x,y; gdk_window_get_pointer( ev->window, &x, &y, &state ); drag.origin_x = drag.previous_x = drag.current_x = x; drag.origin_y = drag.previous_y = drag.current_y = y; OBJLIST_DEF float *centre3d, centre2d[2]; Object3D *current = objlist->get_current(); if ( current == NULL ) return; centre3d = current->get_location(); if ( centre3d == NULL ) { drag.center_x = x; drag.center_y = y; } else { project_point( centre2d, centre3d ); drag.center_x = (int)centre2d[0]; drag.center_y = (int)centre2d[1]; } SCENE_DEF scene->set_modified(); if ( vmanager->get_pointer_mode() == TV_PMODE_SELECT && ev->button != 3) { pick_object( ev ); return; } } break; case 3: gtk_menu_popup( GTK_MENU(popup), NULL, NULL, NULL, NULL, ev->button, ev->time ); break; default: break; } } //*************************************************** // Picking //*************************************************** void glview::pick_object( GdkEventButton *ev ) { //cout << "\nTry to select something !"; cout.flush(); OBJLIST_DEF int x,y; GdkModifierType state; gdk_window_get_pointer( ev->window, &x, &y, &state ); GLuint select_buffer[512]; GLint hits; glSelectBuffer( 512, select_buffer ); glRenderMode( GL_SELECT ); glMatrixMode( GL_PROJECTION ); glLoadIdentity(); GLint viewport[4]; glGetIntegerv( GL_VIEWPORT, viewport ); gluPickMatrix( (GLdouble)x, (GLdouble)(viewport[3] - y ), 5.0, 5.0, viewport ); set_viewport(); objlist->init_pick_names(); objlist->display( this ); glMatrixMode( GL_PROJECTION ); glPopMatrix(); glFlush(); bool last = ( state & GDK_SHIFT_MASK ) ? true : false; int selected = -1; float zmin = 100; float zmax = 0; hits = glRenderMode( GL_RENDER ); GLuint names, *ptr; ptr = (GLuint *)select_buffer; for ( int i = 0 ; i < hits ; i++ ) { names = *ptr; //cout << "\n\t\thit n°" << i ; //cout << "\n\t\tnumber of names for this hit = " << names; ptr++; float z1 = (float)*ptr/0x7fffffff; //cout << "\n\t\tz1 is " << (float)*ptr/0x7fffffff; ptr++; //cout << "\n\t\tz2 is " << (float)*ptr/0x7fffffff; ptr++; //cout << "\n\t\tnames are -> "; for ( unsigned int j = 0 ; j < names; j++ ) { //cout << *ptr << ' '; //if ( j == 0 ) selected = *ptr; if ( z1 < zmin && ! last ) { zmin = z1; selected = *ptr; } if ( z1 > zmax && last ) { zmax = z1; selected = *ptr; } ptr++; } } //cout.flush(); if ( selected == -1 ) return; objlist->select_picked( selected ); } //****************************************************** // Draw axis //****************************************************** void glview::draw_axis() { PREF_DEF if ( ! axis_list.exec() ) { axis_list.begin(); glLineWidth( axis_width ); glBegin( GL_LINES ); pref->axis_color->gl_set_rgb(); // Axes glVertex3f( 0, 0, 0 ); glVertex3f( 1, 0, 0 ); glVertex3f( 0, 0, 0 ); glVertex3f( 0, 1, 0 ); glVertex3f( 0, 0, 0 ); glVertex3f( 0, 0, 1 ); glEnd(); glLineWidth( LINE_WIDTH ); axis_list.end(); } } //****************************************************** // Draw grid //****************************************************** void glview::draw_grid( int mode ) { draw_grid( mode, 1.0); } void glview::draw_grid( int mode , float zoom) { int j = 0; PREF_DEF /*if (( ! grid_lists[mode].exec() ) || (old_zoom != zoom)) */ { //grid_lists[mode].begin(); TvWidget_color *collist[3] = { pref->gridxz_color, pref->gridxy_color, pref->gridyz_color }; collist[mode]->gl_set_rgb_for_wireframe(); glLineWidth (0.5); glBegin (GL_LINES); float tmp_coord = 1.1 * zoom; if(tmp_coord < 1.1) tmp_coord = 1.1; /* Trackball offset */ switch( mode ) { default: break; case TV_VIEW_TOP: tmp_coord += ((fabs(lookat->get(0)))>(fabs(lookat->get(2)))?(fabs(lookat->get(0))):(fabs(lookat->get(2)))); break; case TV_VIEW_FRONT: tmp_coord += ((fabs(lookat->get(0)))>(fabs(lookat->get(1)))?(fabs(lookat->get(0))):(fabs(lookat->get(1)))); break; case TV_VIEW_RIGHT: tmp_coord += ((fabs(lookat->get(1)))>(fabs(lookat->get(2)))?(fabs(lookat->get(1))):(fabs(lookat->get(2)))); break; } // some loop-unrolling. :-) Also make sure a "major line" goes along the axis for ( float i = 0.0 ; i < tmp_coord ; i += grid_scale->value() ) { if ( j % grid_major->value() == 0) glColor3f (0.0F, 0.0F, 0.0F); else collist[mode]->gl_set_rgb_for_wireframe(); j++; switch( mode ) { default: case TV_VIEW_TOP: // XZ glVertex3f( i, 0, -tmp_coord ); glVertex3f( i, 0, tmp_coord ); glVertex3f( -tmp_coord, 0, i ); glVertex3f( tmp_coord, 0, i ); glVertex3f( -i, 0, -tmp_coord ); glVertex3f( -i, 0, tmp_coord ); glVertex3f( -tmp_coord, 0, -i ); glVertex3f( tmp_coord, 0, -i ); break; case TV_VIEW_FRONT: // XY glVertex3f( i, -tmp_coord, 0 ); glVertex3f( i, tmp_coord, 0 ); glVertex3f( -tmp_coord, i, 0 ); glVertex3f( tmp_coord, i, 0 ); glVertex3f( -i, -tmp_coord, 0 ); glVertex3f( -i, tmp_coord, 0 ); glVertex3f( -tmp_coord, -i, 0 ); glVertex3f( tmp_coord, -i, 0 ); break; case TV_VIEW_RIGHT: // YZ glVertex3f( 0, -tmp_coord, i ); glVertex3f( 0, tmp_coord, i ); glVertex3f( 0, i, tmp_coord ); glVertex3f( 0, i, -tmp_coord ); glVertex3f( 0, -tmp_coord, -i ); glVertex3f( 0, tmp_coord, -i ); glVertex3f( 0, -i, tmp_coord ); glVertex3f( 0, -i, -tmp_coord ); break; } } glEnd (); //grid_lists[mode].end(); } old_zoom = zoom; } //**************************************************** // Hide / Show //**************************************************** void glview::RollUp() { if ( rolled_up->value() ) { gtk_widget_show_all( frame ); gtk_image_set_from_file( GTK_IMAGE(buttons_gpix[1]), but_pixmaps_fnames[1] ); rolled_up->set( false ); visible = true; tbar_mouse_click( NULL ); } else { gtk_widget_hide_all( frame ); gtk_image_set_from_file( GTK_IMAGE(buttons_gpix[1]), but_pixmaps_fnames[2] ); rolled_up->set( true ); visible = false; } } //**************************************************** // Maximize / Restore //**************************************************** void glview::MaximizeRestore() { VMAN_DEF if ( maximized->value() ) { vmanager->unhide_sisters(); gtk_image_set_from_file( GTK_IMAGE(buttons_gpix[2]), but_pixmaps_fnames[3] ); maximized->set( false ); tbar_mouse_click( NULL ); } else { vmanager->hide_sisters( this, container ); gtk_image_set_from_file( GTK_IMAGE(buttons_gpix[2]), but_pixmaps_fnames[4] ); maximized->set( true ); tbar_mouse_click( NULL ); } } //**************************************************** // Hide + Show //**************************************************** void glview::Hide() { SCENE_DEF scene->set_modified(); gtk_widget_hide_all( tframe ); gtk_widget_hide_all( frame ); visible = false; } void glview::Show() { SCENE_DEF scene->set_modified(); gtk_widget_show_all( tframe ); if ( !rolled_up->value() ) { gtk_widget_show_all( frame ); visible = true; tbar_mouse_click( NULL ); } } //**************************************************** // Mutate //**************************************************** void glview::mutate( GtkWidget *sender ) { if ( sender == menu_view_types[type] ) { return; } SCENE_DEF scene->set_modified(); int new_type = 0; for ( int i = 0 ; i < view_type_num ; i++ ) if ( GTK_CHECK_MENU_ITEM(menu_view_types[i])->active ) new_type = i; change_type( (ViewType)new_type ); } void glview::change_type( ViewType new_type ) { if ( type == new_type ) return; // de la 2D vers une autre 2D if ( new_type != TV_VIEW_3D && type != TV_VIEW_3D && new_type != TV_VIEW_CAMERA && type != TV_VIEW_CAMERA ) { reset_view( new_type ); return; } else { VMAN_DEF vmanager->change_view( this, (ViewType)new_type, container, frame, tframe, maximized->value() ); return; } } //**************************************************** // Project point //**************************************************** bool glview::project_point( float *point2d, float *point3d ) { if ( !gdk_gl_drawable_gl_begin( get_drawable(), get_context() ) ) return false; GLint viewport[4]; GLdouble mvmatrix[16], projmatrix[16]; glGetIntegerv( GL_VIEWPORT, viewport ); glGetDoublev( GL_MODELVIEW_MATRIX, mvmatrix ); glGetDoublev( GL_PROJECTION_MATRIX, projmatrix ); GLdouble winx, winy, winz; bool res = gluProject( (GLdouble)point3d[0], (GLdouble)point3d[0], (GLdouble)point3d[0], mvmatrix, projmatrix, viewport, &winx, &winy, &winz ); point2d[0] = winx; point2d[1] = winy; gdk_gl_drawable_gl_end( get_drawable() ); return res; } //******************************************************* // Save //******************************************************* void glview::save_basics( ofstream & file ) { TvWidget_int wtype( N_("Type"), "TYPE", NULL, app_ref, type ); wtype.save( file ); local_lookat->save( file ); common_lookat->save( file ); file << " ROT"; rotate.save( file ); maximized->save( file ); rolled_up->save( file ); gl_solid->save( file ); gl_smooth->save( file ); //gl_antialias->save( file ); //gl_depthcue->save( file ); gl_lighting->save( file ); axis->save( file ); label->save( file ); grid_scale->save( file ); } bool glview::load_basics( ifstream & file, char *tag ) { if ( local_lookat->load( file, tag ) ) return true; if ( common_lookat->load( file, tag ) ) return true; if ( gl_solid->load( file, tag ) ) return true; if ( gl_smooth->load( file, tag ) ) return true; if ( gl_lighting->load( file, tag ) ) return true; if ( axis->load( file, tag ) ) return true; if ( label->load( file, tag ) ) return true; if ( grid_scale->load( file, tag ) ) return true; if ( ! strcmp( "ROT", tag ) ) { rotate.load( file ); return true; } return false; } void glview::clear( ViewType cl_type ) { PREF_DEF // Paramétres //visible = true; local_lookat->set( 0, 0, 0 ); common_lookat->set( 0, 0, 0 ); lookat = ( pref->nav2D->value() ) ? common_lookat : local_lookat; if ( maximized->value() ) MaximizeRestore(); if ( rolled_up->value() ) RollUp(); gl_solid->set( false ); gl_lighting->set( false ); gl_smooth->set( true ); GTK_CHECK_MENU_ITEM(menu_gl_solid)->active = gl_solid->value(); GTK_CHECK_MENU_ITEM(menu_gl_lighting)->active = gl_lighting->value(); GTK_CHECK_MENU_ITEM(menu_gl_smooth)->active = gl_smooth->value(); GTK_CHECK_MENU_ITEM(menu_axis)->active = axis->value(); axis->set( false ); label->set( false ); if ( !gdk_gl_drawable_gl_begin( get_drawable(), get_context() ) ) return; OBJLIST_DEF objlist->light_disable_all(); gdk_gl_drawable_gl_end( get_drawable() ); } bool glview::handle_base_key_press( GdkEventKey *ev ) { VMAN_DEF switch ( ev->keyval ) { // GL_SOLID case GDK_Z: case GDK_z: gl_solid->toggle(); GTK_CHECK_MENU_ITEM(menu_gl_solid)->active = gl_solid->value(); refresh(); return true; // GL_LIGHT case GDK_L: case GDK_l: gl_lighting->toggle(); GTK_CHECK_MENU_ITEM(menu_gl_lighting)->active = gl_lighting->value(); refresh(); return true; // GL_SMOOTH case GDK_O: case GDK_o: gl_smooth->toggle(); GTK_CHECK_MENU_ITEM(menu_gl_smooth)->active = gl_smooth->value(); refresh(); return true; // GL_AXIS case GDK_A: case GDK_a: axis->toggle(); GTK_CHECK_MENU_ITEM(menu_axis)->active = axis->value(); refresh(); return true; // GL_REFRESH case GDK_E: case GDK_e: force_refresh(); return true; // HOME case GDK_H: case GDK_h: reset_home(); return true; // FRONT case 65457: for ( int i = 0 ; i < view_type_num ; i++ ) GTK_CHECK_MENU_ITEM(menu_view_types[i])->active = ( i == TV_VIEW_FRONT ) ? TRUE : FALSE; change_type( TV_VIEW_FRONT ); return true; // TOP case 65463: for ( int i = 0 ; i < view_type_num ; i++ ) GTK_CHECK_MENU_ITEM(menu_view_types[i])->active = ( i == TV_VIEW_TOP ) ? TRUE : FALSE; change_type( TV_VIEW_TOP ); return true; // RIGHT case 65459: for ( int i = 0 ; i < view_type_num ; i++ ) GTK_CHECK_MENU_ITEM(menu_view_types[i])->active = ( i == TV_VIEW_RIGHT ) ? TRUE : FALSE; change_type( TV_VIEW_RIGHT ); return true; // PERSPECTIVE case 65461: for ( int i = 0 ; i < view_type_num ; i++ ) GTK_CHECK_MENU_ITEM(menu_view_types[i])->active = ( i == TV_VIEW_3D ) ? TRUE : FALSE; change_type( TV_VIEW_3D ); return true; // CAMERA (2) case 65458: for ( int i = 0 ; i < view_type_num ; i++ ) GTK_CHECK_MENU_ITEM(menu_view_types[i])->active = ( i == TV_VIEW_CAMERA ) ? TRUE : FALSE; change_type( TV_VIEW_CAMERA ); return true; // POINTER TRACKBALL case GDK_T: case GDK_t: vmanager->set_pointer_mode( TV_PMODE_TRACKBALL ); break; // POINTER SELECT case GDK_P: case GDK_p: vmanager->set_pointer_mode( TV_PMODE_SELECT ); break; // POINTER SCALE case GDK_S: case GDK_s: vmanager->set_pointer_mode( TV_PMODE_SCALE ); break; // POINTER ROTATE case GDK_R: case GDK_r: vmanager->set_pointer_mode( TV_PMODE_ROTATE ); break; // POINTER TRANSLATE case GDK_M: case GDK_m: vmanager->set_pointer_mode( TV_PMODE_TRANSLATE ); break; default: return false; break; } return false; }