#include <iostream>
#include <cstdlib>
#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>
class SimpleGLScene : public Gtk::GL::DrawingArea
{
public:
explicit SimpleGLScene(const Glib::RefPtr<const Gdk::GL::Config>& config);
SimpleGLScene(const Glib::RefPtr<const Gdk::GL::Config>& config,
const Glib::RefPtr<const Gdk::GL::Context>& share_list);
virtual ~SimpleGLScene();
protected:
virtual void init_gl();
protected:
virtual bool on_configure_event(GdkEventConfigure* event);
virtual bool on_expose_event(GdkEventExpose* event);
public:
void realize() { Gtk::GL::DrawingArea::realize(); }
public:
void set_light_diffuse(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
{ m_LightDiffuse[0] = r; m_LightDiffuse[1] = g; m_LightDiffuse[2] = b; m_LightDiffuse[3] = a; }
void set_light_position(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{ m_LightPosition[0] = x; m_LightPosition[1] = y; m_LightPosition[2] = z; m_LightPosition[3] = w; }
protected:
GLfloat m_LightDiffuse[4];
GLfloat m_LightPosition[4];
};
SimpleGLScene::SimpleGLScene(const Glib::RefPtr<const Gdk::GL::Config>& config)
: Gtk::GL::DrawingArea(config)
{
set_light_diffuse(1.0, 1.0, 1.0, 1.0);
set_light_position(1.0, 1.0, 1.0, 0.0);
}
SimpleGLScene::SimpleGLScene(const Glib::RefPtr<const Gdk::GL::Config>& config,
const Glib::RefPtr<const Gdk::GL::Context>& share_list)
: Gtk::GL::DrawingArea(config, share_list)
{
set_light_diffuse(1.0, 1.0, 1.0, 1.0);
set_light_position(1.0, 1.0, 1.0, 0.0);
}
SimpleGLScene::~SimpleGLScene()
{
}
void SimpleGLScene::init_gl()
{
glLightfv(GL_LIGHT0, GL_DIFFUSE, m_LightDiffuse);
glLightfv(GL_LIGHT0, GL_POSITION, m_LightPosition);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
glClearColor(1.0, 1.0, 1.0, 1.0);
glClearDepth(1.0);
glViewport(0, 0, get_width(), get_height());
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(40.0, 1.0, 1.0, 10.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0, 0.0, 3.0,
0.0, 0.0, 0.0,
0.0, 1.0, 0.0);
glTranslatef(0.0, 0.0, -3.0);
}
bool SimpleGLScene::on_configure_event(GdkEventConfigure* event)
{
Glib::RefPtr<Gdk::GL::Window> glwindow = get_gl_window();
if (!glwindow->gl_begin(get_gl_context()))
return false;
glViewport(0, 0, get_width(), get_height());
glwindow->gl_end();
return true;
}
bool SimpleGLScene::on_expose_event(GdkEventExpose* event)
{
Glib::RefPtr<Gdk::GL::Window> glwindow = get_gl_window();
if (!glwindow->gl_begin(get_gl_context()))
return false;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glCallList(1);
if (glwindow->is_double_buffered())
glwindow->swap_buffers();
else
glFlush();
glwindow->gl_end();
return true;
}
class SimpleGLSceneMain : public SimpleGLScene
{
public:
explicit SimpleGLSceneMain(const Glib::RefPtr<const Gdk::GL::Config>& config);
virtual ~SimpleGLSceneMain();
protected:
virtual void on_realize();
};
SimpleGLSceneMain::SimpleGLSceneMain(const Glib::RefPtr<const Gdk::GL::Config>& config)
: SimpleGLScene(config)
{
}
SimpleGLSceneMain::~SimpleGLSceneMain()
{
}
void SimpleGLSceneMain::on_realize()
{
SimpleGLScene::on_realize();
Glib::RefPtr<Gdk::GL::Window> glwindow = get_gl_window();
if (!glwindow->gl_begin(get_gl_context()))
return;
GLUquadricObj* qobj = gluNewQuadric();
gluQuadricDrawStyle(qobj, GLU_FILL);
glNewList(1, GL_COMPILE);
gluSphere(qobj, 1.0, 20, 20);
glEndList();
init_gl();
glwindow->gl_end();
}
class SimpleGLSceneSub : public SimpleGLScene
{
public:
SimpleGLSceneSub(const Glib::RefPtr<const Gdk::GL::Config>& config,
const Glib::RefPtr<const Gdk::GL::Context>& share_list);
virtual ~SimpleGLSceneSub();
protected:
virtual void on_realize();
};
SimpleGLSceneSub::SimpleGLSceneSub(const Glib::RefPtr<const Gdk::GL::Config>& config,
const Glib::RefPtr<const Gdk::GL::Context>& share_list)
: SimpleGLScene(config, share_list)
{
}
SimpleGLSceneSub::~SimpleGLSceneSub()
{
}
void SimpleGLSceneSub::on_realize()
{
SimpleGLScene::on_realize();
Glib::RefPtr<Gdk::GL::Window> glwindow = get_gl_window();
if (!glwindow->gl_begin(get_gl_context()))
return;
init_gl();
glwindow->gl_end();
}
class Simple : public Gtk::Window
{
public:
explicit Simple(const Glib::RefPtr<const Gdk::GL::Config>& config);
virtual ~Simple();
protected:
void on_button_quit_clicked();
protected:
Gtk::VBox m_VBox;
SimpleGLScene *m_GLScene1;
SimpleGLScene *m_GLScene2;
SimpleGLScene *m_GLScene3;
Gtk::Button m_ButtonQuit;
};
Simple::Simple(const Glib::RefPtr<const Gdk::GL::Config>& config)
: m_VBox(false, 10), m_ButtonQuit("Quit")
{
set_title("share-lists");
set_reallocate_redraws(true);
set_border_width(10);
add(m_VBox);
m_GLScene1 = new SimpleGLSceneMain(config);
m_GLScene1->set_size_request(120, 120);
m_GLScene1->set_light_diffuse(1.0, 0.0, 0.0, 0.0);
m_VBox.pack_start(*m_GLScene1);
m_GLScene1->realize();
Glib::RefPtr<Gdk::GL::Context> glcontext = m_GLScene1->get_gl_context();
m_GLScene2 = new SimpleGLSceneSub(config, glcontext);
m_GLScene2->set_size_request(120, 120);
m_GLScene2->set_light_diffuse(1.0, 1.0, 0.0, 0.0);
m_VBox.pack_start(*m_GLScene2);
m_GLScene3 = new SimpleGLSceneSub(config, glcontext);
m_GLScene3->set_size_request(120, 120);
m_GLScene3->set_light_diffuse(0.0, 1.0, 0.0, 0.0);
m_VBox.pack_start(*m_GLScene3);
m_ButtonQuit.signal_clicked().connect(
SigC::slot(*this, &Simple::on_button_quit_clicked));
m_VBox.pack_start(m_ButtonQuit, Gtk::PACK_SHRINK, 0);
show_all();
}
Simple::~Simple()
{
delete m_GLScene1;
delete m_GLScene2;
delete m_GLScene3;
}
void Simple::on_button_quit_clicked()
{
Gtk::Main::quit();
}
int main(int argc, char** argv)
{
Gtk::Main kit(argc, argv);
Gtk::GL::init(argc, argv);
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);
}
}
Simple simple(glconfig);
kit.run(simple);
return 0;
}