Page 1 of 2

Animation frame callbacks

Posted: Fri Sep 08, 2006 4:50 am
by Vectrex
I thought it would be good to have embedded tags in animation to trigger callbacks at any keyframe. I noticed Unreal does this http://udn.epicgames.com/Two/AnimNotifies and was wondering if it's best to build support into the animation format.
It's great for artist controlled events like footstep sounds, code triggering of effects at certain frames, a simpiler end anim notification etc
I guess this is the type of thing you'd put in a script file, but animation doesn't have one.
You could poll or use callbacks for the tags.

Posted: Tue Sep 12, 2006 8:05 am
by kneeride
Is it possible to get the frame index? I was thinking of doing this too for footsteps and polling each frame for the animation frame index (if this is possible).

I think ogre might skip frames based on time lapsed. therefore you'd need to check whether a frame has passed (and not when a frame is landed)

Posted: Tue Sep 12, 2006 1:07 pm
by gerds
I've "kind-of" got this working before.

What I do is keep track of the AnimationState::getTimePosition() value. When the value is smaller than the last value (ie: a loop has completed) you can initiate a callback yourself. Write a thin wrapper class around ogre entity to allow you to register callbacks on animation states in a generic way.

Hmmm... this wouldn't work entirely for your walking animation because even if you started the animation with the feet on the ground, you would also need a callback at 'half way though' the animation. I guess you could have a callback on the start of the animation (ie: left foot touching the ground") and also at the midpoint of the animation (ie: right foot touching the ground). This is a bit 'magical' but would do what you require.

Posted: Tue Sep 12, 2006 7:08 pm
by sinbad
I think having information about certain keyframes is useful, but that's mostly for authoring convenience - really what you're saying is that at a certain time in the animation, an event occurs. It may or may not naturally coincide with an animation keyframe, although I can understand where this might be forced for convenience, or where it might be natural. Still, I think the time link is the most generic. Whilst this could probably be recorded if not in the primary mesh/skeleton files, it probably sits better in a separate definition, much like other game-related meta information about a model like movement speed etc.

Even if we did a callback, it will never occor on the keyframe anyway, but slightly off it because time is continuous. Thus the result will need to be interpolated in some way anyway. Some apps may be happy to know that 'this event happened sometime between the last frame and this frame' I guess, but not all.

Really this is another event in your game system. It should be treated the same way. I would personally push this event onto my message queue from my animation manager that tells the animation state to update and let that interpolate the timing like everything else.

Posted: Tue Sep 12, 2006 9:37 pm
by RayKallmeyer
From the artist's point of view this is a must-have feature in an animation editor. Requiring that a separate tool/exporter be used in the animation pipeline is a huge red flag - so I would agree with the original poster that integrating the callbacks into the animation file would be ideal.

Also, I don't agree that the possible time disparency would cause any problems. What is needed is a simple notification mechanism for events occurring in the animation - a shoe hit the floor, a chain rattled,... These notifications are used primary for events corresponding to the animation - sounds, special effects, ... The user should not be using these callbacks for critical notifications like when-to-apply-damage. So even if the callbacks aren't exact, their users only need them to be as accurate as the animation driving them - which can be guaranteed.

At least thats my opinion :wink:

Posted: Tue Sep 12, 2006 10:06 pm
by SunSailor
Don't want to take any position in this debate, as I'm not far enough in it yet, but I want to remind, that sound effects themselves have a significant latency, so a sound effect needs to be played aprox. 2-3 Frames *before* the event (It's also an old rule for face animation, do the animation in sync and then move it 3 frames *before* sync, it simply "feels" much more natural). So a callback is virtually useless for that application.

Posted: Wed Sep 13, 2006 2:01 am
by RayKallmeyer
SunSailor wrote:Don't want to take any position in this debate, as I'm not far enough in it yet, but I want to remind, that sound effects themselves have a significant latency, so a sound effect needs to be played aprox. 2-3 Frames *before* the event (It's also an old rule for face animation, do the animation in sync and then move it 3 frames *before* sync, it simply "feels" much more natural). So a callback is virtually useless for that application.
Unless your animators are aware of the latency and place the callbacks 2-3 Frames before the animation event ;)

Whether or not you are syncing directly to the animation or 2-3 Frames before the animation, it boils down to one of the following options:

-Do it by hand (in code or configuration file) .. ick.
-Do it in an external editor (requires another editor in adition to the 3DS, MAYA, ect*) .. ick
-Do it in the animation editor (requires Ogre format support)

*Requires another editor for the animators. The designers would most likely have have another external editor for characters anyway, but synchronizing effects really shoudln't be the job of the designer - so you'd end up with just one more step in the pipeline for the animators (another editor) which (in my experience) makes for very un-happy animators :cry:

Posted: Wed Sep 13, 2006 4:45 am
by Vectrex
RayKallmeyer - "The user should not be using these callbacks for critical notifications like when-to-apply-damage."

Actually I disagree, for example a decent punch animation you might actually 'trigger' different amounts of damage depending on what part of the animation is playing. So the pullback = 0, the beggining of forward motion = half then it builds up to full damage, etc Obivously it'd be better for the coder to derive that info from the speed of the hand bone, but you get the idea ;) Basically callbacks should be generic and interpreted by the game code but their name etc.


SunSailor - "so a sound effect needs to be played aprox. 2-3 Frames *before* the event (It's also an old rule for face animation)"

Not if you use a decent sound lib. Latency shouldn't be any more than 50ms and at the very most 100. Saying 'it's an old rule' to me says they were probably using the windows wave device which is nasty at like 200-300 ms. DX device is much better and my crap AC97 laptop sound can do 30ms.

Posted: Wed Sep 13, 2006 10:43 am
by SunSailor
Vectrex wrote:Not if you use a decent sound lib. Latency shouldn't be any more than 50ms and at the very most 100. Saying 'it's an old rule' to me says they were probably using the windows wave device which is nasty at like 200-300 ms. DX device is much better and my crap AC97 laptop sound can do 30ms.
First, this is something you only can achieve on a very well configurated pc, which isn't the case with those of most potential customers, so you can't rely on this. Second, this "prelatency" has nothing to do with the real latency, the sound engines produces (Didn't make this very clear, sorry), it has to do with the perception of the animation under no physical latency circumstances, at least in facial animation. This rule is much older than computer animation or windows sound cards themselves.

Posted: Wed Sep 13, 2006 11:14 am
by sinbad
I wasn't arguing about the need for this in an exporter, more that you might want it as a project-specific bolt-on, writing to a file containing other meta-information about your model / animations. However, I guess the event raising requirement is generic enough.

Unfortunately the TODO is pretty stuffed already, not sure when this will be tackled...

Posted: Thu Sep 14, 2006 3:11 am
by chuck_starchaser
Hey, can I chip in? I'm quite probably wrong, but in my mind this is a 5 minute job: add a user data-field to the keyframe class, assuming there's such a thing, and a test for zero in the player class, assuming there's such a thing, that if that data field is not zero it calls back a user functor with the data field as argument; and so I'm willing to give it a try. Haven't downloaded the sources from cvs yet; I'll do so now. In the meantime, any pointers what files to look into would be nice. And whatever I do, someone else will have to test it, since I can't tell a keyframe animation from a hole in the ground. I guess the trick might be to add a way for the user to input the data there... and to create the functor and initialise a global pointer to it... Whatever... I'll play it by ear.

EDIT: Couldn't find any links or info on where the cvs is; I downloaded the sources from the main repository page, for now.

Posted: Thu Sep 14, 2006 6:33 am
by Kentamanos
chuck_starchaser wrote:EDIT: Couldn't find any links or info on where the cvs is; I downloaded the sources from the main repository page, for now.
Check out this page:
http://www.ogre3d.org/index.php?option= ... &Itemid=87

It has a section about getting it from CVS. I'm not sure if you've used CVS a lot, but if you're on Windows, make sure and take a look at TortoiseCVS.

Posted: Thu Sep 14, 2006 6:44 am
by chuck_starchaser
Thanks! Yeah, I got Tortoise, and I've done it before; not to say I don't get sweat drops and adrenaline discharges even thinking about using cvs... :D

Posted: Thu Sep 14, 2006 7:03 am
by Kentamanos
If you run into problems, be aware that it might actually be a sourceforge problem. It seems to be much more stable recently, but it definitely has problems from time to time.

Posted: Thu Sep 14, 2006 7:04 am
by chuck_starchaser
Have I got it right? Somehow it's not taking the password...

Image

Posted: Thu Sep 14, 2006 7:09 am
by Kentamanos
Take off the login off of the Repository folder at the end. (The login command is used when using the command line version, Tortoise automatically handles the commands)

Even when it's working, you'll get a message that says:
Empty password used - try 'cvs login' with a real password

Posted: Thu Sep 14, 2006 7:32 am
by chuck_starchaser
Got it; thanks!

Posted: Thu Sep 14, 2006 9:51 am
by Vectrex
chuck_starchaser wrote:but in my mind this is a 5 minute job: add a user data-field to the keyframe class
keep in mind that there should be the possiblilty of having multiple events triggered from the same frame/time

Posted: Thu Sep 14, 2006 2:11 pm
by chuck_starchaser
I knew I was wrong...

No, wait a minute; why? The artist inserts the events, right? So let the artist move a trigger to the previous or next frame if it doesn't fit. Otherwise this issue will turn something simple and straightforward into something a million times more complex, for the sake of a seldom used feature?
How about this: This data field is 4-bytes. If the client needs multiple trigger, let the client use those 4 bytes as an address or index into a triggers database on the client side that has a one to many relationship to events triggered. For the rest of us, mortals, one trigger per frame shoud suffice.

Posted: Thu Sep 14, 2006 2:56 pm
by Vectrex
well, the animation event might be only one tag in the animation file and as you say, read some script file which maps the event to whatever events should happen. Definately anythings better than making the artist shift events around, eg a footstep would be a sound and dust particles, basically I wouldn't bother unless there was a way to do it properly. So the one tag against the DB or script would be ok.

Posted: Thu Sep 14, 2006 3:10 pm
by chuck_starchaser
I wasn't even thinking you meant multiple consequences to a trigger; those would definitely, in my mind, even for elegance's sake, be listed externally; I thought you meant like a foot fall at the same time as the actor swats a fly, and gets a hiccup, and a bullet kills him.

Posted: Thu Sep 14, 2006 5:45 pm
by sinbad
Patches are certainly welcome, but a bit of guidance:

1. I would not embed this information in the Keyframe class. Why? Because most keyframes won't have an event in them. IMO it is better to keep this information in a sparse, separate entry which is only present when required. Also makes it much easier to locate events in the timeline. Also, you can offset the event times from the animation keyframes if you want, they're not locked together anymore.

2. How best to store this? Well, I would personally store them in a separate time / event list attached directly to the Animation. At first I thought you could have a new track type with a separate keyframe subtype (EventTrack / EventKeyFrame perhaps), but whilst that sort of looks elegant, it's actually not that great since, once again, these events are not interpolated and there's no need for multiple tracks, so the track/keyframe idiom doesn't really fit, and forcing a design just for the sake of pseudo-integration never works IMO. So, a simple time/event list per Animation is better in practice I think.

3. Another reason to keep this separate is serialisation. We always, always try to keep file formats upwardly compatible, so keeping these events in a separate chunk of the file (.mesh for vertex animation, .skeleton for skeletal animation) is a very good thing. Both the XML formats and the binary formats, together with their serialisers, need updating. These new chunks in both formats need to be optional to keep compatibility.

4. Exporters. Obviously this is only of any use if exporters support it. That means both adding the serialisation in and figuring out how the animator interacts & specifies these events in the tool.

So, hardly a 5-minute job I think. But contributions are welcome.

Posted: Thu Sep 14, 2006 6:52 pm
by chuck_starchaser
I got 'ya; list< pair< time, stuff > >. Starting to look like 5 weeks... Just kidding. But I'll be useless at number 4: The only Python I know is the one that bit me. Allright; I got the cvs head, and the dependencies; I'll dust off my helmet and try to compile tonight.

Posted: Mon Sep 18, 2006 10:15 pm
by KungFooMasta
Ogre::NodeAnimationTrack
Ogre::NumericAnimationTrack
Ogre::VertexAnimationTrack

....

Ogre::EventAnimationTrack

Is what this sounds like to me. Note that this class does not exist.. :wink:

KungFooMasta

Posted: Mon Sep 18, 2006 10:26 pm
by Game_Ender
KungFooMasta wrote: Ogre::EventAnimationTrack

Is what this sounds like to me. Note that this class does not exist.. :wink:

KungFooMasta
You should read Sinbad's second point above, where he reasons that its not best to create and entire new track. Instead a simple list attached to the animation would do it.