We want to define an X3DTK::X3D::FCylinder
node, deriving from X3DTK::X3D::Cylinder
and that enables the control of the cylinder discretization.
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.X3DTK::X3D::FCylinder
belongs to it.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.X3DTK::X3D::GLBuilderGeometry3DVisitor
, which will create the X3DTK::GL::FCylinder
from an X3DTK::X3D::FCylinder
.#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 SFAbstractNode 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
#include "X3D_FCylinder.h" namespace X3DTK { namespace X3D { FCylinder::FCylinder() : Cylinder(), _section(8) { // Defines the tag of the node. This string is the one read in the X3D file. 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) { } SFAbstractNode 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; } } }
#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
#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()); } } }
#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 SFAbstractNode clone() const; virtual void update(); protected: // Copy constructor. FCylinder(const FCylinder &C); }; } } #endif
#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) { } SFAbstractNode 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())); } } }
#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
#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::SFNode GC = stateVariables->getNode(C); if (GC == 0) { GC = new GL::FCylinder(); GC->setX3DReference(C); stateVariables->addCoupleNode(C, GC); } stateVariables->pushNode(GC); } } }
#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
#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(); }