Mirroring a skeletal animation

Started by
4 comments, last by Brassx 12 years, 7 months ago
Basically, I have been working on a skeletal animation system. All is good and all works fine until I starting writing the code to mirror the skeleton horizontally, in theory I saw how it should of been fairly simple but I was apparently mistaken, I have been using Gmapi with c++ to write a DLL for game maker to do all the skeletal calculations/drawing.

I use a hierarchy of joints to create the skeleton, and their coordinates are stored as local (relative to the root bone), So now to flip the skeleton, I simply multiply the X value by -1, and the angle of the bone by -1, That seems to flip the skeleton properly, BUT When there are sprites on each bone I ran into some inconsistencies with the way the sprites looked when flipped(Some things not lining up properly and some things have different looking angles), Here is the code(although I'm fairly sure it wont really help much to show it):

double DrawSkeleton(double Id, double aId, double x, double y, double Xscale)
{
double sId = FindSkeletonById(Id);
if (sId == -1) return 0.0;
int i;

for(int b = 0; b < SkeletonClasses[(int) sId]->BoneDepths.size() ; b++)
{

i = SkeletonClasses[(int) sId]->BoneDepths;
if (gm::sprite_exists(SkeletonClasses[(int) sId]->BoneSprite) && SkeletonClasses[(int) sId]->BoneSprite > 0)
{
gm::draw_sprite_ext( SkeletonClasses[(int) sId]->BoneSprite, 0, x + ( SkeletonClasses[(int) sId]->BoneX) * Xscale, y + SkeletonClasses[(int) sId]->BoneY, Xscale, 1, ( (SkeletonClasses[(int) sId]->BoneAngle) + SkeletonClasses[(int) sId]->BoneSpriteAngle ) * Xscale, gm::c_white, 1);
}
}
return 0.0;
}

If you aren't familiar with this game maker function it's as follows :

draw_sprite_ext( SpriteIndex, SubImage, x, y, Xscale, Yscale, Angle, Color, Alpha);


I'm not sure, but I have a hunch it could possibly be the sprite origins causing the issues I'm having.
Now note the skeleton itself looks just fine when flipped, its just the flipping of the sprites that cause issues.

Some screenshots of the issue:
dia2b.jpg

So I was wondering if any of you could help me out with this issue? Could this possibly be an issue with the origin points of the sprites?
I've tested with 'dummy' sprites and gave them random origins, and they flipped fine.. I'm puzzled by this.

If you need any more info please let me know.(like the sprite origins or original sprite orientation, etc..).

Also, I managed to get the sprites to look better, by flipping along the Y axis, then adding 180 to the sprite angle, That made things look more like they should, but still some inconsistencies.
Advertisement
I am not sure, but can it be caused by rounding?

Have you verified, that the actual bone positions of skeleton are precisely mirrored? Maybe you are rounding them down/up somewhere in code and thus they are not exact mirrors any more.

Btw, it seems to me, that the angles are correct in your mirrored sprite, but the positions are slightly (< 2 pixels) off. The apparent change in angle is probably because of filtering during drawing at sub-pixel positions?

I did a difference image of your actual sprite vs. perfect mirrored image and it can be seen, that the difference in position grows gradually as you move towards head.

[attachment=5439:sprites.png]


Lauris Kaplinski

First technology demo of my game Shinya is out: http://lauris.kaplinski.com/shinya
Khayyam 3D - a freeware poser and scene builder application: http://khayyam.kaplinski.com/
Hmm... There is no rounding going on(Unless it's an automatic rounding issue somehow rounding differently when the coordinates are negative), and yeah the positions should be exactly the same seeing as I only flip it when drawing by multiplying the X position and angles by -1.
I don't actually flip the skeleton, I simply flip the drawing coordinates.
Hmm, So any thoughts on why the difference in position grows as you move towards head?
Edit:

originsi.jpg
I still need some help resolving this issue.

I have noticed something though, The difference doesn't increase as it moves from the feet up, It goes from the center(the root bone), so everything below the root bone goes down in position gradually, and everything above the root bone goes up in position gradually...

Anyone have any thoughts? I have tried countless things and I am stuck in a rut..
Some more ideas to test:

Can you check whether the problem is still visible, if you round all drawing positions down to nearest integer (for flipped coordinates first round down and then flip)?

Or if you round them down to nearest half-point (i.e. round down and add 0.5)

Also, can you set sprite origin points to half-pixel and see, what happens.

It may be problem with texture filtering - that above cases should give some clues.
Lauris Kaplinski

First technology demo of my game Shinya is out: http://lauris.kaplinski.com/shinya
Khayyam 3D - a freeware poser and scene builder application: http://khayyam.kaplinski.com/
I have tried to round the positions down(and up) before, and it didn't help any, But I tried it again anyways it got the head to look a little better, but a lot of other things were out of place.

As for the rest, none of them seemed to help the issue, I believe it is somehow related to the origins, I managed to get it to look better by flipping along the Y axis, then adding 180 to the angle of the bone(again), This makes things look almost right, I had to rotate the body sprite by 90 degrees in paint(Actually 270 in paint), then when it flipped along the Y axis it looked fine, otherwise if i left it horizontal it would be too far to the left when flipped, but just fine when not flipped..

That leads me to think it is indeed an issue with the origins, although I can't clearly see why..

As you can see, The head now flips properly, but some other things are a bit out of place now(The body, even though I had to rotate its sprite by 90 degrees, then add an offset to its 'sprite angle' variable of -90 degrees, the effects that used to be on the X axis of it when flipped, are now on the Y axis so when flipped it's a pixel too high).

Also the joint positions are marked with green points, so you can see how the sprites somehow get 'offset' in either the x or y axis only when mirrored.
flipcomparison.png
Edit:
I have away of flipping it now perfectly, although It doesn't appeal to me very much, I'm creating a blank surface, drawing the skeleton to it, then drawing a textured primitive using the texture obtained from the surface, and flipping it that way.. It works, but it seems like a waste of memory to me.

This topic is closed to new replies.

Advertisement