#ifndef _SHAPES_H
#define _SHAPES_H
#include <gtkmm.h>
#include <gtkglmm.h>
namespace Shapes
{
class Scene;
class View : public SigC::Object
{
friend class Scene;
public:
static const float NEAR_CLIP;
static const float FAR_CLIP;
static const float INIT_POS_X;
static const float INIT_POS_Y;
static const float INIT_POS_Z;
static const float INIT_AXIS_X;
static const float INIT_AXIS_Y;
static const float INIT_AXIS_Z;
static const float INIT_ANGLE;
static const float INIT_SCALE;
static const float SCALE_MAX;
static const float SCALE_MIN;
static const float ANIMATE_THRESHOLD;
public:
View();
virtual ~View();
public:
void frustum(int w, int h);
void xform();
void reset();
void set_pos(float x, float y, float z)
{ m_Pos[0] = x; m_Pos[1] = y; m_Pos[2] = z; }
void set_quat(float q0, float q1, float q2, float q3)
{ m_Quat[0] = q0; m_Quat[1] = q1; m_Quat[2] = q2; m_Quat[3] = q3; }
void set_scale(float scale)
{ m_Scale = scale; }
void enable_animation();
void disable_animation();
bool is_animate() const
{ return m_Animate; }
protected:
virtual bool on_button_press_event(GdkEventButton* event, Scene* scene);
virtual bool on_button_release_event(GdkEventButton* event, Scene* scene);
virtual bool on_motion_notify_event(GdkEventMotion* event, Scene* scene);
private:
float m_Pos[3];
float m_Quat[4];
float m_Scale;
float m_QuatDiff[4];
float m_BeginX;
float m_BeginY;
float m_DX;
float m_DY;
bool m_Animate;
};
class Model
{
friend class Scene;
public:
static const unsigned int NUM_SHAPES;
enum ShapeType
{
CUBE,
SPHERE,
CONE,
TORUS,
TETRAHEDRON,
OCTAHEDRON,
DODECAHEDRON,
ICOSAHEDRON,
TEAPOT,
};
static const ShapeType SHAPE_CUBE;
static const ShapeType SHAPE_SPHERE;
static const ShapeType SHAPE_CONE;
static const ShapeType SHAPE_TORUS;
static const ShapeType SHAPE_TETRAHEDRON;
static const ShapeType SHAPE_OCTAHEDRON;
static const ShapeType SHAPE_DODECAHEDRON;
static const ShapeType SHAPE_ICOSAHEDRON;
static const ShapeType SHAPE_TEAPOT;
public:
struct MaterialProp
{
GLfloat ambient[4];
GLfloat diffuse[4];
GLfloat specular[4];
GLfloat shininess;
};
static const MaterialProp MAT_EMERALD;
static const MaterialProp MAT_JADE;
static const MaterialProp MAT_OBSIDIAN;
static const MaterialProp MAT_PEARL;
static const MaterialProp MAT_RUBY;
static const MaterialProp MAT_TURQUOISE;
static const MaterialProp MAT_BRASS;
static const MaterialProp MAT_BRONZE;
static const MaterialProp MAT_CHROME;
static const MaterialProp MAT_COPPER;
static const MaterialProp MAT_GOLD;
static const MaterialProp MAT_SILVER;
public:
Model();
virtual ~Model();
private:
void init_gl(Glib::RefPtr<Gdk::GL::Drawable>& gldrawable);
public:
void draw(Glib::RefPtr<Gdk::GL::Drawable>& gldrawable);
void set_shape(ShapeType shape)
{ m_CurrentShape = shape; }
void set_material(const MaterialProp* material)
{ m_CurrentMat = material; }
private:
unsigned int m_ListBase;
ShapeType m_CurrentShape;
const MaterialProp* m_CurrentMat;
};
class Scene : public Gtk::GL::DrawingArea
{
friend class View;
friend class Model;
public:
static const float CLEAR_COLOR[4];
static const float CLEAR_DEPTH;
static const float LIGHT0_POSITION[4];
static const float LIGHT0_AMBIENT[4];
static const float LIGHT0_DIFFUSE[4];
static const float LIGHT_MODEL_AMBIENT[4];
static const float LIGHT_MODEL_LOCAL_VIEWER[1];
public:
explicit Scene();
virtual ~Scene();
protected:
virtual void on_realize();
virtual bool on_configure_event(GdkEventConfigure* event);
virtual bool on_expose_event(GdkEventExpose* event);
virtual bool on_button_press_event(GdkEventButton* event);
virtual bool on_unmap_event(GdkEventAny* event);
virtual bool on_visibility_notify_event(GdkEventVisibility* event);
virtual bool on_idle();
public:
void invalidate() {
GtkAllocation allocation = get_allocation();
get_window()->invalidate_rect(Gdk::Rectangle(&allocation), false);
}
void update()
{ get_window()->process_updates(false); }
protected:
SigC::Connection m_ConnectionIdle;
void idle_add();
void idle_remove();
protected:
void change_shape(Model::ShapeType shape);
void change_material(const Model::MaterialProp* material);
protected:
Gtk::Menu* create_popup_menu();
protected:
Gtk::Menu* m_Menu;
protected:
View m_View;
Model m_Model;
};
class Application : public Gtk::Window
{
public:
static const Glib::ustring APP_NAME;
public:
Application();
virtual ~Application();
protected:
virtual void on_button_quit_clicked();
virtual bool on_key_press_event(GdkEventKey* event);
protected:
Gtk::VBox m_VBox;
Scene m_Scene;
Gtk::Button m_ButtonQuit;
};
}
#endif // _SHAPES_H