Question: Would it be possible to append animations?

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.
Post Reply
christianclavet
Posts: 1638
Joined: Mon Apr 30, 2007 3:24 am
Location: Montreal, CANADA
Contact:

Question: Would it be possible to append animations?

Post by christianclavet »

Hi, just a question about animations.

I would like to copy animation information (edit, copy, append, delete frames) from a model to another in Irrlicht.
Main use would be for this: take a model that have multiple models that have animation, and with other models that have the same skeleton structure, copy and append the animation frames.

Currently there is a way to use the same animations from a model to another but this will affect all the instances of that model (useAnimationFrom()).

That would allow to have a "collection of animations" and build each character with this collection.

I know this would be possible to do this by modifying the Irrlicht source code, but is it possible but only using the library without patching the engine?
luthyr
Posts: 69
Joined: Wed Dec 30, 2009 5:47 pm

Re: Question: Would it be possible to append animations?

Post by luthyr »

I was able to do this, but not without changing Irrlicht a slight bit. I had to expose the checkForAnimation() function in CSkinnedMesh, as otherwise (if I remember correctly), the number of keys would be cached and it wouldn't be aware of new keys. I'm not sure if there was a better solution, as I wanted to append to an existing model file in the cache.

Another change I made to Irrlicht was to not scrub through and remove duplicate keys on load, so doing "joint1->PositionKeys.getLast().frame = frame + 1.0f;" is probably inaccurate for you, and you'd need to calculate the actual time offset between frames instead of assuming it is 1.

Here is some of the code I used that you could look at. I loaded up character animations through xml into our own 'animation' structs, so that is where some of the original info is defined and updated with new frame ranges. We use .X format for all our animations.

Code: Select all

IAnimatedMesh* m_baseAnimation = game.getDevice()->getSceneManager()->getMesh(m_baseAnimPath);
       m_baseAnimation ->grab();  // Make sure to grab so that it doesn't get removed inadvertently from mesh cache during scene clear.
               IAnimatedMesh* customMesh = game.getDevice()->getSceneManager()->getMesh(animation->customPath);
               if (customMesh->getMeshType() == EAMT_SKINNED)
               {
                  ISkinnedMesh* customSkinnedMesh = (ISkinnedMesh*)customMesh;
 
                  s32 startingCustomFrame = animation->origFrameRange.X;
                  s32 endingCustomFrame = animation->origFrameRange.Y;
                  s32 range = endingCustomFrame - startingCustomFrame;
 
                  animation->frameRange.X = startingFrame + 1;
                  animation->frameRange.Y = startingFrame + range;
 
                  startingFrame += range+1;
 
                  for (u32 x=0; x < skinnedMesh->getJointCount(); ++x)
                  {
                     ISkinnedMesh::SJoint* joint1 = skinnedMesh->getAllJoints()[x];
                     s32 joint2Index = customSkinnedMesh->getJointNumber(joint1->Name.c_str());
                     if (joint2Index >= 0)
                     {
                        ISkinnedMesh::SJoint* joint2 = customSkinnedMesh->getAllJoints()[joint2Index];
 
                        for (u32 i=0; i < joint2->PositionKeys.size(); ++i)
                        {
                           ISkinnedMesh::SPositionKey& key = joint2->PositionKeys[i];
                           
                           if (key.frame >= startingCustomFrame && key.frame <= endingCustomFrame)
                           {
                              f32 frame = joint1->PositionKeys.getLast().frame;
                              joint1->PositionKeys.push_back(key);
                              joint1->PositionKeys.getLast().frame = frame + 1.0f;
                           }
                        }
 
                        for (u32 i=0; i < joint2->RotationKeys.size(); ++i)
                        {
                           ISkinnedMesh::SRotationKey& key = joint2->RotationKeys[i];
                           if (key.frame >= startingCustomFrame && key.frame <= endingCustomFrame)
                           {
                              f32 frame = joint1->RotationKeys.getLast().frame;
                              joint1->RotationKeys.push_back(key);
                              joint1->RotationKeys.getLast().frame = frame + 1.0f;
                           }
                        }
 
                        for (u32 i=0; i < joint2->ScaleKeys.size(); ++i)
                        {
                           ISkinnedMesh::SScaleKey& key = joint2->ScaleKeys[i];
                           if (key.frame >= startingCustomFrame && key.frame <= endingCustomFrame)
                           {
                              f32 frame = joint1->ScaleKeys.getLast().frame;
                              joint1->ScaleKeys.push_back(key);
                              joint1->ScaleKeys.getLast().frame = frame + 1.0f;
                           }
                        }
                     }
                  }
               }
            }
         }
 
         skinnedMesh->checkForAnimation();
christianclavet
Posts: 1638
Joined: Mon Apr 30, 2007 3:24 am
Location: Montreal, CANADA
Contact:

Re: Question: Would it be possible to append animations?

Post by christianclavet »

Thanks for the informations! This give me hints on how I could tackle this. Interesting idea for storing animation in XML! :)
Post Reply