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

Reply via email to