Vertex colour serialisation, and endianness

· by Steve · Read in about 3 min · (566 Words)

My current OGRE job is one that should have got done for Azathoth really, but it got put off for lack of time. Dagon is out of time too really, but I just couldn’t let this one slide again. It’s not a particularly sexy feature - it won’t be demonstrated through any flash demos or anything, but it’s an important core consistency thing that really should be sorted out.

The problem? Well, if you serialize vertex colours under one render system and load them back into another one, the blue and red channels will be inverted due to a difference in the way D3D and GL pack colour values into 32-bit numbers. We’ve always hidden this when defining colours from regular ColourValue instances (which are 4-floats), automatically converting to the right format for the rendersystem, but serialisation to and from files in this packed format is a pain. I’ve chosen to add 2 new vertex element types to refine the regular VET_COLOUR type, VET_COLOUR_ARGB (D3D likes this one) and VET_COLOUR_ABGR (GL likes this one). You can still use VET_COLOUR, at runtime it will be converted for you to one of the more specific types based on the active rendersystem. This means when (de)serialising we can see when there’s a discrepancy and convert. The only issue is when writing tools, no rendersystem may be loaded - in which case you should pick one or other of the specific types yourself (XMLConverter will give you the option of which to prefer), or it will default based on your platform.

You might wonder why I didn’t include both types in the serialised version, burning a little disk space in return for a faster load time. Well, I was thinking about this, but the problem is that because OGRE lets you pack vertex data however you like, vertex colours are often packed in a single buffer along with other vertex elements, which means you can’t store 2 copies in different formats without storing the entire buffer, with all its elements, twice. I wasn’t prepared to do that. If the load time difference is an issue to you (I doubt it, but hey), you can compile your meshes with an affinity to your preferred rendersystem on the platform in question.

Whilst I was at it, I looked at the endian conversion code for the serializers. Right now, all of OGRE’s binary formats are in little endian format, and big-endian platforms like OSX have to convert on the fly, implemented as precompiler directives. I’ve decided to change this while I’m at it, so that every platform will serialise data in it’s native endian mode. Every serialiser will check the endianness of files and perform any conversion necessary just like OSX does now. It means that each platform can load files from different endian platforms, but will load files from their native platform faster. OGRE’s example media will remain little endian (effectively the status quo), since that’s the majority use and we don’t want to clutter CVS, but it means you can create big-endian files for faster loading when deploying your own products on OSX or other big-endian platforms.

I realise OSX will be little endian too once the Intel change filters through, but this is still worth doing since there are other platforms out there which are big endian (like some consoles ;)).

So, not very glamorous but useful work nonetheless methinks.