#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"
namespace Trackball {
extern "C" {
#include "trackball.h"
}
}
#define DIG_2_RAD (G_PI / 180.0)
#define RAD_2_DIG (180.0 / G_PI)
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);
};
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";
}
}
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;
}
namespace Shapes
{
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;
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;
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;
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;
}
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();
return false;
}
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)
{
m_ListBase = glGenLists(NUM_SHAPES);
glNewList(m_ListBase + CUBE, GL_COMPILE);
gldrawable->draw_cube(true, 1.5);
glEndList();
glNewList(m_ListBase + SPHERE, GL_COMPILE);
gldrawable->draw_sphere(true, 1.0, 30, 30);
glEndList();
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();
glNewList(m_ListBase + TORUS, GL_COMPILE);
gldrawable->draw_torus(true, 0.4, 0.8, 30, 30);
glEndList();
glNewList(m_ListBase + TETRAHEDRON, GL_COMPILE);
glPushMatrix();
glScalef(1.2, 1.2, 1.2);
gldrawable->draw_tetrahedron(true);
glPopMatrix();
glEndList();
glNewList(m_ListBase + OCTAHEDRON, GL_COMPILE);
glPushMatrix();
glScalef(1.2, 1.2, 1.2);
gldrawable->draw_octahedron(true);
glPopMatrix();
glEndList();
glNewList(m_ListBase + DODECAHEDRON, GL_COMPILE);
glPushMatrix();
glScalef(0.7, 0.7, 0.7);
gldrawable->draw_dodecahedron(true);
glPopMatrix();
glEndList();
glNewList(m_ListBase + ICOSAHEDRON, GL_COMPILE);
glPushMatrix();
glScalef(1.2, 1.2, 1.2);
gldrawable->draw_icosahedron(true);
glPopMatrix();
glEndList();
glNewList(m_ListBase + TEAPOT, GL_COMPILE);
gldrawable->draw_teapot(true, 1.0);
glEndList();
}
void Model::draw(Glib::RefPtr<Gdk::GL::Drawable>& gldrawable)
{
static bool initialized = false;
if (!initialized) {
init_gl(gldrawable);
initialized = true;
}
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);
}
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)
{
Glib::RefPtr<Gdk::GL::Config> glconfig;
glconfig = Gdk::GL::Config::create(Gdk::GL::MODE_RGB |
Gdk::GL::MODE_DEPTH |
Gdk::GL::MODE_DOUBLE);
if (glconfig.is_null()) {
std::cerr << "*** Cannot find the double-buffered visual.\n"
<< "*** Trying single-buffered visual.\n";
glconfig = Gdk::GL::Config::create(Gdk::GL::MODE_RGB |
Gdk::GL::MODE_DEPTH);
if (glconfig.is_null()) {
std::cerr << "*** Cannot find any OpenGL-capable visual.\n";
std::exit(1);
}
}
GLConfigUtil::examine_gl_attrib(glconfig);
set_gl_capability(glconfig);
add_events(Gdk::BUTTON1_MOTION_MASK |
Gdk::BUTTON2_MOTION_MASK |
Gdk::BUTTON_PRESS_MASK |
Gdk::BUTTON_RELEASE_MASK |
Gdk::VISIBILITY_NOTIFY_MASK);
signal_button_press_event().connect(
SigC::bind(SigC::slot(m_View, &View::on_button_press_event), this));
signal_button_release_event().connect(
SigC::bind(SigC::slot(m_View, &View::on_button_release_event), this));
signal_motion_notify_event().connect(
SigC::bind(SigC::slot(m_View, &View::on_motion_notify_event), this));
m_Menu = create_popup_menu();
}
Scene::~Scene()
{
}
void Scene::on_realize()
{
Gtk::DrawingArea::on_realize();
Glib::RefPtr<Gdk::GL::Drawable> gldrawable = get_gl_drawable();
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();
}
bool Scene::on_configure_event(GdkEventConfigure* event)
{
Glib::RefPtr<Gdk::GL::Drawable> gldrawable = get_gl_drawable();
if (!gldrawable->gl_begin(get_gl_context()))
return false;
m_View.frustum(get_width(), get_height());
gldrawable->gl_end();
return true;
}
bool Scene::on_expose_event(GdkEventExpose* event)
{
Glib::RefPtr<Gdk::GL::Drawable> gldrawable = get_gl_drawable();
if (!gldrawable->gl_begin(get_gl_context()))
return false;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
m_View.xform();
m_Model.draw(gldrawable);
if (gldrawable->is_double_buffered())
gldrawable->swap_buffers();
else
glFlush();
gldrawable->gl_end();
return true;
}
bool Scene::on_button_press_event(GdkEventButton* event)
{
if (event->button == 3) {
m_Menu->popup(event->button, event->time);
return true;
}
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();
update();
return true;
}
void Scene::idle_add()
{
if (!m_ConnectionIdle.connected())
m_ConnectionIdle = Glib::signal_idle().connect(
SigC::slot(*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()
{
Gtk::Menu* shapes_menu = Gtk::manage(new Gtk::Menu());
{
Gtk::Menu::MenuList& menu_list = shapes_menu->items();
menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Cube",
SigC::bind(SigC::slot(*this, &Scene::change_shape),
Model::SHAPE_CUBE)));
menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Sphere",
SigC::bind(SigC::slot(*this, &Scene::change_shape),
Model::SHAPE_SPHERE)));
menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Cone",
SigC::bind(SigC::slot(*this, &Scene::change_shape),
Model::SHAPE_CONE)));
menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Torus",
SigC::bind(SigC::slot(*this, &Scene::change_shape),
Model::SHAPE_TORUS)));
menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Tetrahedron",
SigC::bind(SigC::slot(*this, &Scene::change_shape),
Model::SHAPE_TETRAHEDRON)));
menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Octahedron",
SigC::bind(SigC::slot(*this, &Scene::change_shape),
Model::SHAPE_OCTAHEDRON)));
menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Dodecahedron",
SigC::bind(SigC::slot(*this, &Scene::change_shape),
Model::SHAPE_DODECAHEDRON)));
menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Icosahedron",
SigC::bind(SigC::slot(*this, &Scene::change_shape),
Model::SHAPE_ICOSAHEDRON)));
menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Teapot",
SigC::bind(SigC::slot(*this, &Scene::change_shape),
Model::SHAPE_TEAPOT)));
}
Gtk::Menu* materials_menu = Gtk::manage(new Gtk::Menu());
{
Gtk::Menu::MenuList& menu_list = materials_menu->items();
menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Emerald",
SigC::bind(SigC::slot(*this, &Scene::change_material),
&Model::MAT_EMERALD)));
menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Jade",
SigC::bind(SigC::slot(*this, &Scene::change_material),
&Model::MAT_JADE)));
menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Obsidian",
SigC::bind(SigC::slot(*this, &Scene::change_material),
&Model::MAT_OBSIDIAN)));
menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Pearl",
SigC::bind(SigC::slot(*this, &Scene::change_material),
&Model::MAT_PEARL)));
menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Ruby",
SigC::bind(SigC::slot(*this, &Scene::change_material),
&Model::MAT_RUBY)));
menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Turquoise",
SigC::bind(SigC::slot(*this, &Scene::change_material),
&Model::MAT_TURQUOISE)));
menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Brass",
SigC::bind(SigC::slot(*this, &Scene::change_material),
&Model::MAT_BRASS)));
menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Bronze",
SigC::bind(SigC::slot(*this, &Scene::change_material),
&Model::MAT_BRONZE)));
menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Chrome",
SigC::bind(SigC::slot(*this, &Scene::change_material),
&Model::MAT_CHROME)));
menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Copper",
SigC::bind(SigC::slot(*this, &Scene::change_material),
&Model::MAT_COPPER)));
menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Gold",
SigC::bind(SigC::slot(*this, &Scene::change_material),
&Model::MAT_GOLD)));
menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Silver",
SigC::bind(SigC::slot(*this, &Scene::change_material),
&Model::MAT_SILVER)));
}
Gtk::Menu* menu = Gtk::manage(new Gtk::Menu());
{
Gtk::Menu::MenuList& menu_list = menu->items();
menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Shapes",
*shapes_menu));
menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Materials",
*materials_menu));
menu_list.push_back(Gtk::Menu_Helpers::MenuElem("Quit",
SigC::slot(&Gtk::Main::quit)));
}
return menu;
}
const Glib::ustring Application::APP_NAME = "Shapes";
Application::Application()
: m_VBox(false, 0), m_ButtonQuit("Quit")
{
set_title(APP_NAME);
set_reallocate_redraws(true);
add(m_VBox);
m_Scene.set_size_request(300, 300);
m_VBox.pack_start(m_Scene);
m_ButtonQuit.signal_clicked().connect(
SigC::slot(*this, &Application::on_button_quit_clicked));
m_VBox.pack_start(m_ButtonQuit, Gtk::PACK_SHRINK, 0);
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;
}
}
int main(int argc, char** argv)
{
Gtk::Main kit(argc, argv);
Gtk::GL::init(argc, argv);
int major, minor;
Gdk::GL::query_version(major, minor);
std::cout << "OpenGL extension version - "
<< major << "." << minor << std::endl;
Shapes::Application application;
kit.run(application);
return 0;
}