00001
00002
00003
00004
00005
00006
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
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
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
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
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
00135
00137
00138
namespace Shapes
00139 {
00140
00141
00142
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
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
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
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
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
00324
return false;
00325 }
00326
00327
00328
00329
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
00442 m_ListBase = glGenLists(NUM_SHAPES);
00443
00444
00445 glNewList(m_ListBase + CUBE, GL_COMPILE);
00446 gldrawable->draw_cube(
true, 1.5);
00447 glEndList();
00448
00449
00450 glNewList(m_ListBase + SPHERE, GL_COMPILE);
00451 gldrawable->draw_sphere(
true, 1.0, 30, 30);
00452 glEndList();
00453
00454
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
00463 glNewList(m_ListBase + TORUS, GL_COMPILE);
00464 gldrawable->draw_torus(
true, 0.4, 0.8, 30, 30);
00465 glEndList();
00466
00467
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
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
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
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
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
00508
static bool initialized =
false;
00509
if (!initialized) {
00510 init_gl(gldrawable);
00511 initialized =
true;
00512 }
00513
00514
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
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
00542
00543
00544 Glib::RefPtr<Gdk::GL::Config> glconfig;
00545
00546
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
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
00564 GLConfigUtil::examine_gl_attrib(glconfig);
00565
00566
00567
00568
00569
00570 set_gl_capability(glconfig);
00571
00572
00573
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
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
00591
00592
00593 m_Menu = create_popup_menu();
00594 }
00595
00596 Scene::~Scene()
00597 {
00598 }
00599
00600
void Scene::on_realize()
00601 {
00602
00603 Gtk::DrawingArea::on_realize();
00604
00605
00606
00607
00608
00609 Glib::RefPtr<Gdk::GL::Drawable> gldrawable = get_gl_drawable();
00610
00611
00612
00613
00614
00615
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
00638 }
00639
00640
bool Scene::on_configure_event(GdkEventConfigure* event)
00641 {
00642
00643
00644
00645
00646 Glib::RefPtr<Gdk::GL::Drawable> gldrawable = get_gl_drawable();
00647
00648
00649
00650
00651
00652
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
00660
00661
return true;
00662 }
00663
00664
bool Scene::on_expose_event(GdkEventExpose* event)
00665 {
00666
00667
00668
00669
00670 Glib::RefPtr<Gdk::GL::Drawable> gldrawable = get_gl_drawable();
00671
00672
00673
00674
00675
00676
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
00685 m_View.xform();
00686
00687
00688 m_Model.draw(gldrawable);
00689
00690
00691
if (gldrawable->is_double_buffered())
00692 gldrawable->swap_buffers();
00693
else
00694 glFlush();
00695
00696 gldrawable->gl_end();
00697
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
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
00735 invalidate();
00736
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
00770 Gtk::Menu* shapes_menu = Gtk::manage(
new Gtk::Menu());
00771 {
00772 Gtk::Menu::MenuList& menu_list = shapes_menu->items();
00773
00774
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
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
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
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
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
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
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
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
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
00822 Gtk::Menu* materials_menu = Gtk::manage(
new Gtk::Menu());
00823 {
00824 Gtk::Menu::MenuList& menu_list = materials_menu->items();
00825
00826
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
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
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
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
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
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
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
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
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
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
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
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
00889 Gtk::Menu* menu = Gtk::manage(
new Gtk::Menu());
00890 {
00891 Gtk::Menu::MenuList& menu_list = menu->items();
00892
00893
00894 menu_list.push_back(Gtk::Menu_Helpers::MenuElem(
"Shapes",
00895 *shapes_menu));
00896
00897
00898 menu_list.push_back(Gtk::Menu_Helpers::MenuElem(
"Materials",
00899 *materials_menu));
00900
00901
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
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
00921
00922
00923 set_title(APP_NAME);
00924
00925
00926 set_reallocate_redraws(
true);
00927
00928 add(m_VBox);
00929
00930
00931
00932
00933
00934 m_Scene.set_size_request(300, 300);
00935
00936 m_VBox.pack_start(m_Scene);
00937
00938
00939
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
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 }
00980
00981
00983
00984
00985
00987
00988
int main(
int argc,
char** argv)
00989 {
00990 Gtk::Main kit(argc, argv);
00991
00992
00993
00994
00995
00996
Gtk::GL::init(argc, argv);
00997
00998
00999
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
01009
01010
01011 Shapes::Application application;
01012
01013 kit.run(application);
01014
01015
return 0;
01016 }