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

gears.cc

3-D gear wheels demo.
// -*- C++ -*- /* * 3-D gear wheels. This program is in the public domain. * * Brian Paul */ /* Conversion to gtkglextmm by Naofumi Yasufuku */ #include <iostream> #include <cstdlib> #include <cmath> #include <gtkmm.h> #include <gtkglmm.h> #ifdef G_OS_WIN32 #define WIN32_LEAN_AND_MEAN 1 #include <windows.h> #endif #include <GL/gl.h> #include <GL/glu.h> // // 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; } // // Gears scene. // class GearsScene : public Gtk::GL::DrawingArea { public: explicit GearsScene(bool is_sync = true); virtual ~GearsScene(); protected: void gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width, GLint teeth, GLfloat tooth_depth); protected: // signal handlers: virtual void on_realize(); virtual bool on_configure_event(GdkEventConfigure* event); virtual bool on_expose_event(GdkEventExpose* event); virtual bool on_map_event(GdkEventAny* event); virtual bool on_unmap_event(GdkEventAny* event); virtual bool on_visibility_notify_event(GdkEventVisibility* event); virtual bool on_idle(); public: // Invalidate whole window. void invalidate() { get_window()->invalidate_rect(get_allocation(), false); } // Update window synchronously (fast). void update() { get_window()->process_updates(false); } protected: // idle signal connection: sigc::connection m_ConnectionIdle; public: // get & set view rotation values. void get_view_rot(GLfloat& x, GLfloat& y, GLfloat& z) { x = m_ViewRotX; y = m_ViewRotY; z = m_ViewRotZ; } void set_view_rot(GLfloat x, GLfloat y, GLfloat z) { m_ViewRotX = x; m_ViewRotY = y; m_ViewRotZ = z; } protected: // OpenGL scene related variables: GLint m_Gear1; GLint m_Gear2; GLint m_Gear3; GLfloat m_ViewRotX; GLfloat m_ViewRotY; GLfloat m_ViewRotZ; GLfloat m_Angle; bool m_IsSync; protected: // frame rate evaluation stuff: Glib::Timer m_Timer; int m_Frames; }; GearsScene::GearsScene(bool is_sync) : m_Gear1(0), m_Gear2(0), m_Gear3(0), m_ViewRotX(20.0), m_ViewRotY(30.0), m_ViewRotZ(0.0), m_Angle(0.0), m_IsSync(is_sync), m_Frames(0) { // // 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::VISIBILITY_NOTIFY_MASK); } GearsScene::~GearsScene() { } /* * Draw a gear wheel. You'll probably want to call this function when * building a display list since we do a lot of trig here. * * Input: inner_radius - radius of hole at center * outer_radius - radius at center of teeth * width - width of gear * teeth - number of teeth * tooth_depth - depth of tooth */ void GearsScene::gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width, GLint teeth, GLfloat tooth_depth) { GLint i; GLfloat r0, r1, r2; GLfloat angle, da; GLfloat u, v, len; r0 = inner_radius; r1 = outer_radius - tooth_depth / 2.0; r2 = outer_radius + tooth_depth / 2.0; da = 2.0 * G_PI / teeth / 4.0; glShadeModel(GL_FLAT); glNormal3f(0.0, 0.0, 1.0); /* draw front face */ glBegin(GL_QUAD_STRIP); for (i = 0; i <= teeth; i++) { angle = i * 2.0 * G_PI / teeth; glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); if (i < teeth) { glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5); } } glEnd(); /* draw front sides of teeth */ glBegin(GL_QUADS); da = 2.0 * G_PI / teeth / 4.0; for (i = 0; i < teeth; i++) { angle = i * 2.0 * G_PI / teeth; glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5); glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5); } glEnd(); glNormal3f(0.0, 0.0, -1.0); /* draw back face */ glBegin(GL_QUAD_STRIP); for (i = 0; i <= teeth; i++) { angle = i * 2.0 * G_PI / teeth; glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); if (i < teeth) { glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5); glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); } } glEnd(); /* draw back sides of teeth */ glBegin(GL_QUADS); da = 2.0 * G_PI / teeth / 4.0; for (i = 0; i < teeth; i++) { angle = i * 2.0 * G_PI / teeth; glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5); glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5); glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); } glEnd(); /* draw outward faces of teeth */ glBegin(GL_QUAD_STRIP); for (i = 0; i < teeth; i++) { angle = i * 2.0 * G_PI / teeth; glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); u = r2 * cos(angle + da) - r1 * cos(angle); v = r2 * sin(angle + da) - r1 * sin(angle); len = sqrt(u * u + v * v); u /= len; v /= len; glNormal3f(v, -u, 0.0); glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); glNormal3f(cos(angle), sin(angle), 0.0); glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5); glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5); u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da); v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da); glNormal3f(v, -u, 0.0); glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5); glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5); glNormal3f(cos(angle), sin(angle), 0.0); } glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5); glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5); glEnd(); glShadeModel(GL_SMOOTH); /* draw inside radius cylinder */ glBegin(GL_QUAD_STRIP); for (i = 0; i <= teeth; i++) { angle = i * 2.0 * G_PI / teeth; glNormal3f(-cos(angle), -sin(angle), 0.0); glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); } glEnd(); } void GearsScene::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; static GLfloat pos[4] = {5.0, 5.0, 10.0, 0.0}; static GLfloat red[4] = {0.8, 0.1, 0.0, 1.0}; static GLfloat green[4] = {0.0, 0.8, 0.2, 1.0}; static GLfloat blue[4] = {0.2, 0.2, 1.0, 1.0}; glLightfv(GL_LIGHT0, GL_POSITION, pos); glEnable(GL_CULL_FACE); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_DEPTH_TEST); // Make the gears. m_Gear1 = glGenLists(1); glNewList(m_Gear1, GL_COMPILE); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red); gear(1.0, 4.0, 1.0, 20, 0.7); glEndList(); m_Gear2 = glGenLists(1); glNewList(m_Gear2, GL_COMPILE); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green); gear(0.5, 2.0, 2.0, 10, 0.7); glEndList(); m_Gear3 = glGenLists(1); glNewList(m_Gear3, GL_COMPILE); glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue); gear(1.3, 2.0, 0.5, 10, 0.7); glEndList(); glEnable(GL_NORMALIZE); std::cout << "GL_RENDERER = " << glGetString(GL_RENDERER) << std::endl; std::cout << "GL_VERSION = " << glGetString(GL_VERSION) << std::endl; std::cout << "GL_VENDOR = " << glGetString(GL_VENDOR) << std::endl; std::cout << "GL_EXTENSIONS = " << glGetString(GL_EXTENSIONS) << std::endl; std::cout << std::endl; gldrawable->gl_end(); // *** OpenGL END *** // Start timer. m_Timer.start(); } bool GearsScene::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; GLfloat h = (GLfloat)(get_height()) / (GLfloat)(get_width()); glViewport(0, 0, get_width(), get_height()); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.0, 0.0, -40.0); gldrawable->gl_end(); // *** OpenGL END *** return true; } bool GearsScene::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); glPushMatrix(); glRotatef(m_ViewRotX, 1.0, 0.0, 0.0); glRotatef(m_ViewRotY, 0.0, 1.0, 0.0); glRotatef(m_ViewRotZ, 0.0, 0.0, 1.0); glPushMatrix(); glTranslatef(-3.0, -2.0, 0.0); glRotatef(m_Angle, 0.0, 0.0, 1.0); glCallList(m_Gear1); glPopMatrix(); glPushMatrix(); glTranslatef(3.1, -2.0, 0.0); glRotatef(-2.0 * m_Angle - 9.0, 0.0, 0.0, 1.0); glCallList(m_Gear2); glPopMatrix(); glPushMatrix(); glTranslatef(-3.1, 4.2, 0.0); glRotatef(-2.0 * m_Angle - 25.0, 0.0, 0.0, 1.0); glCallList(m_Gear3); glPopMatrix(); glPopMatrix(); // Swap buffers. if (gldrawable->is_double_buffered()) gldrawable->swap_buffers(); else glFlush(); gldrawable->gl_end(); // *** OpenGL END *** // // Print frame rate. // ++m_Frames; double seconds = m_Timer.elapsed(); if (seconds >= 5.0) { // std::cout.setf(std::ios_base::fixed, std::ios_base::floatfield); std::cout.setf(std::ios::fixed, std::ios::floatfield); std::cout.precision(3); std::cout << m_Frames << " frames in " << seconds << " seconds = " << (m_Frames / seconds) << " FPS\n"; m_Timer.reset(); m_Frames = 0; } return true; } bool GearsScene::on_map_event(GdkEventAny* event) { if (!m_ConnectionIdle.connected()) m_ConnectionIdle = Glib::signal_idle().connect( sigc::mem_fun(*this, &GearsScene::on_idle), GDK_PRIORITY_REDRAW); return true; } bool GearsScene::on_unmap_event(GdkEventAny* event) { if (m_ConnectionIdle.connected()) m_ConnectionIdle.disconnect(); return true; } bool GearsScene::on_visibility_notify_event(GdkEventVisibility* event) { if (event->state == GDK_VISIBILITY_FULLY_OBSCURED) { if (m_ConnectionIdle.connected()) m_ConnectionIdle.disconnect(); } else { if (!m_ConnectionIdle.connected()) m_ConnectionIdle = Glib::signal_idle().connect( sigc::mem_fun(*this, &GearsScene::on_idle), GDK_PRIORITY_REDRAW); } return true; } bool GearsScene::on_idle() { m_Angle += 2.0; // Invalidate the whole window. invalidate(); // Update window synchronously (fast). if (m_IsSync) update(); return true; } // // The application class. // class Gears : public Gtk::Window { public: explicit Gears(bool is_sync = true); virtual ~Gears(); protected: // signal handlers: void on_button_quit_clicked(); virtual bool on_key_press_event(GdkEventKey* event); protected: // member widgets: Gtk::VBox m_VBox; GearsScene m_GearsScene; Gtk::Button m_ButtonQuit; }; Gears::Gears(bool is_sync) : m_VBox(false, 0), m_GearsScene(is_sync), m_ButtonQuit("Quit") { // // Top-level window. // set_title("Gears"); // Get automatically redrawn if any of their children changed allocation. set_reallocate_redraws(true); add(m_VBox); // // Gears scene. // m_GearsScene.set_size_request(300, 300); m_VBox.pack_start(m_GearsScene); // // Simple quit button. // m_ButtonQuit.signal_clicked().connect( sigc::mem_fun(*this, &Gears::on_button_quit_clicked)); m_VBox.pack_start(m_ButtonQuit, Gtk::PACK_SHRINK, 0); // // Show window. // show_all(); } Gears::~Gears() { } void Gears::on_button_quit_clicked() { Gtk::Main::quit(); } bool Gears::on_key_press_event(GdkEventKey* event) { GLfloat x, y, z; m_GearsScene.get_view_rot(x, y, z); switch (event->keyval) { case GDK_z: z += 5.0; break; case GDK_Z: z -= 5.0; break; case GDK_Up: x += 5.0; break; case GDK_Down: x -= 5.0; break; case GDK_Left: y += 5.0; break; case GDK_Right: y -= 5.0; break; case GDK_Escape: Gtk::Main::quit(); break; default: return true; } m_GearsScene.set_view_rot(x, y, z); m_GearsScene.invalidate(); return true; } // // Main. // int main(int argc, char** argv) { Gtk::Main kit(argc, argv); // // Init gtkglextmm. // Gtk::GL::init(argc, argv); // // Parse arguments. // bool is_sync = true; for (int i = 1; i < argc; ++i) { if (std::strcmp(argv[i], "--async") == 0) is_sync = false; } // // Instantiate and run the application. // Gears gears(is_sync); kit.run(gears); return 0; }
00001 // -*- C++ -*- 00002 /* 00003 * 3-D gear wheels. This program is in the public domain. 00004 * 00005 * Brian Paul 00006 */ 00007 00008 /* Conversion to gtkglextmm by Naofumi Yasufuku */ 00009 00010 #include <iostream> 00011 #include <cstdlib> 00012 #include <cmath> 00013 00014 #include <gtkmm.h> 00015 00016 #include <gtkglmm.h> 00017 00018 #ifdef G_OS_WIN32 00019 #define WIN32_LEAN_AND_MEAN 1 00020 #include <windows.h> 00021 #endif 00022 00023 #include <GL/gl.h> 00024 #include <GL/glu.h> 00025 00026 00028 // 00029 // OpenGL frame buffer configuration utilities. 00030 // 00032 00033 struct GLConfigUtil 00034 { 00035 static void print_gl_attrib(const Glib::RefPtr<const Gdk::GL::Config>& glconfig, 00036 const char* attrib_str, 00037 int attrib, 00038 bool is_boolean); 00039 00040 static void examine_gl_attrib(const Glib::RefPtr<const Gdk::GL::Config>& glconfig); 00041 }; 00042 00043 // 00044 // Print a configuration attribute. 00045 // 00046 void GLConfigUtil::print_gl_attrib(const Glib::RefPtr<const Gdk::GL::Config>& glconfig, 00047 const char* attrib_str, 00048 int attrib, 00049 bool is_boolean) 00050 { 00051 int value; 00052 00053 if (glconfig->get_attrib(attrib, value)) 00054 { 00055 std::cout << attrib_str << " = "; 00056 if (is_boolean) 00057 std::cout << (value == true ? "true" : "false") << std::endl; 00058 else 00059 std::cout << value << std::endl; 00060 } 00061 else 00062 { 00063 std::cout << "*** Cannot get " 00064 << attrib_str 00065 << " attribute value\n"; 00066 } 00067 } 00068 00069 // 00070 // Print configuration attributes. 00071 // 00072 void GLConfigUtil::examine_gl_attrib(const Glib::RefPtr<const Gdk::GL::Config>& glconfig) 00073 { 00074 std::cout << "\nOpenGL visual configurations :\n\n"; 00075 00076 std::cout << "glconfig->is_rgba() = " 00077 << (glconfig->is_rgba() ? "true" : "false") 00078 << std::endl; 00079 std::cout << "glconfig->is_double_buffered() = " 00080 << (glconfig->is_double_buffered() ? "true" : "false") 00081 << std::endl; 00082 std::cout << "glconfig->is_stereo() = " 00083 << (glconfig->is_stereo() ? "true" : "false") 00084 << std::endl; 00085 std::cout << "glconfig->has_alpha() = " 00086 << (glconfig->has_alpha() ? "true" : "false") 00087 << std::endl; 00088 std::cout << "glconfig->has_depth_buffer() = " 00089 << (glconfig->has_depth_buffer() ? "true" : "false") 00090 << std::endl; 00091 std::cout << "glconfig->has_stencil_buffer() = " 00092 << (glconfig->has_stencil_buffer() ? "true" : "false") 00093 << std::endl; 00094 std::cout << "glconfig->has_accum_buffer() = " 00095 << (glconfig->has_accum_buffer() ? "true" : "false") 00096 << std::endl; 00097 00098 std::cout << std::endl; 00099 00100 print_gl_attrib(glconfig, "Gdk::GL::USE_GL", Gdk::GL::USE_GL, true); 00101 print_gl_attrib(glconfig, "Gdk::GL::BUFFER_SIZE", Gdk::GL::BUFFER_SIZE, false); 00102 print_gl_attrib(glconfig, "Gdk::GL::LEVEL", Gdk::GL::LEVEL, false); 00103 print_gl_attrib(glconfig, "Gdk::GL::RGBA", Gdk::GL::RGBA, true); 00104 print_gl_attrib(glconfig, "Gdk::GL::DOUBLEBUFFER", Gdk::GL::DOUBLEBUFFER, true); 00105 print_gl_attrib(glconfig, "Gdk::GL::STEREO", Gdk::GL::STEREO, true); 00106 print_gl_attrib(glconfig, "Gdk::GL::AUX_BUFFERS", Gdk::GL::AUX_BUFFERS, false); 00107 print_gl_attrib(glconfig, "Gdk::GL::RED_SIZE", Gdk::GL::RED_SIZE, false); 00108 print_gl_attrib(glconfig, "Gdk::GL::GREEN_SIZE", Gdk::GL::GREEN_SIZE, false); 00109 print_gl_attrib(glconfig, "Gdk::GL::BLUE_SIZE", Gdk::GL::BLUE_SIZE, false); 00110 print_gl_attrib(glconfig, "Gdk::GL::ALPHA_SIZE", Gdk::GL::ALPHA_SIZE, false); 00111 print_gl_attrib(glconfig, "Gdk::GL::DEPTH_SIZE", Gdk::GL::DEPTH_SIZE, false); 00112 print_gl_attrib(glconfig, "Gdk::GL::STENCIL_SIZE", Gdk::GL::STENCIL_SIZE, false); 00113 print_gl_attrib(glconfig, "Gdk::GL::ACCUM_RED_SIZE", Gdk::GL::ACCUM_RED_SIZE, false); 00114 print_gl_attrib(glconfig, "Gdk::GL::ACCUM_GREEN_SIZE", Gdk::GL::ACCUM_GREEN_SIZE, false); 00115 print_gl_attrib(glconfig, "Gdk::GL::ACCUM_BLUE_SIZE", Gdk::GL::ACCUM_BLUE_SIZE, false); 00116 print_gl_attrib(glconfig, "Gdk::GL::ACCUM_ALPHA_SIZE", Gdk::GL::ACCUM_ALPHA_SIZE, false); 00117 00118 std::cout << std::endl; 00119 } 00120 00121 00123 // 00124 // Gears scene. 00125 // 00127 00128 class GearsScene : public Gtk::GL::DrawingArea 00129 { 00130 public: 00131 explicit GearsScene(bool is_sync = true); 00132 virtual ~GearsScene(); 00133 00134 protected: 00135 void gear(GLfloat inner_radius, 00136 GLfloat outer_radius, 00137 GLfloat width, 00138 GLint teeth, 00139 GLfloat tooth_depth); 00140 00141 protected: 00142 // signal handlers: 00143 virtual void on_realize(); 00144 virtual bool on_configure_event(GdkEventConfigure* event); 00145 virtual bool on_expose_event(GdkEventExpose* event); 00146 virtual bool on_map_event(GdkEventAny* event); 00147 virtual bool on_unmap_event(GdkEventAny* event); 00148 virtual bool on_visibility_notify_event(GdkEventVisibility* event); 00149 virtual bool on_idle(); 00150 00151 public: 00152 // Invalidate whole window. 00153 void invalidate() { 00154 get_window()->invalidate_rect(get_allocation(), false); 00155 } 00156 00157 // Update window synchronously (fast). 00158 void update() 00159 { get_window()->process_updates(false); } 00160 00161 protected: 00162 // idle signal connection: 00163 sigc::connection m_ConnectionIdle; 00164 00165 public: 00166 // get & set view rotation values. 00167 void get_view_rot(GLfloat& x, GLfloat& y, GLfloat& z) 00168 { x = m_ViewRotX; y = m_ViewRotY; z = m_ViewRotZ; } 00169 00170 void set_view_rot(GLfloat x, GLfloat y, GLfloat z) 00171 { m_ViewRotX = x; m_ViewRotY = y; m_ViewRotZ = z; } 00172 00173 protected: 00174 // OpenGL scene related variables: 00175 GLint m_Gear1; 00176 GLint m_Gear2; 00177 GLint m_Gear3; 00178 00179 GLfloat m_ViewRotX; 00180 GLfloat m_ViewRotY; 00181 GLfloat m_ViewRotZ; 00182 00183 GLfloat m_Angle; 00184 00185 bool m_IsSync; 00186 00187 protected: 00188 // frame rate evaluation stuff: 00189 Glib::Timer m_Timer; 00190 int m_Frames; 00191 }; 00192 00193 GearsScene::GearsScene(bool is_sync) 00194 : m_Gear1(0), m_Gear2(0), m_Gear3(0), 00195 m_ViewRotX(20.0), m_ViewRotY(30.0), m_ViewRotZ(0.0), 00196 m_Angle(0.0), m_IsSync(is_sync), 00197 m_Frames(0) 00198 { 00199 // 00200 // Configure OpenGL-capable visual. 00201 // 00202 00203 Glib::RefPtr<Gdk::GL::Config> glconfig; 00204 00205 // Try double-buffered visual 00206 glconfig = Gdk::GL::Config::create(Gdk::GL::MODE_RGB | 00207 Gdk::GL::MODE_DEPTH | 00208 Gdk::GL::MODE_DOUBLE); 00209 if (!glconfig) 00210 { 00211 std::cerr << "*** Cannot find the double-buffered visual.\n" 00212 << "*** Trying single-buffered visual.\n"; 00213 00214 // Try single-buffered visual 00215 glconfig = Gdk::GL::Config::create(Gdk::GL::MODE_RGB | 00216 Gdk::GL::MODE_DEPTH); 00217 if (!glconfig) 00218 { 00219 std::cerr << "*** Cannot find any OpenGL-capable visual.\n"; 00220 std::exit(1); 00221 } 00222 } 00223 00224 // print frame buffer attributes. 00225 GLConfigUtil::examine_gl_attrib(glconfig); 00226 00227 // 00228 // Set OpenGL-capability to the widget. 00229 // 00230 00231 set_gl_capability(glconfig); 00232 00233 // Add events. 00234 add_events(Gdk::VISIBILITY_NOTIFY_MASK); 00235 } 00236 00237 GearsScene::~GearsScene() 00238 { 00239 } 00240 00241 /* 00242 * Draw a gear wheel. You'll probably want to call this function when 00243 * building a display list since we do a lot of trig here. 00244 * 00245 * Input: inner_radius - radius of hole at center 00246 * outer_radius - radius at center of teeth 00247 * width - width of gear 00248 * teeth - number of teeth 00249 * tooth_depth - depth of tooth 00250 */ 00251 00252 void GearsScene::gear(GLfloat inner_radius, 00253 GLfloat outer_radius, 00254 GLfloat width, 00255 GLint teeth, 00256 GLfloat tooth_depth) 00257 { 00258 GLint i; 00259 GLfloat r0, r1, r2; 00260 GLfloat angle, da; 00261 GLfloat u, v, len; 00262 00263 r0 = inner_radius; 00264 r1 = outer_radius - tooth_depth / 2.0; 00265 r2 = outer_radius + tooth_depth / 2.0; 00266 00267 da = 2.0 * G_PI / teeth / 4.0; 00268 00269 glShadeModel(GL_FLAT); 00270 00271 glNormal3f(0.0, 0.0, 1.0); 00272 00273 /* draw front face */ 00274 glBegin(GL_QUAD_STRIP); 00275 for (i = 0; i <= teeth; i++) { 00276 angle = i * 2.0 * G_PI / teeth; 00277 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); 00278 glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); 00279 if (i < teeth) { 00280 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); 00281 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5); 00282 } 00283 } 00284 glEnd(); 00285 00286 /* draw front sides of teeth */ 00287 glBegin(GL_QUADS); 00288 da = 2.0 * G_PI / teeth / 4.0; 00289 for (i = 0; i < teeth; i++) { 00290 angle = i * 2.0 * G_PI / teeth; 00291 00292 glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); 00293 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); 00294 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5); 00295 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5); 00296 } 00297 glEnd(); 00298 00299 glNormal3f(0.0, 0.0, -1.0); 00300 00301 /* draw back face */ 00302 glBegin(GL_QUAD_STRIP); 00303 for (i = 0; i <= teeth; i++) { 00304 angle = i * 2.0 * G_PI / teeth; 00305 glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); 00306 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); 00307 if (i < teeth) { 00308 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5); 00309 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); 00310 } 00311 } 00312 glEnd(); 00313 00314 /* draw back sides of teeth */ 00315 glBegin(GL_QUADS); 00316 da = 2.0 * G_PI / teeth / 4.0; 00317 for (i = 0; i < teeth; i++) { 00318 angle = i * 2.0 * G_PI / teeth; 00319 00320 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5); 00321 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5); 00322 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); 00323 glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); 00324 } 00325 glEnd(); 00326 00327 /* draw outward faces of teeth */ 00328 glBegin(GL_QUAD_STRIP); 00329 for (i = 0; i < teeth; i++) { 00330 angle = i * 2.0 * G_PI / teeth; 00331 00332 glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); 00333 glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); 00334 u = r2 * cos(angle + da) - r1 * cos(angle); 00335 v = r2 * sin(angle + da) - r1 * sin(angle); 00336 len = sqrt(u * u + v * v); 00337 u /= len; 00338 v /= len; 00339 glNormal3f(v, -u, 0.0); 00340 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); 00341 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); 00342 glNormal3f(cos(angle), sin(angle), 0.0); 00343 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5); 00344 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5); 00345 u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da); 00346 v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da); 00347 glNormal3f(v, -u, 0.0); 00348 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5); 00349 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5); 00350 glNormal3f(cos(angle), sin(angle), 0.0); 00351 } 00352 00353 glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5); 00354 glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5); 00355 00356 glEnd(); 00357 00358 glShadeModel(GL_SMOOTH); 00359 00360 /* draw inside radius cylinder */ 00361 glBegin(GL_QUAD_STRIP); 00362 for (i = 0; i <= teeth; i++) { 00363 angle = i * 2.0 * G_PI / teeth; 00364 glNormal3f(-cos(angle), -sin(angle), 0.0); 00365 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); 00366 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); 00367 } 00368 glEnd(); 00369 00370 } 00371 00372 void GearsScene::on_realize() 00373 { 00374 // We need to call the base on_realize() 00375 Gtk::DrawingArea::on_realize(); 00376 00377 // 00378 // Get GL::Drawable. 00379 // 00380 00381 Glib::RefPtr<Gdk::GL::Drawable> gldrawable = get_gl_drawable(); 00382 00383 // 00384 // GL calls. 00385 // 00386 00387 // *** OpenGL BEGIN *** 00388 if (!gldrawable->gl_begin(get_gl_context())) 00389 return; 00390 00391 static GLfloat pos[4] = {5.0, 5.0, 10.0, 0.0}; 00392 static GLfloat red[4] = {0.8, 0.1, 0.0, 1.0}; 00393 static GLfloat green[4] = {0.0, 0.8, 0.2, 1.0}; 00394 static GLfloat blue[4] = {0.2, 0.2, 1.0, 1.0}; 00395 00396 glLightfv(GL_LIGHT0, GL_POSITION, pos); 00397 glEnable(GL_CULL_FACE); 00398 glEnable(GL_LIGHTING); 00399 glEnable(GL_LIGHT0); 00400 glEnable(GL_DEPTH_TEST); 00401 00402 // Make the gears. 00403 m_Gear1 = glGenLists(1); 00404 glNewList(m_Gear1, GL_COMPILE); 00405 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red); 00406 gear(1.0, 4.0, 1.0, 20, 0.7); 00407 glEndList(); 00408 00409 m_Gear2 = glGenLists(1); 00410 glNewList(m_Gear2, GL_COMPILE); 00411 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green); 00412 gear(0.5, 2.0, 2.0, 10, 0.7); 00413 glEndList(); 00414 00415 m_Gear3 = glGenLists(1); 00416 glNewList(m_Gear3, GL_COMPILE); 00417 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue); 00418 gear(1.3, 2.0, 0.5, 10, 0.7); 00419 glEndList(); 00420 00421 glEnable(GL_NORMALIZE); 00422 00423 std::cout << "GL_RENDERER = " << glGetString(GL_RENDERER) << std::endl; 00424 std::cout << "GL_VERSION = " << glGetString(GL_VERSION) << std::endl; 00425 std::cout << "GL_VENDOR = " << glGetString(GL_VENDOR) << std::endl; 00426 std::cout << "GL_EXTENSIONS = " << glGetString(GL_EXTENSIONS) << std::endl; 00427 std::cout << std::endl; 00428 00429 gldrawable->gl_end(); 00430 // *** OpenGL END *** 00431 00432 // Start timer. 00433 m_Timer.start(); 00434 } 00435 00436 bool GearsScene::on_configure_event(GdkEventConfigure* event) 00437 { 00438 // 00439 // Get GL::Drawable. 00440 // 00441 00442 Glib::RefPtr<Gdk::GL::Drawable> gldrawable = get_gl_drawable(); 00443 00444 // 00445 // GL calls. 00446 // 00447 00448 // *** OpenGL BEGIN *** 00449 if (!gldrawable->gl_begin(get_gl_context())) 00450 return false; 00451 00452 GLfloat h = (GLfloat)(get_height()) / (GLfloat)(get_width()); 00453 00454 glViewport(0, 0, get_width(), get_height()); 00455 glMatrixMode(GL_PROJECTION); 00456 glLoadIdentity(); 00457 glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0); 00458 glMatrixMode(GL_MODELVIEW); 00459 glLoadIdentity(); 00460 glTranslatef(0.0, 0.0, -40.0); 00461 00462 gldrawable->gl_end(); 00463 // *** OpenGL END *** 00464 00465 return true; 00466 } 00467 00468 bool GearsScene::on_expose_event(GdkEventExpose* event) 00469 { 00470 // 00471 // Get GL::Drawable. 00472 // 00473 00474 Glib::RefPtr<Gdk::GL::Drawable> gldrawable = get_gl_drawable(); 00475 00476 // 00477 // GL calls. 00478 // 00479 00480 // *** OpenGL BEGIN *** 00481 if (!gldrawable->gl_begin(get_gl_context())) 00482 return false; 00483 00484 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 00485 00486 glPushMatrix(); 00487 glRotatef(m_ViewRotX, 1.0, 0.0, 0.0); 00488 glRotatef(m_ViewRotY, 0.0, 1.0, 0.0); 00489 glRotatef(m_ViewRotZ, 0.0, 0.0, 1.0); 00490 00491 glPushMatrix(); 00492 glTranslatef(-3.0, -2.0, 0.0); 00493 glRotatef(m_Angle, 0.0, 0.0, 1.0); 00494 glCallList(m_Gear1); 00495 glPopMatrix(); 00496 00497 glPushMatrix(); 00498 glTranslatef(3.1, -2.0, 0.0); 00499 glRotatef(-2.0 * m_Angle - 9.0, 0.0, 0.0, 1.0); 00500 glCallList(m_Gear2); 00501 glPopMatrix(); 00502 00503 glPushMatrix(); 00504 glTranslatef(-3.1, 4.2, 0.0); 00505 glRotatef(-2.0 * m_Angle - 25.0, 0.0, 0.0, 1.0); 00506 glCallList(m_Gear3); 00507 glPopMatrix(); 00508 00509 glPopMatrix(); 00510 00511 // Swap buffers. 00512 if (gldrawable->is_double_buffered()) 00513 gldrawable->swap_buffers(); 00514 else 00515 glFlush(); 00516 00517 gldrawable->gl_end(); 00518 // *** OpenGL END *** 00519 00520 // 00521 // Print frame rate. 00522 // 00523 00524 ++m_Frames; 00525 00526 double seconds = m_Timer.elapsed(); 00527 if (seconds >= 5.0) 00528 { 00529 // std::cout.setf(std::ios_base::fixed, std::ios_base::floatfield); 00530 std::cout.setf(std::ios::fixed, std::ios::floatfield); 00531 std::cout.precision(3); 00532 std::cout << m_Frames << " frames in " 00533 << seconds << " seconds = " 00534 << (m_Frames / seconds) << " FPS\n"; 00535 m_Timer.reset(); 00536 m_Frames = 0; 00537 } 00538 00539 return true; 00540 } 00541 00542 bool GearsScene::on_map_event(GdkEventAny* event) 00543 { 00544 if (!m_ConnectionIdle.connected()) 00545 m_ConnectionIdle = Glib::signal_idle().connect( 00546 sigc::mem_fun(*this, &GearsScene::on_idle), GDK_PRIORITY_REDRAW); 00547 00548 return true; 00549 } 00550 00551 bool GearsScene::on_unmap_event(GdkEventAny* event) 00552 { 00553 if (m_ConnectionIdle.connected()) 00554 m_ConnectionIdle.disconnect(); 00555 00556 return true; 00557 } 00558 00559 bool GearsScene::on_visibility_notify_event(GdkEventVisibility* event) 00560 { 00561 if (event->state == GDK_VISIBILITY_FULLY_OBSCURED) 00562 { 00563 if (m_ConnectionIdle.connected()) 00564 m_ConnectionIdle.disconnect(); 00565 } 00566 else 00567 { 00568 if (!m_ConnectionIdle.connected()) 00569 m_ConnectionIdle = Glib::signal_idle().connect( 00570 sigc::mem_fun(*this, &GearsScene::on_idle), GDK_PRIORITY_REDRAW); 00571 } 00572 00573 return true; 00574 } 00575 00576 bool GearsScene::on_idle() 00577 { 00578 m_Angle += 2.0; 00579 00580 // Invalidate the whole window. 00581 invalidate(); 00582 00583 // Update window synchronously (fast). 00584 if (m_IsSync) 00585 update(); 00586 00587 return true; 00588 } 00589 00590 00592 // 00593 // The application class. 00594 // 00596 00597 class Gears : public Gtk::Window 00598 { 00599 public: 00600 explicit Gears(bool is_sync = true); 00601 virtual ~Gears(); 00602 00603 protected: 00604 // signal handlers: 00605 void on_button_quit_clicked(); 00606 virtual bool on_key_press_event(GdkEventKey* event); 00607 00608 protected: 00609 // member widgets: 00610 Gtk::VBox m_VBox; 00611 GearsScene m_GearsScene; 00612 Gtk::Button m_ButtonQuit; 00613 }; 00614 00615 Gears::Gears(bool is_sync) 00616 : m_VBox(false, 0), m_GearsScene(is_sync), m_ButtonQuit("Quit") 00617 { 00618 // 00619 // Top-level window. 00620 // 00621 00622 set_title("Gears"); 00623 00624 // Get automatically redrawn if any of their children changed allocation. 00625 set_reallocate_redraws(true); 00626 00627 add(m_VBox); 00628 00629 // 00630 // Gears scene. 00631 // 00632 00633 m_GearsScene.set_size_request(300, 300); 00634 00635 m_VBox.pack_start(m_GearsScene); 00636 00637 // 00638 // Simple quit button. 00639 // 00640 00641 m_ButtonQuit.signal_clicked().connect( 00642 sigc::mem_fun(*this, &Gears::on_button_quit_clicked)); 00643 00644 m_VBox.pack_start(m_ButtonQuit, Gtk::PACK_SHRINK, 0); 00645 00646 // 00647 // Show window. 00648 // 00649 00650 show_all(); 00651 } 00652 00653 Gears::~Gears() 00654 { 00655 } 00656 00657 void Gears::on_button_quit_clicked() 00658 { 00659 Gtk::Main::quit(); 00660 } 00661 00662 bool Gears::on_key_press_event(GdkEventKey* event) 00663 { 00664 GLfloat x, y, z; 00665 00666 m_GearsScene.get_view_rot(x, y, z); 00667 00668 switch (event->keyval) 00669 { 00670 case GDK_z: 00671 z += 5.0; 00672 break; 00673 case GDK_Z: 00674 z -= 5.0; 00675 break; 00676 case GDK_Up: 00677 x += 5.0; 00678 break; 00679 case GDK_Down: 00680 x -= 5.0; 00681 break; 00682 case GDK_Left: 00683 y += 5.0; 00684 break; 00685 case GDK_Right: 00686 y -= 5.0; 00687 break; 00688 case GDK_Escape: 00689 Gtk::Main::quit(); 00690 break; 00691 default: 00692 return true; 00693 } 00694 00695 m_GearsScene.set_view_rot(x, y, z); 00696 00697 m_GearsScene.invalidate(); 00698 00699 return true; 00700 } 00701 00702 00704 // 00705 // Main. 00706 // 00708 00709 int main(int argc, char** argv) 00710 { 00711 Gtk::Main kit(argc, argv); 00712 00713 // 00714 // Init gtkglextmm. 00715 // 00716 00717 Gtk::GL::init(argc, argv); 00718 00719 // 00720 // Parse arguments. 00721 // 00722 00723 bool is_sync = true; 00724 00725 for (int i = 1; i < argc; ++i) { 00726 if (std::strcmp(argv[i], "--async") == 0) 00727 is_sync = false; 00728 } 00729 00730 // 00731 // Instantiate and run the application. 00732 // 00733 00734 Gears gears(is_sync); 00735 00736 kit.run(gears); 00737 00738 return 0; 00739 }

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