Brief Introduction
Nehe Tutorial In this lesson to show us how to simulate the movement of a rope, simply, that is, the rope first discretization, think of it as a tight arrangement of points, each two points with elastic constraints. In fact, this is the simple idea of finite element. The content of this class is the same as that of last class, which is mainly related to physics and mathematics, and has little to do with graphic images. Implement
First we also create the geometry in the scene:
Root->addchild (Createground ()); Ground
Root->addchild (Createropeshadow ());///Rope Shadow
Root->addchild (Createrope ()); Rope
Next, set the update callback for each geometry:
osg::geode* Createrope () {Osg::geode *geode = new Osg::geode;
Osg::geometry *geometry = new Osg::geometry;
Geometry->setupdatecallback (new Ropeupdatecallback);
Osg::vec3array *vertexarray = new Osg::vec3array;
Osg::vec3array *colorarray = new Osg::vec3array;
Colorarray->push_back (OSG::VEC3 (1, 1, 0));
for (int a = 0; a < ropesimulation->numofmasses-1; ++a) {mass* Mass1 = Ropesimulation->getmass (a);
vector3d* POS1 = &mass1->pos;
mass* Mass2 = Ropesimulation->getmass (A + 1);
vector3d* Pos2 = &mass2->pos;
Vertexarray->push_back (OSG::VEC3 (pos1->x, Pos1->y, pos1->z));
Vertexarray->push_back (OSG::VEC3 (pos2->x, Pos2->y, pos2->z));
} geometry->setvertexarray (Vertexarray);
Geometry->setcolorarray (Colorarray, Osg::array::bind_overall);
Geometry->getorcreatestateset ()->setmode (gl_lighting, Osg::stateattribute::off);
Geometry->getorcreatestateset ()->setmode (Gl_depth_test, false); geometry-≫getorcreatestateset ()->setattributeandmodes (new Osg::linewidth (4.0));
Geometry->addprimitiveset (new OSG::D rawarrays (osg::P rimitiveset::lines, 0, Vertexarray->size ()));
Geode->adddrawable (geometry);
return geode; }
Update the parameters of the rope in the frame loop:
Case (Osgga::guieventadapter::frame):
{
double dt = 0.0;
_currenttick = Osg::timer::instance ()->tick ();
if (_currenttick!= _lasttick)
{
dt = osg::timer::instance ()->delta_s (_lasttick, _currenttick);
_lasttick = _currenttick;
}
Ropesimulation->setropeconnectionvel (ropeconnectionvel);
float Maxpossible_dt = 0.002f;
int numofiterations = (int) (DT/MAXPOSSIBLE_DT) + 1;
if (numofiterations!= 0)
dt = dt/numofiterations;
for (int a = 0; a < numofiterations ++a)
ropesimulation->operate (DT);
}
Add each section to the scene root node and compile the program:
Attached: This lesson source code (source code may exist errors and deficiencies, for reference only)
#include ". /osgnehe.h "#include <QtCore/QTimer> #include <QtGui/QApplication> #include <QtGui/QVBoxLayout> Include <osgViewer/Viewer> #include <osgDB/ReadFile> #include <osgQt/GraphicsWindowQt> #include <osg/MatrixTransform> #include <osg/LineWidth> #include "Physics2.h"////////////////////////////////// ropesimulation* ropesimulation = new Ropesimulation (.//Particles ( Masses) 0.05f,//per particle has A Weight grams 10000.0f,//Springconstant in the Rope 0.05f,//N Ormal Length of Springs in the Rope 0.2f,//Spring Inner friction Constant vector3d (0, -9.81f, 0),//gravitational Acceleration 0.02f,//Air friction Constant 100.0f,//Ground Repel Constant 0.2f,///Ground Slide Fricti On Constant 2.0f,//Ground absoption constant-1.5f); The Height of Ground bool Initialize () {Ropesimulation->getmass (ropesimulation->numofmasses-1)->vel.z = 10.0f;
return true; }//////////////////////////////////////////////////////////////////////////class Groundupdatecallback:public OSG ::D rawable::updatecallback {public:virtual void update (osg::nodevisitor*, OSG::D rawable* d) {osg::geometry *geomet
ry = dynamic_cast<osg::geometry*> (d);
if (!geometry) return;
Osg::vec3array *vertexarray = dynamic_cast<osg::vec3array*> (Geometry->getvertexarray ());
if (!vertexarray) return;
Vertexarray->clear ();
Vertexarray->push_back (OSG::VEC3, Ropesimulation->groundheight, 20));
Vertexarray->push_back (OSG::VEC3 ( -20, Ropesimulation->groundheight, 20));
Vertexarray->push_back (OSG::VEC3 ( -20, Ropesimulation->groundheight,-20));
Vertexarray->push_back (OSG::VEC3, Ropesimulation->groundheight,-20));
Geometry->setvertexarray (Vertexarray);
Vertexarray->dirty ();
}
}; Class Ropeshadowupdatecallback:public OSG::D rawable::updatecallback {public:virtual void update (osg::nodevisitor*, OSG::D rawable* d) {osg::geometry *geometry = Dynamic_
Cast<osg::geometry*> (d);
if (!geometry) return;
Osg::vec3array *vertexarray = dynamic_cast<osg::vec3array*> (Geometry->getvertexarray ());
if (!vertexarray) return;
Vertexarray->clear ();
for (int a = 0; a < ropesimulation->numofmasses-1; ++a) {mass* Mass1 = Ropesimulation->getmass (a);
vector3d* POS1 = &mass1->pos;
mass* Mass2 = Ropesimulation->getmass (A + 1);
vector3d* Pos2 = &mass2->pos; Vertexarray->push_back (OSG::VEC3 (pos1->x, Ropesimulation->groundheight, pos1->z)); Draw Shadow at Groundheight vertexarray->push_back (OSG::VEC3 (pos2->x, Ropesimulation->groundheight, pos2- >Z));
Draw Shadow at Groundheight} geometry->setvertexarray (Vertexarray);
Vertexarray->dirty ();
}
}; Class Ropeupdatecallback:public OSG::D Rawable::updatecallbacK {public:virtual void update (osg::nodevisitor*, OSG::D rawable* d) {osg::geometry *geometry = dynamic_cast<osg:
:geometry*> (d);
if (!geometry) return;
Osg::vec3array *vertexarray = dynamic_cast<osg::vec3array*> (Geometry->getvertexarray ());
if (!vertexarray) return;
Vertexarray->clear ();
for (int a = 0; a < ropesimulation->numofmasses-1; ++a) {mass* Mass1 = Ropesimulation->getmass (a);
vector3d* POS1 = &mass1->pos;
mass* Mass2 = Ropesimulation->getmass (A + 1);
vector3d* Pos2 = &mass2->pos;
Vertexarray->push_back (OSG::VEC3 (pos1->x, Pos1->y, pos1->z));
Vertexarray->push_back (OSG::VEC3 (pos2->x, Pos2->y, pos2->z));
} geometry->setvertexarray (Vertexarray);
Vertexarray->dirty ();
}
};
osg::geode* Createground () {Osg::geode *geode = new Osg::geode;
Osg::geometry *geometry = new Osg::geometry;
Geometry->setupdatecallback (new Groundupdatecallback); Osg:: Vec3array *vertexarray = new Osg::vec3array;
Osg::vec3array *colorarray = new Osg::vec3array;
Colorarray->push_back (OSG::VEC3 (0, 0, 1.0));
Vertexarray->push_back (OSG::VEC3, Ropesimulation->groundheight, 20));
Colorarray->push_back (OSG::VEC3 (0, 0, 1.0));
Vertexarray->push_back (OSG::VEC3 ( -20, Ropesimulation->groundheight, 20));
Colorarray->push_back (OSG::VEC3 (0,0,0));
Vertexarray->push_back (OSG::VEC3 ( -20, Ropesimulation->groundheight,-20));
Colorarray->push_back (OSG::VEC3 (0,0,0));
Vertexarray->push_back (OSG::VEC3, Ropesimulation->groundheight,-20));
Geometry->setvertexarray (Vertexarray);
Geometry->setcolorarray (Colorarray, Osg::array::bind_per_vertex);
Geometry->getorcreatestateset ()->setmode (gl_lighting, Osg::stateattribute::off);
Geometry->addprimitiveset (new OSG::D rawarrays (osg::P rimitiveset::quads, 0, Vertexarray->size ()));
Geode->adddrawable (geometry);
return geode; } osg::geode* Createropeshadow () {Osg::geode *geode = new Osg::geode;
Osg::geometry *geometry = new Osg::geometry;
Geometry->setupdatecallback (new Ropeshadowupdatecallback);
Osg::vec3array *vertexarray = new Osg::vec3array;
Osg::vec3array *colorarray = new Osg::vec3array;
Colorarray->push_back (OSG::VEC3 (0, 0, 0));
for (int a = 0; a < ropesimulation->numofmasses-1; ++a) {mass* Mass1 = Ropesimulation->getmass (a);
vector3d* POS1 = &mass1->pos;
mass* Mass2 = Ropesimulation->getmass (A + 1);
vector3d* Pos2 = &mass2->pos; Vertexarray->push_back (OSG::VEC3 (pos1->x, Ropesimulation->groundheight, pos1->z)); Draw Shadow at Groundheight vertexarray->push_back (OSG::VEC3 (pos2->x, Ropesimulation->groundheight, pos2- >Z));
Draw Shadow at Groundheight} geometry->setvertexarray (Vertexarray);
Geometry->setcolorarray (Colorarray, Osg::array::bind_overall); Geometry->getorcreatestateset ()->setmode (gl_lighting, Osg::stateattribute:: OFF);
Geometry->getorcreatestateset ()->setattributeandmodes (new Osg::linewidth (2.0));
Geometry->addprimitiveset (new OSG::D rawarrays (osg::P rimitiveset::lines, 0, Vertexarray->size ()));
Geode->adddrawable (geometry);
return geode;
} osg::geode* Createrope () {Osg::geode *geode = new Osg::geode;
Osg::geometry *geometry = new Osg::geometry;
Geometry->setupdatecallback (new Ropeupdatecallback);
Osg::vec3array *vertexarray = new Osg::vec3array;
Osg::vec3array *colorarray = new Osg::vec3array;
Colorarray->push_back (OSG::VEC3 (1, 1, 0));
for (int a = 0; a < ropesimulation->numofmasses-1; ++a) {mass* Mass1 = Ropesimulation->getmass (a);
vector3d* POS1 = &mass1->pos;
mass* Mass2 = Ropesimulation->getmass (A + 1);
vector3d* Pos2 = &mass2->pos;
Vertexarray->push_back (OSG::VEC3 (pos1->x, Pos1->y, pos1->z));
Vertexarray->push_back (OSG::VEC3 (pos2->x, Pos2->y, pos2->z)); } Geometry->setvertexarray(Vertexarray);
Geometry->setcolorarray (Colorarray, Osg::array::bind_overall);
Geometry->getorcreatestateset ()->setmode (gl_lighting, Osg::stateattribute::off);
Geometry->getorcreatestateset ()->setmode (Gl_depth_test, false);
Geometry->getorcreatestateset ()->setattributeandmodes (new Osg::linewidth (4.0));
Geometry->addprimitiveset (new OSG::D rawarrays (osg::P rimitiveset::lines, 0, Vertexarray->size ()));
Geode->adddrawable (geometry);
return geode; }//////////////////////////////////////////////////////////////////////////Class Manipulatorscenehandler:public
Osgga::guieventhandler {Public:manipulatorscenehandler () {_lasttick = Osg::timer::instance ()->tick ();
_currenttick = _lasttick; } public:virtual bool Handle (const osgga::guieventadapter& EA, osgga::guiactionadapter& aa) {Osgviewer::vie
Wer *viewer = dynamic_cast<osgviewer::viewer*> (&AA);
if (!viewer) return false; if (!viewer->getscenedata ()) REturn false;
if (ea.gethandled ()) return false;
Osg::group *root = Viewer->getscenedata ()->asgroup ();
Switch (Ea.geteventtype ()) {case (Osgga::guieventadapter::frame): {Double dt = 0.0;
_currenttick = Osg::timer::instance ()->tick ();
if (_currenttick!= _lasttick) {dt = Osg::timer::instance ()->delta_s (_lasttick, _currenttick);
_lasttick = _currenttick;
} ropesimulation->setropeconnectionvel (Ropeconnectionvel);
float Maxpossible_dt = 0.002f;
int numofiterations = (int) (DT/MAXPOSSIBLE_DT) + 1;
if (numofiterations!= 0) dt = dt/numofiterations;
for (int a = 0; a < numofiterations ++a) ropesimulation->operate (DT);
} break; Case (Osgga::guieventadapter::keydown): {if (ea.getkey () = = osgga::guieventadapter::key_up) {Ropeconnect
Ionvel.z = 1.0f; } if (Ea.getkey () = = Osgga::guieventadapter::key_down) {ropeconnectionvel.z += 1.0f;
} if (Ea.getkey () = = Osgga::guieventadapter::key_left) {ropeconnectionvel.x = 1.0f;
} if (Ea.getkey () = = osgga::guieventadapter::key_right) {ropeconnectionvel.x = 1.0f;
} if (Ea.getkey () = = osgga::guieventadapter::key_home) {ropeconnectionvel.y = 1.0f;
} if (Ea.getkey () = = osgga::guieventadapter::key_end) {ropeconnectionvel.y = 1.0f;
}} break;
Default:break;
return false;
} osg::timer_t _lasttick;
osg::timer_t _currenttick;
Vector3D Ropeconnectionvel;
}; Class Viewerwidget:public Qwidget, public osgviewer::viewer {public:viewerwidget (osg::node *scene = NULL) {QWidge
t* renderwidget = Getrenderwidget (Creategraphicswindow (0,0,100,100), scene);
qvboxlayout* layout = new Qvboxlayout;
Layout->addwidget (Renderwidget);
Layout->setcontentsmargins (0, 0, 0, 1);
SetLayout (layout);
Connect (&_timer, SIGNAL (timeout ()), this, SLOT (update ())); _tImer.start (10); } qwidget* Getrenderwidget (osgqt::graphicswindowqt* GW, osg::node* scene) {osg::camera* Camera = This->getcamer
A ();
Camera->setgraphicscontext (GW);
Const osg::graphicscontext::traits* Traits = Gw->gettraits ();
Camera->setclearcolor (OSG::VEC4 (0.0, 0.0, 0.0, 0.5));
Camera->setviewport (New Osg::viewport (0, 0, traits->width, traits->height)); Camera->setprojectionmatrixasperspective (45.0f, static_cast<double> (traits->width)/static_cast<
Double> (Traits->height), 0.1f, 100.0f);
Camera->setviewmatrixaslookat (osg::vec3d (0, 0, 4), osg::vec3d (0, 0, 0), osg::vec3d (0, 1, 0));
This->setscenedata (Scene);
This->addeventhandler (new Manipulatorscenehandler);
return Gw->getglwidget (); osgqt::graphicswindowqt* Creategraphicswindow (int x, int y, int w, int h, const std::string& name= "", bool Window
Decoration=false) {osg::D isplaysettings* ds = osg::D isplaysettings::instance (). get (); osg::ref_ptr<osg::graphicscontext::traits> Traits = new Osg::graphicscontext::traits;
Traits->windowname = name;
Traits->windowdecoration = windowdecoration;
traits->x = x;
Traits->y = y;
Traits->width = W;
Traits->height = h;
Traits->doublebuffer = true;
Traits->alpha = Ds->getminimumnumalphabits ();
Traits->stencil = Ds->getminimumnumstencilbits ();
Traits->samplebuffers = Ds->getmultisamples ();
Traits->samples = Ds->getnummultisamples ();
return new OSGQT::GRAPHICSWINDOWQT (Traits.get ());
virtual void PaintEvent (qpaintevent* event) {frame ();
} Protected:qtimer _timer;
};
osg::node* Buildscene () {initialize ();
Osg::group *root = new Osg::group;
Root->addchild (Createground ());
Root->addchild (Createropeshadow ());
Root->addchild (Createrope ());
return root;
int main (int argc, char** argv) {qapplication app (argc, argv); viewerwidget* viewwidget = new Viewerwidget (BuiLdscene ());
Viewwidget->setgeometry (100, 100, 640, 480);
Viewwidget->show ();
return App.exec ();
}