2 * This file is part of the hkl3d library.
3 * inspired from logo-model.c of the GtkGLExt logo models.
4 * written by Naofumi Yasufuku <naofumi@users.sourceforge.net>
6 * The hkl library is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * The hkl library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with the hkl library. If not, see <http://www.gnu.org/licenses/>.
19 * Copyright (C) 2010 Synchrotron SOLEIL
20 * L'Orme des Merisiers Saint-Aubin
21 * BP 48 91192 GIF-sur-YVETTE CEDEX
23 * Authors: Oussama Sboui <oussama.sboui@synchrotron-soleil.fr>
24 * Picca Frédéric-Emmanuel <picca@synchrotron-soleil.fr>
29 #include "hkl3d-gui-scene.h"
31 ///////////////////////////////////////////////////////////////////////////////
33 // OpenGL frame buffer configuration utilities.
35 ///////////////////////////////////////////////////////////////////////////////
39 static void print_gl_attrib(const Glib::RefPtr
<const Gdk::GL::Config
>& glconfig
,
40 const char* attrib_str
,
44 static void examine_gl_attrib(const Glib::RefPtr
<const Gdk::GL::Config
>& glconfig
);
48 // Print a configuration attribute.
50 void GLConfigUtil::print_gl_attrib(const Glib::RefPtr
<const Gdk::GL::Config
>& glconfig
,
51 const char* attrib_str
,
57 if (glconfig
->get_attrib(attrib
, value
)){
58 std::cout
<< attrib_str
<< " = ";
60 std::cout
<< (value
== true ? "true" : "false") << std::endl
;
62 std::cout
<< value
<< std::endl
;
64 std::cout
<< "*** Cannot get "
66 << " attribute value\n";
71 // Print configuration attributes.
73 void GLConfigUtil::examine_gl_attrib(const Glib::RefPtr
<const Gdk::GL::Config
>& glconfig
)
75 std::cout
<< "\nOpenGL visual configurations :\n\n";
77 std::cout
<< "glconfig->is_rgba() = "
78 << (glconfig
->is_rgba() ? "true" : "false")
80 std::cout
<< "glconfig->is_double_buffered() = "
81 << (glconfig
->is_double_buffered() ? "true" : "false")
83 std::cout
<< "glconfig->is_stereo() = "
84 << (glconfig
->is_stereo() ? "true" : "false")
86 std::cout
<< "glconfig->has_alpha() = "
87 << (glconfig
->has_alpha() ? "true" : "false")
89 std::cout
<< "glconfig->has_depth_buffer() = "
90 << (glconfig
->has_depth_buffer() ? "true" : "false")
92 std::cout
<< "glconfig->has_stencil_buffer() = "
93 << (glconfig
->has_stencil_buffer() ? "true" : "false")
95 std::cout
<< "glconfig->has_accum_buffer() = "
96 << (glconfig
->has_accum_buffer() ? "true" : "false")
99 std::cout
<< std::endl
;
101 print_gl_attrib(glconfig
, "Gdk::GL::USE_GL", Gdk::GL::USE_GL
, true);
102 print_gl_attrib(glconfig
, "Gdk::GL::BUFFER_SIZE", Gdk::GL::BUFFER_SIZE
, false);
103 print_gl_attrib(glconfig
, "Gdk::GL::LEVEL", Gdk::GL::LEVEL
, false);
104 print_gl_attrib(glconfig
, "Gdk::GL::RGBA", Gdk::GL::RGBA
, true);
105 print_gl_attrib(glconfig
, "Gdk::GL::DOUBLEBUFFER", Gdk::GL::DOUBLEBUFFER
, true);
106 print_gl_attrib(glconfig
, "Gdk::GL::STEREO", Gdk::GL::STEREO
, true);
107 print_gl_attrib(glconfig
, "Gdk::GL::AUX_BUFFERS", Gdk::GL::AUX_BUFFERS
, false);
108 print_gl_attrib(glconfig
, "Gdk::GL::RED_SIZE", Gdk::GL::RED_SIZE
, false);
109 print_gl_attrib(glconfig
, "Gdk::GL::GREEN_SIZE", Gdk::GL::GREEN_SIZE
, false);
110 print_gl_attrib(glconfig
, "Gdk::GL::BLUE_SIZE", Gdk::GL::BLUE_SIZE
, false);
111 print_gl_attrib(glconfig
, "Gdk::GL::ALPHA_SIZE", Gdk::GL::ALPHA_SIZE
, false);
112 print_gl_attrib(glconfig
, "Gdk::GL::DEPTH_SIZE", Gdk::GL::DEPTH_SIZE
, false);
113 print_gl_attrib(glconfig
, "Gdk::GL::STENCIL_SIZE", Gdk::GL::STENCIL_SIZE
, false);
114 print_gl_attrib(glconfig
, "Gdk::GL::ACCUM_RED_SIZE", Gdk::GL::ACCUM_RED_SIZE
, false);
115 print_gl_attrib(glconfig
, "Gdk::GL::ACCUM_GREEN_SIZE", Gdk::GL::ACCUM_GREEN_SIZE
, false);
116 print_gl_attrib(glconfig
, "Gdk::GL::ACCUM_BLUE_SIZE", Gdk::GL::ACCUM_BLUE_SIZE
, false);
117 print_gl_attrib(glconfig
, "Gdk::GL::ACCUM_ALPHA_SIZE", Gdk::GL::ACCUM_ALPHA_SIZE
, false);
119 std::cout
<< std::endl
;
125 // Scene class implementation.
127 const unsigned int Scene::TIMEOUT_INTERVAL
= 1000;
129 const float Scene::CLEAR_COLOR
[4] = { 0.5, 0.5, 0.8, 1.0 };
130 const float Scene::CLEAR_DEPTH
= 1.0;
132 const float Scene::LIGHT0_POSITION
[4] = { 0.0, 0.0, 30.0, 0.0 };
133 const float Scene::LIGHT0_DIFFUSE
[4] = { 1.0, 1.0, 1.0, 1.0 };
134 const float Scene::LIGHT0_SPECULAR
[4] = { 1.0, 1.0, 1.0, 1.0 };
136 Scene::Scene(unsigned int rot_count
,
138 : m_Menu(0), m_Model(rot_count
, enable_anim
)
141 // Configure OpenGL-capable visual.
143 Glib::RefPtr
<Gdk::GL::Config
> glconfig
;
145 // Try double-buffered visual
146 glconfig
= Gdk::GL::Config::create(Gdk::GL::MODE_RGB
|
147 Gdk::GL::MODE_DEPTH
|
148 Gdk::GL::MODE_DOUBLE
);
150 std::cerr
<< "*** Cannot find the double-buffered visual.\n"
151 << "*** Trying single-buffered visual.\n";
153 // Try single-buffered visual
154 glconfig
= Gdk::GL::Config::create(Gdk::GL::MODE_RGB
|
155 Gdk::GL::MODE_DEPTH
);
157 std::cerr
<< "*** Cannot find any OpenGL-capable visual.\n";
162 // print frame buffer attributes.
163 GLConfigUtil::examine_gl_attrib(glconfig
);
166 // Set OpenGL-capability to the widget.
168 this->set_gl_capability(glconfig
);
173 this->add_events(Gdk::BUTTON1_MOTION_MASK
|
174 Gdk::BUTTON2_MOTION_MASK
|
175 Gdk::BUTTON_PRESS_MASK
|
176 Gdk::VISIBILITY_NOTIFY_MASK
);
178 // View transformation signals.
179 signal_button_press_event().connect(
180 sigc::bind(sigc::mem_fun(m_View
, &View::on_button_press_event
), this));
181 signal_motion_notify_event().connect(
182 sigc::bind(sigc::mem_fun(m_View
, &View::on_motion_notify_event
), this));
187 m_Menu
= this->create_popup_menu();
194 void Scene::on_realize(void)
196 // We need to call the base on_realize()
197 Gtk::DrawingArea::on_realize();
202 Glib::RefPtr
<Gdk::GL::Drawable
> gldrawable
= this->get_gl_drawable();
207 // *** OpenGL BEGIN ***
208 if (!gldrawable
->gl_begin(this->get_gl_context()))
211 glClearColor(CLEAR_COLOR
[0], CLEAR_COLOR
[1], CLEAR_COLOR
[2], CLEAR_COLOR
[3]);
212 glClearDepth(CLEAR_DEPTH
);
214 glLightfv(GL_LIGHT0
, GL_POSITION
, LIGHT0_POSITION
);
215 glLightfv(GL_LIGHT0
, GL_DIFFUSE
, LIGHT0_DIFFUSE
);
216 glLightfv(GL_LIGHT0
, GL_SPECULAR
, LIGHT0_SPECULAR
);
218 glEnable(GL_LIGHTING
);
221 glEnable(GL_DEPTH_TEST
);
223 glShadeModel(GL_SMOOTH
);
225 gldrawable
->gl_end();
226 // *** OpenGL END ***
229 bool Scene::on_configure_event(GdkEventConfigure
* event
)
234 Glib::RefPtr
<Gdk::GL::Drawable
> gldrawable
= this->get_gl_drawable();
239 // *** OpenGL BEGIN ***
240 if (!gldrawable
->gl_begin(this->get_gl_context()))
243 m_View
.frustum(this->get_width(), this->get_height());
245 gldrawable
->gl_end();
246 // *** OpenGL END ***
251 bool Scene::on_expose_event(GdkEventExpose
* event
)
256 Glib::RefPtr
<Gdk::GL::Drawable
> gldrawable
= get_gl_drawable();
261 // *** OpenGL BEGIN ***
262 if (!gldrawable
->gl_begin(get_gl_context()))
265 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
269 // View transformation.
276 if (gldrawable
->is_double_buffered())
277 gldrawable
->swap_buffers();
281 gldrawable
->gl_end();
282 // *** OpenGL END ***
287 bool Scene::on_button_press_event(GdkEventButton
* event
)
289 if (event
->button
== 3) {
290 m_Menu
->popup(event
->button
, event
->time
);
298 bool Scene::on_map_event(GdkEventAny
* event
)
300 if (m_Model
.anim_is_enabled())
306 bool Scene::on_unmap_event(GdkEventAny
* event
)
308 this->timeout_remove();
313 bool Scene::on_visibility_notify_event(GdkEventVisibility
* event
)
315 if (m_Model
.anim_is_enabled()) {
316 if (event
->state
== GDK_VISIBILITY_FULLY_OBSCURED
)
317 this->timeout_remove();
325 bool Scene::on_timeout(void)
327 // Invalidate whole window.
329 // Update window synchronously (fast).
335 void Scene::timeout_add(void)
337 if (!m_ConnectionTimeout
.connected())
338 m_ConnectionTimeout
= Glib::signal_timeout().connect(
339 sigc::mem_fun(*this, &Scene::on_timeout
), TIMEOUT_INTERVAL
);
342 void Scene::timeout_remove(void)
344 if (m_ConnectionTimeout
.connected())
345 m_ConnectionTimeout
.disconnect();
348 void Scene::toggle_anim(void)
350 if (m_Model
.anim_is_enabled()) {
351 m_Model
.disable_anim();
352 this->timeout_remove();
354 m_Model
.enable_anim();
359 void Scene::init_anim(void)
362 m_Model
.reset_anim();
367 Gtk::Menu
* Scene::create_popup_menu(void)
369 Gtk::Menu
* menu
= Gtk::manage(new Gtk::Menu());
371 Gtk::Menu::MenuList
& menu_list
= menu
->items();
375 Gtk::Menu_Helpers::MenuElem("Toggle Animation",
376 sigc::mem_fun(*this, &Scene::toggle_anim
)));
380 Gtk::Menu_Helpers::MenuElem("Initialize",
381 sigc::mem_fun(*this, &Scene::init_anim
)));
385 Gtk::Menu_Helpers::MenuElem("Quit",
386 sigc::ptr_fun(&Gtk::Main::quit
)));