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

glNormalViewer

Introduction

This an example of how to write a new processor. Here we want to define a processor displaying in a GL context the normals of the model and controlling the length of the normals.

GL::NormalRendererGlobalVariables

To control the length of the normals displayed to screen, we have to memorize a variable global to the traverse of the scene graph. That's why we derive GlobalVariables and add methods to set and get the length.

GL::NormalRendererGroupingVisitor

To draw the normals in the correct coordinates, we have to push the Transform matrices. Thus we define the methods enterTransform and leaveTransform operating on the GL::Transform node that belongs to the Grouping component.

GL::NormalRendererGeometry3DVisitor

To draw the normals we have to visit the GL::IndexedFaceSet node which already has the vertexArrays updated to be rendered by OpenGL. We just have to get the normals from the arrays. That is here that we get the length of the normals. The instance of the GL::NormalRendererGlobalVariables is given by GVManager which controls the number of instances.

GL::NormalRenderer

This is the facade of the processor which aggregates the visitors of the different components. It also contains the algorithm GL::DefaultDFS of traversal of the scene graph.

NormalX3DGLScene

We customize SimpleX3DGLScene by adding methods relative to the display of the normals.

code

GLNormalRendererGlobalVariables

GLNormalRendererGlobalVariables.h












//                            GLNormalRendererGlobalVariables.h               //

#ifndef GLNORMALRENDERERGLOBALVARIABLES_H
#define GLNORMALRENDERERGLOBALVARIABLES_H

#include <X3DTK/kernel.h>

namespace X3DTK {
namespace GL {


class NormalRendererGlobalVariables : public GlobalVariables
{
public:
  NormalRendererGlobalVariables();
  virtual ~NormalRendererGlobalVariables();
  
  void setNormalLength(float value);
  float getNormalLength() const {return _normalLength;};
  
private:
  float _normalLength;
};

}
}

#endif

GLNormalRendererGlobalVariables.cpp

#include "GLNormalRendererGlobalVariables.h"

namespace X3DTK {
namespace GL {

NormalRendererGlobalVariables::NormalRendererGlobalVariables()
: GlobalVariables(), _normalLength(1.0f)
{
}

NormalRendererGlobalVariables::~NormalRendererGlobalVariables()
{
}

void NormalRendererGlobalVariables::setNormalLength(float value)
{
  _normalLength = value;
}

}
}

GLNormalRendererGroupingVisitor

GLNormalRendererGroupingVisitor.h












//                            GLNormalRendererGroupingVisitor.h               //

#ifndef GLNORMALRENDERERGROUPINGVISITOR_H
#define GLNORMALRENDERERGROUPINGVISITOR_H

#include <X3DTK/kernel.h>

namespace X3DTK {
namespace GL {


class NormalRendererGroupingVisitor : public GroupingVisitor
{
public:
  NormalRendererGroupingVisitor();
  virtual ~NormalRendererGroupingVisitor();

  virtual void enterTransform(Transform *T) const;

  virtual void leaveTransform(Transform *T) const;
};

}
}

#endif

GLNormalRendererGroupingVisitor.cpp

#include "GLNormalRendererGroupingVisitor.h"

namespace X3DTK {
namespace GL {

NormalRendererGroupingVisitor::NormalRendererGroupingVisitor()
: GroupingVisitor()
{
  // Enter functions.
  defineNewEnterFunction<NormalRendererGroupingVisitor, Transform>(&NormalRendererGroupingVisitor::enterTransform);

  // Leave functions
  defineNewLeaveFunction<NormalRendererGroupingVisitor, Transform>(&NormalRendererGroupingVisitor::leaveTransform);
}

NormalRendererGroupingVisitor::~NormalRendererGroupingVisitor()
{
}

void NormalRendererGroupingVisitor::enterTransform(Transform *T) const
{
  glMatrixMode(GL_MODELVIEW);
  glPushMatrix();
  glMultMatrixf(&T->getTransformMatrix().front());
}

void NormalRendererGroupingVisitor::leaveTransform(Transform *T) const
{
  glMatrixMode(GL_MODELVIEW);
  glPopMatrix();  
}

}
}

GLNormalRendererGeometry3DVisitor

GLNormalRendererGeometry3DVisitor.h












//                            GLNormalRendererGeometry3DVisitor.h             //

#ifndef GLNORMALRENDERERGEOMETRY3DVISITOR_H
#define GLNORMALRENDERERGEOMETRY3DVISITOR_H

#include "GLNormalRendererGlobalVariables.h"

#include <X3DTK/kernel.h>

namespace X3DTK {
namespace GL {


class NormalRendererGeometry3DVisitor : public Geometry3DVisitor
{
public:
  NormalRendererGeometry3DVisitor();
  virtual ~NormalRendererGeometry3DVisitor();

  virtual void enterIndexedFaceSet(IndexedFaceSet *I) const;

protected:
  NormalRendererGlobalVariables *globalVariables;
};

}
}

#endif

GLNormalRendererGeometry3DVisitor.cpp

#include "GLNormalRendererGeometry3DVisitor.h"

#include <vector>

using namespace std;

namespace X3DTK {
namespace GL {

NormalRendererGeometry3DVisitor::NormalRendererGeometry3DVisitor()
: Geometry3DVisitor()
{
  // Enter functions.
  defineNewEnterFunction<NormalRendererGeometry3DVisitor, IndexedFaceSet>(&NormalRendererGeometry3DVisitor::enterIndexedFaceSet);

  // GlobalVariables assignation.
  globalVariables = GVManager::getInstanceOf<NormalRendererGlobalVariables>();
}

NormalRendererGeometry3DVisitor::~NormalRendererGeometry3DVisitor()
{
}

void NormalRendererGeometry3DVisitor::enterIndexedFaceSet(IndexedFaceSet *G) const
{
  float coef = globalVariables->getNormalLength();

  glColor3f(1.0f, 0.0f, 0.0f);
  glDisable(GL_LIGHTING);
  
  if ((G->getColor()) && (G->getTexCoord()))
  {
    const vector<T2F_C4F_N3F_V3F> &vertexArray = G->T2F_C4F_N3F_V3F_vertexArray();
    
    glBegin(GL_LINES);
    for (vector<T2F_C4F_N3F_V3F>::const_iterator it = vertexArray.begin(); it != vertexArray.end(); ++it)
    {
      SFVec3f vertex = (*it).vertex;
      SFVec3f vnormal = vertex + coef*(*it).normal;
      glVertex3fv(vertex.f_data());
      glVertex3fv(vnormal.f_data());
    }
    glEnd();    
  }  
    
  if ((G->getColor()) && (!G->getTexCoord()))
  {
    const vector<C4F_N3F_V3F> &vertexArray = G->C4F_N3F_V3F_vertexArray();
    
    glBegin(GL_LINES);
    for (vector<C4F_N3F_V3F>::const_iterator it = vertexArray.begin(); it != vertexArray.end(); ++it)
    {
      SFVec3f vertex = (*it).vertex;
      SFVec3f vnormal = vertex + coef*(*it).normal;
      glVertex3fv(vertex.f_data());
      glVertex3fv(vnormal.f_data());
    }
    glEnd();    
  }  
    
  if ((!G->getColor()) && (G->getTexCoord()))
  {
    const vector<T2F_N3F_V3F> &vertexArray = G->T2F_N3F_V3F_vertexArray();
    
    glBegin(GL_LINES);
    for (vector<T2F_N3F_V3F>::const_iterator it = vertexArray.begin(); it != vertexArray.end(); ++it)
    {
      SFVec3f vertex = (*it).vertex;
      SFVec3f vnormal = vertex + coef*(*it).normal;
      glVertex3fv(vertex.f_data());
      glVertex3fv(vnormal.f_data());
    }
    glEnd();    
  }  
  
  if ((!G->getColor()) && (!G->getTexCoord()))
  {
    const vector<N3F_V3F> &vertexArray = G->N3F_V3F_vertexArray();
    
    glBegin(GL_LINES);
    for (vector<N3F_V3F>::const_iterator it = vertexArray.begin(); it != vertexArray.end(); ++it)
    {
      SFVec3f vertex = (*it).vertex;
      SFVec3f vnormal = vertex + coef*(*it).normal;
      glVertex3fv(vertex.f_data());
      glVertex3fv(vnormal.f_data());
    }
    glEnd();    
  }
  
  glEnable(GL_LIGHTING);
}

}
}

GLNormalRenderer

GLNormalRenderer.h












//                            GLNormalRenderer.h                              //

#ifndef GLNORMALRENDERER_H
#define GLNORMALRENDERER_H

#include "GLNormalRendererGlobalVariables.h"

#include <X3DTK/kernel.h>

namespace X3DTK {
namespace GL {


class NormalRenderer
{
public:
  NormalRenderer();
  virtual ~NormalRenderer();
  
  void setNormalLength(float value);
  void setComponentVisitor(X3DComponentVisitor *component);
    
  virtual void render(SFNode N) const;

protected:
  DFS *dfs;
  NormalRendererGlobalVariables *globalVariables;
};

}
}

#endif

GLNormalRenderer.cpp

#include "GLNormalRenderer.h"
#include "GLNormalRendererGeometry3DVisitor.h"
#include "GLNormalRendererGroupingVisitor.h"

#include <iostream>

using namespace std;

namespace X3DTK {
namespace GL {

NormalRenderer::NormalRenderer()
{
  dfs = new DefaultDFS();
  
  globalVariables = GVManager::getInstanceOf<NormalRendererGlobalVariables>();
  
  dfs->setComponentVisitor(new NormalRendererGeometry3DVisitor());
  dfs->setComponentVisitor(new NormalRendererGroupingVisitor());
}

NormalRenderer::~NormalRenderer()
{
  delete dfs;
}

void NormalRenderer::setNormalLength(float value)
{
  globalVariables->setNormalLength(value);
}

void NormalRenderer::setComponentVisitor(X3DComponentVisitor *component)
{
  dfs->setComponentVisitor(component);
} 

void NormalRenderer::render(SFNode N) const
{
  glDisable(GL_COLOR_MATERIAL);
  dfs->traverse(N);
}

}
}

NormalX3DGLScene

NormalX3DGLScene.h







#ifndef NORMALX3DGLSCENE_H
#define NORMALX3DGLSCENE_H

#include <X3DTK/simplex3dglscene.h>
#include "GLNormalRenderer.h"

namespace X3DTK {

class NormalX3DGLScene : public SimpleX3DGLScene
{
public:
  NormalX3DGLScene();
  virtual ~NormalX3DGLScene();
  
  void setNormal(bool value);
  void setNormalLength(float value);
  
  virtual void draw();

private:
  GL::NormalRenderer *_normalRenderer;
  bool _normal;
};

}

#endif

NormalX3DGLScene.cpp

#include "NormalX3DGLScene.h"

namespace X3DTK {

NormalX3DGLScene::NormalX3DGLScene()
: SimpleX3DGLScene(), _normalRenderer(new GL::NormalRenderer()), _normal(false)
{
}

NormalX3DGLScene::~NormalX3DGLScene()
{
  delete _normalRenderer;
}

void NormalX3DGLScene::setNormal(bool value)
{
  _normal = value;
}

void NormalX3DGLScene::setNormalLength(float value)
{
  _normalRenderer->setNormalLength(value);
}

void NormalX3DGLScene::draw()
{
  SimpleX3DGLScene::draw();
  if (_normal)
    _normalRenderer->render(glscene);
}

}

Viewer

Viewer.h







//                            Viewer.h                                        //

#ifndef VIEWER_H
#define VIEWER_H

#include <QGLViewer/qglviewer.h>
#include "NormalX3DGLScene.h"


class Viewer : public QGLViewer
{
public:
  Viewer(const char *file);
  ~Viewer();
  
protected :
  void loadFile();
  void keyPressEvent(QKeyEvent *e);
  void init();
  void draw();
  void about();
  void help();
  
private:
  float normLength;
  X3DTK::NormalX3DGLScene scene;
  X3DTK::Bbox BB;
  char *x3dfile;
  bool normal;
};

#endif

Viewer.cpp

#include "Viewer.h"
#include <X3DTK/glrenderer.h>

#include <math.h>
#include <iostream>
#include <qfiledialog.h>

using namespace X3DTK;
using namespace std;

Viewer::Viewer(const char *file)
: normLength(1.0f), normal(false)
{
  x3dfile = (char *)file;
}

Viewer::~Viewer()
{
  scene.release();
}

void Viewer::keyPressEvent(QKeyEvent *e)
{
  switch (e->key())
  {
    case Qt::Key_L : 
      loadFile(); break;
    case Qt::Key_N : 
      normal = !normal;
      scene.setNormal(normal);
      break;
    case Qt::Key_Minus :
      normLength /= 2.0f;
      scene.setNormalLength(normLength);
      break;
    case Qt::Key_Plus :
      normLength *= 2.0f;
      scene.setNormalLength(normLength);
      break;
    default: 
      QGLViewer::keyPressEvent(e);
  }
  updateGL();
}

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

  // Loads the file name.
  scene.load(name, false);

  setSceneBoundingBox(scene.getBboxMin().f_data(), scene.getBboxMax().f_data());
  showEntireScene();
}

void Viewer::init()
{
  loadFile();
  glEnable(GL_RESCALE_NORMAL);
}

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


Generated on Wed Sep 10 11:25:17 2003 for X3DToolKit by doxygen1.3