Introduction
Osganimationskinning This example mainly uses the skeletal skin animation in osganimation, the introduction of the skeleton skin animation can refer to skinned mesh principle analysis and one of the simplest implementation examples of this CSDN blog, Inside with glut to achieve a simple skin animation, the whole article on the skeleton animation and skin of the detailed elaboration, I believe that after reading can have a deeper understanding of skeletal animation. Example
In the source code, Createaxis creates a coordinate system, which is simple enough to draw only three axes of coordinates.
osg::geode* Createaxis () {osg::geode* Geode (new Osg::geode ());
osg::geometry* Geometry (New Osg::geometry ());
osg::vec3array* vertices (new Osg::vec3array ());
Vertices->push_back (OSG::VEC3 (0.0, 0.0, 0.0));
Vertices->push_back (OSG::VEC3 (1.0, 0.0, 0.0));
Vertices->push_back (OSG::VEC3 (0.0, 0.0, 0.0));
Vertices->push_back (OSG::VEC3 (0.0, 1.0, 0.0));
Vertices->push_back (OSG::VEC3 (0.0, 0.0, 0.0));
Vertices->push_back (OSG::VEC3 (0.0, 0.0, 1.0));
Geometry->setvertexarray (vertices);
osg::vec4array* Colors (new Osg::vec4array ());
Colors->push_back (OSG::VEC4 (1.0f, 0.0f, 0.0f, 1.0f));
Colors->push_back (OSG::VEC4 (1.0f, 0.0f, 0.0f, 1.0f));
Colors->push_back (OSG::VEC4 (0.0f, 1.0f, 0.0f, 1.0f));
Colors->push_back (OSG::VEC4 (0.0f, 1.0f, 0.0f, 1.0f));
Colors->push_back (OSG::VEC4 (0.0f, 0.0f, 1.0f, 1.0f));
Colors->push_back (OSG::VEC4 (0.0f, 0.0f, 1.0f, 1.0f)); GeoMetRy->setcolorarray (colors, Osg::array::bind_per_vertex);
Geometry->addprimitiveset (new OSG::D rawarrays (OSG::P rimitiveset::lines,0,6));
Geode->adddrawable (geometry);
return geode;
}
Createtesselatedbox This function is to create a skeleton animation of the skin mesh, the equivalent of a bone to do a "clothes", we see how it was created:
Float step = size/static_cast<float> (Nsplit);
float s = 0.5f/4.0f;
for (int i = 0; i < Nsplit; i++) {float x = -1.0f + static_cast<float> (i) * step;
Std::cout << x << Std::endl;
Vertices->push_back (OSG::VEC3 (x, S, s));
Vertices->push_back (OSG::VEC3 (x, S, s));
Vertices->push_back (OSG::VEC3 (x,-S,-s));
Vertices->push_back (OSG::VEC3 (x, S,-s));
OSG::VEC3 c (0.0f,0.0f,0.0f);
C[I%3] = 1.0f;
Colors->push_back (c);
Colors->push_back (c);
Colors->push_back (c);
Colors->push_back (c);
} osg::ref_ptr<osg::uintarray> array = new Osg::uintarray;
for (int i = 0; i < nsplit-1; i++) {int base = i * 4;
Top Array->push_back (base);
Array->push_back (base+1);
Array->push_back (BASE+4);
Array->push_back (base+1);
Array->push_back (base+5);
Array->push_back (BASE+4);
Back Array->push_back (base+3);
Array->push_back (base); Array->push_back (base+4);
Array->push_back (BASE+7);
Array->push_back (base+3);
Array->push_back (BASE+4);
Front Array->push_back (base+5);
Array->push_back (base+1);
Array->push_back (base+2);
Array->push_back (base+2);
Array->push_back (BASE+6);
Array->push_back (base+5);
Bottom Array->push_back (base+2);
Array->push_back (base+3);
Array->push_back (BASE+7);
Array->push_back (BASE+6);
Array->push_back (base+2);
Array->push_back (BASE+7); }
By the above annotations you can know that the function createtesselatedbox (int nsplit, float size) two parameters, where nsplit is to divide the cube column into Nsplit-1 segment, and then each segment of the 4 polygons of a cube, This code is created using the Drawelement method, so it passes in the index value.
Next is the operation of the skin info, to bind the different vertices to the bones, and to assign weights to these vertices, the way to set weights in this example is relatively simple, all x between 1 to 0 vertices are only affected by the bone Bon0, all x 0 to 1 vertex is only affected by BONE1, All vertices with an X value greater than 1 are only affected by Bone2.
void Initvertexmap (osganimation::bone* b0, osganimation::bone* B1, Osganimation::bon e* B2, osganimation::riggeometry* geom, osg::vec3array* array) {//osganimation:
: Vertexinfluenceset vertexesinfluences;
osganimation::vertexinfluencemap* vim = new Osganimation::vertexinfluencemap; (*vim)
[B0->getname ()].setname (B0->getname ()); (*vim)
[B1->getname ()].setname (B1->getname ()); (*vim)
[B2->getname ()].setname (B2->getname ());
for (int i = 0; i < (int) array->size (); i++) {Float val = (*array) [i][0];
Std::cout << Val << Std::endl; if (Val >= -1.0f && val <= 0.0f) (*vim) [B0->getname ()].push_back (Osganimation::vertexindexwei
Ght (i,1.0f)); else if (val > 0.0f && val <= 1.0f) (*vim) [B1->getname ()].push_back (Osganimation::vertexinde
Xweight (i,1.0f)); else if (Val >
1.0f) (*vim) [B2->getname ()].push_back (Osganimation::vertexindexweight (i,1.0f));
} geom->setinfluencemap (VIM); }
Main function main inside the skeleton animation is created:
osg::ref_ptr<osganimation::skeleton> skelroot = new Osganimation::skeleton;
Skelroot->setdefaultupdatecallback ();
osg::ref_ptr<osganimation::bone> root = new Osganimation::bone;
Root->setinvbindmatrixinskeletonspace (Osg::matrix::inverse (Osg::matrix::translate ( -1.0,0.0,0.0)));
Root->setname ("root");
osganimation::updatebone* prootupdate = new Osganimation::updatebone ("root"); Prootupdate->getstackedtransforms (). push_back (New Osganimation::stackedtranslateelement ("Translate", OSG::
VEC3 ( -1.0f,0.0f,0.0f));
Root->setupdatecallback (prootupdate);
osg::ref_ptr<osganimation::bone> right0 = new Osganimation::bone;
Right0->setinvbindmatrixinskeletonspace (Osg::matrix::inverse (Osg::matrix::translate (0.0,0.0,0.0)));
Right0->setname ("Right0");
osganimation::updatebone* pright0update = new Osganimation::updatebone ("Right0"); Pright0update->getstackedtransforms (). push_back (New Osganimation::stackedtranslateelEment ("Translate", OSG::VEC3 (1.0f,0.0f,0.0f))); Pright0update->getstackedtransforms (). push_back (New osganimation::stackedrotateaxiselement ("Rotate", OSG::
VEC3 (0.0f,0.0f,1.0f), 0.0);
Right0->setupdatecallback (pright0update);
osg::ref_ptr<osganimation::bone> right1 = new Osganimation::bone;
Right1->setinvbindmatrixinskeletonspace (Osg::matrix::inverse (Osg::matrix::translate (1.0,0.0,0.0)));
Right1->setname ("right1");
osganimation::updatebone* pright1update = new Osganimation::updatebone ("right1"); Pright1update->getstackedtransforms (). push_back (New Osganimation::stackedtranslateelement ("Translate", OSG::
VEC3 (1.0f,0.0f,0.0f)); Pright1update->getstackedtransforms (). push_back (New osganimation::stackedrotateaxiselement ("Rotate", OSG::
VEC3 (0.0f,0.0f,1.0f), 0.0);
Right1->setupdatecallback (pright1update);
Root->addchild (Right0.get ());
Right0->addchild (Right1.get ()); Skelroot->addchild (Root.get ());
The above code creates a skeleton frame, the pattern to create the skeleton is still relatively fixed, it should be noted that the name of Updatebone and the channel below the settargetname name of the same, Updatebone inside the stackedtransformelement needs to be consistent with the channel name.
osg::group* scene = new Osg::group;
Osg::ref_ptr<osganimation::basicanimationmanager> manager = new Osganimation::basicanimationmanager;
Scene->setupdatecallback (Manager.get ());
osganimation::animation* anim = new Osganimation::animation;
{osganimation::floatkeyframecontainer* keys0 = new Osganimation::floatkeyframecontainer;
Keys0->push_back (Osganimation::floatkeyframe (0.0,0.0f));
Keys0->push_back (Osganimation::floatkeyframe (3.0,osg::P i_2));
Keys0->push_back (Osganimation::floatkeyframe (6.0,osg::P i_2));
osganimation::floatlinearsampler* sampler = new Osganimation::floatlinearsampler;
Sampler->setkeyframecontainer (KEYS0);
osganimation::floatlinearchannel* channel = new Osganimation::floatlinearchannel (sampler);
Channel->setname ("rotate");
Channel->settargetname ("Right0");
Anim->addchannel (channel); } {osganimation::floatkeyframecontainer*keys1 = new Osganimation::floatkeyframecontainer;
Keys1->push_back (Osganimation::floatkeyframe (0.0,0.0f));
Keys1->push_back (Osganimation::floatkeyframe (3.0,0.0f));
Keys1->push_back (Osganimation::floatkeyframe (6.0,osg::P i_2));
osganimation::floatlinearsampler* sampler = new Osganimation::floatlinearsampler;
Sampler->setkeyframecontainer (KEYS1);
osganimation::floatlinearchannel* channel = new Osganimation::floatlinearchannel (sampler);
Channel->setname ("rotate");
Channel->settargetname ("right1");
Anim->addchannel (channel);
} manager->registeranimation (Anim);
Manager->buildtargetreference ();
Let ' s start! Manager->playanimation (ANIM);
This code creates keyframes for the skeleton animation to run.
osg::matrixtransform* roottransform = new Osg::matrixtransform;
Roottransform->setmatrix (Osg::matrix::rotate (OSG::P i_2,osg::vec3 (1.0f,0.0f,0.0f)));
Right0->addchild (Createaxis ());
Right0->setdatavariance (osg::object::D ynamic);
Right1->addchild (Createaxis ());
Right1->setdatavariance (osg::object::D ynamic);
osg::matrixtransform* trueroot = new Osg::matrixtransform;
Trueroot->setmatrix (Osg::matrix (Root->getmatrixinbonespace (). PTR ()));
Trueroot->addchild (Createaxis ());
Trueroot->addchild (Skelroot.get ());
Trueroot->setdatavariance (osg::object::D ynamic);
Roottransform->addchild (trueroot);
Scene->addchild (Roottransform);
The above code adds a drawing entity to the skeletal animation so that we can see the actual effect of the skeletal animation. These Geode the abstract skeleton transformation, which allows us to see the movement of the bones bound to the Geode.
The final step, of course, is to Mompicao the skeletal animation, set the skin mesh to bind to the bone and the weight, and add the node below the skeleton node:
osganimation::riggeometry* Geom = Createtesselatedbox (4, 4.0f);
osg::geode* Geode = new Osg::geode;
Geode->adddrawable (GEOM);
Skelroot->addchild (Geode);
osg::ref_ptr<osg::vec3array> src = dynamic_cast<osg::vec3array*> (geom->getsourcegeometry () Getvertexarray ());
Geom->getorcreatestateset ()->setmode (gl_lighting, false);
Geom->setdatavariance (osg::object::D ynamic);
Initvertexmap (Root.get (), Right0.get (), Right1.get (), Geom, Src.get ());
Last Compile Run program