Main Page Namespace List Class Hierarchy Compound List File List Namespace Members Compound Members File Members Related Pages
Introduction
This an example of how to animate an X3D model. Here we want to deform the model globally. This is realized by deforming directly the GL graph scene. At each time step, the tree is traversed and the vertices of the GL::IndexedFaceSet
nodes are moved.
GL::SimpleAnimatorGlobalVariables
To animate the model, we need to store the time as a global variable to the traversal, as well as the bounding box of the scene, necessary to the deformation function.
GL::SimpleAnimatorGeometry3DVisitor
We have to visit the GL::IndexedFaceSet
nodes. To be general, we have to process the different possible types of vertex arrays, implying that the code is redundant. There are 8 cases: 4 vertex formats plus the fact that the vertices can be duplicated. Indeed sometimes the model requires that the GL vertices are duplicated. It means that for a vertex of the X3D::IndexedFaceSet
node, there are one or more vertices for the GL::IndexedFaceSet
node. That is why, to find the relation between the X3D vertices and the GL vertices, we use the X3DToGLIndex.
GL::SimpleAnimator
This is the facade of the processor.
SimpleAnimationScene
We customize SimpleX3DGLScene
by adding methods relative to the animation of the model.
code
GLSimpleAnimatorGlobalVariables
GLSimpleAnimatorGlobalVariables.h
#ifndef GLSIMPLEANIMATORGLOBALVARIABLES_H
#define GLSIMPLEANIMATORGLOBALVARIABLES_H
#include <X3DTK/kernel.h>
namespace X3DTK {
namespace GL {
class SimpleAnimatorGlobalVariables : public GlobalVariables
{
public:
SimpleAnimatorGlobalVariables();
virtual ~SimpleAnimatorGlobalVariables();
void setBboxSize(const SFVec3f &size);
void setTime(float time);
float getTime() const {return _time;};
inline SFVec3f getBboxSize() const {return _bboxSize;};
private:
float _time;
SFVec3f _bboxSize;
};
}
}
#endif
GLSimpleAnimatorGlobalVariables.cpp
#include "GLSimpleAnimatorGlobalVariables.h"
namespace X3DTK {
namespace GL {
SimpleAnimatorGlobalVariables::SimpleAnimatorGlobalVariables()
: GlobalVariables(), _time(0.0f)
{
}
SimpleAnimatorGlobalVariables::~SimpleAnimatorGlobalVariables()
{
}
void SimpleAnimatorGlobalVariables::setBboxSize(const SFVec3f &size)
{
_bboxSize = size;
}
void SimpleAnimatorGlobalVariables::setTime(float time)
{
_time = time;
}
}
}
GLSimpleAnimatorGeometry3DVisitor
GLSimpleAnimatorGeometry3DVisitor.h
#ifndef GLSIMPLEANIMATORGEOMETRY3DVISITOR_H
#define GLSIMPLEANIMATORGEOMETRY3DVISITOR_H
#include "GLSimpleAnimatorGlobalVariables.h"
#include <X3DTK/kernel.h>
namespace X3DTK {
namespace GL {
class IndexedFaceSet;
class SimpleAnimatorGeometry3DVisitor : public Geometry3DVisitor
{
public:
SimpleAnimatorGeometry3DVisitor();
virtual ~SimpleAnimatorGeometry3DVisitor();
virtual void enterIndexedFaceSet(IndexedFaceSet *I) const;
protected:
SimpleAnimatorGlobalVariables *globalVariables;
};
}
}
#endif
GLSimpleAnimatorGeometry3DVisitor.cpp
#include "GLSimpleAnimatorGeometry3DVisitor.h"
#include <iostream>
#include <cmath>
using namespace std;
namespace X3DTK {
namespace GL {
SimpleAnimatorGeometry3DVisitor::SimpleAnimatorGeometry3DVisitor()
: Geometry3DVisitor()
{
defineNewEnterFunction<SimpleAnimatorGeometry3DVisitor, IndexedFaceSet>(&SimpleAnimatorGeometry3DVisitor::enterIndexedFaceSet);
globalVariables = GVManager::getInstanceOf<SimpleAnimatorGlobalVariables>();
}
SimpleAnimatorGeometry3DVisitor::~SimpleAnimatorGeometry3DVisitor()
{
}
void SimpleAnimatorGeometry3DVisitor::enterIndexedFaceSet(IndexedFaceSet *I) const
{
SFVec3f size = globalVariables->getBboxSize();
float mz = size.z;
float mxy = (size.x < size.y ? size.y : size.x);
float a = mxy*mxy*mz*0.1f*cosf(globalVariables->getTime());
float b = mxy*mxy;
float c = 1.0f;
float d = a/b;
if (I->getVertexFormat() == GL_N3F_V3F)
{
vector<N3F_V3F> &vertexArray = I->N3F_V3F_vertexArray();
if (I->getVerticesDuplicated())
{
const vector<MFInt32> &X3DToGLIndex = I->getX3DToGLIndex();
for (vector<MFInt32>::const_iterator itIndexArray = X3DToGLIndex.begin(); itIndexArray != X3DToGLIndex.end(); ++itIndexArray)
{
if ((*itIndexArray).size() > 0)
{
N3F_V3F *V = &vertexArray[(*itIndexArray).front()];
V->vertex.y = V->vertex.y - d + a/(b + c*(V->vertex.x*V->vertex.x + V->vertex.z*V->vertex.z));
for (MFInt32::const_iterator itIndex = ++((*itIndexArray).begin()); itIndex != (*itIndexArray).end(); ++itIndex)
vertexArray[*itIndex].vertex = V->vertex;
}
}
}
else
{
for (vector<N3F_V3F>::iterator itVertex = vertexArray.begin(); itVertex != vertexArray.end(); ++itVertex)
(*itVertex).vertex.y = (*itVertex).vertex.y - d + a/(b + c*((*itVertex).vertex.x*(*itVertex).vertex.x + (*itVertex).vertex.z*(*itVertex).vertex.z));
}
}
if (I->getVertexFormat() == GL_C4F_N3F_V3F)
{
vector<C4F_N3F_V3F> &vertexArray = I->C4F_N3F_V3F_vertexArray();
if (I->getVerticesDuplicated())
{
const vector<MFInt32> &X3DToGLIndex = I->getX3DToGLIndex();
for (vector<MFInt32>::const_iterator itIndexArray = X3DToGLIndex.begin(); itIndexArray != X3DToGLIndex.end(); ++itIndexArray)
{
if ((*itIndexArray).size() > 0)
{
C4F_N3F_V3F *V = &vertexArray[(*itIndexArray).front()];
V->vertex.y = V->vertex.y - d + a/(b + c*(V->vertex.x*V->vertex.x + V->vertex.z*V->vertex.z));
for (MFInt32::const_iterator itIndex = ++((*itIndexArray).begin()); itIndex != (*itIndexArray).end(); ++itIndex)
vertexArray[*itIndex].vertex = V->vertex;
}
}
}
else
{
for (vector<C4F_N3F_V3F>::iterator itVertex = vertexArray.begin(); itVertex != vertexArray.end(); ++itVertex)
(*itVertex).vertex.y = (*itVertex).vertex.y - d + a/(b + c*((*itVertex).vertex.x*(*itVertex).vertex.x + (*itVertex).vertex.z*(*itVertex).vertex.z));
}
}
if (I->getVertexFormat() == GL_T2F_N3F_V3F)
{
vector<T2F_N3F_V3F> &vertexArray = I->T2F_N3F_V3F_vertexArray();
if (I->getVerticesDuplicated())
{
const vector<MFInt32> &X3DToGLIndex = I->getX3DToGLIndex();
for (vector<MFInt32>::const_iterator itIndexArray = X3DToGLIndex.begin(); itIndexArray != X3DToGLIndex.end(); ++itIndexArray)
{
if ((*itIndexArray).size() > 0)
{
T2F_N3F_V3F *V = &vertexArray[(*itIndexArray).front()];
V->vertex.y = V->vertex.y - d + a/(b + c*(V->vertex.x*V->vertex.x + V->vertex.z*V->vertex.z));
for (MFInt32::const_iterator itIndex = ++((*itIndexArray).begin()); itIndex != (*itIndexArray).end(); ++itIndex)
vertexArray[*itIndex].vertex = V->vertex;
}
}
}
else
{
for (vector<T2F_N3F_V3F>::iterator itVertex = vertexArray.begin(); itVertex != vertexArray.end(); ++itVertex)
(*itVertex).vertex.y = (*itVertex).vertex.y - d + a/(b + c*((*itVertex).vertex.x*(*itVertex).vertex.x + (*itVertex).vertex.z*(*itVertex).vertex.z));
}
}
if (I->getVertexFormat() == GL_T2F_C4F_N3F_V3F)
{
vector<T2F_C4F_N3F_V3F> &vertexArray = I->T2F_C4F_N3F_V3F_vertexArray();
if (I->getVerticesDuplicated())
{
const vector<MFInt32> &X3DToGLIndex = I->getX3DToGLIndex();
for (vector<MFInt32>::const_iterator itIndexArray = X3DToGLIndex.begin(); itIndexArray != X3DToGLIndex.end(); ++itIndexArray)
{
if ((*itIndexArray).size() > 0)
{
T2F_C4F_N3F_V3F *V = &vertexArray[(*itIndexArray).front()];
V->vertex.y = V->vertex.y - d + a/(b + c*(V->vertex.x*V->vertex.x + V->vertex.z*V->vertex.z));
for (MFInt32::const_iterator itIndex = ++((*itIndexArray).begin()); itIndex != (*itIndexArray).end(); ++itIndex)
vertexArray[*itIndex].vertex = V->vertex;
}
}
}
else
{
for (vector<T2F_C4F_N3F_V3F>::iterator itVertex = vertexArray.begin(); itVertex != vertexArray.end(); ++itVertex)
(*itVertex).vertex.y = (*itVertex).vertex.y - d + a/(b + c*((*itVertex).vertex.x*(*itVertex).vertex.x + (*itVertex).vertex.z*(*itVertex).vertex.z));
}
}
I->computeNormals();
}
}
}
GLSimpleAnimator
GLSimpleAnimator.h
#ifndef GLSIMPLEANIMATOR_H
#define GLSIMPLEANIMATOR_H
#include "GLSimpleAnimatorGlobalVariables.h"
#include <X3DTK/kernel.h>
namespace X3DTK {
namespace GL {
class SimpleAnimator : public X3DTTAlgorithm
{
public:
SimpleAnimator();
virtual ~SimpleAnimator();
void setBboxSize(const SFVec3f &size);
virtual void animate(SFNode N, float time);
protected:
SimpleAnimatorGlobalVariables *globalVariables;
DFS *dfs;
};
}
}
#endif
GLSimpleAnimator.cpp
#include "GLSimpleAnimator.h"
#include "GLSimpleAnimatorGeometry3DVisitor.h"
namespace X3DTK {
namespace GL {
SimpleAnimator::SimpleAnimator()
: X3DTTAlgorithm()
{
globalVariables = GVManager::getInstanceOf<SimpleAnimatorGlobalVariables>();
dfs = new DefaultDFS();
dfs->setComponentVisitor(new SimpleAnimatorGeometry3DVisitor());
}
SimpleAnimator::~SimpleAnimator()
{
delete dfs;
}
void SimpleAnimator::setBboxSize(const SFVec3f &size)
{
globalVariables->setBboxSize(size);
}
void SimpleAnimator::animate(SFNode N, float time)
{
globalVariables->setTime(time);
dfs->traverse(N);
}
}
}
SimpleAnimationScene
SimpleAnimationScene.h
#ifndef SIMPLEANIMATIONSCENE_H
#define SIMPLEANIMATIONSCENE_H
#include <X3DTK/simplex3dglscene.h>
#include <X3DTK/worldcoordtranslator.h>
#include "GLSimpleAnimator.h"
namespace X3DTK {
class SimpleAnimationScene : public SimpleX3DGLScene
{
public:
SimpleAnimationScene();
virtual ~SimpleAnimationScene();
virtual void load(const char *file, bool fileValidation = true);
virtual void init();
virtual void animate();
private:
GL::SimpleAnimator *_glSimpleAnimator;
X3D::WorldCoordTranslator *_translator;
float _time;
};
}
#endif
SimpleAnimationScene.cpp
#include "SimpleAnimationScene.h"
#include <iostream>
using namespace std;
namespace X3DTK {
SimpleAnimationScene::SimpleAnimationScene()
: SimpleX3DGLScene(), _time(0.0f)
{
_glSimpleAnimator = new GL::SimpleAnimator();
_translator = new X3D::WorldCoordTranslator();
}
SimpleAnimationScene::~SimpleAnimationScene()
{
delete _glSimpleAnimator;
}
void SimpleAnimationScene::load(const char *file, bool fileValidation)
{
loadFile(file, fileValidation);
_translator->translate(scene);
computeBbox();
buildGLScene();
}
void SimpleAnimationScene::init()
{
_time = 0.0f;
if (scene != 0)
_glSimpleAnimator->setBboxSize(scene->getBboxSize());
}
void SimpleAnimationScene::animate()
{
_time += 0.03f;
_glSimpleAnimator->animate(glscene, _time);
}
}
Viewer
Viewer.h
#ifndef VIEWER_H
#define VIEWER_H
#include <QGLViewer/qglviewer.h>
#include "SimpleAnimationScene.h"
class Viewer : public QGLViewer
{
public:
Viewer(const char *file);
~Viewer();
protected :
void loadFile();
void keyPressEvent(QKeyEvent *e);
void init();
void animate();
void draw();
void about();
void help();
private:
X3DTK::SimpleAnimationScene scene;
X3DTK::Bbox BB;
char *x3dfile;
};
#endif
Viewer.cpp
#include "Viewer.h"
#include <math.h>
#include <iostream>
#include <qfiledialog.h>
#include <qmessagebox.h>
using namespace X3DTK;
using namespace std;
Viewer::Viewer(const char *file)
{
x3dfile = (char *)file;
}
Viewer::~Viewer()
{
scene.release();
}
void Viewer::keyPressEvent(QKeyEvent *e)
{
switch (e->key())
{
case Qt::Key_L :
loadFile(); break;
case Qt::Key_S :
startAnimation(); break;
case Qt::Key_P :
stopAnimation(); break;
default:
QGLViewer::keyPressEvent(e);
}
updateGL();
}
void Viewer::loadFile()
{
QString name = QFileDialog::getOpenFileName("", "X3D files (*.x3d *.X3D);;All files (*)", this);
if (name.isEmpty())
return;
scene.load(name, false);
scene.init();
setSceneBoundingBox(scene.getBboxMin().f_data(), scene.getBboxMax().f_data());
setSceneRadius(2.0f*sceneRadius());
showEntireScene();
}
void Viewer::init()
{
glEnable(GL_RESCALE_NORMAL);
about();
loadFile();
}
void Viewer::animate()
{
scene.animate();
}
void Viewer::draw()
{
scene.draw();
}
void Viewer::about()
{
QMessageBox::about(this, "about the simpleAnimation", "this is an example showing how to animate a simple X3D scene.Type 'h' to display help");
}
void Viewer::help()
{
QMessageBox *mb = new QMessageBox("QGLViewer 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 Sep 10 11:25:17 2003 for X3DToolKit by
1.3