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

shapes.cc

Geometric object rendering example.
// -*- C++ -*- /* * shapes.cc: * shapes demo. * * written by Naofumi Yasufuku <naofumi@users.sourceforge.net> */ #include <iostream> #include <cstdlib> #include <cstring> #include <cmath> #ifdef G_OS_WIN32 #define WIN32_LEAN_AND_MEAN 1 #include <windows.h> #endif #include <GL/gl.h> #include <GL/glu.h> #include "shapes.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; } // // Shapes classes. // namespace Shapes { // // View class implementation. // const float View::NEAR_CLIP = 5.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 = -10.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 = 0.0; const float View::INIT_SCALE = 1.0; const float View::SCALE_MAX = 2.0; const float View::SCALE_MIN = 0.5; const float View::ANIMATE_THRESHOLD = 25.0; View::View() : m_Scale(INIT_SCALE), m_BeginX(0.0), m_BeginY(0.0), m_DX(0.0), m_DY(0.0), m_Animate(false) { 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::add_quats(m_QuatDiff, m_Quat, m_Quat); 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; m_QuatDiff[0] = 0.0; m_QuatDiff[1] = 0.0; m_QuatDiff[2] = 0.0; m_QuatDiff[3] = 1.0; } void View::enable_animation() { m_Animate = true; } void View::disable_animation() { m_Animate = false; m_QuatDiff[0] = 0.0; m_QuatDiff[1] = 0.0; m_QuatDiff[2] = 0.0; m_QuatDiff[3] = 1.0; } bool View::on_button_press_event(GdkEventButton* event, Scene* scene) { if (is_animate()) { if (event->button == 1) { disable_animation(); scene->idle_remove(); scene->invalidate(); } } else { m_QuatDiff[0] = 0.0; m_QuatDiff[1] = 0.0; m_QuatDiff[2] = 0.0; m_QuatDiff[3] = 1.0; } m_BeginX = event->x; m_BeginY = event->y; // don't block return false; } bool View::on_button_release_event(GdkEventButton* event, Scene* scene) { if (!is_animate()) { if (event->button == 1 && ((m_DX*m_DX + m_DY*m_DY) > ANIMATE_THRESHOLD)) { enable_animation(); scene->idle_add(); } } m_DX = 0.0; m_DY = 0.0; // don't block return false; } bool View::on_motion_notify_event(GdkEventMotion* event, Scene* scene) { float w = scene->get_width(); float h = scene->get_height(); float x = event->x; float y = event->y; bool redraw = false; // Rotation. if (event->state & GDK_BUTTON1_MASK) { Trackball::trackball(m_QuatDiff, (2.0 * m_BeginX - w) / w, (h - 2.0 * m_BeginY) / h, (2.0 * x - w) / w, (h - 2.0 * y) / h); m_DX = x - m_BeginX; m_DY = y - m_BeginY; 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->invalidate(); // don't block return false; } // // Model class implementation. // const unsigned int Model::NUM_SHAPES = 9; const Model::ShapeType Model::SHAPE_CUBE = CUBE; const Model::ShapeType Model::SHAPE_SPHERE = SPHERE; const Model::ShapeType Model::SHAPE_CONE = CONE; const Model::ShapeType Model::SHAPE_TORUS = TORUS; const Model::ShapeType Model::SHAPE_TETRAHEDRON = TETRAHEDRON; const Model::ShapeType Model::SHAPE_OCTAHEDRON = OCTAHEDRON; const Model::ShapeType Model::SHAPE_DODECAHEDRON = DODECAHEDRON; const Model::ShapeType Model::SHAPE_ICOSAHEDRON = ICOSAHEDRON; const Model::ShapeType Model::SHAPE_TEAPOT = TEAPOT; const Model::MaterialProp Model::MAT_EMERALD = { {0.0215, 0.1745, 0.0215, 1.0}, {0.07568, 0.61424, 0.07568, 1.0}, {0.633, 0.727811, 0.633, 1.0}, 0.6 }; const Model::MaterialProp Model::MAT_JADE = { {0.135, 0.2225, 0.1575, 1.0}, {0.54, 0.89, 0.63, 1.0}, {0.316228, 0.316228, 0.316228, 1.0}, 0.1 }; const Model::MaterialProp Model::MAT_OBSIDIAN = { {0.05375, 0.05, 0.06625, 1.0}, {0.18275, 0.17, 0.22525, 1.0}, {0.332741, 0.328634, 0.346435, 1.0}, 0.3 }; const Model::MaterialProp Model::MAT_PEARL = { {0.25, 0.20725, 0.20725, 1.0}, {1.0, 0.829, 0.829, 1.0}, {0.296648, 0.296648, 0.296648, 1.0}, 0.088 }; const Model::MaterialProp Model::MAT_RUBY = { {0.1745, 0.01175, 0.01175, 1.0}, {0.61424, 0.04136, 0.04136, 1.0}, {0.727811, 0.626959, 0.626959, 1.0}, 0.6 }; const Model::MaterialProp Model::MAT_TURQUOISE = { {0.1, 0.18725, 0.1745, 1.0}, {0.396, 0.74151, 0.69102, 1.0}, {0.297254, 0.30829, 0.306678, 1.0}, 0.1 }; const Model::MaterialProp Model::MAT_BRASS = { {0.329412, 0.223529, 0.027451, 1.0}, {0.780392, 0.568627, 0.113725, 1.0}, {0.992157, 0.941176, 0.807843, 1.0}, 0.21794872 }; const Model::MaterialProp Model::MAT_BRONZE = { {0.2125, 0.1275, 0.054, 1.0}, {0.714, 0.4284, 0.18144, 1.0}, {0.393548, 0.271906, 0.166721, 1.0}, 0.2 }; const Model::MaterialProp Model::MAT_CHROME = { {0.25, 0.25, 0.25, 1.0}, {0.4, 0.4, 0.4, 1.0}, {0.774597, 0.774597, 0.774597, 1.0}, 0.6 }; const Model::MaterialProp Model::MAT_COPPER = { {0.19125, 0.0735, 0.0225, 1.0}, {0.7038, 0.27048, 0.0828, 1.0}, {0.256777, 0.137622, 0.086014, 1.0}, 0.1 }; const Model::MaterialProp Model::MAT_GOLD = { {0.24725, 0.1995, 0.0745, 1.0}, {0.75164, 0.60648, 0.22648, 1.0}, {0.628281, 0.555802, 0.366065, 1.0}, 0.4 }; const Model::MaterialProp Model::MAT_SILVER = { {0.19225, 0.19225, 0.19225, 1.0}, {0.50754, 0.50754, 0.50754, 1.0}, {0.508273, 0.508273, 0.508273, 1.0}, 0.4 }; Model::Model() : m_ListBase(0), m_CurrentShape(TEAPOT), m_CurrentMat(&MAT_SILVER) { } Model::~Model() { } void Model::init_gl(Glib::RefPtr<Gdk::GL::Drawable>& gldrawable) { /* Shape display lists */ m_ListBase = glGenLists(NUM_SHAPES); /* Cube */ glNewList(m_ListBase + CUBE, GL_COMPILE); gldrawable->draw_cube(true, 1.5); glEndList(); /* Sphere */ glNewList(m_ListBase + SPHERE, GL_COMPILE); gldrawable->draw_sphere(true, 1.0, 30, 30); glEndList(); /* Cone */ glNewList(m_ListBase + CONE, GL_COMPILE); glPushMatrix(); glTranslatef(0.0, 0.0, -1.0); gldrawable->draw_cone(true, 1.0, 2.0, 30, 30); glPopMatrix(); glEndList(); /* Torus */ glNewList(m_ListBase + TORUS, GL_COMPILE); gldrawable->draw_torus(true, 0.4, 0.8, 30, 30); glEndList(); /* Tetrahedron */ glNewList(m_ListBase + TETRAHEDRON, GL_COMPILE); glPushMatrix(); glScalef(1.2, 1.2, 1.2); gldrawable->draw_tetrahedron(true); glPopMatrix(); glEndList(); /* Octahedron */ glNewList(m_ListBase + OCTAHEDRON, GL_COMPILE); glPushMatrix(); glScalef(1.2, 1.2, 1.2); gldrawable->draw_octahedron(true); glPopMatrix(); glEndList(); /* Dodecahedron */ glNewList(m_ListBase + DODECAHEDRON, GL_COMPILE); glPushMatrix(); glScalef(0.7, 0.7, 0.7); gldrawable->draw_dodecahedron(true); glPopMatrix(); glEndList(); /* Icosahedron */ glNewList(m_ListBase + ICOSAHEDRON, GL_COMPILE); glPushMatrix(); glScalef(1.2, 1.2, 1.2); gldrawable->draw_icosahedron(true); glPopMatrix(); glEndList(); /* Teapot */ glNewList(m_ListBase + TEAPOT, GL_COMPILE); gldrawable->draw_teapot(true, 1.0); glEndList(); } void Model::draw(Glib::RefPtr<Gdk::GL::Drawable>& gldrawable) { // Init GL context. static bool initialized = false; if (!initialized) { init_gl(gldrawable); initialized = true; } // Render shape glMaterialfv(GL_FRONT, GL_AMBIENT, m_CurrentMat->ambient); glMaterialfv(GL_FRONT, GL_DIFFUSE, m_CurrentMat->diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, m_CurrentMat->specular); glMaterialf(GL_FRONT, GL_SHININESS, m_CurrentMat->shininess * 128.0); glCallList(m_ListBase + m_CurrentShape); } // // Scene class implementation. // 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, 3.0, 3.0, 0.0 }; const float Scene::LIGHT0_AMBIENT[4] = { 0.0, 0.0, 0.0, 1.0 }; const float Scene::LIGHT0_DIFFUSE[4] = { 1.0, 1.0, 1.0, 1.0 }; const float Scene::LIGHT_MODEL_AMBIENT[4] = { 0.2, 0.2, 0.2, 1.0 }; const float Scene::LIGHT_MODEL_LOCAL_VIEWER[1] = { 0.0 }; Scene::Scene() : m_Menu(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::BUTTON1_MOTION_MASK | Gdk::BUTTON2_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_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_button_release_event().connect( sigc::bind(sigc::mem_fun(m_View, &View::on_button_release_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_AMBIENT, LIGHT0_AMBIENT); glLightfv(GL_LIGHT0, GL_DIFFUSE, LIGHT0_DIFFUSE); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, LIGHT_MODEL_AMBIENT); glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, LIGHT_MODEL_LOCAL_VIEWER); glFrontFace(GL_CW); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_AUTO_NORMAL); glEnable(GL_NORMALIZE); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); 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(gldrawable); // 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_unmap_event(GdkEventAny* event) { idle_remove(); return true; } bool Scene::on_visibility_notify_event(GdkEventVisibility* event) { if (m_View.is_animate()) { if (event->state == GDK_VISIBILITY_FULLY_OBSCURED) idle_remove(); else idle_add(); } return true; } bool Scene::on_idle() { // Invalidate whole window. invalidate(); // Update window synchronously (fast). update(); return true; } void Scene::idle_add() { if (!m_ConnectionIdle.connected()) m_ConnectionIdle = Glib::signal_idle().connect( sigc::mem_fun(*this, &Scene::on_idle), GDK_PRIORITY_REDRAW); } void Scene::idle_remove() { if (m_ConnectionIdle.connected()) m_ConnectionIdle.disconnect(); } void Scene::change_shape(Model::ShapeType shape) { m_Model.set_shape(shape); m_View.reset(); } void Scene::change_material(const Model::MaterialProp* material) { m_Model.set_material(material); } Gtk::Menu* Scene::create_popup_menu() { // Shapes submenu Gtk::Menu* shapes_menu = Gtk::manage(new Gtk::Menu()); { Gtk::Menu::MenuList& menu_list = shapes_menu->items(); // Cube menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Cube", sigc::bind(sigc::mem_fun(*this, &Scene::change_shape), Model::SHAPE_CUBE))); // Sphere menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Sphere", sigc::bind(sigc::mem_fun(*this, &Scene::change_shape), Model::SHAPE_SPHERE))); // Cone menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Cone", sigc::bind(sigc::mem_fun(*this, &Scene::change_shape), Model::SHAPE_CONE))); // Torus menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Torus", sigc::bind(sigc::mem_fun(*this, &Scene::change_shape), Model::SHAPE_TORUS))); // Tetrahedron menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Tetrahedron", sigc::bind(sigc::mem_fun(*this, &Scene::change_shape), Model::SHAPE_TETRAHEDRON))); // Octahedron menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Octahedron", sigc::bind(sigc::mem_fun(*this, &Scene::change_shape), Model::SHAPE_OCTAHEDRON))); // Dodecahedron menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Dodecahedron", sigc::bind(sigc::mem_fun(*this, &Scene::change_shape), Model::SHAPE_DODECAHEDRON))); // Icosahedron menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Icosahedron", sigc::bind(sigc::mem_fun(*this, &Scene::change_shape), Model::SHAPE_ICOSAHEDRON))); // Teapot menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Teapot", sigc::bind(sigc::mem_fun(*this, &Scene::change_shape), Model::SHAPE_TEAPOT))); } // Materials submenu Gtk::Menu* materials_menu = Gtk::manage(new Gtk::Menu()); { Gtk::Menu::MenuList& menu_list = materials_menu->items(); // Emerald menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Emerald", sigc::bind(sigc::mem_fun(*this, &Scene::change_material), &Model::MAT_EMERALD))); // Jade menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Jade", sigc::bind(sigc::mem_fun(*this, &Scene::change_material), &Model::MAT_JADE))); // Obsidian menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Obsidian", sigc::bind(sigc::mem_fun(*this, &Scene::change_material), &Model::MAT_OBSIDIAN))); // Pearl menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Pearl", sigc::bind(sigc::mem_fun(*this, &Scene::change_material), &Model::MAT_PEARL))); // Ruby menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Ruby", sigc::bind(sigc::mem_fun(*this, &Scene::change_material), &Model::MAT_RUBY))); // Turquoise menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Turquoise", sigc::bind(sigc::mem_fun(*this, &Scene::change_material), &Model::MAT_TURQUOISE))); // Brass menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Brass", sigc::bind(sigc::mem_fun(*this, &Scene::change_material), &Model::MAT_BRASS))); // Bronze menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Bronze", sigc::bind(sigc::mem_fun(*this, &Scene::change_material), &Model::MAT_BRONZE))); // Chrome menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Chrome", sigc::bind(sigc::mem_fun(*this, &Scene::change_material), &Model::MAT_CHROME))); // Copper menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Copper", sigc::bind(sigc::mem_fun(*this, &Scene::change_material), &Model::MAT_COPPER))); // Gold menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Gold", sigc::bind(sigc::mem_fun(*this, &Scene::change_material), &Model::MAT_GOLD))); // Silver menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Silver", sigc::bind(sigc::mem_fun(*this, &Scene::change_material), &Model::MAT_SILVER))); } // Root popup menu Gtk::Menu* menu = Gtk::manage(new Gtk::Menu()); { Gtk::Menu::MenuList& menu_list = menu->items(); // Shapes submenu menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Shapes", *shapes_menu)); // Materials submenu menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Materials", *materials_menu)); // 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 = "Shapes"; Application::Application() : m_VBox(false, 0), 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); // // 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_Escape: Gtk::Main::quit(); break; default: return true; } m_Scene.invalidate(); return true; } } // namespace Shapes // // Main. // int main(int argc, char** argv) { Gtk::Main kit(argc, argv); // // Init gtkglextmm. // Gtk::GL::init(argc, argv); // // 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. // Shapes::Application application; kit.run(application); return 0; }
00001 // -*- C++ -*- 00002 /* 00003 * shapes.cc: 00004 * shapes 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 #ifdef G_OS_WIN32 00015 #define WIN32_LEAN_AND_MEAN 1 00016 #include <windows.h> 00017 #endif 00018 00019 #include <GL/gl.h> 00020 #include <GL/glu.h> 00021 00022 #include "shapes.h" 00023 00024 // 00025 // Trackball utilities. 00026 // 00027 namespace Trackball { 00028 extern "C" { 00029 #include "trackball.h" 00030 } 00031 } 00032 00033 #define DIG_2_RAD (G_PI / 180.0) 00034 #define RAD_2_DIG (180.0 / G_PI) 00035 00036 00038 // 00039 // OpenGL frame buffer configuration utilities. 00040 // 00042 00043 struct GLConfigUtil 00044 { 00045 static void print_gl_attrib(const Glib::RefPtr<const Gdk::GL::Config>& glconfig, 00046 const char* attrib_str, 00047 int attrib, 00048 bool is_boolean); 00049 00050 static void examine_gl_attrib(const Glib::RefPtr<const Gdk::GL::Config>& glconfig); 00051 }; 00052 00053 // 00054 // Print a configuration attribute. 00055 // 00056 void GLConfigUtil::print_gl_attrib(const Glib::RefPtr<const Gdk::GL::Config>& glconfig, 00057 const char* attrib_str, 00058 int attrib, 00059 bool is_boolean) 00060 { 00061 int value; 00062 00063 if (glconfig->get_attrib(attrib, value)) 00064 { 00065 std::cout << attrib_str << " = "; 00066 if (is_boolean) 00067 std::cout << (value == true ? "true" : "false") << std::endl; 00068 else 00069 std::cout << value << std::endl; 00070 } 00071 else 00072 { 00073 std::cout << "*** Cannot get " 00074 << attrib_str 00075 << " attribute value\n"; 00076 } 00077 } 00078 00079 // 00080 // Print configuration attributes. 00081 // 00082 void GLConfigUtil::examine_gl_attrib(const Glib::RefPtr<const Gdk::GL::Config>& glconfig) 00083 { 00084 std::cout << "\nOpenGL visual configurations :\n\n"; 00085 00086 std::cout << "glconfig->is_rgba() = " 00087 << (glconfig->is_rgba() ? "true" : "false") 00088 << std::endl; 00089 std::cout << "glconfig->is_double_buffered() = " 00090 << (glconfig->is_double_buffered() ? "true" : "false") 00091 << std::endl; 00092 std::cout << "glconfig->is_stereo() = " 00093 << (glconfig->is_stereo() ? "true" : "false") 00094 << std::endl; 00095 std::cout << "glconfig->has_alpha() = " 00096 << (glconfig->has_alpha() ? "true" : "false") 00097 << std::endl; 00098 std::cout << "glconfig->has_depth_buffer() = " 00099 << (glconfig->has_depth_buffer() ? "true" : "false") 00100 << std::endl; 00101 std::cout << "glconfig->has_stencil_buffer() = " 00102 << (glconfig->has_stencil_buffer() ? "true" : "false") 00103 << std::endl; 00104 std::cout << "glconfig->has_accum_buffer() = " 00105 << (glconfig->has_accum_buffer() ? "true" : "false") 00106 << std::endl; 00107 00108 std::cout << std::endl; 00109 00110 print_gl_attrib(glconfig, "Gdk::GL::USE_GL", Gdk::GL::USE_GL, true); 00111 print_gl_attrib(glconfig, "Gdk::GL::BUFFER_SIZE", Gdk::GL::BUFFER_SIZE, false); 00112 print_gl_attrib(glconfig, "Gdk::GL::LEVEL", Gdk::GL::LEVEL, false); 00113 print_gl_attrib(glconfig, "Gdk::GL::RGBA", Gdk::GL::RGBA, true); 00114 print_gl_attrib(glconfig, "Gdk::GL::DOUBLEBUFFER", Gdk::GL::DOUBLEBUFFER, true); 00115 print_gl_attrib(glconfig, "Gdk::GL::STEREO", Gdk::GL::STEREO, true); 00116 print_gl_attrib(glconfig, "Gdk::GL::AUX_BUFFERS", Gdk::GL::AUX_BUFFERS, false); 00117 print_gl_attrib(glconfig, "Gdk::GL::RED_SIZE", Gdk::GL::RED_SIZE, false); 00118 print_gl_attrib(glconfig, "Gdk::GL::GREEN_SIZE", Gdk::GL::GREEN_SIZE, false); 00119 print_gl_attrib(glconfig, "Gdk::GL::BLUE_SIZE", Gdk::GL::BLUE_SIZE, false); 00120 print_gl_attrib(glconfig, "Gdk::GL::ALPHA_SIZE", Gdk::GL::ALPHA_SIZE, false); 00121 print_gl_attrib(glconfig, "Gdk::GL::DEPTH_SIZE", Gdk::GL::DEPTH_SIZE, false); 00122 print_gl_attrib(glconfig, "Gdk::GL::STENCIL_SIZE", Gdk::GL::STENCIL_SIZE, false); 00123 print_gl_attrib(glconfig, "Gdk::GL::ACCUM_RED_SIZE", Gdk::GL::ACCUM_RED_SIZE, false); 00124 print_gl_attrib(glconfig, "Gdk::GL::ACCUM_GREEN_SIZE", Gdk::GL::ACCUM_GREEN_SIZE, false); 00125 print_gl_attrib(glconfig, "Gdk::GL::ACCUM_BLUE_SIZE", Gdk::GL::ACCUM_BLUE_SIZE, false); 00126 print_gl_attrib(glconfig, "Gdk::GL::ACCUM_ALPHA_SIZE", Gdk::GL::ACCUM_ALPHA_SIZE, false); 00127 00128 std::cout << std::endl; 00129 } 00130 00131 00133 // 00134 // Shapes classes. 00135 // 00137 00138 namespace Shapes 00139 { 00140 00141 // 00142 // View class implementation. 00143 // 00144 00145 const float View::NEAR_CLIP = 5.0; 00146 const float View::FAR_CLIP = 60.0; 00147 00148 const float View::INIT_POS_X = 0.0; 00149 const float View::INIT_POS_Y = 0.0; 00150 const float View::INIT_POS_Z = -10.0; 00151 00152 const float View::INIT_AXIS_X = 1.0; 00153 const float View::INIT_AXIS_Y = 0.0; 00154 const float View::INIT_AXIS_Z = 0.0; 00155 const float View::INIT_ANGLE = 0.0; 00156 00157 const float View::INIT_SCALE = 1.0; 00158 00159 const float View::SCALE_MAX = 2.0; 00160 const float View::SCALE_MIN = 0.5; 00161 00162 const float View::ANIMATE_THRESHOLD = 25.0; 00163 00164 View::View() 00165 : m_Scale(INIT_SCALE), 00166 m_BeginX(0.0), m_BeginY(0.0), 00167 m_DX(0.0), m_DY(0.0), 00168 m_Animate(false) 00169 { 00170 reset(); 00171 } 00172 00173 View::~View() 00174 { 00175 } 00176 00177 void View::frustum(int w, int h) 00178 { 00179 glViewport(0, 0, w, h); 00180 00181 glMatrixMode(GL_PROJECTION); 00182 glLoadIdentity(); 00183 00184 if (w > h) { 00185 float aspect = static_cast<float>(w) / static_cast<float>(h); 00186 glFrustum(-aspect, aspect, -1.0, 1.0, NEAR_CLIP, FAR_CLIP); 00187 } else { 00188 float aspect = static_cast<float>(h) / static_cast<float>(w); 00189 glFrustum(-1.0, 1.0, -aspect, aspect, NEAR_CLIP, FAR_CLIP); 00190 } 00191 00192 glMatrixMode(GL_MODELVIEW); 00193 } 00194 00195 void View::xform() 00196 { 00197 glTranslatef(m_Pos[0], m_Pos[1], m_Pos[2]); 00198 00199 glScalef(m_Scale, m_Scale, m_Scale); 00200 00201 float m[4][4]; 00202 Trackball::add_quats(m_QuatDiff, m_Quat, m_Quat); 00203 Trackball::build_rotmatrix(m, m_Quat); 00204 glMultMatrixf(&m[0][0]); 00205 } 00206 00207 void View::reset() 00208 { 00209 m_Pos[0] = INIT_POS_X; 00210 m_Pos[1] = INIT_POS_Y; 00211 m_Pos[2] = INIT_POS_Z; 00212 00213 float sine = sin(0.5 * INIT_ANGLE * DIG_2_RAD); 00214 m_Quat[0] = INIT_AXIS_X * sine; 00215 m_Quat[1] = INIT_AXIS_Y * sine; 00216 m_Quat[2] = INIT_AXIS_Z * sine; 00217 m_Quat[3] = cos(0.5 * INIT_ANGLE * DIG_2_RAD); 00218 00219 m_Scale = INIT_SCALE; 00220 00221 m_QuatDiff[0] = 0.0; 00222 m_QuatDiff[1] = 0.0; 00223 m_QuatDiff[2] = 0.0; 00224 m_QuatDiff[3] = 1.0; 00225 } 00226 00227 void View::enable_animation() 00228 { 00229 m_Animate = true; 00230 } 00231 00232 void View::disable_animation() 00233 { 00234 m_Animate = false; 00235 00236 m_QuatDiff[0] = 0.0; 00237 m_QuatDiff[1] = 0.0; 00238 m_QuatDiff[2] = 0.0; 00239 m_QuatDiff[3] = 1.0; 00240 } 00241 00242 bool View::on_button_press_event(GdkEventButton* event, 00243 Scene* scene) 00244 { 00245 if (is_animate()) { 00246 if (event->button == 1) { 00247 disable_animation(); 00248 scene->idle_remove(); 00249 scene->invalidate(); 00250 } 00251 } else { 00252 m_QuatDiff[0] = 0.0; 00253 m_QuatDiff[1] = 0.0; 00254 m_QuatDiff[2] = 0.0; 00255 m_QuatDiff[3] = 1.0; 00256 } 00257 00258 m_BeginX = event->x; 00259 m_BeginY = event->y; 00260 00261 // don't block 00262 return false; 00263 } 00264 00265 bool View::on_button_release_event(GdkEventButton* event, 00266 Scene* scene) 00267 { 00268 if (!is_animate()) { 00269 if (event->button == 1 && 00270 ((m_DX*m_DX + m_DY*m_DY) > ANIMATE_THRESHOLD)) { 00271 enable_animation(); 00272 scene->idle_add(); 00273 } 00274 } 00275 00276 m_DX = 0.0; 00277 m_DY = 0.0; 00278 00279 // don't block 00280 return false; 00281 } 00282 00283 bool View::on_motion_notify_event(GdkEventMotion* event, 00284 Scene* scene) 00285 { 00286 float w = scene->get_width(); 00287 float h = scene->get_height(); 00288 float x = event->x; 00289 float y = event->y; 00290 bool redraw = false; 00291 00292 // Rotation. 00293 if (event->state & GDK_BUTTON1_MASK) { 00294 Trackball::trackball(m_QuatDiff, 00295 (2.0 * m_BeginX - w) / w, 00296 (h - 2.0 * m_BeginY) / h, 00297 (2.0 * x - w) / w, 00298 (h - 2.0 * y) / h); 00299 00300 m_DX = x - m_BeginX; 00301 m_DY = y - m_BeginY; 00302 00303 redraw = true; 00304 } 00305 00306 // Scaling. 00307 if (event->state & GDK_BUTTON2_MASK) { 00308 m_Scale = m_Scale * (1.0 + (y - m_BeginY) / h); 00309 if (m_Scale > SCALE_MAX) 00310 m_Scale = SCALE_MAX; 00311 else if (m_Scale < SCALE_MIN) 00312 m_Scale = SCALE_MIN; 00313 00314 redraw = true; 00315 } 00316 00317 m_BeginX = x; 00318 m_BeginY = y; 00319 00320 if (redraw) 00321 scene->invalidate(); 00322 00323 // don't block 00324 return false; 00325 } 00326 00327 00328 // 00329 // Model class implementation. 00330 // 00331 00332 const unsigned int Model::NUM_SHAPES = 9; 00333 00334 const Model::ShapeType Model::SHAPE_CUBE = CUBE; 00335 const Model::ShapeType Model::SHAPE_SPHERE = SPHERE; 00336 const Model::ShapeType Model::SHAPE_CONE = CONE; 00337 const Model::ShapeType Model::SHAPE_TORUS = TORUS; 00338 const Model::ShapeType Model::SHAPE_TETRAHEDRON = TETRAHEDRON; 00339 const Model::ShapeType Model::SHAPE_OCTAHEDRON = OCTAHEDRON; 00340 const Model::ShapeType Model::SHAPE_DODECAHEDRON = DODECAHEDRON; 00341 const Model::ShapeType Model::SHAPE_ICOSAHEDRON = ICOSAHEDRON; 00342 const Model::ShapeType Model::SHAPE_TEAPOT = TEAPOT; 00343 00344 const Model::MaterialProp Model::MAT_EMERALD = { 00345 {0.0215, 0.1745, 0.0215, 1.0}, 00346 {0.07568, 0.61424, 0.07568, 1.0}, 00347 {0.633, 0.727811, 0.633, 1.0}, 00348 0.6 00349 }; 00350 00351 const Model::MaterialProp Model::MAT_JADE = { 00352 {0.135, 0.2225, 0.1575, 1.0}, 00353 {0.54, 0.89, 0.63, 1.0}, 00354 {0.316228, 0.316228, 0.316228, 1.0}, 00355 0.1 00356 }; 00357 00358 const Model::MaterialProp Model::MAT_OBSIDIAN = { 00359 {0.05375, 0.05, 0.06625, 1.0}, 00360 {0.18275, 0.17, 0.22525, 1.0}, 00361 {0.332741, 0.328634, 0.346435, 1.0}, 00362 0.3 00363 }; 00364 00365 const Model::MaterialProp Model::MAT_PEARL = { 00366 {0.25, 0.20725, 0.20725, 1.0}, 00367 {1.0, 0.829, 0.829, 1.0}, 00368 {0.296648, 0.296648, 0.296648, 1.0}, 00369 0.088 00370 }; 00371 00372 const Model::MaterialProp Model::MAT_RUBY = { 00373 {0.1745, 0.01175, 0.01175, 1.0}, 00374 {0.61424, 0.04136, 0.04136, 1.0}, 00375 {0.727811, 0.626959, 0.626959, 1.0}, 00376 0.6 00377 }; 00378 00379 const Model::MaterialProp Model::MAT_TURQUOISE = { 00380 {0.1, 0.18725, 0.1745, 1.0}, 00381 {0.396, 0.74151, 0.69102, 1.0}, 00382 {0.297254, 0.30829, 0.306678, 1.0}, 00383 0.1 00384 }; 00385 00386 const Model::MaterialProp Model::MAT_BRASS = { 00387 {0.329412, 0.223529, 0.027451, 1.0}, 00388 {0.780392, 0.568627, 0.113725, 1.0}, 00389 {0.992157, 0.941176, 0.807843, 1.0}, 00390 0.21794872 00391 }; 00392 00393 const Model::MaterialProp Model::MAT_BRONZE = { 00394 {0.2125, 0.1275, 0.054, 1.0}, 00395 {0.714, 0.4284, 0.18144, 1.0}, 00396 {0.393548, 0.271906, 0.166721, 1.0}, 00397 0.2 00398 }; 00399 00400 const Model::MaterialProp Model::MAT_CHROME = { 00401 {0.25, 0.25, 0.25, 1.0}, 00402 {0.4, 0.4, 0.4, 1.0}, 00403 {0.774597, 0.774597, 0.774597, 1.0}, 00404 0.6 00405 }; 00406 00407 const Model::MaterialProp Model::MAT_COPPER = { 00408 {0.19125, 0.0735, 0.0225, 1.0}, 00409 {0.7038, 0.27048, 0.0828, 1.0}, 00410 {0.256777, 0.137622, 0.086014, 1.0}, 00411 0.1 00412 }; 00413 00414 const Model::MaterialProp Model::MAT_GOLD = { 00415 {0.24725, 0.1995, 0.0745, 1.0}, 00416 {0.75164, 0.60648, 0.22648, 1.0}, 00417 {0.628281, 0.555802, 0.366065, 1.0}, 00418 0.4 00419 }; 00420 00421 const Model::MaterialProp Model::MAT_SILVER = { 00422 {0.19225, 0.19225, 0.19225, 1.0}, 00423 {0.50754, 0.50754, 0.50754, 1.0}, 00424 {0.508273, 0.508273, 0.508273, 1.0}, 00425 0.4 00426 }; 00427 00428 Model::Model() 00429 : m_ListBase(0), 00430 m_CurrentShape(TEAPOT), 00431 m_CurrentMat(&MAT_SILVER) 00432 { 00433 } 00434 00435 Model::~Model() 00436 { 00437 } 00438 00439 void Model::init_gl(Glib::RefPtr<Gdk::GL::Drawable>& gldrawable) 00440 { 00441 /* Shape display lists */ 00442 m_ListBase = glGenLists(NUM_SHAPES); 00443 00444 /* Cube */ 00445 glNewList(m_ListBase + CUBE, GL_COMPILE); 00446 gldrawable->draw_cube(true, 1.5); 00447 glEndList(); 00448 00449 /* Sphere */ 00450 glNewList(m_ListBase + SPHERE, GL_COMPILE); 00451 gldrawable->draw_sphere(true, 1.0, 30, 30); 00452 glEndList(); 00453 00454 /* Cone */ 00455 glNewList(m_ListBase + CONE, GL_COMPILE); 00456 glPushMatrix(); 00457 glTranslatef(0.0, 0.0, -1.0); 00458 gldrawable->draw_cone(true, 1.0, 2.0, 30, 30); 00459 glPopMatrix(); 00460 glEndList(); 00461 00462 /* Torus */ 00463 glNewList(m_ListBase + TORUS, GL_COMPILE); 00464 gldrawable->draw_torus(true, 0.4, 0.8, 30, 30); 00465 glEndList(); 00466 00467 /* Tetrahedron */ 00468 glNewList(m_ListBase + TETRAHEDRON, GL_COMPILE); 00469 glPushMatrix(); 00470 glScalef(1.2, 1.2, 1.2); 00471 gldrawable->draw_tetrahedron(true); 00472 glPopMatrix(); 00473 glEndList(); 00474 00475 /* Octahedron */ 00476 glNewList(m_ListBase + OCTAHEDRON, GL_COMPILE); 00477 glPushMatrix(); 00478 glScalef(1.2, 1.2, 1.2); 00479 gldrawable->draw_octahedron(true); 00480 glPopMatrix(); 00481 glEndList(); 00482 00483 /* Dodecahedron */ 00484 glNewList(m_ListBase + DODECAHEDRON, GL_COMPILE); 00485 glPushMatrix(); 00486 glScalef(0.7, 0.7, 0.7); 00487 gldrawable->draw_dodecahedron(true); 00488 glPopMatrix(); 00489 glEndList(); 00490 00491 /* Icosahedron */ 00492 glNewList(m_ListBase + ICOSAHEDRON, GL_COMPILE); 00493 glPushMatrix(); 00494 glScalef(1.2, 1.2, 1.2); 00495 gldrawable->draw_icosahedron(true); 00496 glPopMatrix(); 00497 glEndList(); 00498 00499 /* Teapot */ 00500 glNewList(m_ListBase + TEAPOT, GL_COMPILE); 00501 gldrawable->draw_teapot(true, 1.0); 00502 glEndList(); 00503 } 00504 00505 void Model::draw(Glib::RefPtr<Gdk::GL::Drawable>& gldrawable) 00506 { 00507 // Init GL context. 00508 static bool initialized = false; 00509 if (!initialized) { 00510 init_gl(gldrawable); 00511 initialized = true; 00512 } 00513 00514 // Render shape 00515 glMaterialfv(GL_FRONT, GL_AMBIENT, m_CurrentMat->ambient); 00516 glMaterialfv(GL_FRONT, GL_DIFFUSE, m_CurrentMat->diffuse); 00517 glMaterialfv(GL_FRONT, GL_SPECULAR, m_CurrentMat->specular); 00518 glMaterialf(GL_FRONT, GL_SHININESS, m_CurrentMat->shininess * 128.0); 00519 glCallList(m_ListBase + m_CurrentShape); 00520 } 00521 00522 00523 // 00524 // Scene class implementation. 00525 // 00526 00527 const float Scene::CLEAR_COLOR[4] = { 0.5, 0.5, 0.8, 1.0 }; 00528 const float Scene::CLEAR_DEPTH = 1.0; 00529 00530 const float Scene::LIGHT0_POSITION[4] = { 0.0, 3.0, 3.0, 0.0 }; 00531 const float Scene::LIGHT0_AMBIENT[4] = { 0.0, 0.0, 0.0, 1.0 }; 00532 const float Scene::LIGHT0_DIFFUSE[4] = { 1.0, 1.0, 1.0, 1.0 }; 00533 00534 const float Scene::LIGHT_MODEL_AMBIENT[4] = { 0.2, 0.2, 0.2, 1.0 }; 00535 const float Scene::LIGHT_MODEL_LOCAL_VIEWER[1] = { 0.0 }; 00536 00537 Scene::Scene() 00538 : m_Menu(0) 00539 { 00540 // 00541 // Configure OpenGL-capable visual. 00542 // 00543 00544 Glib::RefPtr<Gdk::GL::Config> glconfig; 00545 00546 // Try double-buffered visual 00547 glconfig = Gdk::GL::Config::create(Gdk::GL::MODE_RGB | 00548 Gdk::GL::MODE_DEPTH | 00549 Gdk::GL::MODE_DOUBLE); 00550 if (!glconfig) { 00551 std::cerr << "*** Cannot find the double-buffered visual.\n" 00552 << "*** Trying single-buffered visual.\n"; 00553 00554 // Try single-buffered visual 00555 glconfig = Gdk::GL::Config::create(Gdk::GL::MODE_RGB | 00556 Gdk::GL::MODE_DEPTH); 00557 if (!glconfig) { 00558 std::cerr << "*** Cannot find any OpenGL-capable visual.\n"; 00559 std::exit(1); 00560 } 00561 } 00562 00563 // print frame buffer attributes. 00564 GLConfigUtil::examine_gl_attrib(glconfig); 00565 00566 // 00567 // Set OpenGL-capability to the widget. 00568 // 00569 00570 set_gl_capability(glconfig); 00571 00572 // 00573 // Add events. 00574 // 00575 add_events(Gdk::BUTTON1_MOTION_MASK | 00576 Gdk::BUTTON2_MOTION_MASK | 00577 Gdk::BUTTON_PRESS_MASK | 00578 Gdk::BUTTON_RELEASE_MASK | 00579 Gdk::VISIBILITY_NOTIFY_MASK); 00580 00581 // View transformation signals. 00582 signal_button_press_event().connect( 00583 sigc::bind(sigc::mem_fun(m_View, &View::on_button_press_event), this)); 00584 signal_button_release_event().connect( 00585 sigc::bind(sigc::mem_fun(m_View, &View::on_button_release_event), this)); 00586 signal_motion_notify_event().connect( 00587 sigc::bind(sigc::mem_fun(m_View, &View::on_motion_notify_event), this)); 00588 00589 // 00590 // Popup menu. 00591 // 00592 00593 m_Menu = create_popup_menu(); 00594 } 00595 00596 Scene::~Scene() 00597 { 00598 } 00599 00600 void Scene::on_realize() 00601 { 00602 // We need to call the base on_realize() 00603 Gtk::DrawingArea::on_realize(); 00604 00605 // 00606 // Get GL::Drawable. 00607 // 00608 00609 Glib::RefPtr<Gdk::GL::Drawable> gldrawable = get_gl_drawable(); 00610 00611 // 00612 // GL calls. 00613 // 00614 00615 // *** OpenGL BEGIN *** 00616 if (!gldrawable->gl_begin(get_gl_context())) 00617 return; 00618 00619 glClearColor(CLEAR_COLOR[0], CLEAR_COLOR[1], CLEAR_COLOR[2], CLEAR_COLOR[3]); 00620 glClearDepth(CLEAR_DEPTH); 00621 00622 glLightfv(GL_LIGHT0, GL_POSITION, LIGHT0_POSITION); 00623 glLightfv(GL_LIGHT0, GL_AMBIENT, LIGHT0_AMBIENT); 00624 glLightfv(GL_LIGHT0, GL_DIFFUSE, LIGHT0_DIFFUSE); 00625 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, LIGHT_MODEL_AMBIENT); 00626 glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, LIGHT_MODEL_LOCAL_VIEWER); 00627 00628 glFrontFace(GL_CW); 00629 glEnable(GL_LIGHTING); 00630 glEnable(GL_LIGHT0); 00631 glEnable(GL_AUTO_NORMAL); 00632 glEnable(GL_NORMALIZE); 00633 glEnable(GL_DEPTH_TEST); 00634 glDepthFunc(GL_LESS); 00635 00636 gldrawable->gl_end(); 00637 // *** OpenGL END *** 00638 } 00639 00640 bool Scene::on_configure_event(GdkEventConfigure* event) 00641 { 00642 // 00643 // Get GL::Drawable. 00644 // 00645 00646 Glib::RefPtr<Gdk::GL::Drawable> gldrawable = get_gl_drawable(); 00647 00648 // 00649 // GL calls. 00650 // 00651 00652 // *** OpenGL BEGIN *** 00653 if (!gldrawable->gl_begin(get_gl_context())) 00654 return false; 00655 00656 m_View.frustum(get_width(), get_height()); 00657 00658 gldrawable->gl_end(); 00659 // *** OpenGL END *** 00660 00661 return true; 00662 } 00663 00664 bool Scene::on_expose_event(GdkEventExpose* event) 00665 { 00666 // 00667 // Get GL::Drawable. 00668 // 00669 00670 Glib::RefPtr<Gdk::GL::Drawable> gldrawable = get_gl_drawable(); 00671 00672 // 00673 // GL calls. 00674 // 00675 00676 // *** OpenGL BEGIN *** 00677 if (!gldrawable->gl_begin(get_gl_context())) 00678 return false; 00679 00680 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 00681 00682 glLoadIdentity(); 00683 00684 // View transformation. 00685 m_View.xform(); 00686 00687 // Logo model. 00688 m_Model.draw(gldrawable); 00689 00690 // Swap buffers. 00691 if (gldrawable->is_double_buffered()) 00692 gldrawable->swap_buffers(); 00693 else 00694 glFlush(); 00695 00696 gldrawable->gl_end(); 00697 // *** OpenGL END *** 00698 00699 return true; 00700 } 00701 00702 bool Scene::on_button_press_event(GdkEventButton* event) 00703 { 00704 if (event->button == 3) { 00705 m_Menu->popup(event->button, event->time); 00706 return true; 00707 } 00708 00709 // don't block 00710 return false; 00711 } 00712 00713 bool Scene::on_unmap_event(GdkEventAny* event) 00714 { 00715 idle_remove(); 00716 00717 return true; 00718 } 00719 00720 bool Scene::on_visibility_notify_event(GdkEventVisibility* event) 00721 { 00722 if (m_View.is_animate()) { 00723 if (event->state == GDK_VISIBILITY_FULLY_OBSCURED) 00724 idle_remove(); 00725 else 00726 idle_add(); 00727 } 00728 00729 return true; 00730 } 00731 00732 bool Scene::on_idle() 00733 { 00734 // Invalidate whole window. 00735 invalidate(); 00736 // Update window synchronously (fast). 00737 update(); 00738 00739 return true; 00740 } 00741 00742 void Scene::idle_add() 00743 { 00744 if (!m_ConnectionIdle.connected()) 00745 m_ConnectionIdle = Glib::signal_idle().connect( 00746 sigc::mem_fun(*this, &Scene::on_idle), GDK_PRIORITY_REDRAW); 00747 } 00748 00749 void Scene::idle_remove() 00750 { 00751 if (m_ConnectionIdle.connected()) 00752 m_ConnectionIdle.disconnect(); 00753 } 00754 00755 void Scene::change_shape(Model::ShapeType shape) 00756 { 00757 m_Model.set_shape(shape); 00758 m_View.reset(); 00759 } 00760 00761 void Scene::change_material(const Model::MaterialProp* material) 00762 { 00763 m_Model.set_material(material); 00764 } 00765 00766 Gtk::Menu* Scene::create_popup_menu() 00767 { 00768 00769 // Shapes submenu 00770 Gtk::Menu* shapes_menu = Gtk::manage(new Gtk::Menu()); 00771 { 00772 Gtk::Menu::MenuList& menu_list = shapes_menu->items(); 00773 00774 // Cube 00775 menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Cube", 00776 sigc::bind(sigc::mem_fun(*this, &Scene::change_shape), 00777 Model::SHAPE_CUBE))); 00778 00779 // Sphere 00780 menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Sphere", 00781 sigc::bind(sigc::mem_fun(*this, &Scene::change_shape), 00782 Model::SHAPE_SPHERE))); 00783 00784 // Cone 00785 menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Cone", 00786 sigc::bind(sigc::mem_fun(*this, &Scene::change_shape), 00787 Model::SHAPE_CONE))); 00788 00789 // Torus 00790 menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Torus", 00791 sigc::bind(sigc::mem_fun(*this, &Scene::change_shape), 00792 Model::SHAPE_TORUS))); 00793 00794 // Tetrahedron 00795 menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Tetrahedron", 00796 sigc::bind(sigc::mem_fun(*this, &Scene::change_shape), 00797 Model::SHAPE_TETRAHEDRON))); 00798 00799 // Octahedron 00800 menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Octahedron", 00801 sigc::bind(sigc::mem_fun(*this, &Scene::change_shape), 00802 Model::SHAPE_OCTAHEDRON))); 00803 00804 // Dodecahedron 00805 menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Dodecahedron", 00806 sigc::bind(sigc::mem_fun(*this, &Scene::change_shape), 00807 Model::SHAPE_DODECAHEDRON))); 00808 00809 // Icosahedron 00810 menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Icosahedron", 00811 sigc::bind(sigc::mem_fun(*this, &Scene::change_shape), 00812 Model::SHAPE_ICOSAHEDRON))); 00813 00814 // Teapot 00815 menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Teapot", 00816 sigc::bind(sigc::mem_fun(*this, &Scene::change_shape), 00817 Model::SHAPE_TEAPOT))); 00818 00819 } 00820 00821 // Materials submenu 00822 Gtk::Menu* materials_menu = Gtk::manage(new Gtk::Menu()); 00823 { 00824 Gtk::Menu::MenuList& menu_list = materials_menu->items(); 00825 00826 // Emerald 00827 menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Emerald", 00828 sigc::bind(sigc::mem_fun(*this, &Scene::change_material), 00829 &Model::MAT_EMERALD))); 00830 00831 // Jade 00832 menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Jade", 00833 sigc::bind(sigc::mem_fun(*this, &Scene::change_material), 00834 &Model::MAT_JADE))); 00835 00836 // Obsidian 00837 menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Obsidian", 00838 sigc::bind(sigc::mem_fun(*this, &Scene::change_material), 00839 &Model::MAT_OBSIDIAN))); 00840 00841 // Pearl 00842 menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Pearl", 00843 sigc::bind(sigc::mem_fun(*this, &Scene::change_material), 00844 &Model::MAT_PEARL))); 00845 00846 // Ruby 00847 menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Ruby", 00848 sigc::bind(sigc::mem_fun(*this, &Scene::change_material), 00849 &Model::MAT_RUBY))); 00850 00851 // Turquoise 00852 menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Turquoise", 00853 sigc::bind(sigc::mem_fun(*this, &Scene::change_material), 00854 &Model::MAT_TURQUOISE))); 00855 00856 // Brass 00857 menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Brass", 00858 sigc::bind(sigc::mem_fun(*this, &Scene::change_material), 00859 &Model::MAT_BRASS))); 00860 00861 // Bronze 00862 menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Bronze", 00863 sigc::bind(sigc::mem_fun(*this, &Scene::change_material), 00864 &Model::MAT_BRONZE))); 00865 00866 // Chrome 00867 menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Chrome", 00868 sigc::bind(sigc::mem_fun(*this, &Scene::change_material), 00869 &Model::MAT_CHROME))); 00870 00871 // Copper 00872 menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Copper", 00873 sigc::bind(sigc::mem_fun(*this, &Scene::change_material), 00874 &Model::MAT_COPPER))); 00875 00876 // Gold 00877 menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Gold", 00878 sigc::bind(sigc::mem_fun(*this, &Scene::change_material), 00879 &Model::MAT_GOLD))); 00880 00881 // Silver 00882 menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Silver", 00883 sigc::bind(sigc::mem_fun(*this, &Scene::change_material), 00884 &Model::MAT_SILVER))); 00885 00886 } 00887 00888 // Root popup menu 00889 Gtk::Menu* menu = Gtk::manage(new Gtk::Menu()); 00890 { 00891 Gtk::Menu::MenuList& menu_list = menu->items(); 00892 00893 // Shapes submenu 00894 menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Shapes", 00895 *shapes_menu)); 00896 00897 // Materials submenu 00898 menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Materials", 00899 *materials_menu)); 00900 00901 // Quit 00902 menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Quit", 00903 sigc::ptr_fun(&Gtk::Main::quit))); 00904 } 00905 00906 return menu; 00907 } 00908 00909 00910 // 00911 // Application class implementation. 00912 // 00913 00914 const Glib::ustring Application::APP_NAME = "Shapes"; 00915 00916 Application::Application() 00917 : m_VBox(false, 0), m_ButtonQuit("Quit") 00918 { 00919 // 00920 // Top-level window. 00921 // 00922 00923 set_title(APP_NAME); 00924 00925 // Get automatically redrawn if any of their children changed allocation. 00926 set_reallocate_redraws(true); 00927 00928 add(m_VBox); 00929 00930 // 00931 // Scene. 00932 // 00933 00934 m_Scene.set_size_request(300, 300); 00935 00936 m_VBox.pack_start(m_Scene); 00937 00938 // 00939 // Simple quit button. 00940 // 00941 00942 m_ButtonQuit.signal_clicked().connect( 00943 sigc::mem_fun(*this, &Application::on_button_quit_clicked)); 00944 00945 m_VBox.pack_start(m_ButtonQuit, Gtk::PACK_SHRINK, 0); 00946 00947 // 00948 // Show window. 00949 // 00950 00951 show_all(); 00952 } 00953 00954 Application::~Application() 00955 { 00956 } 00957 00958 void Application::on_button_quit_clicked() 00959 { 00960 Gtk::Main::quit(); 00961 } 00962 00963 bool Application::on_key_press_event(GdkEventKey* event) 00964 { 00965 switch (event->keyval) { 00966 case GDK_Escape: 00967 Gtk::Main::quit(); 00968 break; 00969 default: 00970 return true; 00971 } 00972 00973 m_Scene.invalidate(); 00974 00975 return true; 00976 } 00977 00978 00979 } // namespace Shapes 00980 00981 00983 // 00984 // Main. 00985 // 00987 00988 int main(int argc, char** argv) 00989 { 00990 Gtk::Main kit(argc, argv); 00991 00992 // 00993 // Init gtkglextmm. 00994 // 00995 00996 Gtk::GL::init(argc, argv); 00997 00998 // 00999 // Query OpenGL extension version. 01000 // 01001 01002 int major, minor; 01003 Gdk::GL::query_version(major, minor); 01004 std::cout << "OpenGL extension version - " 01005 << major << "." << minor << std::endl; 01006 01007 // 01008 // Instantiate and run the application. 01009 // 01010 01011 Shapes::Application application; 01012 01013 kit.run(application); 01014 01015 return 0; 01016 }

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