An interesting part of programming is how much you can do for no visible difference. My focus has recently been on improving the resource infrastructure of the code, specifically creating a generic resource package class that can hold serializable data for the engine to convert at run-time into the actual 3d assets for the game (models, props, all that fun stuff). This also required a quick thrown-together packaging tool to be built.
Initially, (as I've mentioned using Assimp.NET before) I was loading from the COLLADA model format because it had a handy exporter from Blender and is known for playing nice between most graphics tools and pipelines. Part of this is because it's designed to store as much information as possible about the 3d scene. My engine only needs a handful of data types from the .dae file (mostly vertex information, a material string, and skeleton/animation keyframes). That meant everything else that Assimp loaded from the file (and the resulting Scene object in memory during the load process) was superfluous wasted effort during runtime. The process (while the game was running, mind you) went
- Load COLLADA file from disk
- Parse COLLADA file into Assimp's Scene object
- Hand completed Scene object to content manager
- Have content manager pick apart Scene object and convert data types into SharpDX-specific formats
- Build new Mesh object (specific to my library) from the few pieces content manager pulled out of the Scene
- Delete Scene and Importer objects
- Return the Mesh
Now the tool does all the conversion (of multiple COLLADA files, as many as I want really) to in-memory Mesh objects, and then packs those objects into a tight, serializable format that only stores specifically what I need to re-create the object at runtime. That data (in memory) is then written out to a proprietary resource pack file format (on disk). This all means smaller resource files, fewer files to manage on disk(since the resource pack tracks everything internally, I just have to know which resource file holds which models), and faster loading of resources on the fly.
The new resource flow?
- At level load-time, read list of required resource packs from level file
- Pass list to resource manager, loads any not currently ready from disk and closes handles to those no longer needed
- Call "ResourceManager.Load(modelX)" for resource named modelX at any point I need to create a mesh object (again, mostly at initial level load).
As a bonus, I tasked the Resource Manager with smart object loading: it tracks which meshes have been deserialized into memory, and if a requested object is already built, it just copies the existing object instead of building a brand new one.
The funny part, appropriate to the post title, is that my metric for completion is that there is no visible difference in the game with the new resource system. It makes my code simpler and more data-driven, but if someone were to run the previous build alongside the new enhanced-resource-manager version, it just looks like I sat on my hands for two weeks.
Other than that, I've been making tweaks to the level editor, camera system, and laying some groundwork for AI and Physics. Thinking I'll need some kind of marshaller between data the physics library can play with, and data the AI routines can use for Navigational-Mesh generation.
Oh, and I've been exploring character designs and more bug concepts to nail down the look of the heroes and their new unfriendly neighbors. Getting close, I like what I'm homing in on, so I should have more of that available to show soon.
Man, these video games are a lot of work. Who knew? :)