newNodeViewer

Introduction

In icosahedronViewer, we showed how to define a new X3D node and extend processors. Here we define a new node and its GL equivalent too, but we show how we can reuse the existing processors and extend only the necessary ones. For more details about the creation of a node see the scene graph API page.

We want to define an X3DTK::X3D::FCylinder node, deriving from X3DTK::X3D::Cylinder and that enables the control of the cylinder discretization.

Some important functions and classes:

Deriving X3D::Cylinder

We derive X3DTK::X3D::Cylinder and we add a section attribute. In the constructor the type name and its attribute are recorded.

Loading X3D::FCylinder

To load the node, we have to derive the creator for the nodes belonging to the Geometry3D, because X3DTK::X3D::FCylinder belongs to it.

Deriving GL::Cylinder

To render X3DTK::X3D::FCylinder, we first have to define its openGL equivalent node, X3DTK::GL::FCylinder. Note that there are different namespaces for the scene graphs X3D and GL. There is no attribute to add to the X3DTK::GL::Cylinder. The update method which updates the attributes of the node from the equivalent X3DTK::X3D::FCylinder x3dReference has to be redefined. To the contrary, the draw method has not to be redefined. However the type name of the node has to be recorded in the constructor.

Building GL::FCylinder

We derive the X3DTK::X3D::GLBuilderGeometry3DVisitor, which will create the X3DTK::GL::FCylinder from an X3DTK::X3D::FCylinder.

code

X3D_FCylinder.h

#ifndef FCYLINDER_H
#define FCYLINDER_H

#include <X3DTK/X3D/scenegraph.h>

namespace X3DTK {
namespace X3D {

class FCylinder : public Cylinder
{
public:
  FCylinder();
  virtual ~FCylinder();

  void setSection(SFInt32 section);
  inline SFInt32 getSection() const {return _section;};

private:
  SFInt32 _section;
};

}
}

#endif

X3D_FCylinder.cpp

#include "X3D_FCylinder.h"

namespace X3DTK {
namespace X3D {

FCylinder::FCylinder()
: Cylinder()
{
  // Defines the tag of the node. This string is the one read in the X3D file.
  define(Recorder<FCylinder>::getTypeName("FCylinder"));
  
  // Defines an attribute. The first parameter is the string read in the X3D file.
  define(Recorder<FCylinder, SFInt32>::getAttribute("section", &FCylinder::_section, 8));
}

FCylinder::~FCylinder()
{
}

void FCylinder::setSection(SFInt32 section)
{
  _section = section;
}

}
}

X3D_MyGeometry3DCreator.h

#ifndef MYGEOMETRY3DCREATOR_H
#define MYGEOMETRY3DCREATOR_H

#include <X3DTK/X3D/scenegraph.h>

namespace X3DTK {
namespace X3D {

// Concrete component Creator for the geometry3D component defining the default 
// X3D nodes.

class MyGeometry3DCreator : public Geometry3DCreator
{
public:
  // Constructor.
  MyGeometry3DCreator();
};

}
}

#endif

X3D_MyGeometry3DCreator.cpp

#include "X3D_MyGeometry3DCreator.h"
#include "X3D_FCylinder.h"

namespace X3DTK {
namespace X3D {

MyGeometry3DCreator::MyGeometry3DCreator()
: Geometry3DCreator()
{
  // Defines a new creation function for the FCylinder node.
  define(Recorder<FCylinder>::getCreationFunction());
}

}
}

GL_FCylinder.h

#ifndef GL_FCYLINDER_H
#define GL_FCYLINDER_H

#include <X3DTK/GL/scenegraph.h>

namespace X3DTK {
namespace GL {

class FCylinder : public Cylinder
{
public:
  FCylinder();
  virtual ~FCylinder();

  virtual void update();
};

}
}

#endif

GL_FCylinder.cpp

#include "GL_FCylinder.h"
#include "X3D_FCylinder.h"

#include <iostream>

using namespace std;

namespace X3DTK {
namespace GL {

FCylinder::FCylinder()
: Cylinder()
{
  // Defines the tag of the node. 
  define(Recorder<FCylinder>::getTypeName("FCylinder"));
}

FCylinder::~FCylinder()
{
}

void FCylinder::update()
{
  X3D::FCylinder *C = static_cast<X3D::FCylinder *>(x3dReference);
  
  // update the attributes.
  setBottom(C->getBottom());
  setRadius(C->getRadius());
  setHeight(C->getHeight());
  setSide(C->getSide());
  setTop(C->getTop());
  
  // Get the instance of CylinderDrawArray.
  setCylinderArray(CylinderDrawArray::getInstanceOfSection(C->getSection()));
}

}
}

X3D_MyGLBuilderGeometry3DVisitor.h

#ifndef MYGLBUILDERGEOMETRY3DVISITOR_H
#define MYGLBUILDERGEOMETRY3DVISITOR_H

#include <X3DTK/X3D/glbuilder.h>

namespace X3DTK {
namespace X3D {

class FCylinder;

// My visitor for the Geometry3D component of the GLCreator module.

class MyGLBuilderGeometry3DVisitor : public GLBuilderGeometry3DVisitor
{
public:
  // Constructor.
  MyGLBuilderGeometry3DVisitor();
  
  // Enters an FCylinder.
  static void enterFCylinder(FCylinder *C);
};

}
}

#endif

X3D_MyGLBuilderGeometry3DVisitor.cpp

#include "X3D_MyGLBuilderGeometry3DVisitor.h"
#include "X3D_FCylinder.h"
#include "GL_FCylinder.h"

#include <iostream>

using namespace std;

namespace X3DTK {
namespace X3D {

MyGLBuilderGeometry3DVisitor::MyGLBuilderGeometry3DVisitor()
: GLBuilderGeometry3DVisitor()
{
  // Define new enter function for FCylinder.
  define(Recorder<FCylinder>::getEnterFunction(&MyGLBuilderGeometry3DVisitor::enterFCylinder));
}

void MyGLBuilderGeometry3DVisitor::enterFCylinder(FCylinder *C)
{
  GLBuilderStateVariables *stateVariables = Singleton<GLBuilderStateVariables>::getInstance();
  
  GL::X3DNode *GC = stateVariables->getNode(C);
  if (GC == 0)
  {
    GC = new GL::FCylinder();
    GC->setX3DReference(C);
    stateVariables->addCoupleNode(C, GC);
  }
  stateVariables->pushNode(GC);
}

}
}

Viewer.h

#ifndef VIEWER_H
#define VIEWER_H

#include <QGLViewer/qglviewer.h>
#include <X3DTK/simplex3dglscene.h>

// Class providing an X3D Viewer by implementing QGLViewer.

class Viewer : public QGLViewer
{
protected :
  void init();
  void draw();
  void keyPressEvent(QKeyEvent *e);
  void loadFile();
  void about();
  QString helpString() const;
  void help() const;
  
private:
  X3DTK::SimpleX3DGLScene scene;
};

#endif

Viewer.cpp

#include "Viewer.h"
#include "X3D_MyGeometry3DCreator.h"
#include "X3D_MyGLBuilderGeometry3DVisitor.h"

#include <qfiledialog.h>
#include <qmessagebox.h> 
#include <X3DTK/kernel.h>

using namespace X3DTK;
using namespace std;

void Viewer::init()
{
  // We customize the SimpleX3DGLScene, by changing its X3DLoader, GLCreator
  scene.getLoader()->setComponentCreator(new X3D::MyGeometry3DCreator());
  scene.getGLBuilder()->setComponentVisitor(new X3D::MyGLBuilderGeometry3DVisitor());
  
#ifdef GL_RESCALE_NORMAL
  glEnable(GL_RESCALE_NORMAL);
#endif
  about();
  loadFile();
}

void Viewer::keyPressEvent(QKeyEvent *e)
{
  switch (e->key())
  {
    case Qt::Key_L : loadFile(); break;
    default:         QGLViewer::keyPressEvent(e);
  }
}

void Viewer::loadFile()
{
  QString name = QFileDialog::getOpenFileName("", "X3D files (*.x3d *.X3D);;All files (*)", this);
  
  // In case of Cancel
  if (name.isEmpty())
    return;

  scene.release();
  // Loads the scene.
  scene.load(name);
  
  // Shows the inheritance tree.
  SFType::printInheritanceTree(); 
  cout << endl;
  
  // QGLViewer settings.
  setSceneBoundingBox(scene.getBBoxMin().f_data(), scene.getBBoxMax().f_data());
  showEntireScene();
}

void Viewer::draw()
{
  // Draws the scene.
  scene.draw();
}

void Viewer::about()
{
  QMessageBox::about(this, "about the newNodeViewer", "this is an example showing how to create a new node.Type 'h' to display help");
}

QString Viewer::helpString() const
{
  QString message("");
  
  message += "<b>L</b>" + QString(" loads a new file<br>");
  
  message += QGLViewer::helpString();
  
  return message;
}

void Viewer::help() const
{
  QMessageBox *mb = new QMessageBox("help", helpString(), QMessageBox::NoIcon,QMessageBox::Ok | QMessageBox::Default, QMessageBox::NoButton,QMessageBox::NoButton, NULL, "Help", false,Qt::WStyle_DialogBorder | Qt::WType_Dialog | Qt::WDestructiveClose);
  mb->show();
}

Generated on Fri Jul 30 12:02:32 2004 for X3DToolKit by doxygen 1.3.6