Dynamic animation of skinned meshes

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.

Dynamic animation of skinned meshes

Postby mongoose7 » Sun May 01, 2011 7:36 am

I've written an example of animating a skinned mesh in real time. I think this is referred to as "Ragdoll Animation".

Code: Select all
#include <iostream>
#include <irrlicht.h>
#include "SSkinMeshBuffer.h"
#include "CSkinnedMesh.h"
#include "coreutil.h"

static int angles[] = {0, 1, 2, 2, 1, 0, -1, -2, -2, -1, 0};

using namespace irr;

static scene::IAnimatedMesh *get_mesh(void);

int main(int argc, char **argv)
{
   scene::IAnimatedMesh* mesh;
   scene::IAnimatedMeshSceneNode *node;
   IrrlichtDevice *device;
   scene::ISceneManager *smgr;
   scene::ICameraSceneNode *cam;
   scene::IBoneSceneNode *sbone;

   if (!(device = createDevice(video::EDT_OPENGL,
      core::dimension2d<u32>(800, 600), 32, false)))
   {
      std::cout << "Unable to create device" << std::endl;
      return 1;
   }
   smgr = device->getSceneManager();

   if (!(mesh = get_mesh()))
   {
      std::cout << "Unable to load mesh" << std::endl;
      return 1;
   }

   if (!(node = smgr->addAnimatedMeshSceneNode(mesh)))
   {
      std::cout << "Unable to create node" << std::endl;
      return 1;
   }

   node->setScale(core::vector3df(1.0f, 1.0f, 1.0f));
   node->setDebugDataVisible(scene::EDS_SKELETON);
   node->setMaterialFlag(video::EMF_LIGHTING, false);
   node->setMaterialFlag(video::EMF_BACK_FACE_CULLING, false);
   node->setAnimationSpeed(5);
   node->setJointMode(scene::EJUOR_CONTROL);

   if (!(cam = smgr->addCameraSceneNodeMaya()))
   {
      std::cout << "Unable to create camera" << std::endl;
      return 1;
   }
   //cam->setPosition(core::vector3df(0, 0, -1000));
   cam->setTarget(core::vector3df(0, 0, 0));

   while (device->run())
   {
      int i = (int) node->getFrameNr();
      node->animateJoints();   // not needed if you control all joints
      sbone = node->getJointNode((u32) 0);
      sbone->setRotation(core::vector3df(0, 0, 6.0f*angles[i%11]));

      device->getVideoDriver()->beginScene(true, true,
         video::SColor(255,128,128,128));
      device->getSceneManager()->drawAll();
      device->getVideoDriver()->endScene();
   }

   device->drop();
   return 0;
}

static int vertices[] = {
   0, 1, 3, 2,      // base
   0, 4, 6, 2,      // lower front
   0, 4, 5, 1,      // lower left
   2, 6, 7, 3,      // lower right
   1, 5, 7, 3,      // lower back
   4, 8, 10, 6,      // upper front
   4, 8, 9, 5,         // upper left
   6, 10, 11, 7,      // upper right
   5, 9, 11, 7,      // upper back
   8, 9, 11, 10      // top
};

static scene::IAnimatedMesh *get_mesh(void)
{
   scene::CSkinnedMesh *mesh;
   scene::SSkinMeshBuffer *mbuffer;
   scene::ISkinnedMesh::SJoint* jnt;
   scene::ISkinnedMesh::SWeight wt;
   irr::scene::ISkinnedMesh::SPositionKey *k1;
   irr::scene::ISkinnedMesh::SRotationKey *k2;
   video::S3DVertex vtx;
   int i, j, k;

   mesh = new scene::CSkinnedMesh();

   if (!(mbuffer = mesh->addMeshBuffer()))
      return 0;
   // need vertices and faces
   mbuffer->Vertices_Standard.reallocate(12);
   mbuffer->Indices.reallocate(10);

   vtx.Normal.X = vtx.Normal.Y = vtx.Normal.Z = 0;
   vtx.TCoords.X = vtx.TCoords.Y = 0;

   // 12 vertices
   for (i = 0; i < 3; ++i)
   for (j = 0; j < 2; ++j)
   for (k = 0; k < 2; ++k)
   {
      vtx.Pos.X = j*10.0f;
      vtx.Pos.Y = i*10.0f;
      vtx.Pos.Z = k*10.0f;

      vtx.Color.set(0xff000000 + 0x700000*i + 0xe000*j + 240*k);
      mbuffer->Vertices_Standard.push_back(vtx);
   }

   // 10 faces
   for (i = 0; i < 40; i += 4)
   {
      mbuffer->Indices.push_back(vertices[i + 0]);
      mbuffer->Indices.push_back(vertices[i + 1]);
      mbuffer->Indices.push_back(vertices[i + 2]);

      mbuffer->Indices.push_back(vertices[i + 0]);
      mbuffer->Indices.push_back(vertices[i + 2]);
      mbuffer->Indices.push_back(vertices[i + 3]);
   }

   wt.buffer_id = 0;

   // 2 bones
   jnt = mesh->addJoint(0);
   jnt->Name = "Joint0";
   //jnt->Animatedposition = core::vector3df(5, 0, 5);
   jnt->LocalMatrix.setTranslation(core::vector3df(5, 0, 5));

   // weights
   for (i = 0; i < 4; ++i)
   {
      wt.vertex_id = 4 + i;
      wt.strength = 0.5f;
      jnt->Weights.push_back(wt);
   }

   // frames
   for (i = 0; i < 11; ++i)
   {
      k1 = mesh->addPositionKey(jnt);
      k2 = mesh->addRotationKey(jnt);
      k1->frame = k2->frame = (float) i;
      k1->position = core::vector3df(5, 0, 5);
      k2->rotation = core::quaternion(0, 0, 0.1f*angles[i]);
   }

   jnt = mesh->addJoint(jnt);
   jnt->Name = "Joint1";
   //jnt->Animatedposition = core::vector3df(5, 10, 5);
   jnt->LocalMatrix.setTranslation(core::vector3df(0, 10, 0));

   // weights
   for (i = 0; i < 4; ++i)
   {
      wt.vertex_id = 8 + i;
      wt.strength = 1;
      jnt->Weights.push_back(wt);

      wt.vertex_id = 4 + i;
      wt.strength = 0.5f;
      jnt->Weights.push_back(wt);
   }

   // frames
   for (i = 0; i < 11; ++i)
   {
      k1 = mesh->addPositionKey(jnt);
      k2 = mesh->addRotationKey(jnt);
      k1->frame = k2->frame = (float) i;
      k1->position = core::vector3df(0, 10, 0);
      k2->rotation = core::quaternion(0, 0, 0.2f*angles[i]);
   }

   // material
   mbuffer->Material.MaterialType = video::EMT_SOLID;
   mbuffer->Material.AmbientColor =
      video::SColorf(0.2f, 0.2f, 0.2f).toSColor();
   mbuffer->Material.DiffuseColor =
      video::SColorf(1.0f, 1.0f, 0.0f).toSColor();
   // no emissive colour
   mbuffer->Material.SpecularColor =
      video::SColorf(1.0f, 1.0f, 1.0f).toSColor();
   mbuffer->Material.Shininess = 50.0f;

   mesh->finalize();
   return mesh;
}


I only animate one bone, the other takes the static animation. However, both bones can be animated in this way and the call to 'animateJoints' woud be unnecessary. Once again, te code below 'get_mesh' requires CSkinnedMesh.h. Loading meshes with one of the core loaders gets around this.
mongoose7
 
Posts: 514
Joined: Wed Apr 06, 2011 12:13 pm

Return to Beginners Help

Who is online

Users browsing this forum: No registered users and 1 guest