Main Page | Modules | Namespace List | Class Hierarchy | Compound List | File List | Namespace Members | Compound Members | File Members | Related Pages

newNodeViewer

Introduction

In icosahedronViewer, we showed how to define a new node and extend processors. Here we define a new node too, but we show how we can reuse the existing processors and extend only the necessary ones.

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

Deriving X3D::Cylinder

We derive X3DTK::X3D::Cylinder and we add a section attribute. Note that the copy constructor is protected, because the nodes must be passed by pointers, and not by value. Nevertheless we define a clone method. For the node be loaded, the load method has to be redefined, as well as the write method, to enable the writing of the X3DTK::X3D::FCylinder node in an X3D file.

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 has not to be redefined.

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:
  // Constructor.
  FCylinder();
  // Constructs a Cylinder from its attributes.
  FCylinder(SFBool bottom, 
            SFFloat radius, 
            SFFloat height, 
            SFBool side, 
            SFBool top,
            SFInt32 section);
            
  // Clones the node.
  virtual SFNode clone() const;  
  // sets the number of sections.
  void setSection(SFInt32 section);

  // gets the number of sections.
  inline SFInt32 getSection() const {return _section;};
  
  // Loads the attributes from a X3DFileElement e.
  virtual void load(const X3DFileElement *element);
  // Writes the attributes of the node.
  virtual SFString &write(SFString &output) const;

protected:
  // Copy constructor.     
  FCylinder(const FCylinder &C);

private:
  SFInt32 _section;
};

}
}

#endif

X3D_FCylinder.cpp

#include "X3D_FCylinder.h"

namespace X3DTK {
namespace X3D {

FCylinder::FCylinder()
: Cylinder(), _section(8)
{
  // Defines the tag of the node. This string must be the same than the one 
  // entered for the creation function, otherwise the node won't be loaded.
  defineTypeName("FCylinder");
}

FCylinder::FCylinder(SFBool bottom, SFFloat radius, SFFloat height, SFBool side, SFBool top, SFInt32 section)
: Cylinder(bottom, radius, height, side, top), _section(section)
{
  // Defines the tag of the node.
  defineTypeName("FCylinder");
}

FCylinder::FCylinder(const FCylinder &C)
: Cylinder(C), _section(C._section)
{
}

SFNode FCylinder::clone() const
{
  return new FCylinder(*this);
}

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

void FCylinder::load(const X3DFileElement *element)
{
  Cylinder::load(element);
  
  int index;
  index = element->getIndexAttribute("section");
  if (index != -1)
    _section = element->getAttribute(index).toInt();
}

SFString &FCylinder::write(SFString &output) const
{
  Cylinder::write(output);
  if (_section != 8)    
    output += " section=\"" + toSFString(_section) + "\"";
      
  return output;
}

}
}

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.
  defineNode<FCylinder>();
}

}
}

GL_FCylinder.h

#ifndef GL_FCYLINDER_H
#define GL_FCYLINDER_H

#include <X3DTK/GL/scenegraph.h>

namespace X3DTK {
namespace GL {

// Class providing a implementation of the X3DGLNode corresponding to the X3DNode 
// FCylinder.

class FCylinder : public Cylinder
{
public:
  // Constructor.
  FCylinder();
  // Clones the node.
  virtual SFNode clone() const;

  virtual void update();

protected:
  // Copy constructor.
  FCylinder(const FCylinder &C);  
};

}
}

#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. 
  defineTypeName("FCylinder");
}

FCylinder::FCylinder(const FCylinder &C)
: Cylinder(C)
{
}

SFNode FCylinder::clone() const
{
  // returns the copy constructor.
  return new FCylinder(*this);
}

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.
  defineEnterFunction(&MyGLBuilderGeometry3DVisitor::enterFCylinder);
}

void MyGLBuilderGeometry3DVisitor::enterFCylinder(FCylinder *C)
{
  GLBuilderStateVariables *stateVariables = GraphTraversal::getInstanceOf<GLBuilderStateVariables>();
  
  GL::SFNode 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 Wed Apr 7 12:15:26 2004 for X3DToolKit by doxygen 1.3.3