At the moment I'm in the middle of enhancing the asset management in my engine.
I find myself needing to make a distinction between "internal" assets and "external" assets.
Internal assets are assets that are compiled specifically for my engine using my own tools, to a basic data chunk format which defines a set of data chunks and pointer references between those chunks. Nothing super complicated, just something to get compiled static assets up and loaded with a minimum of fuss without having to write a loader or interpreter for each and every different kind of asset.
External assets are assets such as textures and shaders which I want to be able to deal with generically as assets, but are actually directly loaded and dealt with by Direct X.
So, I have a base class "Asset", so for every asset I can quickly and easily just cast to an Asset and release it's reference count, etc, etc, all the basic stuff that one would want to do to a basic asset. But I also want to deal with external asset through the same Asset interface, to make things simpler for my whole engine.
At the moment, most internal assets are composed of basic C structures, where the "Asset" structure is the first.
Example:
struct ModelTemplate{
Asset m_Asset;
// blah other Model and geometry related data
};
But most of my engine had been written in C style, and not C++ style, and I recently decided that it was stupid, and have spent a bit of time converting things to C++ OO style, including the Asset Managers, and the Asset struct into proper classes.My current problem is that I can have the base Asset Manager class quite easily load from my internal data chunk format, but if I want to keep the same Asset Manager -> Asset interface, then I'll start having issues, because with C++ objects, it's quite likely that I'll at some point be dealing with virtual functions in my derived Asset classes. Which means that with External assets, I can always create an Asset object and set a ptr to the Direct 3D asset (ie. texture or shader, etc) without an issue, but then if I ever have a virtual function on a non-external assets, then I immediately have problems, because the power of the Internal asset system (chunk based format) is also it's weakness, the fact that it just copies data around and links pointers, and has no knowledge of virtual function tables, whereas when referencing data members of a class, the size of the virtual function table is automatically accounted for and offset from the beginning of the object.
I'm certain that at some point, I'll end up overwriting a virtual table of function pointers. And I don't want to have to remember and re-compile all the assets of a certain type whenever I add another virtual function to an Asset derived class.
I'm trying to think of my options, and I can only think of 2:
- Make the asset compilation much more complicated, much more akin to a full serialization, de-serialization set of methods.
- Go back to the old way of having all the assets be simple data structs without any virtual functions and write all their functionality as C-style functions which accept a ptr to the struct as the first parameter.
Does anyone have any suggestions? Have I been clear enough, or did I ramble a bit? Is there a standard way to handle something like this? I mean, I'm not dealing with legacy code, just an Asset Manager generic asset loader which is blind to type, and other Asset Managers which are specific and don't load the assets themselves ...