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

icosahedronViewer

Introduction

This is an example on how to create a new X3D node that we want to render. Here we define an X3D::Icosahedron node.

Defining X3D::Icosahedron

The special methods to define necessarily are clone, load and write. For the attributes of the node be loaded, the load method has to be redefined, as well as the write method, to enable the writing of the X3D::Icosahedron node in an X3D file. 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 to enable the cloning of the scene graph. The other methods are relative to the access and the setting of the attributes of the node.

Loading X3D::Icosahedron

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

Computing the bounding box

To render the node, the bounding box must be computed. That is why we extend the BboxUpdater processor. We derive BboxUpdaterGeometry3DVisitor to add the enterIcosahedron function.

Defining GL::Icosahedron

To render X3D::Icosahedron, we first have to define its openGL equivalent node, GL::Icosahedron. Note that there are different namespaces for the scene graphs X3D and GL. The special methods update and draw have to be redefined. Note that the clone method is also present.

building GL::Icosahedron

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

code

X3D_Icosahedron.h




#ifndef ICOSAHEDRON_H
#define ICOSAHEDRON_H

#include <X3DTK/x3d_scenegraph.h>

namespace X3DTK {
namespace X3D {

class Icosahedron : public X3DGeometry3DNode
{
public:
  // Constructor.
  Icosahedron();
  // Constructs an Icosahedron from its attributes.
  Icosahedron(SFFloat radius);
            
  // Clones the node.
  virtual SFNode clone() const;  
  // sets the radius.
  void setRadius(const SFFloat &radius);

  // gets the radius.
  inline const SFFloat &getRadius() const {return _radius;};
  
  // Loads the attributes from a X3DFileElement.
  virtual void load(const X3DFileElement *element);
  // Writes the attributes of the node.
  virtual SFString write() const;

protected:
  // Copy constructor.     
  Icosahedron(const Icosahedron &I);

private:
  SFFloat _radius;
};

}
}

#endif

X3D_Icosahedron.cpp

#include "X3D_Icosahedron.h"

#include <iostream>

using namespace std;

namespace X3DTK {
namespace X3D {

Icosahedron::Icosahedron()
: X3DGeometry3DNode(), _radius(1.0f)
{
  // 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("Icosahedron", "Geometry3D");
}

Icosahedron::Icosahedron(SFFloat radius)
: X3DGeometry3DNode(), _radius(radius)
{
  // Defines the tag of the node.
  defineTypeName("Icosahedron", "Geometry3D");
}

Icosahedron::Icosahedron(const Icosahedron &I)
: X3DGeometry3DNode(I), _radius(I._radius)
{
}

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

void Icosahedron::setRadius(const SFFloat &radius)
{
  _radius = radius;
}
  
void Icosahedron::load(const X3DFileElement *element)
{
  // Converting the text attributes to the memory attributes.
  int index;
  index = element->getIndexAttribute("radius");
  if (index != -1)
    _radius = element->getAttribute(index).toFloat();
}

SFString Icosahedron::write() const
{
  // Converting the memory attributes to the text attributes.
  SFString attr;
  if (_radius != 1.0f)    
    attr += " radius=\"" + toSFString(_radius) + "\"";
      
  return attr;
}

}
}

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_Icosahedron.h"

namespace X3DTK {
namespace X3D {

MyGeometry3DCreator::MyGeometry3DCreator()
: Geometry3DCreator()
{
  // Defines a new creation function for the Icosahedron node.
  defineNode<Icosahedron>();
}

}
}

X3D_MyBBoxUpdaterGeometry3DVisitor.h




#ifndef MYBBOXUPDATERGEOMETRY3DVISITOR_H
#define MYBBOXUPDATERGEOMETRY3DVISITOR_H

#include <X3DTK/x3d_bboxupdater.h>

namespace X3DTK {
namespace X3D {

class Icosahedron;

// Visitor for the Geometry3D component of the MyBBoxUpdater processor.

class MyBBoxUpdaterGeometry3DVisitor : public BBoxUpdaterGeometry3DVisitor
{
public:
  // Constructor.
  MyBBoxUpdaterGeometry3DVisitor();

  // Enters an X3DAbstractNode.
  virtual void enterIcosahedron(Icosahedron *I) const;
  
};

}
}

#endif

X3D_MyBBoxUpdaterGeometry3DVisitor.cpp

#include "X3D_MyBBoxUpdaterGeometry3DVisitor.h"
#include "X3D_Icosahedron.h"

#include <iostream>

using namespace std;

namespace X3DTK {
namespace X3D {

MyBBoxUpdaterGeometry3DVisitor::MyBBoxUpdaterGeometry3DVisitor()
: BBoxUpdaterGeometry3DVisitor()
{
  // Defines the new enter function for the X3DAbstractNode.
  defineEnterFunction(&MyBBoxUpdaterGeometry3DVisitor::enterIcosahedron);
}

void MyBBoxUpdaterGeometry3DVisitor::enterIcosahedron(Icosahedron *I) const
{
  // Checking whether the BBox of the node has already been computed.
  BBox *BB = stateVariables->getBBox(I);
  if (BB == 0)
  {
    BB = new BBox(SFVec3f(0.0f, 0.0f, 0.0f), SFVec3f(2.0f*I->getRadius(), 2.0f*I->getRadius(), 2.0f*I->getRadius()));
    stateVariables->addBBox(I, BB);
    stateVariables->setShapeBBox(*BB);
  }
}

}
}

GL_Icosahedron.h




#ifndef GL_ICOSAHEDRON_H
#define GL_ICOSAHEDRON_H

#include <X3DTK/gl_scenegraph.h>

namespace X3DTK {
namespace GL {

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

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

  // Sets the radius.
  void setRadius(const SFFloat &radius);
  
  // Gets the radius.
  inline const SFFloat &getRadius() const {return _radius;};

  // Updates the attributes of the node.
  virtual void update();
  // Draws the node.
  virtual void draw() const;

protected:
  // Copy constructor.
  Icosahedron(const Icosahedron &I); 

private:  
  MFVec3f _vertices;
  short _indexes[12][5];
  MFVec3f _normal;
  SFFloat _radius; 
};

}
}

#endif

GL_Icosahedron.cpp

#include "GL_Icosahedron.h"
#include "X3D_Icosahedron.h"

#include <cmath>

#include <iostream>

namespace X3DTK {
namespace GL {

Icosahedron::Icosahedron()
: X3DGeometry3DNode()
{
  // Defines the tag of the node. 
  defineTypeName("Icosahedron", "Geometry3D");
}

Icosahedron::Icosahedron(const Icosahedron &I)
: X3DGeometry3DNode(I)
{
}

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

void Icosahedron::update()
{
  X3D::Icosahedron *I = static_cast<X3D::Icosahedron *>(x3dReference);
  
  // updating the attributes.
  _radius = I->getRadius();
  
  // building the vertex array.
  
  const float c = cos(M_PI/3.0);
  const float s = sin(M_PI/3.0);

  _vertices = MFVec3f(20);

  _vertices[0] = SFVec3f(c+2.0*s, s, 0.0);
  _vertices[1] = SFVec3f(-c-2.0*s, s, 0.0);
  _vertices[2] = SFVec3f(c+2.0*s, -s, 0.0);
  _vertices[3] = SFVec3f(-c-2.0*s, -s, 0.0);
  _vertices[4] = SFVec3f(0.0, 2.0*s+c,  s);
  _vertices[5] = SFVec3f(0.0, -2.0*s-c,  s);
  _vertices[6] = SFVec3f(0.0, 2.0*s+c, -s);
  _vertices[7] = SFVec3f(0.0, -2.0*s-c, -s);
  _vertices[8] = SFVec3f(-c-s,  -c-s, c+s);
  _vertices[9] = SFVec3f(-c-s,  c+s,  c+s);
  _vertices[10] = SFVec3f(-c-s, -c-s, -c-s);
  _vertices[11] = SFVec3f(-c-s, c+s,  -c-s);
  _vertices[12] = SFVec3f(c+s, -c-s, c+s);
  _vertices[13] = SFVec3f(c+s, c+s,  c+s);
  _vertices[14] = SFVec3f(c+s, -c-s, -c-s);
  _vertices[15] = SFVec3f(c+s, c+s,  -c-s);
  _vertices[16] = SFVec3f(-s, 0.0, -2.0*s-c);
  _vertices[17] = SFVec3f(s, 0.0, -2.0*s-c);
  _vertices[18] = SFVec3f(-s, 0.0, 2.0*s+c);
  _vertices[19] = SFVec3f(s, 0.0, 2.0*s+c);

  static short array[12][5] = {
    { 0, 13, 19, 12, 2 },
    { 0, 2, 14, 17, 15 } ,
    { 0, 15, 6, 4, 13 } ,
    { 6, 15, 17, 16, 11 } ,
    { 4, 6, 11, 1, 9 } ,
    { 11, 16, 10, 3, 1 } ,
    { 16, 17, 14, 7, 10 } ,
    { 10, 7, 5, 8, 3 } ,
    { 5, 12, 19, 18, 8 } ,
    { 12, 5, 7, 14, 2 } ,
    { 18, 19, 13, 4, 9 } ,
    { 1, 3, 8, 18, 9 } };

  _normal = MFVec3f(12);

  for (int i = 0; i < 12; ++i)
  {
    _normal[i] = SFVec3f(0.0, 0.0, 0.0);
    for (int j = 0; j < 5; ++j)
    {
      _indexes[i][j] = array[i][j];
      _normal[i] += _vertices[_indexes[i][j]];
    }
    _normal[i].normalize();
  }  
}

void Icosahedron::setRadius(const SFFloat &radius)
{
  _radius = radius;
}

void Icosahedron::draw() const
{
  // drawing the polygon.
  // Changing the scale for the radius of the object.
  
  glMatrixMode(GL_MODELVIEW);
  glPushMatrix();
  glScalef(_radius, _radius, _radius);
  
  for (int i = 0; i < 12; ++i)
  {
    // drawing the normals and the faces.
    glNormal3f(_normal[i].x, _normal[i].y, _normal[i].z);
    glBegin(GL_POLYGON);
    for (int j = 0; j < 5; ++j)
      glVertex3f(_vertices[_indexes[i][j]].x, _vertices[_indexes[i][j]].y, _vertices[_indexes[i][j]].z);
    glEnd();
  }  
  
  glPopMatrix();
}

}
}

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.
  void enterFCylinder(FCylinder *C) const;
};

}
}

#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) const
{
  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 derivation tree.
  SFType::printDerivationTree(); 
  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 Thu Dec 4 13:25:52 2003 for X3DToolKit by doxygen1.2.18