Last week started with a thought – “Copying skinning and animations from unit to unit should be trivial, right?”
Let’s see, but first – some intro:
All games need to store their assets (models, textures, sfx, etc.). For most games assets are prepared and stored in a way that their engine requires. With a custom engine, this goes a bit other way round – engine is created around common formats of asset formats that engine’s creators chose. Of course each game (and Knights Province is not an exception) might eventually distill required pieces and rearrange them in a way to speed up data loading and enrich with engine-specific features (i.e. KP has add-on info for house building steps or vertex weights for terrain tiles).
I’m mostly using Lightwave 3D format (LWO) for in-game models. I’m fairly experienced with it and when I need to create or tweak a model – Lightwave 3D is my tool of choice. Currently ~90% of models in the game are in LWO format (to be distilled later on, to improve loadig times and save space). Since all models were mostly static in early games life and I knew how to model staticobjects, I used LW to model placeholder houses and units.
However, game also needs animations, and that’s something I’m not really experienced nor skilled at. So after creating sample unit animation I went to hire freelancers to do better models and animations. Now I had to deal with their preferences, since asking someone to create both good models AND requiring them to convert it to format unknown to them is a tough/expensive thing. Fortunately, there’s a common ground – FBX is kind of a standard file format when it comes to models and animations for games. Most freelancers use it (also OBJ, but it’s less common).
So I was tasked with extracting models and animations from FBX. Since LW can open FBX files, I decided simply to use LW to convert FBX and call it a day. LW animation format is quite complex (and complicated). To extract animation data needed for the game, I wrote a special Python plugin to export animation frames into a text file in compact and straightforward form. Because of all that, existing process of animation import is rather lengthy:
- Obtain FBX animation from freelancer
- Convert FBX to LWO
- Tweak skeleton setup in LW
- Export static skeleton from LW to game format with a Python plugin
- Export animation same way
In actuality that’s a tedious 19-step process prone to mistakes. It works okay for 2-3 models, but it’s unbearable for anything larger.
So far game has just a bunch of animations. It would be nice to reuse some, e.g. walking unit animation is the same for all citizen (for warriors it’s a bit different, since they walk with regard to carried weapon).
It would be great to copy common animations from models who have them to the rest (e.g. idle and walk animations).
To make things right, I decided to write FBX animation importer. It’s not strictly necessary for the task, but once I’m at animations, it’s better to fix several adjoined areas. I already had code to read and parse FBX file format (few in-game houses are actually FBX, not LWO models). Expanding the code with reading of skeletal and animation info should not be that hard .. so I thought.
Last week was dedicated to that task. Things learned and reinforced:
- Anything that seems trivial could easily take 20 hours because of unforeseen details, auxiliary things and need to wrap it all into a neat “API”.
- Even with unforeseen details, if something seems doable (i.e. without involving words “automatically” or “somehow” in its description), it’s really doable, just needs more time.
- The way FBX and LWO stack transformation operations is different (and learning that alone cost me a day).
- Automation is great. Writing a small dedicated tool to convert, copy and launch preview instead of manually doing the same – saved my sanity.
- When something seems about right, but not quite – it’s almost as good as wrong.
- Animation bugs are fun:
Now with swordsman animations working, I intend to:
- Re-import existing unit animations (and throw out LWO animation code)
- Write methods for copying skinning between models
- Tweak couple stray errors in skinning
- Have all units have common walk/idle animation in Alpha 10