Hi, currently i'm writing an Ogre XML import plugin for OSG. Source will be available if it's working as expected. Import of meshes is working fine, but the skinning of skeleton animations in OSG drives me crazy.
I created a demo model, skeleton and animation (quad with two bones) in Blender (2.49) and exported it with the OGRE mesh exporter. The Ogre tool CEGUI Mesh Viewer (http://www.ogre3d.org/tikiwiki/CEGUI+Mesh+Viewer) can display it correct. The model consists of 4 vertices and two triangles (face0: v0, v1, v3 and face1: v1, v2, v3). The bone "Bone" influences the vertices v0, v1 and v2 and the child bone "Bone.001" influences the vertex v3. The image below shows the quad with the two bones. Both bones are laying in the same level (XY-plane) as the quad. http://lib-dev.com/osganim_skinning/blender.png See below for the generated Ogre XML mesh and skeleton file. For testing and demonstration purposes i hard coded the model with OSG (see below), based on the data given by the files. The result looks like like this. http://lib-dev.com/osganim_skinning/osg_result.png The quad isn't any longer a quad, even if no animation to the the bones is applied. And the origin of the second bone "Bone.001" is at y=1. It should be located at y=-1, because of the rotation of the previos bone, but it isn't. However the second bone is relative to the first one. Result screenshot is taken during a rotation of "Bone" about the X-axis. The big coordinate axes marks the origin and the small ones show the position of the bones. I think i did a mistake at the creation of the bones, but i can't figure it out. Is the setMatrixInSkeletonSpace(...) call correct, or did i forget something? The source is adapted from the osganimationskinning example. I already spent days to find and fix it without any success. Thanks for advices or ideas! I'm using OSG 3.0.1 on Linux. Kindly regards, Stefan Frings Code: #include <osg/Geometry> #include <osgAnimation/Bone> #include <osgAnimation/Skeleton> #include <osgAnimation/UpdateBone> #include <osgAnimation/RigGeometry> #include <osgAnimation/StackedTranslateElement> #include <osgAnimation/StackedQuaternionElement> #include <osgAnimation/StackedRotateAxisElement> #include <osgAnimation/BasicAnimationManager> #include <osgDB/ReadFile> #include <osgViewer/Viewer> osgAnimation::RigGeometry* createRigGeo() { osg::Geometry* geo = new osg::Geometry; osg::ref_ptr<osg::Vec3Array> vertices(new osg::Vec3Array(4)); osg::ref_ptr<osg::Vec3Array> colors(new osg::Vec3Array(4)); geo->setVertexArray(vertices.get()); geo->setColorArray(colors.get()); geo->setColorBinding(osg::Geometry::BIND_PER_VERTEX); (*vertices)[0].set(1, 1, 0); (*colors)[0].set(1, 0, 0); (*vertices)[1].set(-1, 1, 0); (*colors)[1].set(0, 1, 0); (*vertices)[2].set(-1, -1, 0); (*colors)[2].set(0, 0, 1); (*vertices)[3].set(1, -1, 0); (*colors)[3].set(1, 1, 1); osg::DrawElementsUInt* triangles = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 2 * 3); geo->addPrimitiveSet(triangles); (*triangles)[0] = 0; (*triangles)[1] = 1; (*triangles)[2] = 3; (*triangles)[3] = 1; (*triangles)[4] = 2; (*triangles)[5] = 3; geo->getOrCreateStateSet()->setMode(GL_LIGHTING, false); geo->setDataVariance(osg::Object::DYNAMIC); geo->setUseDisplayList(false); osgAnimation::RigGeometry* rigGeo = new osgAnimation::RigGeometry; rigGeo->setSourceGeometry(geo); return rigGeo; } osgAnimation::VertexInfluenceMap* initVertexMap() { osgAnimation::VertexInfluenceMap* vim = new osgAnimation::VertexInfluenceMap; (*vim)["bone0"].setName("bone0"); (*vim)["bone0"].push_back(osgAnimation::VertexIndexWeight(0, 1.0f)); (*vim)["bone0"].push_back(osgAnimation::VertexIndexWeight(1, 1.0f)); (*vim)["bone0"].push_back(osgAnimation::VertexIndexWeight(2, 1.0f)); (*vim)["bone1"].setName("bone1"); (*vim)["bone1"].push_back(osgAnimation::VertexIndexWeight(3, 1.0f)); return vim; } int main(int argc, char* argv[]) { /// here i expect the mistake /////////////////////////// // create root bone (bone0, called "Bone" in blender) osg::ref_ptr<osgAnimation::Bone> bone0 = new osgAnimation::Bone; bone0->setMatrixInSkeletonSpace( osg::Matrix::rotate(M_PI, osg::Vec3(1, 0, 0)) * osg::Matrix::translate(0.0,0.0,0.0) * bone0->getMatrixInSkeletonSpace() ); bone0->setName("bone0"); bone0->setDataVariance(osg::Object::DYNAMIC); osgAnimation::UpdateBone* bone0Update = new osgAnimation::UpdateBone("bone0"); bone0Update->getStackedTransforms().push_back(new osgAnimation::StackedTranslateElement("translate",osg::Vec3(0, 0, 0))); bone0Update->getStackedTransforms().push_back(new osgAnimation::StackedRotateAxisElement("rotate", osg::Vec3(1, 0, 0), M_PI)); bone0->setUpdateCallback(bone0Update); // create child bone (bone1, called "Bone.001" in blender) osg::ref_ptr<osgAnimation::Bone> bone1 = new osgAnimation::Bone; bone1->setMatrixInSkeletonSpace( osg::Matrix::rotate(0.f, osg::Vec3(0, 0, 1)) * osg::Matrix::translate(0, 1, 0) * bone1->getMatrixInSkeletonSpace() ); bone1->setName("bone1"); bone1->setDataVariance(osg::Object::DYNAMIC); osgAnimation::UpdateBone* bone1Update = new osgAnimation::UpdateBone("bone1"); bone1Update->getStackedTransforms().push_back(new osgAnimation::StackedTranslateElement("translate", osg::Vec3(0, 1, 0))); bone1Update->getStackedTransforms().push_back(new osgAnimation::StackedRotateAxisElement("rotate", osg::Vec3(0, 0, 1), 0.f)); bone1->setUpdateCallback(bone1Update); ////////////////////////////////////////////////////////////////////// // create skeleton hierarchy osg::ref_ptr<osgAnimation::Skeleton> skeleton = new osgAnimation::Skeleton; skeleton->setDefaultUpdateCallback(); skeleton->addChild(bone0); bone0->addChild(bone1); // create scene osg::Group* scene = new osg::Group; osg::ref_ptr<osgAnimation::BasicAnimationManager> manager = new osgAnimation::BasicAnimationManager; scene->setUpdateCallback(manager.get()); // add animation osgAnimation::Animation* anim = new osgAnimation::Animation; anim->setPlayMode(osgAnimation::Animation::PPONG); { osgAnimation::FloatKeyframeContainer* keys0 = new osgAnimation::FloatKeyframeContainer; keys0->push_back(osgAnimation::FloatKeyframe(0.0, 0.0f)); keys0->push_back(osgAnimation::FloatKeyframe(3.0, osg::PI_2)); /*keys0->push_back(osgAnimation::FloatKeyframe(6.0, osg::PI_2)); keys0->push_back(osgAnimation::FloatKeyframe(9.0, osg::PI));*/ osgAnimation::FloatLinearSampler* sampler = new osgAnimation::FloatLinearSampler; sampler->setKeyframeContainer(keys0); osgAnimation::FloatLinearChannel* channel = new osgAnimation::FloatLinearChannel(sampler); channel->setName("rotate"); channel->setTargetName("bone0"); 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::PI_2)); keys1->push_back(osgAnimation::FloatKeyframe(9.0,osg::PI));*/ osgAnimation::FloatLinearSampler* sampler = new osgAnimation::FloatLinearSampler; sampler->setKeyframeContainer(keys1); osgAnimation::FloatLinearChannel* channel = new osgAnimation::FloatLinearChannel(sampler); channel->setName("rotate"); channel->setTargetName("bone1"); anim->addChannel(channel); } manager->registerAnimation(anim); manager->buildTargetReference(); manager->playAnimation(anim); // add geometry to the skeleton osgAnimation::RigGeometry* rigGeo = createRigGeo(); osg::Geode* geode = new osg::Geode; geode->addDrawable(rigGeo); skeleton->addChild(geode); // and link vertices to bones rigGeo->setInfluenceMap(initVertexMap()); // add skeleton to the scene scene->addChild(skeleton); // big coordinate axes at origin scene->addChild(osgDB::readNodeFile("axes.osgt")); // smaller axes at each bone osg::MatrixTransform* transAx = new osg::MatrixTransform(osg::Matrix::scale(osg::Vec3(0.5, 0.5, 0.5))); transAx->addChild(osgDB::readNodeFile("axes.osgt")); bone0->addChild(transAx); bone1->addChild(transAx); osgViewer::Viewer viewer; viewer.setSceneData(scene); viewer.realize(); return viewer.run(); } ## ogre_mesh.xml ########################################################## <mesh> <submeshes> <submesh material="Material" usesharedvertices="false" use32bitindexes="false" operationtype="triangle_list"> <faces count="2"> <face v1="0" v2="1" v3="3"/> <face v1="1" v2="2" v3="3"/> </faces> <geometry vertexcount="4"> <vertexbuffer positions="true"> <vertex> <position x="1.000000" y="0.999999" z="0.000000"/> </vertex> <vertex> <position x="-1.000000" y="1.000000" z="0.000000"/> </vertex> <vertex> <position x="-1.000000" y="-1.000000" z="0.000000"/> </vertex> <vertex> <position x="0.999999" y="-1.000001" z="0.000000"/> </vertex> </vertexbuffer> </geometry> <boneassignments> <vertexboneassignment vertexindex="0" boneindex="1" weight="1.000000"/> <vertexboneassignment vertexindex="1" boneindex="1" weight="1.000000"/> <vertexboneassignment vertexindex="2" boneindex="1" weight="1.000000"/> <vertexboneassignment vertexindex="3" boneindex="0" weight="1.000000"/> </boneassignments> </submesh> </submeshes> <skeletonlink name="ogre_skeleton.xml"/> </mesh> ## ogre_skeleton.xml ###################################################### <skeleton> <bones> <bone id="1" name="Bone"> <position x="0.000000" y="0.000000" z="0.000000"/> <rotation angle="3.141593"> <axis x="1.000000" y="0.000000" z="0.000000"/> </rotation> </bone> <bone id="0" name="Bone.001"> <position x="0.000000" y="1.000000" z="0.000000"/> <rotation angle="2.094394"> <axis x="-0.577350" y="-0.577350" z="-0.577350"/> </rotation> </bone> </bones> <bonehierarchy> <boneparent bone="Bone.001" parent="Bone" /> </bonehierarchy> <animations> </animations> </skeleton> _______________________________________________ osg-users mailing list [email protected] http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

