Looking at Gtkmm support code for Opencascade Makebottle to see what makes it tick.

As a kid, my mom would give me old broken clocks to take apart. She said that it would keep me occupied for hours. I guess this blog is my adult version of the same thing..

I have had a hard time finding basic documentation on how to get a basic window open in Ubuntu Linux to display a opencascade model using Gtk+.
I stumbled on a very basic program using Google code search

I think something is screwed up with this tarball and I wound up cutting and pasting from the Google page.
My installation of opencascade differs from most (I think) since I installed it from a .deb file which put the libraries in a standard location. The consequences of this is that I need to re-write the Makefile to have it point to the appropriate location (see prior post)

I had been experimenting with Automake but, I still  having some issues with it…. So since I have working code at the moment using a Manually configured makefile… that project is on the back-burner for the moment…. Ok…. enough of looking backwards… Time to look forwards.

So the basic task at hand is to try to understand the concepts of what it takes to get a basic opencascade object to display using Gtkmm / C++ in Ubuntu Linux.

I suppose the way to do this is to start with Main.cpp

#include <gtkmm.h>
#include <gtkmmocascade.h>

TopoDS_Shape
MakeBottle(const Standard_Real myWidth , const Standard_Real myHeight , const Standard_Real myThickness);


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

protected:
  // signal handlers:
  void on_button_quit_clicked();
  void on_button_make_bottle_clicked();
  void on_ocascade_init(GtkOpenCascade3d &data);

protected:

  bool m_isMadeBottle;
  // member widgets:
  Gtk::VBox m_VBox;
  GtkOpenCascade3d m_SimpleGLScene;
  Gtk::Button m_ButtonQuit;
  Gtk::Button m_ButtonMakeBottle;

};

Simple::Simple()
  : m_isMadeBottle(false),m_VBox(false, 0), m_ButtonQuit("Quit"),m_ButtonMakeBottle("Make Bottle")
{
  //
  // Top-level window.
  //

  set_title("Simple");

  // Get automatically redrawn if any of their children changed allocation.
  set_reallocate_redraws(true);

  add(m_VBox);

  //
  // Simple OpenGL scene.
  //

  m_SimpleGLScene.set_size_request(300, 300);

  m_SimpleGLScene.signal_on_init().connect(sigc::mem_fun(*this, &Simple::on_ocascade_init));



  m_VBox.pack_start(m_SimpleGLScene);


  //
  // Simple MakeBottle button.
  //

  m_ButtonMakeBottle.signal_clicked().connect(sigc::mem_fun(*this, &Simple::on_button_make_bottle_clicked));

  m_VBox.pack_start(m_ButtonMakeBottle, Gtk::PACK_SHRINK, 0);

  //
  // Simple quit button.
  //

  m_ButtonQuit.signal_clicked().connect(
    sigc::mem_fun(*this, &Simple::on_button_quit_clicked));

  m_VBox.pack_start(m_ButtonQuit, Gtk::PACK_SHRINK, 0);

  //
  // Show window.
  //


  show_all();

}

Simple::~Simple()
{}

void Simple::on_button_quit_clicked()
{
  Gtk::Main::quit();
}

void Simple::on_button_make_bottle_clicked()
{
  if(m_SimpleGLScene.isInitialized() && ! m_isMadeBottle )
    {
      TopoDS_Shape aBottle=MakeBottle(50,70,30);
      Handle(AIS_Shape) AISBottle=new AIS_Shape(aBottle);
      m_SimpleGLScene.getContext()->SetMaterial(AISBottle,Graphic3d_NOM_GOLD);
      m_SimpleGLScene.getContext()->SetDisplayMode(AISBottle,1,Standard_False);
      m_SimpleGLScene.getContext()->Display(AISBottle,Standard_False);

      //myContext->SetCurrentObject(AISBottle,Standard_False);

      //myContext->Activate(AISBottle,0);

      m_SimpleGLScene.getView()->FitAll();
      m_SimpleGLScene.getView()->ZFitAll();

      m_isMadeBottle = true;
    }
}


void Simple::on_ocascade_init(GtkOpenCascade3d &data)
{
 TopoDS_Shape aBottle=MakeBottle(50,70,30);
 Handle(AIS_Shape) AISBottle=new AIS_Shape(aBottle);
 data.getContext()->SetMaterial(AISBottle,Graphic3d_NOM_GOLD);
 data.getContext()->SetDisplayMode(AISBottle,1,Standard_False);
 data.getContext()->Display(AISBottle,Standard_False);

 //myContext->SetCurrentObject(AISBottle,Standard_False);

 //myContext->Activate(AISBottle,0);

 data.getView()->FitAll();
 data.getView()->ZFitAll();
 m_isMadeBottle = true;
}

//
// Main.
//

int main(int argc, char** argv)
{
  Gtk::Main kit(argc, argv);

  //
  // Init gtkglextmm.
  //

  Gtk::GL::init(argc, argv);

  //
  // Instantiate and run the application.
  //

  Simple *simple;

  simple = new Simple;

  kit.run(*simple);

  return 0;
}

So…. What’s going on here…
Alrightly, starting out with main()
This is covered in the Gtkmm manual so no need to go there.

Gtk::Main kit(argc, argv);

Ok.. The next line, may be in the gtkmm manual which I may have not gotten to because I got bored to tears…
I need to research this one to understand.

Gtk::GL::init(argc, argv);

Ok… an interesting code source which I may try a little later on: http://gtkglext.sourceforge.net/reference/gtkglextmm/share-lists_8cc-example.html

I think I may have found a starting point to start:http://www.k-3d.org/gtkglext/Main_Page
Dohhh.. I should look at the comment line about to understand what this does…

//
// Init gtkglextmm.
//

This wiki link pretty much explains it>

gtkglextmm, a C++ wrapper for GtkGLExt, is also available. C++ programmers can use it to write GTK+-based OpenGL applications using gtkmm 2.

I that’s good enough for now…
I need to pick this up a little later on with a edit…
😉
Lets see if I can figure out the next bit.


  Simple *simple;
  simple = new Simple;
  kit.run(*simple);

So… we’re declaring a pointer (simple) to an Class called Simple.
Next line we’re creating and object and assigning its location to the pointer..
After that we’re firing up Gtkmm using the pointer to the object..
Now that all seems very straight forwards..

I guess the next logical step would be to tear apart the class Simple

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

protected:
// signal handlers:
void on_button_quit_clicked();
void on_button_make_bottle_clicked();
void on_ocascade_init(GtkOpenCascade3d &data);

protected:

bool m_isMadeBottle;
// member widgets:
Gtk::VBox m_VBox;
GtkOpenCascade3d m_SimpleGLScene;
Gtk::Button m_ButtonQuit;
Gtk::Button m_ButtonMakeBottle;

};

The Class Simple inherits a Gtk::window class… Got that part…
Everything makes more or less sense to be at the moment. I think to have my curiosity satisfied as to how a opencascade object is drawn I need to look at the following:

// signal handlers:
void on_button_quit_clicked();
void on_button_make_bottle_clicked();
void on_ocascade_init(GtkOpenCascade3d &data);

As well as:

// member widgets:
Gtk::VBox m_VBox;
GtkOpenCascade3d m_SimpleGLScene;
Gtk::Button m_ButtonQuit;
Gtk::Button m_ButtonMakeBottle;

I think I need to understand whats going on with GtkOpenCascade3d before looking at on_ocacade_init

gtkmmocascade.h has the class declaration for GtkOpenCascade3d and it looks like this;

#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>

#include <AIS_InteractiveContext.hxx>

#include <V3d_View.hxx>
#include <V3d_Viewer.hxx>

#include <Geom_BSplineSurface.hxx>

#include <AIS_InteractiveObject.hxx>
#include <Graphic3d_NameOfMaterial.hxx>

#include <TopoDS_Shape.hxx>
#include <AIS_Shape.hxx>

#include <Handle_V3d_OrthographicView.hxx>
#include <Handle_V3d_PerspectiveView.hxx>
#include <V3d_OrthographicView.hxx>
#include <V3d_PerspectiveView.hxx>
#include <Aspect_Handle.hxx>
#include <Handle_AIS_Trihedron.hxx>
#include <AIS_Trihedron.hxx>
#include <Geom_Axis2Placement.hxx>

#ifndef __GTK_MM_OPEN_CASCADE__
#define __GTK_MM_OPEN_CASCADE__

class GtkOpenCascade3d : public Gtk::DrawingArea,
			 public Gtk::GL::Widget<GtkOpenCascade3d>
{
public:

  typedef sigc::signal<void,GtkOpenCascade3d &> type_signal_gtkocascade3d;

  //
  // Signal !
  //

  type_signal_gtkocascade3d signal_on_init(void);

  //
  // Methods
  //

  GtkOpenCascade3d ();
  virtual ~GtkOpenCascade3d ();

  bool isInitialized(void)
    {
      return opencascade_inited;
    }


  Handle(V3d_View) & getView(void)
    {
      return myView;
    }

  Handle(V3d_Viewer) & getViewer(void)
    {
      return myViewer;
    }

  Handle(AIS_InteractiveContext) & getContext(void)
    {
      return myContext;
    }

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);
  virtual bool on_button_press_event  (GdkEventButton* event);
  virtual bool on_button_release_event(GdkEventButton* event);

  type_signal_gtkocascade3d m_signal_on_init;

private:
  Handle(V3d_View)   myView;
  Handle(V3d_Viewer) myViewer;
  Handle(AIS_InteractiveContext) myContext;
  bool opencascade_inited;

  bool is_mouse_button_pressed;

  guint mouse_button_press;


  void opencascade_realize (void);
  void opencascade_init    (void);
};

#endif // __GTK_MM_OPEN_CASCADE__

Time to tear it apart

class GtkOpenCascade3d : public Gtk::DrawingArea,
			 public Gtk::GL::Widget<GtkOpenCascade3d>

This is my first time looking at this stuff.

The inherited “public Gtk::DrawingArea,” seems straightforward enough.  I just need to find a Link to some reference information: http://www.gtkmm.org/docs/gtkmm-2.4/docs/tutorial/html/chapter-drawingarea.html This will take some time to digest.

It appears that gtkmm a while back used gdk but utilizes cairo as well as pango. The former handles graphics and the latter text..

Going through the first 5 or so pages of the tutorial on drawingarea didn’t seem to incite full.  Hopefully, it’ll all come together…
This is a little fuzzy to me at the moment:

public Gtk::GL::Widget<GtkOpenCascade3d>

I found the Gtk::GL::Widget Class Reference

This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *