Difference between revisions of "Tutorial - Setup Horde with Gtkmm"

From Horde3D Wiki
Jump to: navigation, search
 
(2 intermediate revisions by the same user not shown)
Line 21: Line 21:
 
#include <math.h>
 
#include <math.h>
 
#include <iomanip>
 
#include <iomanip>
 +
#include <glibmm/timer.h>
  
 
using namespace std;
 
using namespace std;
Line 30: Line 31:
 
         virtual ~cHordeWidget();
 
         virtual ~cHordeWidget();
 
         bool on_timeout();
 
         bool on_timeout();
 
+
        float _x, _y, _z, _rx, _ry; // Viewer position and orientation
 +
        float _curFPS;
 
     protected:
 
     protected:
 
         virtual void on_realize();
 
         virtual void on_realize();
 
         virtual bool on_configure_event(GdkEventConfigure* event);
 
         virtual bool on_configure_event(GdkEventConfigure* event);
 
         virtual bool on_expose_event(GdkEventExpose* event);
 
         virtual bool on_expose_event(GdkEventExpose* event);
         //our horde init function
+
         virtual bool on_motion_notify_event(GdkEventMotion* event);
 
         void init_hordeScene();
 
         void init_hordeScene();
        //our horde viewport functon
 
 
         void setup_hordeViewport();
 
         void setup_hordeViewport();
        //our horde render function
 
 
         void render_hordeScene();
 
         void render_hordeScene();
        //finnaly our horde update function
 
 
         void update_hordeScene();
 
         void update_hordeScene();
 
+
        void get_FramesPerSecond();
 
     private:
 
     private:
         ResHandle _pipeRes, _fontMatRes, _logoMatRes, _hdrPipeRes, _forwardPipeRes;
+
         ResHandle _pipeRes, _fontMatRes, _logoMatRes, _hdrPipeRes, _forwardPipeRes, _deferredPipeRes;
 
         NodeHandle _cam, _knight, _particleSys;
 
         NodeHandle _cam, _knight, _particleSys;
        float _x, _y, _z, _rx, _ry; // Viewer position and orientation
 
        float _velocity; // Velocity for movement
 
        float _curFPS, _timer;
 
  
        stringstream _fpsText;
 
  
         bool _freeze, _showFPS, _debugViewMode, _wireframeMode;
+
         bool _freeze;
         float _animTime, _weight,fps;
+
         float _animTime, _weight;
 +
 
 +
        double          last_time;
 +
        int            frames;
 +
 
 +
        Glib::Timer    m_animtimer;
 +
        Glib::Timer    m_fpstimer;
  
 
};
 
};
Line 73: Line 74:
  
 
cHordeWidget::cHordeWidget(){
 
cHordeWidget::cHordeWidget(){
    //sets the fps we want
 
    fps = 60;
 
    _curFPS = fps;
 
  
 
     Glib::RefPtr<Gdk::GL::Config> glconfig;
 
     Glib::RefPtr<Gdk::GL::Config> glconfig;
    //Pick our opengl options
+
 
 
     glconfig = Gdk::GL::Config::create(Gdk::GL::MODE_RGB | Gdk::GL::MODE_DEPTH | Gdk::GL::MODE_DOUBLE);
 
     glconfig = Gdk::GL::Config::create(Gdk::GL::MODE_RGB | Gdk::GL::MODE_DEPTH | Gdk::GL::MODE_DOUBLE);
     //set the opengl options
+
     add_events(Gdk::POINTER_MOTION_MASK);
 
     set_gl_capability(glconfig);
 
     set_gl_capability(glconfig);
    //add our idle signal.
+
     Glib::signal_timeout().connect( sigc::mem_fun(*this, &cHordeWidget::on_timeout), 10);
     Glib::signal_timeout().connect( sigc::mem_fun(*this, &cHordeWidget::on_timeout), 20 );
+
    m_animtimer.start();
  
 
}
 
}
Line 165: Line 163:
 
Horde3D::setOption( EngineOptions::ShadowMapSize, 2048 );
 
Horde3D::setOption( EngineOptions::ShadowMapSize, 2048 );
  
// Add resources
 
// Pipelines
 
 
_hdrPipeRes = Horde3D::addResource( ResourceTypes::Pipeline, "hdr.pipeline.xml", 0 );
 
_hdrPipeRes = Horde3D::addResource( ResourceTypes::Pipeline, "hdr.pipeline.xml", 0 );
 
_forwardPipeRes = Horde3D::addResource( ResourceTypes::Pipeline, "forward.pipeline.xml", 0 );
 
_forwardPipeRes = Horde3D::addResource( ResourceTypes::Pipeline, "forward.pipeline.xml", 0 );
 +
_deferredPipeRes = Horde3D::addResource( ResourceTypes::Pipeline, "deferred.pipeline.xml",0);
 
// Font
 
// Font
 
_fontMatRes = Horde3D::addResource( ResourceTypes::Material, "font.material.xml", 0 );
 
_fontMatRes = Horde3D::addResource( ResourceTypes::Material, "font.material.xml", 0 );
Line 182: Line 179:
 
ResHandle particleSysRes = Horde3D::addResource( ResourceTypes::SceneGraph, "particleSys1.scene.xml", 0 );
 
ResHandle particleSysRes = Horde3D::addResource( ResourceTypes::SceneGraph, "particleSys1.scene.xml", 0 );
  
// Load resources
+
        ResHandle skyBoxRes = Horde3D::addResource( ResourceTypes::SceneGraph, "skybox.scene.xml" ,0);
 +
        // Load resources
 
Horde3DUtils::loadResourcesFromDisk( "media" );
 
Horde3DUtils::loadResourcesFromDisk( "media" );
  
// Add scene nodes
+
 
 
// Add camera
 
// Add camera
_cam = Horde3D::addCameraNode( RootNode, "Camera", _hdrPipeRes );
+
_cam = Horde3D::addCameraNode( RootNode, "Camera", _forwardPipeRes );
 
//Horde3D::setNodeParami( _cam, CameraNodeParams::OcclusionCulling, 1 );
 
//Horde3D::setNodeParami( _cam, CameraNodeParams::OcclusionCulling, 1 );
 
// Add environment
 
// Add environment
 
NodeHandle env = Horde3D::addNodes( RootNode, envRes );
 
NodeHandle env = Horde3D::addNodes( RootNode, envRes );
 +
 
Horde3D::setNodeTransform( env, 0, -20, 0, 0, 0, 0, 20, 20, 20 );
 
Horde3D::setNodeTransform( env, 0, -20, 0, 0, 0, 0, 20, 20, 20 );
 
// Add knight
 
// Add knight
Line 197: Line 196:
 
Horde3D::setupModelAnimStage( _knight, 0, knightAnim1Res, "", false );
 
Horde3D::setupModelAnimStage( _knight, 0, knightAnim1Res, "", false );
 
Horde3D::setupModelAnimStage( _knight, 1, knightAnim2Res, "", false );
 
Horde3D::setupModelAnimStage( _knight, 1, knightAnim2Res, "", false );
 +
 
// Attach particle system to hand joint
 
// Attach particle system to hand joint
 
Horde3D::findNodes( _knight, "Bip01_R_Hand", SceneNodeTypes::Joint );
 
Horde3D::findNodes( _knight, "Bip01_R_Hand", SceneNodeTypes::Joint );
Line 203: Line 203:
 
Horde3D::setNodeTransform( _particleSys, 0, 40, 0, 90, 0, 0, 1, 1, 1 );
 
Horde3D::setNodeTransform( _particleSys, 0, 40, 0, 90, 0, 0, 1, 1, 1 );
  
 +
        //add skybox
 +
NodeHandle sky = Horde3D::addNodes( RootNode, skyBoxRes);
 +
//set skybox position
 +
Horde3D::setNodeTransform( sky, 0, 0, 0, 0, 0, 0, 210, 50, 210 );
 
// Add light source
 
// Add light source
 
NodeHandle light = Horde3D::addLightNode( RootNode, "Light1", 0, "LIGHTING", "SHADOWMAP" );
 
NodeHandle light = Horde3D::addLightNode( RootNode, "Light1", 0, "LIGHTING", "SHADOWMAP" );
Line 231: Line 235:
  
 
void cHordeWidget::render_hordeScene(){
 
void cHordeWidget::render_hordeScene(){
 +
    m_fpstimer.start();
  
     Horde3D::setOption( EngineOptions::DebugViewMode, _debugViewMode ? 1.0f : 0.0f );
+
     //Horde3D::setOption( EngineOptions::DebugViewMode, _debugViewMode ? 1.0f : 0.0f );
     Horde3D::setOption( EngineOptions::WireframeMode, _wireframeMode ? 1.0f : 0.0f );
+
     //Horde3D::setOption( EngineOptions::WireframeMode, _wireframeMode ? 1.0f : 0.0f );
  
// Do animation blending
+
    // Do animation blending
     Horde3D::setModelAnimParams( _knight, 0, _animTime * 24.0f, _weight );
+
     Horde3D::setModelAnimParams( _knight, 0, _animTime , _weight );
     Horde3D::setModelAnimParams( _knight, 1, _animTime * 24.0f, 1.0f - _weight );
+
     Horde3D::setModelAnimParams( _knight, 1, _animTime , 1.0f - _weight );
  
 
     // Animate particle systems (several emitters in a group node)
 
     // Animate particle systems (several emitters in a group node)
 
     unsigned int cnt = cnt = Horde3D::findNodes( _particleSys, "", SceneNodeTypes::Emitter );
 
     unsigned int cnt = cnt = Horde3D::findNodes( _particleSys, "", SceneNodeTypes::Emitter );
 +
 
     for( unsigned int i = 0; i < cnt; ++i )
 
     for( unsigned int i = 0; i < cnt; ++i )
 
         Horde3D::advanceEmitterTime( Horde3D::getNodeFindResult( i ), 1.0f / _curFPS );
 
         Horde3D::advanceEmitterTime( Horde3D::getNodeFindResult( i ), 1.0f / _curFPS );
  
  
// Set camera parameters
+
    // Set camera parameters
Horde3D::setNodeTransform( _cam, _x, _y, _z, _rx ,_ry, 0, 1, 1, 1 );
 
  
  
// Show logo
+
    // Show logo
Horde3D::showOverlay( 0.75f, 0, 0, 0, 1, 0, 1, 0,
+
    Horde3D::showOverlay( 0.75f, 0, 0, 0, 1, 0, 1, 0,
  1, 0.2f, 1, 1, 0.75f, 0.2f, 0, 1,
+
  1, 0.2f, 1, 1, 0.75f, 0.2f, 0, 1,
  7, _logoMatRes );
+
  7, _logoMatRes );
  
// Render scene
+
    // Render scene
Horde3D::render( _cam );
+
    Horde3D::render( _cam );
  
// Remove all overlays
+
    // Remove all overlays
Horde3D::clearOverlays();
+
    Horde3D::clearOverlays();
 +
 
 +
    get_FramesPerSecond();
  
 
}
 
}
  
 
void cHordeWidget::update_hordeScene(){
 
void cHordeWidget::update_hordeScene(){
    //This is to update the screen when it goes idle you can use this has a extra update function.
 
    _timer += 1 / fps;
 
    _animTime += 1.0f / _curFPS;
 
  
 +
    double seconds = m_animtimer.elapsed();
 +
 +
    _animTime +=  seconds * 30;
 +
 +
    m_animtimer.reset();
 +
    Horde3D::setNodeTransform( _cam, _x, _y, _z, _rx ,_ry, 0, 1, 1, 1 );
 
     Gtk::Widget::queue_draw();
 
     Gtk::Widget::queue_draw();
 
}
 
}
  
 +
void cHordeWidget::get_FramesPerSecond(){
 +
    ++frames;
 +
 +
    last_time = last_time + m_fpstimer.elapsed();
 +
 +
    if(last_time >= 0){
 +
        _curFPS = (float)(frames / last_time);
 +
        frames = 0;
 +
        last_time = 0;
 +
        m_fpstimer.reset();
 +
    }
 +
 +
    std::cout<<_curFPS<<endl;
 +
}
 +
 +
//This event handler must be set and return false in order for are mouse movement to be captured
 +
bool cHordeWidget::on_motion_notify_event(GdkEventMotion* event){
 +
 +
        return false;
 +
}
  
 
</source>
 
</source>
Line 282: Line 312:
 
#define CWINDOW_HPP_INCLUDED
 
#define CWINDOW_HPP_INCLUDED
 
#include <gtkmm.h>
 
#include <gtkmm.h>
 +
#include <math.h>
 
#include "cHordeWidget.hpp"
 
#include "cHordeWidget.hpp"
  
Line 292: Line 323:
  
 
         virtual bool on_key_press_event(GdkEventKey* event);
 
         virtual bool on_key_press_event(GdkEventKey* event);
 
+
        virtual bool on_key_release_event(GdkEventKey* event);
 +
        virtual bool on_motion_notify_event(GdkEventMotion* event);
 +
        virtual bool on_focus_in (GdkEventFocus*);
 +
        bool on_timeout();
 +
        void handleinput();
 
     private:
 
     private:
 
         Gtk::VBox m_vBox;
 
         Gtk::VBox m_vBox;
Line 311: Line 346:
  
 
#include "../include/cWindow.hpp"
 
#include "../include/cWindow.hpp"
 +
 +
inline float degToRad( float f )
 +
{
 +
return f * (3.1415926f / 180.0f);
 +
}
 +
//array to hold keys
 +
int keyDown[256];
  
 
cWindow::cWindow(){
 
cWindow::cWindow(){
    //set the windows title
 
 
     set_title("Horde with gtkmm");
 
     set_title("Horde with gtkmm");
    //makes the window update if it is expanded etc.
 
 
     set_reallocate_redraws(true);
 
     set_reallocate_redraws(true);
    //adds a box to place the hordewidget and other widgets into
+
 
 
     add(m_vBox);
 
     add(m_vBox);
     //sets the minimum and default size for our window
+
     add_events(Gdk::POINTER_MOTION_MASK | Gdk::POINTER_MOTION_HINT_MASK |
 +
    Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK);
 +
    Glib::signal_timeout().connect( sigc::mem_fun(*this, &cWindow::on_timeout), 10);
 +
    signal_focus_in_event().connect(sigc::mem_fun(*this, &cWindow::on_focus_in) );
 
     m_hordeWidget.set_size_request(800,600);
 
     m_hordeWidget.set_size_request(800,600);
    //makes the widget expand when the window is expanded
+
 
 
     m_vBox.pack_start(m_hordeWidget);
 
     m_vBox.pack_start(m_hordeWidget);
    //shows all widgets. by default all widgets are invisible. 
+
 
 
     show_all();
 
     show_all();
 
}
 
}
Line 333: Line 376:
 
bool cWindow::on_key_press_event(GdkEventKey* event){
 
bool cWindow::on_key_press_event(GdkEventKey* event){
  
     switch (event->keyval)
+
     if(event->keyval == GDK_Escape){
     {
+
      Gtk::Main::quit();}else{
     case GDK_a:
+
 
      std::cout<<"test";
+
    //sets the key in the array to true
      break;
+
    keyDown[event->keyval] = 1;}
 +
     return true;
 +
}
 +
 
 +
bool cWindow::on_key_release_event(GdkEventKey *event){
 +
     //sets the key in the array to false
 +
    keyDown[event->keyval] = 0;
 +
    return true;
 +
}
 +
 
 +
void cWindow::handleinput(){
 +
    float curVel = 240/m_hordeWidget._curFPS;
 +
    //checks if a certain key is true and acts on it
 +
    if(keyDown['w']){
 +
        m_hordeWidget._x -= sinf( degToRad( m_hordeWidget._ry ) ) * cosf( -degToRad( m_hordeWidget._rx ) ) * curVel;
 +
m_hordeWidget._y -= sinf( -degToRad( m_hordeWidget._rx ) ) * curVel;
 +
m_hordeWidget._z -= cosf( degToRad( m_hordeWidget._ry ) ) * cosf( -degToRad( m_hordeWidget._rx ) ) * curVel;
 +
    }
 +
 
 +
    if(keyDown['s']){
 +
        m_hordeWidget._x += sinf( degToRad( m_hordeWidget._ry ) ) * cosf( -degToRad( m_hordeWidget._rx ) ) * curVel;
 +
m_hordeWidget._y += sinf( -degToRad( m_hordeWidget._rx ) ) * curVel;
 +
m_hordeWidget._z += cosf( degToRad( m_hordeWidget._ry ) ) * cosf( -degToRad( m_hordeWidget._rx ) ) * curVel;
 +
    }
  
     case GDK_Escape:
+
     if(keyDown['a']){
      //ends our app
+
        m_hordeWidget._x += sinf( degToRad( m_hordeWidget._ry - 90) ) * curVel;
      Gtk::Main::quit();
+
m_hordeWidget._z += cosf( degToRad( m_hordeWidget._ry - 90 ) ) * curVel;
 +
    }
  
      break;
+
    if(keyDown['d']){
      default:
+
        m_hordeWidget._x += sinf( degToRad( m_hordeWidget._ry + 90 ) ) * curVel;
      return true;
+
m_hordeWidget._z += cosf( degToRad( m_hordeWidget._ry + 90 ) ) * curVel;
 
     }
 
     }
 +
 +
}
 +
//called only when mouse is moved *cause for the camera appearing glitchy*
 +
bool cWindow::on_motion_notify_event(GdkEventMotion* event){
 +
 +
    m_hordeWidget._ry -= (event->x -(get_width() /2)) / 450 ;
 +
 +
  m_hordeWidget._rx -= (event->y -(get_height()/2)) / 450 ;
 +
 +
if( m_hordeWidget._rx > 90 ) m_hordeWidget._rx = 90;
 +
if( m_hordeWidget._rx < -90 ) m_hordeWidget._rx = -90;
 +
 +
    return false;
 +
}
 +
//called constantly
 +
bool cWindow::on_timeout(){
 +
    int xp = 0;
 +
    int yp = 0;
 +
    get_pointer(xp,yp);
 +
    handleinput();
 +
    return true;
 +
}
 +
 +
bool cWindow::on_focus_in(GdkEventFocus* event )
 +
{
 +
    //Hide the curosr
 +
    // Ok, here we create a dummy cursor. See gdkmm reference for more details
 +
    Gdk::Cursor cursor = Gdk::Cursor(Gdk::Display::get_default(),
 +
    Gdk::Pixbuf::create(
 +
Gdk::COLORSPACE_RGB, true, 8, 1, 1),
 +
    0, 0);
 +
 +
    get_window()->set_cursor(cursor);
  
 
     return true;
 
     return true;
Line 361: Line 461:
 
#include <gtkmm.h>
 
#include <gtkmm.h>
 
//Include our custom widget
 
//Include our custom widget
#include "include/cHordeWidget.hpp"
+
#include "include/cWindow.hpp"
  
 
int main(int argc, char *argv[]){
 
int main(int argc, char *argv[]){
Line 369: Line 469:
 
     Gtk::GL::init (argc, argv);
 
     Gtk::GL::init (argc, argv);
 
     //Create our Window object
 
     //Create our Window object
     Gtk::Window window;
+
     cWindow window;
     //Set our window title
+
     //Run the program
    window.set_title ("Horde3D In Gtk+ Window");
+
     Gtk::Main::run(window);
    //Create our cHordeWidget
+
     //Safe exit message
    cHordeWidget drawing;
 
    //Set the cHordeWidgets size
 
    drawing.set_size_request(800, 600);
 
    //Add the cHordeWidget to our window
 
    window.add (drawing);
 
    //Show our cHordeWidget. All widgets are invisible by default.
 
    window.show_all ();
 
    //Run our window
 
     Gtk::Main::run (window);
 
     //Just a return statement
 
 
     return EXIT_SUCCESS;
 
     return EXIT_SUCCESS;
 +
 
}
 
}
  

Latest revision as of 20:06, 17 August 2008

Here is a small example on how to use Horde with Gtkmm.

This is a small tutorial on how to setup Horde with Gtk+ using Gtkmm and Gtkglextmm. This one is setup with the knight example. I leave the adjusting of the camera to you :)

cHordeWidget.hpp
#ifndef CHORDEWIDGET_HPP_INCLUDED
#define CHORDEWIDGET_HPP_INCLUDED
#include <iostream>
#include <Horde3D.h>
#include <Horde3DUtils.h>
#include <cstdlib>
#include <gtkmm.h>
#include <gtkglmm.h>
#include <sstream>
#include <math.h>
#include <iomanip>
#include <glibmm/timer.h>

using namespace std;


class cHordeWidget : public Gtk::GL::DrawingArea{
    public:
        cHordeWidget();
        virtual ~cHordeWidget();
        bool on_timeout();
        float			_x, _y, _z, _rx, _ry;	// Viewer position and orientation
        float			_curFPS;
    protected:
        virtual void on_realize();
        virtual bool on_configure_event(GdkEventConfigure* event);
        virtual bool on_expose_event(GdkEventExpose* event);
        virtual bool on_motion_notify_event(GdkEventMotion* event);
        void init_hordeScene();
        void setup_hordeViewport();
        void render_hordeScene();
        void update_hordeScene();
        void get_FramesPerSecond();
    private:
        ResHandle		_pipeRes, _fontMatRes, _logoMatRes, _hdrPipeRes, _forwardPipeRes, _deferredPipeRes;
        NodeHandle		_cam, _knight, _particleSys;


        bool			_freeze;
        float			_animTime, _weight;

        double          last_time;
        int             frames;

        Glib::Timer     m_animtimer;
        Glib::Timer     m_fpstimer;

};

#endif // CHORDEWIDGET_HPP_INCLUDED

Now for the cHordeWidget.cpp *Read the comments*

cHordeWidget.cpp
#include "../include/cHordeWidget.hpp"

NodeHandle model = 0, cam = 0;

cHordeWidget::cHordeWidget(){

    Glib::RefPtr<Gdk::GL::Config> glconfig;

    glconfig = Gdk::GL::Config::create(Gdk::GL::MODE_RGB | Gdk::GL::MODE_DEPTH | Gdk::GL::MODE_DOUBLE);
    add_events(Gdk::POINTER_MOTION_MASK);
    set_gl_capability(glconfig);
    Glib::signal_timeout().connect( sigc::mem_fun(*this, &cHordeWidget::on_timeout), 10);
    m_animtimer.start();

}

cHordeWidget::~cHordeWidget(){
    Horde3D::release();
}

void cHordeWidget::on_realize(){
    Gtk::GL::DrawingArea::on_realize();

    //get gl::window
    Glib::RefPtr<Gdk::GL::Window> glwindow = get_gl_window();

    //begin gl commands
    glwindow->gl_begin(get_gl_context());

    //init horde
    init_hordeScene();
    
    /end gl commands
    glwindow->gl_end();
}

bool cHordeWidget::on_configure_event(GdkEventConfigure* event){

    Glib::RefPtr<Gdk::GL::Window> glwindow = get_gl_window();

    glwindow->gl_begin(get_gl_context());

    //setup the viewport
    setup_hordeViewport();

    glwindow->gl_end();

    return true;
}

bool cHordeWidget::on_expose_event(GdkEventExpose* event){
    
    Glib::RefPtr<Gdk::GL::Window> glwindow = get_gl_window();

    glwindow->gl_begin(get_gl_context());

    //render the horde scene
    render_hordeScene();
    
    //swap our gl buffers use glflush if you use only one buffer
    glwindow->swap_buffers();
    glwindow->gl_end();

    return true;
}

bool cHordeWidget::on_timeout(){

    //update the horde scee
    update_hordeScene();

    return true;
}

void cHordeWidget::init_hordeScene(){

	Horde3DUtils::setResourcePath( ResourceTypes::SceneGraph, "models" );
	Horde3DUtils::setResourcePath( ResourceTypes::Geometry, "models" );
	Horde3DUtils::setResourcePath( ResourceTypes::Animation, "models" );
	Horde3DUtils::setResourcePath( ResourceTypes::Material, "materials" );
	Horde3DUtils::setResourcePath( ResourceTypes::Code, "shaders" );
	Horde3DUtils::setResourcePath( ResourceTypes::Shader, "shaders" );
	Horde3DUtils::setResourcePath( ResourceTypes::Texture2D, "textures" );
	Horde3DUtils::setResourcePath( ResourceTypes::TextureCube, "textures" );
	Horde3DUtils::setResourcePath( ResourceTypes::Effect, "effects" );
	Horde3DUtils::setResourcePath( ResourceTypes::Pipeline, "pipelines" );

	// Set options
	Horde3D::setOption( EngineOptions::LoadTextures, 1 );
	Horde3D::setOption( EngineOptions::TexCompression, 0 );
	Horde3D::setOption( EngineOptions::FastAnimation, 0 );
	Horde3D::setOption( EngineOptions::AnisotropyFactor, 8 );
	Horde3D::setOption( EngineOptions::ShadowMapSize, 2048 );

	_hdrPipeRes = Horde3D::addResource( ResourceTypes::Pipeline, "hdr.pipeline.xml", 0 );
	_forwardPipeRes = Horde3D::addResource( ResourceTypes::Pipeline, "forward.pipeline.xml", 0 );
	_deferredPipeRes = Horde3D::addResource( ResourceTypes::Pipeline, "deferred.pipeline.xml",0);
	// Font
	_fontMatRes = Horde3D::addResource( ResourceTypes::Material, "font.material.xml", 0 );
	// Logo
	_logoMatRes = Horde3D::addResource( ResourceTypes::Material, "logo.material.xml", 0 );
	// Environment
	ResHandle envRes = Horde3D::addResource( ResourceTypes::SceneGraph, "sphere.scene.xml", 0 );
	// Knight
	ResHandle knightRes = Horde3D::addResource( ResourceTypes::SceneGraph, "knight.scene.xml", 0 );
	ResHandle knightAnim1Res = Horde3D::addResource( ResourceTypes::Animation, "knight_order.anim", 0 );
	ResHandle knightAnim2Res = Horde3D::addResource( ResourceTypes::Animation, "knight_attack.anim", 0 );
	// Particle system
	ResHandle particleSysRes = Horde3D::addResource( ResourceTypes::SceneGraph, "particleSys1.scene.xml", 0 );

        ResHandle skyBoxRes = Horde3D::addResource( ResourceTypes::SceneGraph, "skybox.scene.xml" ,0);
        // Load resources
	Horde3DUtils::loadResourcesFromDisk( "media" );


	// Add camera
	_cam = Horde3D::addCameraNode( RootNode, "Camera", _forwardPipeRes );
	//Horde3D::setNodeParami( _cam, CameraNodeParams::OcclusionCulling, 1 );
	// Add environment
	NodeHandle env = Horde3D::addNodes( RootNode, envRes );

	Horde3D::setNodeTransform( env, 0, -20, 0, 0, 0, 0, 20, 20, 20 );
	// Add knight
	_knight = Horde3D::addNodes( RootNode, knightRes );
	Horde3D::setNodeTransform( _knight, 0, 0, 0, 0, 180, 0, 0.1f, 0.1f, 0.1f );
	Horde3D::setupModelAnimStage( _knight, 0, knightAnim1Res, "", false );
	Horde3D::setupModelAnimStage( _knight, 1, knightAnim2Res, "", false );

	// Attach particle system to hand joint
	Horde3D::findNodes( _knight, "Bip01_R_Hand", SceneNodeTypes::Joint );
	NodeHandle hand = Horde3D::getNodeFindResult( 0 );
	_particleSys = Horde3D::addNodes( hand, particleSysRes );
	Horde3D::setNodeTransform( _particleSys, 0, 40, 0, 90, 0, 0, 1, 1, 1 );

        //add skybox
	NodeHandle sky = Horde3D::addNodes( RootNode, skyBoxRes);
	//set skybox position
	Horde3D::setNodeTransform( sky, 0, 0, 0, 0, 0, 0, 210, 50, 210 );
	// Add light source
	NodeHandle light = Horde3D::addLightNode( RootNode, "Light1", 0, "LIGHTING", "SHADOWMAP" );
	Horde3D::setNodeTransform( light, 0, 15, 10, -60, 0, 0, 1, 1, 1 );
	Horde3D::setNodeParamf( light, LightNodeParams::Radius, 30 );
	Horde3D::setNodeParamf( light, LightNodeParams::FOV, 90 );
	Horde3D::setNodeParami( light, LightNodeParams::ShadowMapCount, 1 );
	Horde3D::setNodeParamf( light, LightNodeParams::ShadowMapBias, 0.01f );
	Horde3D::setNodeParamf( light, LightNodeParams::Col_R, 1.0f );
	Horde3D::setNodeParamf( light, LightNodeParams::Col_G, 0.8f );
	Horde3D::setNodeParamf( light, LightNodeParams::Col_B, 0.7f );

	// Customize post processing effects
	NodeHandle matRes = Horde3D::findResource( ResourceTypes::Material, "postHDR.material.xml" );
	// hdrParams: exposure, brightpass threshold, brightpass offset (see shader for description)
	Horde3D::setMaterialUniform( matRes, "hdrParams", 2.5f, 0.5f, 0.08f, 0 );

}

void cHordeWidget::setup_hordeViewport(){
    //We have to init horde here becuase this is the first thing gtkmm calls when the widget is created. 
    //This is also called everytime the window is expanded the boolean is there just so nothing bad happens when initing horde over and over.
    bool hinit = false;
    if(hinit == false){ Horde3D::init(); hinit = true;}
    Horde3D::resize(0,0,get_width(),get_height());
    Horde3D::setupCameraView(cam,45.0f,(float)get_width()/get_height(),0.1f,1000.0f);
}

void cHordeWidget::render_hordeScene(){
    m_fpstimer.start();

    //Horde3D::setOption( EngineOptions::DebugViewMode, _debugViewMode ? 1.0f : 0.0f );
    //Horde3D::setOption( EngineOptions::WireframeMode, _wireframeMode ? 1.0f : 0.0f );

    // Do animation blending
    Horde3D::setModelAnimParams( _knight, 0, _animTime  , _weight );
    Horde3D::setModelAnimParams( _knight, 1, _animTime , 1.0f - _weight );

    // Animate particle systems (several emitters in a group node)
    unsigned int cnt = cnt = Horde3D::findNodes( _particleSys, "", SceneNodeTypes::Emitter );

    for( unsigned int i = 0; i < cnt; ++i )
        Horde3D::advanceEmitterTime( Horde3D::getNodeFindResult( i ), 1.0f / _curFPS );


    // Set camera parameters


    // Show logo
    Horde3D::showOverlay( 0.75f, 0, 0, 0, 1, 0, 1, 0,
					  1, 0.2f, 1, 1, 0.75f, 0.2f, 0, 1,
					  7, _logoMatRes );

    // Render scene
    Horde3D::render( _cam );

    // Remove all overlays
    Horde3D::clearOverlays();

    get_FramesPerSecond();

}

void cHordeWidget::update_hordeScene(){

    double seconds = m_animtimer.elapsed();

    _animTime +=  seconds * 30;

    m_animtimer.reset();
    Horde3D::setNodeTransform( _cam, _x, _y, _z, _rx ,_ry, 0, 1, 1, 1 );
    Gtk::Widget::queue_draw();
}

void cHordeWidget::get_FramesPerSecond(){
    ++frames;

    last_time = last_time + m_fpstimer.elapsed();

    if(last_time >= 0){
        _curFPS = (float)(frames / last_time);
        frames = 0;
        last_time = 0;
        m_fpstimer.reset();
    }

    std::cout<<_curFPS<<endl;
}

//This event handler must be set and return false in order for are mouse movement to be captured
bool cHordeWidget::on_motion_notify_event(GdkEventMotion* event){

        return false;
}

Now for the window widget.

cWindow.hpp
#ifndef CWINDOW_HPP_INCLUDED
#define CWINDOW_HPP_INCLUDED
#include <gtkmm.h>
#include <math.h>
#include "cHordeWidget.hpp"

class cWindow : public Gtk::Window{
    public:
        cWindow();
        virtual ~cWindow();

    protected:

        virtual bool on_key_press_event(GdkEventKey* event);
        virtual bool on_key_release_event(GdkEventKey* event);
        virtual bool on_motion_notify_event(GdkEventMotion* event);
        virtual bool on_focus_in (GdkEventFocus*);
        bool on_timeout();
        void handleinput();
    private:
        Gtk::VBox m_vBox;

        cHordeWidget m_hordeWidget;

};

#endif // CWINDOW_HPP_INCLUDED

Now the window widgets cpp

cWindow.cpp
#include "../include/cWindow.hpp"

inline float degToRad( float f )
{
	return f * (3.1415926f / 180.0f);
}
//array to hold keys
int keyDown[256];

cWindow::cWindow(){
    set_title("Horde with gtkmm");
    set_reallocate_redraws(true);

    add(m_vBox);
    add_events(Gdk::POINTER_MOTION_MASK | Gdk::POINTER_MOTION_HINT_MASK |
    Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK);
    Glib::signal_timeout().connect( sigc::mem_fun(*this, &cWindow::on_timeout), 10);
    signal_focus_in_event().connect(sigc::mem_fun(*this, &cWindow::on_focus_in) );
    m_hordeWidget.set_size_request(800,600);

    m_vBox.pack_start(m_hordeWidget);

    show_all();
}

cWindow::~cWindow(){

}

bool cWindow::on_key_press_event(GdkEventKey* event){

    if(event->keyval == GDK_Escape){
      Gtk::Main::quit();}else{

    //sets the key in the array to true
    keyDown[event->keyval] = 1;}
    return true;
}

bool cWindow::on_key_release_event(GdkEventKey *event){
    //sets the key in the array to false
    keyDown[event->keyval] = 0;
    return true;
}

void cWindow::handleinput(){
    float curVel = 240/m_hordeWidget._curFPS;
    //checks if a certain key is true and acts on it
    if(keyDown['w']){
        m_hordeWidget._x -= sinf( degToRad( m_hordeWidget._ry ) ) * cosf( -degToRad( m_hordeWidget._rx ) ) * curVel;
		m_hordeWidget._y -= sinf( -degToRad( m_hordeWidget._rx ) ) * curVel;
		m_hordeWidget._z -= cosf( degToRad( m_hordeWidget._ry ) ) * cosf( -degToRad( m_hordeWidget._rx ) ) * curVel;
    }

    if(keyDown['s']){
        m_hordeWidget._x += sinf( degToRad( m_hordeWidget._ry ) ) * cosf( -degToRad( m_hordeWidget._rx ) ) * curVel;
		m_hordeWidget._y += sinf( -degToRad( m_hordeWidget._rx ) ) * curVel;
		m_hordeWidget._z += cosf( degToRad( m_hordeWidget._ry ) ) * cosf( -degToRad( m_hordeWidget._rx ) ) * curVel;
    }

    if(keyDown['a']){
        m_hordeWidget._x += sinf( degToRad( m_hordeWidget._ry - 90) ) * curVel;
		m_hordeWidget._z += cosf( degToRad( m_hordeWidget._ry - 90 ) ) * curVel;
    }

    if(keyDown['d']){
        m_hordeWidget._x += sinf( degToRad( m_hordeWidget._ry + 90 ) ) * curVel;
		m_hordeWidget._z += cosf( degToRad( m_hordeWidget._ry + 90 ) ) * curVel;
    }

}
//called only when mouse is moved *cause for the camera appearing glitchy*
bool cWindow::on_motion_notify_event(GdkEventMotion* event){

    m_hordeWidget._ry -= (event->x -(get_width() /2)) / 450 ;

   	m_hordeWidget._rx -= (event->y -(get_height()/2)) / 450 ;

	if( m_hordeWidget._rx > 90 ) m_hordeWidget._rx = 90;
	if( m_hordeWidget._rx < -90 ) m_hordeWidget._rx = -90;

    return false;
}
//called constantly
bool cWindow::on_timeout(){
    int xp = 0;
    int yp = 0;
    get_pointer(xp,yp);
    handleinput();
    return true;
}

bool cWindow::on_focus_in(GdkEventFocus* event )
{
    //Hide the curosr
    // Ok, here we create a dummy cursor. See gdkmm reference for more details
    Gdk::Cursor cursor = Gdk::Cursor(Gdk::Display::get_default(),
				     Gdk::Pixbuf::create(
					 Gdk::COLORSPACE_RGB, true, 8, 1, 1),
				     0, 0);

    get_window()->set_cursor(cursor);

    return true;
}

Finnaly the main.cpp *Read the Comments*

main.cpp
#include <gtkmm.h>
//Include our custom widget
#include "include/cWindow.hpp"

int main(int argc, char *argv[]){
    //Init Gtk+
    Gtk::Main init (argc, argv);
    //Init Gtk+ opengl
    Gtk::GL::init (argc, argv);
    //Create our Window object
    cWindow window;
    //Run the program
    Gtk::Main::run(window);
    //Safe exit message
    return EXIT_SUCCESS;

}

--Rj 23:21, 8 August 2008 (CEST)

Horde With Gtkmm
H3DPlaceHolder.png
This tutorial introduces the use of Horde3D with Gtkmm
Version: 1.0
Compatible with Horde3D: 1.0 beta
Release date: 2008-07-8
Author(s): Raynaldo Rivera