Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Examples

logo.cc

GtkGLExt logo demo.
// -*- C++ -*- /* * logo.cc: * GtkGLExt logo demo. * * written by Naofumi Yasufuku <naofumi@users.sourceforge.net> */ #include <iostream> #include <cstdlib> #include <cstring> #include <cmath> #include <GL/gl.h> #include <GL/glu.h> #ifdef G_OS_WIN32 #define WIN32_LEAN_AND_MEAN 1 #include <windows.h> #endif #include "logo.h" // // logo_draw_*() functions. // namespace LogoModel { #include "logo-model.h" } // // Trackball utilities. // namespace Trackball { extern "C" { #include "trackball.h" } } #define DIG_2_RAD (G_PI / 180.0) #define RAD_2_DIG (180.0 / G_PI) // // OpenGL frame buffer configuration utilities. // struct GLConfigUtil { static void print_gl_attrib(const Glib::RefPtr<const Gdk::GL::Config>& glconfig, const char* attrib_str, int attrib, bool is_boolean); static void examine_gl_attrib(const Glib::RefPtr<const Gdk::GL::Config>& glconfig); }; // // Print a configuration attribute. // void GLConfigUtil::print_gl_attrib(const Glib::RefPtr<const Gdk::GL::Config>& glconfig, const char* attrib_str, int attrib, bool is_boolean) { int value; if (glconfig->get_attrib(attrib, value)) { std::cout << attrib_str << " = "; if (is_boolean) std::cout << (value == true ? "true" : "false") << std::endl; else std::cout << value << std::endl; } else { std::cout << "*** Cannot get " << attrib_str << " attribute value\n"; } } // // Print configuration attributes. // void GLConfigUtil::examine_gl_attrib(const Glib::RefPtr<const Gdk::GL::Config>& glconfig) { std::cout << "\nOpenGL visual configurations :\n\n"; std::cout << "glconfig->is_rgba() = " << (glconfig->is_rgba() ? "true" : "false") << std::endl; std::cout << "glconfig->is_double_buffered() = " << (glconfig->is_double_buffered() ? "true" : "false") << std::endl; std::cout << "glconfig->is_stereo() = " << (glconfig->is_stereo() ? "true" : "false") << std::endl; std::cout << "glconfig->has_alpha() = " << (glconfig->has_alpha() ? "true" : "false") << std::endl; std::cout << "glconfig->has_depth_buffer() = " << (glconfig->has_depth_buffer() ? "true" : "false") << std::endl; std::cout << "glconfig->has_stencil_buffer() = " << (glconfig->has_stencil_buffer() ? "true" : "false") << std::endl; std::cout << "glconfig->has_accum_buffer() = " << (glconfig->has_accum_buffer() ? "true" : "false") << std::endl; std::cout << std::endl; print_gl_attrib(glconfig, "Gdk::GL::USE_GL", Gdk::GL::USE_GL, true); print_gl_attrib(glconfig, "Gdk::GL::BUFFER_SIZE", Gdk::GL::BUFFER_SIZE, false); print_gl_attrib(glconfig, "Gdk::GL::LEVEL", Gdk::GL::LEVEL, false); print_gl_attrib(glconfig, "Gdk::GL::RGBA", Gdk::GL::RGBA, true); print_gl_attrib(glconfig, "Gdk::GL::DOUBLEBUFFER", Gdk::GL::DOUBLEBUFFER, true); print_gl_attrib(glconfig, "Gdk::GL::STEREO", Gdk::GL::STEREO, true); print_gl_attrib(glconfig, "Gdk::GL::AUX_BUFFERS", Gdk::GL::AUX_BUFFERS, false); print_gl_attrib(glconfig, "Gdk::GL::RED_SIZE", Gdk::GL::RED_SIZE, false); print_gl_attrib(glconfig, "Gdk::GL::GREEN_SIZE", Gdk::GL::GREEN_SIZE, false); print_gl_attrib(glconfig, "Gdk::GL::BLUE_SIZE", Gdk::GL::BLUE_SIZE, false); print_gl_attrib(glconfig, "Gdk::GL::ALPHA_SIZE", Gdk::GL::ALPHA_SIZE, false); print_gl_attrib(glconfig, "Gdk::GL::DEPTH_SIZE", Gdk::GL::DEPTH_SIZE, false); print_gl_attrib(glconfig, "Gdk::GL::STENCIL_SIZE", Gdk::GL::STENCIL_SIZE, false); print_gl_attrib(glconfig, "Gdk::GL::ACCUM_RED_SIZE", Gdk::GL::ACCUM_RED_SIZE, false); print_gl_attrib(glconfig, "Gdk::GL::ACCUM_GREEN_SIZE", Gdk::GL::ACCUM_GREEN_SIZE, false); print_gl_attrib(glconfig, "Gdk::GL::ACCUM_BLUE_SIZE", Gdk::GL::ACCUM_BLUE_SIZE, false); print_gl_attrib(glconfig, "Gdk::GL::ACCUM_ALPHA_SIZE", Gdk::GL::ACCUM_ALPHA_SIZE, false); std::cout << std::endl; } // // Logo classes. // namespace Logo { // // View class implementation. // const float View::NEAR_CLIP = 2.0; const float View::FAR_CLIP = 60.0; const float View::INIT_POS_X = 0.0; const float View::INIT_POS_Y = 0.0; const float View::INIT_POS_Z = -30.0; const float View::INIT_AXIS_X = 1.0; const float View::INIT_AXIS_Y = 0.0; const float View::INIT_AXIS_Z = 0.0; const float View::INIT_ANGLE = 20.0; const float View::INIT_SCALE = 1.0; const float View::SCALE_MAX = 2.0; const float View::SCALE_MIN = 0.5; View::View() : m_Scale(INIT_SCALE), m_BeginX(0.0), m_BeginY(0.0) { reset(); } View::~View() { } void View::frustum(int w, int h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (w > h) { float aspect = static_cast<float>(w) / static_cast<float>(h); glFrustum(-aspect, aspect, -1.0, 1.0, NEAR_CLIP, FAR_CLIP); } else { float aspect = static_cast<float>(h) / static_cast<float>(w); glFrustum(-1.0, 1.0, -aspect, aspect, NEAR_CLIP, FAR_CLIP); } glMatrixMode(GL_MODELVIEW); } void View::xform() { glTranslatef(m_Pos[0], m_Pos[1], m_Pos[2]); glScalef(m_Scale, m_Scale, m_Scale); float m[4][4]; Trackball::build_rotmatrix(m, m_Quat); glMultMatrixf(&m[0][0]); } void View::reset() { m_Pos[0] = INIT_POS_X; m_Pos[1] = INIT_POS_Y; m_Pos[2] = INIT_POS_Z; float sine = sin(0.5 * INIT_ANGLE * DIG_2_RAD); m_Quat[0] = INIT_AXIS_X * sine; m_Quat[1] = INIT_AXIS_Y * sine; m_Quat[2] = INIT_AXIS_Z * sine; m_Quat[3] = cos(0.5 * INIT_ANGLE * DIG_2_RAD); m_Scale = INIT_SCALE; } bool View::on_button_press_event(GdkEventButton* event, Scene* scene) { m_BeginX = event->x; m_BeginY = event->y; // don't block return false; } bool View::on_motion_notify_event(GdkEventMotion* event, Scene* scene) { if (scene == 0) return false; float w = scene->get_width(); float h = scene->get_height(); float x = event->x; float y = event->y; float d_quat[4]; bool redraw = false; // Rotation. if (event->state & GDK_BUTTON1_MASK) { Trackball::trackball(d_quat, (2.0 * m_BeginX - w) / w, (h - 2.0 * m_BeginY) / h, (2.0 * x - w) / w, (h - 2.0 * y) / h); Trackball::add_quats(d_quat, m_Quat, m_Quat); redraw = true; } // Scaling. if (event->state & GDK_BUTTON2_MASK) { m_Scale = m_Scale * (1.0 + (y - m_BeginY) / h); if (m_Scale > SCALE_MAX) m_Scale = SCALE_MAX; else if (m_Scale < SCALE_MIN) m_Scale = SCALE_MIN; redraw = true; } m_BeginX = x; m_BeginY = y; if (redraw && !scene->anim_is_enabled()) scene->invalidate(); // don't block return false; } // // Model class implementation. // const float Model::MAT_SPECULAR[4] = { 0.5, 0.5, 0.5, 1.0 }; const float Model::MAT_SHININESS[1] = { 10.0 }; const float Model::MAT_BLACK[4] = { 0.0, 0.0, 0.0, 1.0 }; const float Model::MAT_RED[4] = { 1.0, 0.0, 0.0, 1.0 }; const float Model::MAT_GREEN[4] = { 0.0, 1.0, 0.0, 1.0 }; const float Model::MAT_BLUE[4] = { 0.0, 0.0, 1.0, 1.0 }; const unsigned int Model::DEFAULT_ROT_COUNT = 100; static float AXIS_X[3] = { 1.0, 0.0, 0.0 }; static float AXIS_Y[3] = { 0.0, 1.0, 0.0 }; static float AXIS_Z[3] = { 0.0, 0.0, 1.0 }; const Model::RotMode Model::ROT_MODE[] = { { AXIS_X, 1.0 }, { AXIS_Y, 1.0 }, { AXIS_X, 1.0 }, { AXIS_Z, 1.0 }, { AXIS_X, 1.0 }, { AXIS_Y, -1.0 }, { AXIS_X, 1.0 }, { AXIS_Z, -1.0 }, { 0, 0.0 } // terminator }; Model::Model(unsigned int rot_count, bool enable_anim) : m_RotCount(rot_count), m_EnableAnim(enable_anim), m_Mode(0), m_Counter(0) { reset_anim(); } Model::~Model() { } void Model::init_gl() { glEnable(GL_CULL_FACE); glPushMatrix(); glMaterialfv(GL_FRONT, GL_SPECULAR, MAT_SPECULAR); glMaterialfv(GL_FRONT, GL_SHININESS, MAT_SHININESS); /* Center black cube. */ glNewList(CUBE, GL_COMPILE); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, MAT_BLACK); LogoModel::logo_draw_cube(); glEndList(); /* Forward "G". */ glNewList(G_FORWARD, GL_COMPILE); glDisable(GL_CULL_FACE); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, MAT_BLUE); LogoModel::logo_draw_g_plane(); glEnable(GL_CULL_FACE); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, MAT_BLACK); LogoModel::logo_draw_g(); glEndList(); /* Backward "G". */ glNewList(G_BACKWARD, GL_COMPILE); glPushMatrix(); glRotatef(180.0, 1.0, 0.0, 0.0); glDisable(GL_CULL_FACE); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, MAT_BLUE); LogoModel::logo_draw_g_plane(); glEnable(GL_CULL_FACE); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, MAT_BLACK); LogoModel::logo_draw_g(); glPopMatrix(); glEndList(); /* Forward "T". */ glNewList(T_FORWARD, GL_COMPILE); glDisable(GL_CULL_FACE); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, MAT_RED); LogoModel::logo_draw_t_plane(); glEnable(GL_CULL_FACE); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, MAT_BLACK); LogoModel::logo_draw_t(); glEndList(); /* Backward "T". */ glNewList(T_BACKWARD, GL_COMPILE); glPushMatrix(); glRotatef(180.0, 1.0, 0.0, 0.0); glDisable(GL_CULL_FACE); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, MAT_RED); LogoModel::logo_draw_t_plane(); glEnable(GL_CULL_FACE); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, MAT_BLACK); LogoModel::logo_draw_t(); glPopMatrix(); glEndList(); /* Forward "K". */ glNewList(K_FORWARD, GL_COMPILE); glDisable(GL_CULL_FACE); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, MAT_GREEN); LogoModel::logo_draw_k_plane(); glEnable(GL_CULL_FACE); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, MAT_BLACK); LogoModel::logo_draw_k(); glEndList(); /* Backward "K". */ glNewList(K_BACKWARD, GL_COMPILE); glPushMatrix(); glRotatef(180.0, 0.0, 0.0, 1.0); glDisable(GL_CULL_FACE); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, MAT_GREEN); LogoModel::logo_draw_k_plane(); glEnable(GL_CULL_FACE); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, MAT_BLACK); LogoModel::logo_draw_k(); glPopMatrix(); glEndList(); glPopMatrix(); glEnable(GL_NORMALIZE); } void Model::draw() { // Init GL context. static bool initialized = false; if (!initialized) { init_gl(); initialized = true; } // Animation. if (m_EnableAnim) { if (m_Counter == m_RotCount) { if (ROT_MODE[++m_Mode].axis == 0) m_Mode = 0; m_Counter = 0; } float d_quat[4]; Trackball::axis_to_quat(ROT_MODE[m_Mode].axis, ROT_MODE[m_Mode].sign * G_PI_2 / m_RotCount, d_quat); Trackball::add_quats(d_quat, m_Quat, m_Quat); ++m_Counter; } // Draw logo model. glPushMatrix(); glTranslatef(m_Pos[0], m_Pos[1], m_Pos[2]); float m[4][4]; Trackball::build_rotmatrix(m, m_Quat); glMultMatrixf(&m[0][0]); glRotatef(90.0, 1.0, 0.0, 0.0); glCallList(CUBE); glCallList(G_FORWARD); glCallList(G_BACKWARD); glCallList(T_FORWARD); glCallList(T_BACKWARD); glCallList(K_FORWARD); glCallList(K_BACKWARD); glPopMatrix(); } void Model::reset_anim() { m_Pos[0] = 0.0; m_Pos[1] = 0.0; m_Pos[2] = 0.0; m_Quat[0] = 0.0; m_Quat[1] = 0.0; m_Quat[2] = 0.0; m_Quat[3] = 1.0; m_Mode = 0; m_Counter = 0; } // // Scene class implementation. // const unsigned int Scene::TIMEOUT_INTERVAL = 10; const float Scene::CLEAR_COLOR[4] = { 0.5, 0.5, 0.8, 1.0 }; const float Scene::CLEAR_DEPTH = 1.0; const float Scene::LIGHT0_POSITION[4] = { 0.0, 0.0, 30.0, 0.0 }; const float Scene::LIGHT0_DIFFUSE[4] = { 1.0, 1.0, 1.0, 1.0 }; const float Scene::LIGHT0_SPECULAR[4] = { 1.0, 1.0, 1.0, 1.0 }; Scene::Scene(unsigned int rot_count, bool enable_anim) : m_Menu(0), m_Model(rot_count, enable_anim) { // // Configure OpenGL-capable visual. // Glib::RefPtr<Gdk::GL::Config> glconfig; // Try double-buffered visual glconfig = Gdk::GL::Config::create(Gdk::GL::MODE_RGB | Gdk::GL::MODE_DEPTH | Gdk::GL::MODE_DOUBLE); if (!glconfig) { std::cerr << "*** Cannot find the double-buffered visual.\n" << "*** Trying single-buffered visual.\n"; // Try single-buffered visual glconfig = Gdk::GL::Config::create(Gdk::GL::MODE_RGB | Gdk::GL::MODE_DEPTH); if (!glconfig) { std::cerr << "*** Cannot find any OpenGL-capable visual.\n"; std::exit(1); } } // print frame buffer attributes. GLConfigUtil::examine_gl_attrib(glconfig); // // Set OpenGL-capability to the widget. // set_gl_capability(glconfig); // // Add events. // add_events(Gdk::BUTTON1_MOTION_MASK | Gdk::BUTTON2_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::VISIBILITY_NOTIFY_MASK); // View transformation signals. signal_button_press_event().connect( sigc::bind(sigc::mem_fun(m_View, &View::on_button_press_event), this)); signal_motion_notify_event().connect( sigc::bind(sigc::mem_fun(m_View, &View::on_motion_notify_event), this)); // // Popup menu. // m_Menu = create_popup_menu(); } Scene::~Scene() { } void Scene::on_realize() { // We need to call the base on_realize() Gtk::DrawingArea::on_realize(); // // Get GL::Drawable. // Glib::RefPtr<Gdk::GL::Drawable> gldrawable = get_gl_drawable(); // // GL calls. // // *** OpenGL BEGIN *** if (!gldrawable->gl_begin(get_gl_context())) return; glClearColor(CLEAR_COLOR[0], CLEAR_COLOR[1], CLEAR_COLOR[2], CLEAR_COLOR[3]); glClearDepth(CLEAR_DEPTH); glLightfv(GL_LIGHT0, GL_POSITION, LIGHT0_POSITION); glLightfv(GL_LIGHT0, GL_DIFFUSE, LIGHT0_DIFFUSE); glLightfv(GL_LIGHT0, GL_SPECULAR, LIGHT0_SPECULAR); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_DEPTH_TEST); glShadeModel(GL_SMOOTH); gldrawable->gl_end(); // *** OpenGL END *** } bool Scene::on_configure_event(GdkEventConfigure* event) { // // Get GL::Drawable. // Glib::RefPtr<Gdk::GL::Drawable> gldrawable = get_gl_drawable(); // // GL calls. // // *** OpenGL BEGIN *** if (!gldrawable->gl_begin(get_gl_context())) return false; m_View.frustum(get_width(), get_height()); gldrawable->gl_end(); // *** OpenGL END *** return true; } bool Scene::on_expose_event(GdkEventExpose* event) { // // Get GL::Drawable. // Glib::RefPtr<Gdk::GL::Drawable> gldrawable = get_gl_drawable(); // // GL calls. // // *** OpenGL BEGIN *** if (!gldrawable->gl_begin(get_gl_context())) return false; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); // View transformation. m_View.xform(); // Logo model. m_Model.draw(); // Swap buffers. if (gldrawable->is_double_buffered()) gldrawable->swap_buffers(); else glFlush(); gldrawable->gl_end(); // *** OpenGL END *** return true; } bool Scene::on_button_press_event(GdkEventButton* event) { if (event->button == 3) { m_Menu->popup(event->button, event->time); return true; } // don't block return false; } bool Scene::on_map_event(GdkEventAny* event) { if (m_Model.anim_is_enabled()) timeout_add(); return true; } bool Scene::on_unmap_event(GdkEventAny* event) { timeout_remove(); return true; } bool Scene::on_visibility_notify_event(GdkEventVisibility* event) { if (m_Model.anim_is_enabled()) { if (event->state == GDK_VISIBILITY_FULLY_OBSCURED) timeout_remove(); else timeout_add(); } return true; } bool Scene::on_timeout() { // Invalidate whole window. invalidate(); // Update window synchronously (fast). update(); return true; } void Scene::timeout_add() { if (!m_ConnectionTimeout.connected()) m_ConnectionTimeout = Glib::signal_timeout().connect( sigc::mem_fun(*this, &Scene::on_timeout), TIMEOUT_INTERVAL); } void Scene::timeout_remove() { if (m_ConnectionTimeout.connected()) m_ConnectionTimeout.disconnect(); } void Scene::toggle_anim() { if (m_Model.anim_is_enabled()) { m_Model.disable_anim(); timeout_remove(); } else { m_Model.enable_anim(); timeout_add(); } } void Scene::init_anim() { m_View.reset(); m_Model.reset_anim(); invalidate(); } Gtk::Menu* Scene::create_popup_menu() { Gtk::Menu* menu = Gtk::manage(new Gtk::Menu()); Gtk::Menu::MenuList& menu_list = menu->items(); // Toggle animation menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Toggle Animation", sigc::mem_fun(*this, &Scene::toggle_anim))); // Init orientation menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Initialize", sigc::mem_fun(*this, &Scene::init_anim))); // Quit menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Quit", sigc::ptr_fun(&Gtk::Main::quit))); return menu; } // // Application class implementation. // const Glib::ustring Application::APP_NAME = "Logo"; Application::Application(unsigned int rot_count, bool enable_anim) : m_VBox(false, 0), m_Scene(rot_count, enable_anim), m_ButtonQuit("Quit") { // // Top-level window. // set_title(APP_NAME); // Get automatically redrawn if any of their children changed allocation. set_reallocate_redraws(true); add(m_VBox); // // Application scene. // m_Scene.set_size_request(300, 300); m_VBox.pack_start(m_Scene); // // Simple quit button. // m_ButtonQuit.signal_clicked().connect( sigc::mem_fun(*this, &Application::on_button_quit_clicked)); m_VBox.pack_start(m_ButtonQuit, Gtk::PACK_SHRINK, 0); // // Show window. // show_all(); } Application::~Application() { } void Application::on_button_quit_clicked() { Gtk::Main::quit(); } bool Application::on_key_press_event(GdkEventKey* event) { switch (event->keyval) { case GDK_a: m_Scene.toggle_anim(); break; case GDK_i: m_Scene.init_anim(); break; case GDK_Escape: Gtk::Main::quit(); break; default: return true; } m_Scene.invalidate(); return true; } } // namespace Logo // // Main. // int main(int argc, char** argv) { Gtk::Main kit(argc, argv); // // Init gtkglextmm. // Gtk::GL::init(argc, argv); // // Parse arguments. // unsigned int rot_count = Logo::Model::DEFAULT_ROT_COUNT; bool enable_anim = true; bool arg_count = false; for (int i = 1; i < argc; ++i) { if (arg_count) rot_count = std::atoi(argv[i]); if (std::strcmp(argv[i], "--help") == 0 || std::strcmp(argv[i], "-h") == 0) { std::cerr << "Usage: " << argv[0] << " [-count num] [-noanim] [--help]\n"; std::exit(0); } if (std::strcmp(argv[i], "-count") == 0) arg_count = true; if (std::strcmp(argv[i], "-noanim") == 0) enable_anim = false; } // // Query OpenGL extension version. // int major, minor; Gdk::GL::query_version(major, minor); std::cout << "OpenGL extension version - " << major << "." << minor << std::endl; // // Instantiate and run the application. // Logo::Application application(rot_count, enable_anim); kit.run(application); return 0; }
00001 // -*- C++ -*- 00002 /* 00003 * logo.cc: 00004 * GtkGLExt logo demo. 00005 * 00006 * written by Naofumi Yasufuku <naofumi@users.sourceforge.net> 00007 */ 00008 00009 #include <iostream> 00010 #include <cstdlib> 00011 #include <cstring> 00012 #include <cmath> 00013 00014 #include <GL/gl.h> 00015 #include <GL/glu.h> 00016 00017 #ifdef G_OS_WIN32 00018 #define WIN32_LEAN_AND_MEAN 1 00019 #include <windows.h> 00020 #endif 00021 00022 #include "logo.h" 00023 00024 // 00025 // logo_draw_*() functions. 00026 // 00027 namespace LogoModel { 00028 #include "logo-model.h" 00029 } 00030 00031 // 00032 // Trackball utilities. 00033 // 00034 namespace Trackball { 00035 extern "C" { 00036 #include "trackball.h" 00037 } 00038 } 00039 00040 #define DIG_2_RAD (G_PI / 180.0) 00041 #define RAD_2_DIG (180.0 / G_PI) 00042 00043 00045 // 00046 // OpenGL frame buffer configuration utilities. 00047 // 00049 00050 struct GLConfigUtil 00051 { 00052 static void print_gl_attrib(const Glib::RefPtr<const Gdk::GL::Config>& glconfig, 00053 const char* attrib_str, 00054 int attrib, 00055 bool is_boolean); 00056 00057 static void examine_gl_attrib(const Glib::RefPtr<const Gdk::GL::Config>& glconfig); 00058 }; 00059 00060 // 00061 // Print a configuration attribute. 00062 // 00063 void GLConfigUtil::print_gl_attrib(const Glib::RefPtr<const Gdk::GL::Config>& glconfig, 00064 const char* attrib_str, 00065 int attrib, 00066 bool is_boolean) 00067 { 00068 int value; 00069 00070 if (glconfig->get_attrib(attrib, value)) 00071 { 00072 std::cout << attrib_str << " = "; 00073 if (is_boolean) 00074 std::cout << (value == true ? "true" : "false") << std::endl; 00075 else 00076 std::cout << value << std::endl; 00077 } 00078 else 00079 { 00080 std::cout << "*** Cannot get " 00081 << attrib_str 00082 << " attribute value\n"; 00083 } 00084 } 00085 00086 // 00087 // Print configuration attributes. 00088 // 00089 void GLConfigUtil::examine_gl_attrib(const Glib::RefPtr<const Gdk::GL::Config>& glconfig) 00090 { 00091 std::cout << "\nOpenGL visual configurations :\n\n"; 00092 00093 std::cout << "glconfig->is_rgba() = " 00094 << (glconfig->is_rgba() ? "true" : "false") 00095 << std::endl; 00096 std::cout << "glconfig->is_double_buffered() = " 00097 << (glconfig->is_double_buffered() ? "true" : "false") 00098 << std::endl; 00099 std::cout << "glconfig->is_stereo() = " 00100 << (glconfig->is_stereo() ? "true" : "false") 00101 << std::endl; 00102 std::cout << "glconfig->has_alpha() = " 00103 << (glconfig->has_alpha() ? "true" : "false") 00104 << std::endl; 00105 std::cout << "glconfig->has_depth_buffer() = " 00106 << (glconfig->has_depth_buffer() ? "true" : "false") 00107 << std::endl; 00108 std::cout << "glconfig->has_stencil_buffer() = " 00109 << (glconfig->has_stencil_buffer() ? "true" : "false") 00110 << std::endl; 00111 std::cout << "glconfig->has_accum_buffer() = " 00112 << (glconfig->has_accum_buffer() ? "true" : "false") 00113 << std::endl; 00114 00115 std::cout << std::endl; 00116 00117 print_gl_attrib(glconfig, "Gdk::GL::USE_GL", Gdk::GL::USE_GL, true); 00118 print_gl_attrib(glconfig, "Gdk::GL::BUFFER_SIZE", Gdk::GL::BUFFER_SIZE, false); 00119 print_gl_attrib(glconfig, "Gdk::GL::LEVEL", Gdk::GL::LEVEL, false); 00120 print_gl_attrib(glconfig, "Gdk::GL::RGBA", Gdk::GL::RGBA, true); 00121 print_gl_attrib(glconfig, "Gdk::GL::DOUBLEBUFFER", Gdk::GL::DOUBLEBUFFER, true); 00122 print_gl_attrib(glconfig, "Gdk::GL::STEREO", Gdk::GL::STEREO, true); 00123 print_gl_attrib(glconfig, "Gdk::GL::AUX_BUFFERS", Gdk::GL::AUX_BUFFERS, false); 00124 print_gl_attrib(glconfig, "Gdk::GL::RED_SIZE", Gdk::GL::RED_SIZE, false); 00125 print_gl_attrib(glconfig, "Gdk::GL::GREEN_SIZE", Gdk::GL::GREEN_SIZE, false); 00126 print_gl_attrib(glconfig, "Gdk::GL::BLUE_SIZE", Gdk::GL::BLUE_SIZE, false); 00127 print_gl_attrib(glconfig, "Gdk::GL::ALPHA_SIZE", Gdk::GL::ALPHA_SIZE, false); 00128 print_gl_attrib(glconfig, "Gdk::GL::DEPTH_SIZE", Gdk::GL::DEPTH_SIZE, false); 00129 print_gl_attrib(glconfig, "Gdk::GL::STENCIL_SIZE", Gdk::GL::STENCIL_SIZE, false); 00130 print_gl_attrib(glconfig, "Gdk::GL::ACCUM_RED_SIZE", Gdk::GL::ACCUM_RED_SIZE, false); 00131 print_gl_attrib(glconfig, "Gdk::GL::ACCUM_GREEN_SIZE", Gdk::GL::ACCUM_GREEN_SIZE, false); 00132 print_gl_attrib(glconfig, "Gdk::GL::ACCUM_BLUE_SIZE", Gdk::GL::ACCUM_BLUE_SIZE, false); 00133 print_gl_attrib(glconfig, "Gdk::GL::ACCUM_ALPHA_SIZE", Gdk::GL::ACCUM_ALPHA_SIZE, false); 00134 00135 std::cout << std::endl; 00136 } 00137 00138 00140 // 00141 // Logo classes. 00142 // 00144 00145 namespace Logo 00146 { 00147 00148 // 00149 // View class implementation. 00150 // 00151 00152 const float View::NEAR_CLIP = 2.0; 00153 const float View::FAR_CLIP = 60.0; 00154 00155 const float View::INIT_POS_X = 0.0; 00156 const float View::INIT_POS_Y = 0.0; 00157 const float View::INIT_POS_Z = -30.0; 00158 00159 const float View::INIT_AXIS_X = 1.0; 00160 const float View::INIT_AXIS_Y = 0.0; 00161 const float View::INIT_AXIS_Z = 0.0; 00162 const float View::INIT_ANGLE = 20.0; 00163 00164 const float View::INIT_SCALE = 1.0; 00165 00166 const float View::SCALE_MAX = 2.0; 00167 const float View::SCALE_MIN = 0.5; 00168 00169 View::View() 00170 : m_Scale(INIT_SCALE), m_BeginX(0.0), m_BeginY(0.0) 00171 { 00172 reset(); 00173 } 00174 00175 View::~View() 00176 { 00177 } 00178 00179 void View::frustum(int w, int h) 00180 { 00181 glViewport(0, 0, w, h); 00182 00183 glMatrixMode(GL_PROJECTION); 00184 glLoadIdentity(); 00185 00186 if (w > h) { 00187 float aspect = static_cast<float>(w) / static_cast<float>(h); 00188 glFrustum(-aspect, aspect, -1.0, 1.0, NEAR_CLIP, FAR_CLIP); 00189 } else { 00190 float aspect = static_cast<float>(h) / static_cast<float>(w); 00191 glFrustum(-1.0, 1.0, -aspect, aspect, NEAR_CLIP, FAR_CLIP); 00192 } 00193 00194 glMatrixMode(GL_MODELVIEW); 00195 } 00196 00197 void View::xform() 00198 { 00199 glTranslatef(m_Pos[0], m_Pos[1], m_Pos[2]); 00200 00201 glScalef(m_Scale, m_Scale, m_Scale); 00202 00203 float m[4][4]; 00204 Trackball::build_rotmatrix(m, m_Quat); 00205 glMultMatrixf(&m[0][0]); 00206 } 00207 00208 void View::reset() 00209 { 00210 m_Pos[0] = INIT_POS_X; 00211 m_Pos[1] = INIT_POS_Y; 00212 m_Pos[2] = INIT_POS_Z; 00213 00214 float sine = sin(0.5 * INIT_ANGLE * DIG_2_RAD); 00215 m_Quat[0] = INIT_AXIS_X * sine; 00216 m_Quat[1] = INIT_AXIS_Y * sine; 00217 m_Quat[2] = INIT_AXIS_Z * sine; 00218 m_Quat[3] = cos(0.5 * INIT_ANGLE * DIG_2_RAD); 00219 00220 m_Scale = INIT_SCALE; 00221 } 00222 00223 bool View::on_button_press_event(GdkEventButton* event, 00224 Scene* scene) 00225 { 00226 m_BeginX = event->x; 00227 m_BeginY = event->y; 00228 00229 // don't block 00230 return false; 00231 } 00232 00233 bool View::on_motion_notify_event(GdkEventMotion* event, 00234 Scene* scene) 00235 { 00236 if (scene == 0) 00237 return false; 00238 00239 float w = scene->get_width(); 00240 float h = scene->get_height(); 00241 float x = event->x; 00242 float y = event->y; 00243 float d_quat[4]; 00244 bool redraw = false; 00245 00246 // Rotation. 00247 if (event->state & GDK_BUTTON1_MASK) { 00248 Trackball::trackball(d_quat, 00249 (2.0 * m_BeginX - w) / w, 00250 (h - 2.0 * m_BeginY) / h, 00251 (2.0 * x - w) / w, 00252 (h - 2.0 * y) / h); 00253 Trackball::add_quats(d_quat, m_Quat, m_Quat); 00254 redraw = true; 00255 } 00256 00257 // Scaling. 00258 if (event->state & GDK_BUTTON2_MASK) { 00259 m_Scale = m_Scale * (1.0 + (y - m_BeginY) / h); 00260 if (m_Scale > SCALE_MAX) 00261 m_Scale = SCALE_MAX; 00262 else if (m_Scale < SCALE_MIN) 00263 m_Scale = SCALE_MIN; 00264 redraw = true; 00265 } 00266 00267 m_BeginX = x; 00268 m_BeginY = y; 00269 00270 if (redraw && !scene->anim_is_enabled()) 00271 scene->invalidate(); 00272 00273 // don't block 00274 return false; 00275 } 00276 00277 00278 // 00279 // Model class implementation. 00280 // 00281 00282 const float Model::MAT_SPECULAR[4] = { 0.5, 0.5, 0.5, 1.0 }; 00283 const float Model::MAT_SHININESS[1] = { 10.0 }; 00284 const float Model::MAT_BLACK[4] = { 0.0, 0.0, 0.0, 1.0 }; 00285 const float Model::MAT_RED[4] = { 1.0, 0.0, 0.0, 1.0 }; 00286 const float Model::MAT_GREEN[4] = { 0.0, 1.0, 0.0, 1.0 }; 00287 const float Model::MAT_BLUE[4] = { 0.0, 0.0, 1.0, 1.0 }; 00288 00289 const unsigned int Model::DEFAULT_ROT_COUNT = 100; 00290 00291 static float AXIS_X[3] = { 1.0, 0.0, 0.0 }; 00292 static float AXIS_Y[3] = { 0.0, 1.0, 0.0 }; 00293 static float AXIS_Z[3] = { 0.0, 0.0, 1.0 }; 00294 00295 const Model::RotMode Model::ROT_MODE[] = { 00296 { AXIS_X, 1.0 }, 00297 { AXIS_Y, 1.0 }, 00298 { AXIS_X, 1.0 }, 00299 { AXIS_Z, 1.0 }, 00300 { AXIS_X, 1.0 }, 00301 { AXIS_Y, -1.0 }, 00302 { AXIS_X, 1.0 }, 00303 { AXIS_Z, -1.0 }, 00304 { 0, 0.0 } // terminator 00305 }; 00306 00307 Model::Model(unsigned int rot_count, 00308 bool enable_anim) 00309 : m_RotCount(rot_count), 00310 m_EnableAnim(enable_anim), m_Mode(0), m_Counter(0) 00311 { 00312 reset_anim(); 00313 } 00314 00315 Model::~Model() 00316 { 00317 } 00318 00319 void Model::init_gl() 00320 { 00321 glEnable(GL_CULL_FACE); 00322 00323 glPushMatrix(); 00324 00325 glMaterialfv(GL_FRONT, GL_SPECULAR, MAT_SPECULAR); 00326 glMaterialfv(GL_FRONT, GL_SHININESS, MAT_SHININESS); 00327 00328 /* Center black cube. */ 00329 glNewList(CUBE, GL_COMPILE); 00330 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, MAT_BLACK); 00331 LogoModel::logo_draw_cube(); 00332 glEndList(); 00333 00334 /* Forward "G". */ 00335 glNewList(G_FORWARD, GL_COMPILE); 00336 glDisable(GL_CULL_FACE); 00337 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, MAT_BLUE); 00338 LogoModel::logo_draw_g_plane(); 00339 glEnable(GL_CULL_FACE); 00340 00341 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, MAT_BLACK); 00342 LogoModel::logo_draw_g(); 00343 glEndList(); 00344 00345 /* Backward "G". */ 00346 glNewList(G_BACKWARD, GL_COMPILE); 00347 glPushMatrix(); 00348 glRotatef(180.0, 1.0, 0.0, 0.0); 00349 00350 glDisable(GL_CULL_FACE); 00351 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, MAT_BLUE); 00352 LogoModel::logo_draw_g_plane(); 00353 glEnable(GL_CULL_FACE); 00354 00355 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, MAT_BLACK); 00356 LogoModel::logo_draw_g(); 00357 00358 glPopMatrix(); 00359 glEndList(); 00360 00361 /* Forward "T". */ 00362 glNewList(T_FORWARD, GL_COMPILE); 00363 glDisable(GL_CULL_FACE); 00364 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, MAT_RED); 00365 LogoModel::logo_draw_t_plane(); 00366 glEnable(GL_CULL_FACE); 00367 00368 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, MAT_BLACK); 00369 LogoModel::logo_draw_t(); 00370 glEndList(); 00371 00372 /* Backward "T". */ 00373 glNewList(T_BACKWARD, GL_COMPILE); 00374 glPushMatrix(); 00375 glRotatef(180.0, 1.0, 0.0, 0.0); 00376 00377 glDisable(GL_CULL_FACE); 00378 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, MAT_RED); 00379 LogoModel::logo_draw_t_plane(); 00380 glEnable(GL_CULL_FACE); 00381 00382 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, MAT_BLACK); 00383 LogoModel::logo_draw_t(); 00384 00385 glPopMatrix(); 00386 glEndList(); 00387 00388 /* Forward "K". */ 00389 glNewList(K_FORWARD, GL_COMPILE); 00390 glDisable(GL_CULL_FACE); 00391 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, MAT_GREEN); 00392 LogoModel::logo_draw_k_plane(); 00393 glEnable(GL_CULL_FACE); 00394 00395 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, MAT_BLACK); 00396 LogoModel::logo_draw_k(); 00397 glEndList(); 00398 00399 /* Backward "K". */ 00400 glNewList(K_BACKWARD, GL_COMPILE); 00401 glPushMatrix(); 00402 glRotatef(180.0, 0.0, 0.0, 1.0); 00403 00404 glDisable(GL_CULL_FACE); 00405 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, MAT_GREEN); 00406 LogoModel::logo_draw_k_plane(); 00407 glEnable(GL_CULL_FACE); 00408 00409 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, MAT_BLACK); 00410 LogoModel::logo_draw_k(); 00411 glPopMatrix(); 00412 glEndList(); 00413 00414 glPopMatrix(); 00415 00416 glEnable(GL_NORMALIZE); 00417 } 00418 00419 void Model::draw() 00420 { 00421 // Init GL context. 00422 static bool initialized = false; 00423 if (!initialized) { 00424 init_gl(); 00425 initialized = true; 00426 } 00427 00428 // Animation. 00429 if (m_EnableAnim) { 00430 if (m_Counter == m_RotCount) { 00431 if (ROT_MODE[++m_Mode].axis == 0) 00432 m_Mode = 0; 00433 m_Counter = 0; 00434 } 00435 00436 float d_quat[4]; 00437 Trackball::axis_to_quat(ROT_MODE[m_Mode].axis, 00438 ROT_MODE[m_Mode].sign * G_PI_2 / m_RotCount, 00439 d_quat); 00440 Trackball::add_quats(d_quat, m_Quat, m_Quat); 00441 00442 ++m_Counter; 00443 } 00444 00445 // Draw logo model. 00446 glPushMatrix(); 00447 glTranslatef(m_Pos[0], m_Pos[1], m_Pos[2]); 00448 00449 float m[4][4]; 00450 Trackball::build_rotmatrix(m, m_Quat); 00451 glMultMatrixf(&m[0][0]); 00452 00453 glRotatef(90.0, 1.0, 0.0, 0.0); 00454 glCallList(CUBE); 00455 glCallList(G_FORWARD); 00456 glCallList(G_BACKWARD); 00457 glCallList(T_FORWARD); 00458 glCallList(T_BACKWARD); 00459 glCallList(K_FORWARD); 00460 glCallList(K_BACKWARD); 00461 glPopMatrix(); 00462 } 00463 00464 void Model::reset_anim() 00465 { 00466 m_Pos[0] = 0.0; 00467 m_Pos[1] = 0.0; 00468 m_Pos[2] = 0.0; 00469 00470 m_Quat[0] = 0.0; 00471 m_Quat[1] = 0.0; 00472 m_Quat[2] = 0.0; 00473 m_Quat[3] = 1.0; 00474 00475 m_Mode = 0; 00476 m_Counter = 0; 00477 } 00478 00479 00480 // 00481 // Scene class implementation. 00482 // 00483 00484 const unsigned int Scene::TIMEOUT_INTERVAL = 10; 00485 00486 const float Scene::CLEAR_COLOR[4] = { 0.5, 0.5, 0.8, 1.0 }; 00487 const float Scene::CLEAR_DEPTH = 1.0; 00488 00489 const float Scene::LIGHT0_POSITION[4] = { 0.0, 0.0, 30.0, 0.0 }; 00490 const float Scene::LIGHT0_DIFFUSE[4] = { 1.0, 1.0, 1.0, 1.0 }; 00491 const float Scene::LIGHT0_SPECULAR[4] = { 1.0, 1.0, 1.0, 1.0 }; 00492 00493 Scene::Scene(unsigned int rot_count, 00494 bool enable_anim) 00495 : m_Menu(0), m_Model(rot_count, enable_anim) 00496 { 00497 // 00498 // Configure OpenGL-capable visual. 00499 // 00500 00501 Glib::RefPtr<Gdk::GL::Config> glconfig; 00502 00503 // Try double-buffered visual 00504 glconfig = Gdk::GL::Config::create(Gdk::GL::MODE_RGB | 00505 Gdk::GL::MODE_DEPTH | 00506 Gdk::GL::MODE_DOUBLE); 00507 if (!glconfig) { 00508 std::cerr << "*** Cannot find the double-buffered visual.\n" 00509 << "*** Trying single-buffered visual.\n"; 00510 00511 // Try single-buffered visual 00512 glconfig = Gdk::GL::Config::create(Gdk::GL::MODE_RGB | 00513 Gdk::GL::MODE_DEPTH); 00514 if (!glconfig) { 00515 std::cerr << "*** Cannot find any OpenGL-capable visual.\n"; 00516 std::exit(1); 00517 } 00518 } 00519 00520 // print frame buffer attributes. 00521 GLConfigUtil::examine_gl_attrib(glconfig); 00522 00523 // 00524 // Set OpenGL-capability to the widget. 00525 // 00526 00527 set_gl_capability(glconfig); 00528 00529 // 00530 // Add events. 00531 // 00532 add_events(Gdk::BUTTON1_MOTION_MASK | 00533 Gdk::BUTTON2_MOTION_MASK | 00534 Gdk::BUTTON_PRESS_MASK | 00535 Gdk::VISIBILITY_NOTIFY_MASK); 00536 00537 // View transformation signals. 00538 signal_button_press_event().connect( 00539 sigc::bind(sigc::mem_fun(m_View, &View::on_button_press_event), this)); 00540 signal_motion_notify_event().connect( 00541 sigc::bind(sigc::mem_fun(m_View, &View::on_motion_notify_event), this)); 00542 00543 // 00544 // Popup menu. 00545 // 00546 00547 m_Menu = create_popup_menu(); 00548 } 00549 00550 Scene::~Scene() 00551 { 00552 } 00553 00554 void Scene::on_realize() 00555 { 00556 // We need to call the base on_realize() 00557 Gtk::DrawingArea::on_realize(); 00558 00559 // 00560 // Get GL::Drawable. 00561 // 00562 00563 Glib::RefPtr<Gdk::GL::Drawable> gldrawable = get_gl_drawable(); 00564 00565 // 00566 // GL calls. 00567 // 00568 00569 // *** OpenGL BEGIN *** 00570 if (!gldrawable->gl_begin(get_gl_context())) 00571 return; 00572 00573 glClearColor(CLEAR_COLOR[0], CLEAR_COLOR[1], CLEAR_COLOR[2], CLEAR_COLOR[3]); 00574 glClearDepth(CLEAR_DEPTH); 00575 00576 glLightfv(GL_LIGHT0, GL_POSITION, LIGHT0_POSITION); 00577 glLightfv(GL_LIGHT0, GL_DIFFUSE, LIGHT0_DIFFUSE); 00578 glLightfv(GL_LIGHT0, GL_SPECULAR, LIGHT0_SPECULAR); 00579 00580 glEnable(GL_LIGHTING); 00581 glEnable(GL_LIGHT0); 00582 00583 glEnable(GL_DEPTH_TEST); 00584 00585 glShadeModel(GL_SMOOTH); 00586 00587 gldrawable->gl_end(); 00588 // *** OpenGL END *** 00589 } 00590 00591 bool Scene::on_configure_event(GdkEventConfigure* event) 00592 { 00593 // 00594 // Get GL::Drawable. 00595 // 00596 00597 Glib::RefPtr<Gdk::GL::Drawable> gldrawable = get_gl_drawable(); 00598 00599 // 00600 // GL calls. 00601 // 00602 00603 // *** OpenGL BEGIN *** 00604 if (!gldrawable->gl_begin(get_gl_context())) 00605 return false; 00606 00607 m_View.frustum(get_width(), get_height()); 00608 00609 gldrawable->gl_end(); 00610 // *** OpenGL END *** 00611 00612 return true; 00613 } 00614 00615 bool Scene::on_expose_event(GdkEventExpose* event) 00616 { 00617 // 00618 // Get GL::Drawable. 00619 // 00620 00621 Glib::RefPtr<Gdk::GL::Drawable> gldrawable = get_gl_drawable(); 00622 00623 // 00624 // GL calls. 00625 // 00626 00627 // *** OpenGL BEGIN *** 00628 if (!gldrawable->gl_begin(get_gl_context())) 00629 return false; 00630 00631 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 00632 00633 glLoadIdentity(); 00634 00635 // View transformation. 00636 m_View.xform(); 00637 00638 // Logo model. 00639 m_Model.draw(); 00640 00641 // Swap buffers. 00642 if (gldrawable->is_double_buffered()) 00643 gldrawable->swap_buffers(); 00644 else 00645 glFlush(); 00646 00647 gldrawable->gl_end(); 00648 // *** OpenGL END *** 00649 00650 return true; 00651 } 00652 00653 bool Scene::on_button_press_event(GdkEventButton* event) 00654 { 00655 if (event->button == 3) { 00656 m_Menu->popup(event->button, event->time); 00657 return true; 00658 } 00659 00660 // don't block 00661 return false; 00662 } 00663 00664 bool Scene::on_map_event(GdkEventAny* event) 00665 { 00666 if (m_Model.anim_is_enabled()) 00667 timeout_add(); 00668 00669 return true; 00670 } 00671 00672 bool Scene::on_unmap_event(GdkEventAny* event) 00673 { 00674 timeout_remove(); 00675 00676 return true; 00677 } 00678 00679 bool Scene::on_visibility_notify_event(GdkEventVisibility* event) 00680 { 00681 if (m_Model.anim_is_enabled()) { 00682 if (event->state == GDK_VISIBILITY_FULLY_OBSCURED) 00683 timeout_remove(); 00684 else 00685 timeout_add(); 00686 } 00687 00688 return true; 00689 } 00690 00691 bool Scene::on_timeout() 00692 { 00693 // Invalidate whole window. 00694 invalidate(); 00695 // Update window synchronously (fast). 00696 update(); 00697 00698 return true; 00699 } 00700 00701 void Scene::timeout_add() 00702 { 00703 if (!m_ConnectionTimeout.connected()) 00704 m_ConnectionTimeout = Glib::signal_timeout().connect( 00705 sigc::mem_fun(*this, &Scene::on_timeout), TIMEOUT_INTERVAL); 00706 } 00707 00708 void Scene::timeout_remove() 00709 { 00710 if (m_ConnectionTimeout.connected()) 00711 m_ConnectionTimeout.disconnect(); 00712 } 00713 00714 void Scene::toggle_anim() 00715 { 00716 if (m_Model.anim_is_enabled()) { 00717 m_Model.disable_anim(); 00718 timeout_remove(); 00719 } else { 00720 m_Model.enable_anim(); 00721 timeout_add(); 00722 } 00723 } 00724 00725 void Scene::init_anim() 00726 { 00727 m_View.reset(); 00728 m_Model.reset_anim(); 00729 00730 invalidate(); 00731 } 00732 00733 Gtk::Menu* Scene::create_popup_menu() 00734 { 00735 Gtk::Menu* menu = Gtk::manage(new Gtk::Menu()); 00736 00737 Gtk::Menu::MenuList& menu_list = menu->items(); 00738 00739 // Toggle animation 00740 menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Toggle Animation", 00741 sigc::mem_fun(*this, &Scene::toggle_anim))); 00742 00743 // Init orientation 00744 menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Initialize", 00745 sigc::mem_fun(*this, &Scene::init_anim))); 00746 00747 // Quit 00748 menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Quit", 00749 sigc::ptr_fun(&Gtk::Main::quit))); 00750 00751 return menu; 00752 } 00753 00754 00755 // 00756 // Application class implementation. 00757 // 00758 00759 const Glib::ustring Application::APP_NAME = "Logo"; 00760 00761 Application::Application(unsigned int rot_count, 00762 bool enable_anim) 00763 : m_VBox(false, 0), m_Scene(rot_count, enable_anim), m_ButtonQuit("Quit") 00764 { 00765 // 00766 // Top-level window. 00767 // 00768 00769 set_title(APP_NAME); 00770 00771 // Get automatically redrawn if any of their children changed allocation. 00772 set_reallocate_redraws(true); 00773 00774 add(m_VBox); 00775 00776 // 00777 // Application scene. 00778 // 00779 00780 m_Scene.set_size_request(300, 300); 00781 00782 m_VBox.pack_start(m_Scene); 00783 00784 // 00785 // Simple quit button. 00786 // 00787 00788 m_ButtonQuit.signal_clicked().connect( 00789 sigc::mem_fun(*this, &Application::on_button_quit_clicked)); 00790 00791 m_VBox.pack_start(m_ButtonQuit, Gtk::PACK_SHRINK, 0); 00792 00793 // 00794 // Show window. 00795 // 00796 00797 show_all(); 00798 } 00799 00800 Application::~Application() 00801 { 00802 } 00803 00804 void Application::on_button_quit_clicked() 00805 { 00806 Gtk::Main::quit(); 00807 } 00808 00809 bool Application::on_key_press_event(GdkEventKey* event) 00810 { 00811 switch (event->keyval) { 00812 case GDK_a: 00813 m_Scene.toggle_anim(); 00814 break; 00815 case GDK_i: 00816 m_Scene.init_anim(); 00817 break; 00818 case GDK_Escape: 00819 Gtk::Main::quit(); 00820 break; 00821 default: 00822 return true; 00823 } 00824 00825 m_Scene.invalidate(); 00826 00827 return true; 00828 } 00829 00830 00831 } // namespace Logo 00832 00833 00835 // 00836 // Main. 00837 // 00839 00840 int main(int argc, char** argv) 00841 { 00842 Gtk::Main kit(argc, argv); 00843 00844 // 00845 // Init gtkglextmm. 00846 // 00847 00848 Gtk::GL::init(argc, argv); 00849 00850 // 00851 // Parse arguments. 00852 // 00853 00854 unsigned int rot_count = Logo::Model::DEFAULT_ROT_COUNT; 00855 bool enable_anim = true; 00856 00857 bool arg_count = false; 00858 for (int i = 1; i < argc; ++i) { 00859 if (arg_count) 00860 rot_count = std::atoi(argv[i]); 00861 00862 if (std::strcmp(argv[i], "--help") == 0 || 00863 std::strcmp(argv[i], "-h") == 0) { 00864 std::cerr << "Usage: " 00865 << argv[0] 00866 << " [-count num] [-noanim] [--help]\n"; 00867 std::exit(0); 00868 } 00869 00870 if (std::strcmp(argv[i], "-count") == 0) 00871 arg_count = true; 00872 00873 if (std::strcmp(argv[i], "-noanim") == 0) 00874 enable_anim = false; 00875 } 00876 00877 // 00878 // Query OpenGL extension version. 00879 // 00880 00881 int major, minor; 00882 Gdk::GL::query_version(major, minor); 00883 std::cout << "OpenGL extension version - " 00884 << major << "." << minor << std::endl; 00885 00886 // 00887 // Instantiate and run the application. 00888 // 00889 00890 Logo::Application application(rot_count, enable_anim); 00891 00892 kit.run(application); 00893 00894 return 0; 00895 }

Generated on Sun Jun 20 16:59:38 2004 for gtkglextmm by doxygen 1.3.7