From 66a35d2b466e75604eeaa42b6ff0dfd0e19d2c3b Mon Sep 17 00:00:00 2001 From: Ludovic Pouzenc Date: Sat, 5 Jan 2013 15:55:31 +0000 Subject: - Ajout des dependances de compilation dans le README - Renommage MyGTKGlScene en MyGTKGlSceneWidget - Refactoring du maigre code OpenGL exitant (meilleure ventillation des events) - Modifications cosmétiques (commentaires / indentation / ordre des méthodes...) - Ajout gestion des évènement souris (reste des bugs avec les modifieurs clavier) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: file:///var/svn/2013-gpudataviz/trunk@4 371a6b4a-a258-45f8-9dcc-bdd82ce0ac9d --- src/README | 4 + src/boring_parts.cc | 20 +++++ src/boring_parts.h | 6 +- src/gpudataviz.cc | 184 ++++++++++++++++++++++++++++++------------- src/gtk_win_main.cc | 4 +- src/gtk_win_main.h | 6 +- src/my_gtk_gl_scene.h | 23 ------ src/my_gtk_gl_scene_widget.h | 27 +++++++ 8 files changed, 190 insertions(+), 84 deletions(-) create mode 100644 src/README delete mode 100644 src/my_gtk_gl_scene.h create mode 100644 src/my_gtk_gl_scene_widget.h diff --git a/src/README b/src/README new file mode 100644 index 0000000..f9570a2 --- /dev/null +++ b/src/README @@ -0,0 +1,4 @@ + +# Compilation depedencies +# Tested on Ubuntu 12.04 and 12.10 +# apt-get install pkg-config libgtkglextmm-x11-1.2-dev libgtkmm-2.4-dev diff --git a/src/boring_parts.cc b/src/boring_parts.cc index 5e240c2..3973c23 100644 --- a/src/boring_parts.cc +++ b/src/boring_parts.cc @@ -103,3 +103,23 @@ int initOpenCL() { } #endif /*HAS_OPENCL*/ +bool updateGLProjectionMatrix(Glib::RefPtr glCtx, Glib::RefPtr glWin, int width, int height) { + + GLdouble aspect = (GLdouble) width/height; + + // *** OpenGL BEGIN *** + if (!glWin->gl_begin(glCtx)) return false; + + glViewport(0, 0, width, height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(60.0, aspect, 0.1, 10.0); + glMatrixMode(GL_MODELVIEW); + + glWin->gl_end(); + // *** OpenGL END *** + + return true; + +} + diff --git a/src/boring_parts.h b/src/boring_parts.h index 431a46f..4060f67 100644 --- a/src/boring_parts.h +++ b/src/boring_parts.h @@ -1,4 +1,8 @@ #include +// TODO : only need OpenGL things, not GTK ones for now +#include "gtk_includes.h" + +int initLibs(); #ifdef HAS_OPENCL #include @@ -12,5 +16,5 @@ typedef union { } cl_float4; #endif /*HAS_OPENCL*/ -int initLibs(); +bool updateGLProjectionMatrix(Glib::RefPtr glCtx, Glib::RefPtr glWin, int width, int height); diff --git a/src/gpudataviz.cc b/src/gpudataviz.cc index 6f1ebd0..eef7e5c 100644 --- a/src/gpudataviz.cc +++ b/src/gpudataviz.cc @@ -3,7 +3,7 @@ #include "gpudataviz.h" #include "boring_parts.h" #include "gtk_win_main.h" -#include "my_gtk_gl_scene.h" +#include "my_gtk_gl_scene_widget.h" // Macro to make things readable in main() function #define EXIT_IF_FAIL(val, expr) do { \ @@ -13,6 +13,7 @@ } \ } while(0) +// For understanding the event sequences #define CALL_TRACE do { \ std::cout << "trace " <<__PRETTY_FUNCTION__ << std::endl; \ } while(0) @@ -27,9 +28,9 @@ int main(int argc, char* argv[]) { Gtk::GL::init(argc, argv); // gtkglextmm // Query and print OpenGL version - int glVersionMajor, glVersionMinor; - EXIT_IF_FAIL(1, Gdk::GL::query_version(glVersionMajor, glVersionMinor) ); - std::cout << "OpenGL extension version - " << glVersionMajor << "." << glVersionMinor << std::endl; + int glVersionMajor, glVersionMinor; + EXIT_IF_FAIL(1, Gdk::GL::query_version(glVersionMajor, glVersionMinor) ); + std::cout << "OpenGL extension version - " << glVersionMajor << "." << glVersionMinor << std::endl; // Initialize OpenGL Gdk::GL::ConfigMode glMode = Gdk::GL::MODE_RGB | Gdk::GL::MODE_DEPTH | Gdk::GL::MODE_DOUBLE; @@ -44,7 +45,7 @@ int main(int argc, char* argv[]) { EXIT_IF_FAIL(4, hostWorkMem); // Initialize the OpenGL scene - MyGTKGLScene glScene(glconfig); + MyGTKGLSceneWidget glScene(glconfig); // Instantiate and run the GTK app GTKWinMain gtkwinmain(glScene); @@ -53,28 +54,27 @@ int main(int argc, char* argv[]) { return 0; } -/* MyGTKGLScene implementation +/* MyGTKGLSceneWidget implementation I want to keep interesting code part in this file in natural reading order */ -MyGTKGLScene::MyGTKGLScene(Glib::RefPtr &glconfig) { - CALL_TRACE; - set_gl_capability(glconfig); // Set OpenGL-capability to the widget. +MyGTKGLSceneWidget::MyGTKGLSceneWidget(Glib::RefPtr &glconfig) { + set_gl_capability(glconfig); + Gdk::EventMask mask = Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK; + set_events(mask); // The containing window should have those attributes too } -MyGTKGLScene::~MyGTKGLScene() { - CALL_TRACE; -} +MyGTKGLSceneWidget::~MyGTKGLSceneWidget() { } -void MyGTKGLScene::on_size_request(Gtk::Requisition* requisition) { - CALL_TRACE; - - *requisition = Gtk::Requisition(); - requisition->width = 320; requisition->height = 240; +void MyGTKGLSceneWidget::on_size_request(Gtk::Requisition* requisition) { + CALL_TRACE; // Technical stuff : GTK call this to ask the widget minimal size + *requisition = Gtk::Requisition(); + requisition->width = 320; requisition->height = 240; } -void MyGTKGLScene::on_realize() { - CALL_TRACE; // This run once at window creation time +void MyGTKGLSceneWidget::on_realize() { + CALL_TRACE; // This one runs once at window creation time + // It's time to setup GL things that don't change on each frame Gtk::DrawingArea::on_realize(); Glib::RefPtr glwindow = get_gl_window(); @@ -85,12 +85,14 @@ void MyGTKGLScene::on_realize() { return; } + // Programmatically create rendering lists : opengl will able to replay that efficiently GLUquadricObj* qobj = gluNewQuadric(); gluQuadricDrawStyle(qobj, GLU_FILL); glNewList(1, GL_COMPILE); gluSphere(qobj, 1.0, 20, 20); glEndList(); + // Setup scene envrionnement static GLfloat light_diffuse[] = {1.0, 0.0, 0.0, 1.0}; static GLfloat light_position[] = {1.0, 1.0, 1.0, 0.0}; glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); @@ -101,69 +103,139 @@ void MyGTKGLScene::on_realize() { glClearColor(1.0, 1.0, 1.0, 1.0); glClearDepth(1.0); -/* - glViewport(0, 0, get_width(), get_height()); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluPerspective(40.0, 1.0, 1.0, 10.0); - glMatrixMode(GL_MODELVIEW); -*/ - glLoadIdentity(); - gluLookAt(0.0, 0.0, 3.0, - 0.0, 0.0, 0.0, - 0.0, 1.0, 0.0); - glTranslatef(0.0, 0.0, -3.0); - + + // Projection setup is done at on_configure_event + // Camera setup (ie initial MODELVIEW matrix) is done at on_expose_event + glwindow->gl_end(); // *** OpenGL END *** } -bool MyGTKGLScene::on_configure_event(GdkEventConfigure* event) { - CALL_TRACE ; // This run mainly when GTK GL Widget is resized +bool MyGTKGLSceneWidget::on_configure_event(GdkEventConfigure* event) { + CALL_TRACE ; // This one runs mainly when GTK GL Widget is resized + // See boring_parts.cc. In short : gluPerspective(60.0, aspect, 0.1, 10.0); + return updateGLProjectionMatrix(get_gl_context(), get_gl_window(), get_width(), get_height()); +} + +bool MyGTKGLSceneWidget::on_expose_event(GdkEventExpose* event) { + CALL_TRACE ; // This one runs mainly when GTK GL Widget have to be redrawn Glib::RefPtr glwindow = get_gl_window(); + // *** OpenGL BEGIN *** if (!glwindow->gl_begin(get_gl_context())) { std::cerr << "Oups : glwindow->gl_begin(get_gl_context())" << std::endl; return false; } - int width = get_width(); - int height = get_height(); - GLdouble ratio = (GLdouble) width/height; - glViewport(0, 0, width, height); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluPerspective(60.0, ratio, 0.1, 10.0); + //Camera position update glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt(0.0, 0.0, 3.0, + 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0); + glTranslatef(0.0, 0.0, -3.0); + + // Drawing all the stuff + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glCallList(1); glwindow->gl_end(); // *** OpenGL END *** + glwindow->swap_buffers(); // Display the rendered image + return true; } -bool MyGTKGLScene::on_expose_event(GdkEventExpose* event) { - CALL_TRACE ; // This run mainly when GTK GL Widget have to be redrawn +bool MyGTKGLSceneWidget::on_motion_notify_event (GdkEventMotion *event) { + return do_mouse_logic(event->type, event->state, event->x, event->y); +} - Glib::RefPtr glwindow = get_gl_window(); +bool MyGTKGLSceneWidget::on_button_press_event(GdkEventButton *event) { + return do_mouse_logic(event->type, event->state, event->x, event->y); +} - // *** OpenGL BEGIN *** - if (!glwindow->gl_begin(get_gl_context())) { - std::cerr << "Oups : glwindow->gl_begin(get_gl_context())" << std::endl; - return false; +bool MyGTKGLSceneWidget::on_button_release_event(GdkEventButton *event) { + return do_mouse_logic(event->type, event->state, event->x, event->y); +} + +#define KEYBOARD_MODIFIERS ( \ + GDK_SHIFT_MASK | GDK_LOCK_MASK | GDK_CONTROL_MASK \ + | GDK_SUPER_MASK | GDK_HYPER_MASK | GDK_META_MASK \ +) +/* | GDK_MOD1_MASK | GDK_MOD2_MASK | GDK_MOD3_MASK | GDK_MOD4_MASK |GDK_MOD5_MASK \ */ + +#define MOUSE_CLIC(button, allowed_modifier_mask) if ( \ + type == GDK_BUTTON_RELEASE \ + && ( state & button ) == button \ + && ( ( state & KEYBOARD_MODIFIERS ) & ~allowed_modifier_mask ) == 0 \ +) +#define MOUSE_DOUBLECLIC(state_mask) if ( \ + type == GDK_BUTTON_RELEASE \ + && ( state & state_mask ) == state_mask \ + && prev_type == GDK_2BUTTON_PRESS \ +) +#define MOUSE_DRAGING(state_mask) if ( \ + ( type == GDK_BUTTON_PRESS || type == GDK_MOTION_NOTIFY ) \ + && ( state & state_mask ) == state_mask \ +) +#define MOUSE_DRAG_END(state_mask) if ( \ + type == GDK_BUTTON_RELEASE \ + && ( state & state_mask ) == state_mask \ +) + +bool MyGTKGLSceneWidget::do_mouse_logic(GdkEventType type, guint state, guint x, guint y) { +/* + * type : the type of the event. + * Simple motion : GDK_MOTION_NOTIFY (3) + * Simple clic : GDK_BUTTON_PRESS then GDK_BUTTON_RELEASE (4 then 7) + * Double clic : GDK_BUTTON_PRESS, GDK_BUTTON_RELEASE, GDK_BUTTON_PRESS, GDK_2BUTTON_PRESS, GDK_BUTTON_RELEASE (4 7 4 5 7) + * + * stat : a bit-mask representing the state of the modifier keys and the pointer buttons. + * GDK_BUTTON1_MASK, ... , GDK_BUTTON5_MASK (mouse buttons) + * GDK_SHIFT_MASK, GDK_LOCK_MASK, GDK_CONTROL_MASK (keyboard standard modifier keys) + * GDK_MOD1_MASK, ... (normally MOD1 it is the Alt key) + * GDK_SUPER_MASK, GDK_HYPER_MASK, GDK_META_MASK (extra keybord modifier keys) + */ + static GdkEventType prev_type = GDK_NOTHING; +// static guint prev_state= 0; // Empty mask +// + std::cout << "event type " << type << " state " << state << " on (" << x << "," << y << ") " << std::endl; +// std::cout << "DEBUG ( state & KEYBOARD_MODIFIERS ) == " << ( state & KEYBOARD_MODIFIERS ) << std::endl; + + + /* *** BEGIN event filtering *** */ + MOUSE_DOUBLECLIC(GDK_BUTTON1_MASK) { + std::cout << "Mouse 1 double clic" << std::endl; } - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glCallList(1); + MOUSE_DRAGING(GDK_BUTTON2_MASK) { + std::cout << "Mouse 2 dragging" << " on (" << x << "," << y << ") " << std::endl; + } - glwindow->gl_end(); - // *** OpenGL END *** + MOUSE_CLIC(GDK_BUTTON3_MASK, 0) { + std::cout << "Mouse 3 clic without any key modifier" << std::endl; + } + + //FIXME : this is buggy !!! + MOUSE_CLIC(GDK_BUTTON3_MASK, GDK_SHIFT_MASK) { + std::cout << "Mouse 3 clic with shift or control" << std::endl; + } - // Display the rendered image - glwindow->swap_buffers(); + /* *** END event filtering *** */ + + // Previous button event retention for double-clic filtering + switch(type) { + case GDK_BUTTON_PRESS: + case GDK_BUTTON_RELEASE: + case GDK_2BUTTON_PRESS: + prev_type=type; +// prev_state=state; + break; + default: + break; + } return true; } - diff --git a/src/gtk_win_main.cc b/src/gtk_win_main.cc index eca9df0..8997b56 100644 --- a/src/gtk_win_main.cc +++ b/src/gtk_win_main.cc @@ -1,7 +1,7 @@ #include "gtk_win_main.h" -GTKWinMain::GTKWinMain(MyGTKGLScene &glScene) +GTKWinMain::GTKWinMain(MyGTKGLSceneWidget &glScene) : m_VBox(false, 0), m_ButtonQuit("Quit"), m_GLScene(glScene) { set_title(WIN_MAIN_TITLE); @@ -14,6 +14,8 @@ GTKWinMain::GTKWinMain(MyGTKGLScene &glScene) // Link signal handlers on events m_ButtonQuit.signal_clicked().connect( sigc::mem_fun(*this, >KWinMain::on_button_quit_clicked) ); + Gdk::EventMask mask = Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK; + set_events(mask); show_all(); } diff --git a/src/gtk_win_main.h b/src/gtk_win_main.h index ab14a4a..c377040 100644 --- a/src/gtk_win_main.h +++ b/src/gtk_win_main.h @@ -1,12 +1,12 @@ #include "gtk_includes.h" -#include "my_gtk_gl_scene.h" +#include "my_gtk_gl_scene_widget.h" #define WIN_MAIN_TITLE "GPU Data Viz v0.1" class GTKWinMain : public Gtk::Window { public: - GTKWinMain(MyGTKGLScene &glScene); + GTKWinMain(MyGTKGLSceneWidget &glScene); virtual ~GTKWinMain(); protected: @@ -17,5 +17,5 @@ class GTKWinMain : public Gtk::Window // member widgets Gtk::VBox m_VBox; Gtk::Button m_ButtonQuit; - MyGTKGLScene & m_GLScene; + MyGTKGLSceneWidget & m_GLScene; }; diff --git a/src/my_gtk_gl_scene.h b/src/my_gtk_gl_scene.h deleted file mode 100644 index dc8afbe..0000000 --- a/src/my_gtk_gl_scene.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef MY_GTK_GL_SCENE_H -#define MY_GTK_GL_SCENE_H - -#include "gtk_includes.h" - -// Class that will contain all the OpenGL logic for displaying the OpenCL computed data -// Implementation is kept in gpudataviz.cc (I want to keep interesting code part in this file) - -// TODO : rename it to MyGTKGLSceneWidget -class MyGTKGLScene : public Gtk::DrawingArea, public Gtk::GL::Widget -{ - public: - MyGTKGLScene(Glib::RefPtr &glconfig); - virtual ~MyGTKGLScene(); - - protected: - virtual void on_size_request(Gtk::Requisition* requisition); - virtual void on_realize(); - virtual bool on_configure_event(GdkEventConfigure* event); - virtual bool on_expose_event(GdkEventExpose* event); -}; - -#endif /*MY_GTK_GL_SCENE_H*/ diff --git a/src/my_gtk_gl_scene_widget.h b/src/my_gtk_gl_scene_widget.h new file mode 100644 index 0000000..8445252 --- /dev/null +++ b/src/my_gtk_gl_scene_widget.h @@ -0,0 +1,27 @@ +#ifndef MY_GTK_GL_SCENE_H +#define MY_GTK_GL_SCENE_H + +#include "gtk_includes.h" + +// Class that will contain all the OpenGL logic for displaying the OpenCL computed data +// Implementation is kept in gpudataviz.cc (I want to keep interesting code part in this file) + +class MyGTKGLSceneWidget : public Gtk::DrawingArea, public Gtk::GL::Widget +{ + public: + MyGTKGLSceneWidget(Glib::RefPtr &glconfig); + virtual ~MyGTKGLSceneWidget(); + + protected: + virtual void on_size_request(Gtk::Requisition* requisition); + virtual void on_realize(); + virtual bool on_configure_event(GdkEventConfigure* event); + virtual bool on_expose_event(GdkEventExpose* event); + virtual bool on_motion_notify_event (GdkEventMotion *event); + virtual bool on_button_press_event(GdkEventButton *event); + virtual bool on_button_release_event(GdkEventButton *event); + + bool do_mouse_logic(GdkEventType type, guint state, guint x, guint y); +}; + +#endif /*MY_GTK_GL_SCENE_H*/ -- cgit v1.2.3