Animation layering

Everything about development and the OpenMW source code.
Chris
Posts: 1626
Joined: 04 Sep 2011, 08:33

Animation layering

Post by Chris »

I've been playing around with weapon states. Unfortunately there's not much farther I can go without animation layering.

Hrnchamd and LizTail have/had some experience with Morrowind's animation system, so if you're still around, I'd very much appreciate any help you can give. Though if anyone else has any insight or useful tips, I'm all ears.

Basically what I need to know is how Morrowind handles the various controllers from the various animation sources an actor can have (an Argonian, for instance, has base_animkna.nif and argonian_swimkna.nif for animations, where they each specify keyframe controllers for their own Bip01* bone hierarchy to animate the character, and the game will use controllers from one or the other depending on what animation is played). I can handle separate sources like that when dealing with one layer, where I"m only using one source at a time. But I'm having trouble coming up with a method to handle the case where different layers are using different sources, while ensuring the controllers aren't fighting each other over a given bone, or aren't being neglected (i.e. what to do with controllers that aren't directly targeting a recognized bone for the various layers).

The simplest way to deal with it would be to require all layers use animations from the same source NIF. I don't think the vanilla assets would have a real problem with this, though I can't be sure. I also don't know what existing mods may try to do, so I'm hoping someone familiar with the inner-workings of the vanilla game's animation system can provide information on how it works.

Other ways are more complex, requiring breaking up the controllers into separate lists based on what bone they're targeting, then going through and collecting the right controllers whenever an animation starts or stops to make sure the right ones update. Though that leads to the problem of figuring out which ones to get.
jhooks1
Posts: 780
Joined: 06 Aug 2011, 21:34

Re: Animation layering

Post by jhooks1 »

Would making one huge animation track (from the various animation files) help anything? You would have to add time offsets to the track keys and text keys.
Chris
Posts: 1626
Joined: 04 Sep 2011, 08:33

Re: Animation layering

Post by Chris »

jhooks1 wrote:Would making one huge animation track (from the various animation files) help anything?
Not really. At least, not without bringing up more questions and possible pitfalls. We're effectively dealing with at least 4 or 5 time sources, maybe more. Various controllers are expected to run off the same source and are synchronized as such, so changing the keys' times could risk desynchronizing controllers.

There's other issues too. For example, a controller that doesn't normally have a kind of track (e.g. a KeyframeController that doesn't have position transformation keys) may suddenly get one if it's combined with a source that does, which would change its behavior.


I'm thinking the best course for now would be to assume all layers need to come from the same source, unless there's any egregious problems that causes. If any minor problems pop up, they can be dealt with later.
LizTail
Posts: 27
Joined: 31 Oct 2012, 21:50

Re: Animation layering

Post by LizTail »

Hey Chris,

Sorry, I haven't been checking here for a while, but I happened to see this today.

IIRC, layers work in the content creation tool by specifying a layer root node, and everything below that node in the character's skeleton hierarchy is controlled by the layer sequence rather than the main sequence that's attached to the character's root node.

This is documentation that mentions layers from a more current Gamebryo version, so it may not be exactly the same as Morrowind, but it could offer some clues:

https://support.gamebryo.com/index.php? ... SmaxTools4
https://support.gamebryo.com/index.php? ... SmayaAnim3
https://support.gamebryo.com/index.php? ... spaceRef23

Now as far as how exactly it's implemented in the NIF/KF files... it's been a while, but I'm thinking that Morrowind KF files were basically lists of animation controllers and the names of the scene graph node (or property of that node) that they control? So I'm not sure if this layer root node is actually stored anywhere in the file and it might just be as simple as swapping out any animation controller that's active on the referenced bone when you activate the animation as a layer instead of as a whole body animation, and then swapping the original controller back in when the layer's animation is done or removed by code.

In other words, the main animation file would have a controller for every animated node/property in the character, but the layer would only have controllers for a subset of those. When the layer is active, any controllers it has temporarily override those in the main animation that match the same node/property.

In the case where you have multiple layers, there's a priority value that's passed into the function, and that determines which layer takes precedence. In Morrowind there shouldn't have been any blending, just highest priority controller for each bone wins.

I don't have access to any files that I can look at for reference right now, so let me know if any of that doesn't match what you're seeing or doesn't make sense.

Anyway, I hope that helps, but I'm still having trouble following what you said here:
But I'm having trouble coming up with a method to handle the case where different layers are using different sources, while ensuring the controllers aren't fighting each other over a given bone, or aren't being neglected (i.e. what to do with controllers that aren't directly targeting a recognized bone for the various layers).
Maybe going over a specific example would help?
Chris
Posts: 1626
Joined: 04 Sep 2011, 08:33

Re: Animation layering

Post by Chris »

LizTail wrote:IIRC, layers work in the content creation tool by specifying a layer root node, and everything below that node in the character's skeleton hierarchy is controlled by the layer sequence rather than the main sequence that's attached to the character's root node.

This is documentation that mentions layers from a more current Gamebryo version, so it may not be exactly the same as Morrowind, but it could offer some clues:

https://support.gamebryo.com/index.php? ... SmaxTools4
https://support.gamebryo.com/index.php? ... SmayaAnim3
https://support.gamebryo.com/index.php? ... spaceRef23
Hi. Thanks for those links. That last ones gives some pretty interesting insights into how it was expected to work, particularly the ListenForTextKeyEvents method. Also interesting how they deal with the textkeys, but still specify sequences (which, if I understand right, are the animation group names stored in the textkeys) as numeric IDs or strings.
Now as far as how exactly it's implemented in the NIF/KF files... it's been a while, but I'm thinking that Morrowind KF files were basically lists of animation controllers and the names of the scene graph node (or property of that node) that they control? So I'm not sure if this layer root node is actually stored anywhere in the file and it might just be as simple as swapping out any animation controller that's active on the referenced bone when you activate the animation as a layer instead of as a whole body animation, and then swapping the original controller back in when the layer's animation is done or removed by code.
With Morrowind, the animation controllers were actually in the NIF itself. Though oddly, for most animated foo.nif models, there was also an xfoo.nif (without the controllers) and xfoo.kf (the controllers only, and a list of bone names) pair. Not sure what the purpose of those are since it's just duplicating the info in the original model, but they're there, unreferenced by anything in the game data.

The layer roots don't seem to be in the file, they're probably hard-coded.
In other words, the main animation file would have a controller for every animated node/property in the character, but the layer would only have controllers for a subset of those. When the layer is active, any controllers it has temporarily override those in the main animation that match the same node/property.
With Morrowind, it doesn't seem to work like that. You have the NIF which defines the nodes, controllers, and possibly meshes (depending on the NIF). Each controller has a start time and a stop time, and the associated data is one contiguous array for all animation groups. The character root has a NiTextKeyExtraData, which has a list of time:textkey pairs. The textkey is in the format "name: event", where 'name' is the animation group name (idle, death1, swimrunback, jumphh, etc), and 'event' is some kind of action (start, equip attach, target release, etc).

So for example, if you wanted to play the "idle2" animation, you'd look through the NiTextKeyExtraData for "idle2: start", and the associated time is what you use for processing the controllers. Processing the controllers will then apply its effects for this time. The time then increments forward each frame, processing the controllers again each iteration, until it reaches an "idle2: stop" textkey which basically says the idle2 animation is over (at which point, it can loop or switch to another idle or something).

If you want to play an animation layered on that, say a target spell casting animation, you'd do a lookup for the "spellcast: touch start" textkey as the animation's start time, and have the appropriate controllers use that time instead, and have it go until it reaches "spellcast: touch stop". The layer uses the same controller, but it's at a different time offset.

This isn't hard to handle. It basically means you have a time value for each layer, and you make sure controllers use the correct time value for whichever layer their target affects when you process them all.
Anyway, I hope that helps, but I'm still having trouble following what you said here:
But I'm having trouble coming up with a method to handle the case where different layers are using different sources, while ensuring the controllers aren't fighting each other over a given bone, or aren't being neglected (i.e. what to do with controllers that aren't directly targeting a recognized bone for the various layers).
Maybe going over a specific example would help?
Say you're playing an Argonian. By default, he has base_animkna.nif which defines his skeleton, various controllers, and the textkeys for all the third-person beast race animation groups. He also has argonian_swimkna.nif, which defines a skeleton (using similar bone names), various controllers, and the textkeys... but these controllers and textkeys only define animation groups "swimwalkforward" and "swimrunforward". So when you play one of the swim forward animations, you use the controllers from argonian_swimkna.nif, while any other animation, like a weapon attack, uses the controllers from base_animkna.nif.

Now, like I said above, when you play a layered animation, you're basically using the same controller at a different time offset, which means you just run through and update all controllers after updating the layers' time values.

However, in this case, it's theoretically possible to have one animation from base_animkna.nif and another animation from argonian_swimkna.nif both playing at the same time, on different layers. This means, some bones should be using the controllers from base_animkna.nif and others should be using controllers from argonian_swimkna.nif.

This becomes pretty difficult to manage since you can't just run through and process all controllers from the active animation source, since with two animation sources you'll have multiple controllers affect one target, with the end result depending on which order they get processed in rather than any kind of animation priority. You can only process the controllers that are supposed to be affecting a given bone based on which layer is using which animation source. This is compounded by how some controllers don't affect bones (they can affect properties, meshes, particle systems, etc), or they may affect a bone unaffiliated with a layer.

It's easy enough to make sure the controllers from various sources are targeting the actual bones (or other resources) they should be, but it doesn't seem to be straight forward to determine which controllers are supposed to get processed when you're playing from more than one source at a time. Having to look and see what a controller is targeting, cross-referencing that with the layer the target is on, and checking whether the controller is from a source that is supposed to be affecting that layer, just sounds like a nightmare when you have to do it for every controller in every animation source. And it still leaves the question of what to do for controllers that aren't affecting some layer's bones.
LizTail
Posts: 27
Joined: 31 Oct 2012, 21:50

Re: Animation layering

Post by LizTail »

OK, I think I get where you're coming from now.

First, I'm pretty sure that the basic .NIF files that have animation encoded in them are just used to let you select something in the editor. I don't think the animations in them actually affect the game, and it's really the KF files and x...nif files that are used. So while all the NIF files in the base game always have matching animation, I'm not sure if that will always be true for mods. You could confirm this by renaming one of the KF files or x...NIF files and see if the game still loads the animation, or by using NIFskope to mess up the animation info in the NIF and see if that has any effect on the game. If I'm correct, I think the safest thing to do would be to ignore the NIF file and always use the KF files.

Second, thanks for reminding me about the merged controllers. I should have remembered that since I wrote a tool to un-merge and re-merge sequences for morrowind. You can look at it here if you want.

I think the problem that you're getting hung up on is that you have two controllers with two separate timelines in the source NIF files, and you're trying to retain that structure at runtime. What would probably be better would be to build a directory of animation sequences and treat the raw keyframe data as a resource that's shared by many controllers. Then when you switch sequences, or apply sequences as layers, all you're doing is selecting a sequence to apply rather than moving times around. This would also give you more flexibility in the future if you wanted to explore the idea of blending sequences during transitions or allowing people to apply arbitrary KF files as animations with mods.

So anyway, my idea of a solution might be:

Have a class that's function is to serve up the correct animation sequence for a particular actor, I'll call it ActorAnimBinding for the sake of this post. It has the ability to specify a parent, so that if it doesn't specify an animation of it's own, it looks it up in the parent, then its parent, etc.

The ActorAnimBinding class would have a function to read in a KF file and parse through the text keys to build a list of sequences and their start start/stop time. For each sequence, the function would build a map of the information needed to connect that sequence to an actor at runtime. So it would need to know how bind it to a node/controller, and it would need links to the data structures that contains its keyframe data, along with the start/stop times in that data.

With that, you could build what you need to figure out the right animations for any character in the game. Right now I think only humanoids use layered animation, but it would be great if new mods could apply arbitrary animations to arbitrary things. Anyway, for the humanoids you would need something like this at startup:

First, define an ActorAnimBinding instance that represents the basic animation for all humanoids in the game. Use it to load the base humanoid KF file.

Next, define another ActorAnimBinding instance that represents animations for female humanoids. When you load the female KF file, it will only contain animations that are unique to females, but that's fine because you can set the parent of this instance to the previous one you created. Then when you use it to attach an animation, if you ask for a sequence that doesn't exist in the female KF file, it will find it in the base humanoid one.

Next, do the same thing for the base beast animations. I'm not sure if these inherit from the basic humanoid ones since those don't have tails, but it might be possible.

Finally, create an instance for Argonians that inherits from the base beast animation bindings for the right gender, but patches in the special Argonian swimming animation.

Then, by default, any humanoid player or creature would use these basic ActorAnimBinding instances as their animation binding class. Only those that had special animations defined would need to have a new instance of ActorAnimBinding created which referenced the original default for that race/gender as its parent.

When you want to attach an animation as a layer, you would have all the information you need stored in the ActorAnimBinding. You would use it to spawn some new controllers for the new animation, but not clear old ones. If all of the controllers are defined in all sequences, though, you will probably need to specify the layer root when attaching a layer, and only change controllers that are below that root in the hierarchy.

When activating layers, you'd probably want to keep a reference to the old controller around so that you can go back to it if the layer animation ends first. In Gamebryo I think the new one was just added to the list and the old one was set to inactive, and then set back to active when the one above it was removed, like a stack. I'm not sure if Ogre3D has something similar or if you'd have to store your own stack somehow.

Wow, that was long! Sorry ^_^; This just seems like the most straight-forward way of doing it off the top of my head, but I could always be missing something. Hopefully it's helpful for you in any case. Let me know if any parts of this don't make sense.
User avatar
sirherrbatka
Posts: 2159
Joined: 07 Aug 2011, 17:21

Re: Animation layering

Post by sirherrbatka »

Thanks liz, it's good that you are still around the project.
Chris
Posts: 1626
Joined: 04 Sep 2011, 08:33

Re: Animation layering

Post by Chris »

Nifs and the vanilla engine find no end in ways to annoy me.

It seems that Nifs that have animation sequences defined in them (with the appropriate keyframe controllers) will have foo.nif, xfoo.nif, and xfoo.kf files. xfoo.nif contains the majority of the structure, including all non-keyframe controllers, while the xfoo.kf includes the TextKey data along with the keyframe controllers and matching bone names. Examples of this are base_anim.nif and r\lordvivec.nif.

However, if the Nif does not define any animation sequences, then you'll only have foo.nif. For example, r\golden saint.nif has no animation sequences itself (it's a biped creature, so it uses base_anim), so it has no r\xgolden saint.nif or r\xgolden saint.kf.

I suppose the way they're split up between nif/kf pairs where needed will actually help me sort animation sources out. But it annoys me how the game data will always reference foo.nif, regardless if it has/uses the xfoo.nif/xfoo.kf files or not. It'd have made much more sense if the game would reference foo.nif, and then use foo.nif or foo.kf depending on what it needed (with xfoo.nif being the "source" that the other two are generated from).


And, of course, this doesn't apply to the head animation sequences, since they use GeoMorpherControllers instead of KeyframeControllers. Can't make things too simple now.


EDIT

I think what I'll do is create one "ObjectRoot" which defines the meshes, particle systems, and base controllers from the xfoo.nif, and then an array of "AnimSource"s which each has the TextKey data and controllers as defined in a kf file (with the controllers targeting the skeleton bones from the ObjectRoot). The controllers in the AnimSource will be split up according to the layer, which I have to figure out anyway to make sure they get the correct time source.

Then each animation layer will reference an AnimSource, and run all controllers for its given layer and above when updating. When playing an animation, it will look through the AnimSources in reverse, finding one that has the appropriate TextKeys and using that source for the given layer.

In the future we can create resource managers for Nif and Kf files, which can pre-create the mesh and skeleton resources as well as load the necessary shared info.
LizTail
Posts: 27
Joined: 31 Oct 2012, 21:50

Re: Animation layering

Post by LizTail »

I feel your pain! I can't think of any reason they did it this way, and you can see that they fixed the situation in later games, switching to the method that you suggested.

I like the approach of having a stack of animation sources on each NPC rather than hard-coding a parent/child relationship like what I suggested. I think that will make it easier to expose this sort of thing for custom races/npcs so they can have many different animation files specified.

Good luck!
Chris
Posts: 1626
Joined: 04 Sep 2011, 08:33

Re: Animation layering

Post by Chris »

Have a treat.

I've had to start redesigning the character controller to be able to properly handle this. It seems as though I need to get away from the assumption that there'll be one character state, but rather, known states are toggled on and off according to the various conditions on the actor. This also means that death handling will need to be fixed up since the mechanics can't rely on polling the character's current state as being Death1..Death5 to know whether the actor was previously known to be dead or not.

I've also been running into some really odd behavior with regard to the weapon model. If the weapon is readied and the player switches to another weapon (via the quick keys or the menu), it will recognize the new weapon's type, but it may not actually replace the model with the correct one right away. It eventually will, but may require the weapon to be unreadied first. I don't notice anything wrong with the NpcAnimation::updateParts method... it should detect a different ContainerStoreIterator for the weapon (since something new was equipped), which will then force an update of the parts on the character, remove the old weapon model and add the new one if it should be shown. But that doesn't seem to be the case. Any ideas on that?
Post Reply