Monday, December 17, 2012

Texture Packer for C++

http://www.codeandweb.com/texturepacker is the place to go for an excellent texture packer. It will pack a bunch of sprites together andexport a new Texture Image alongside a nice texture Atlas.

I want to use this kind of functionality for several reasons listed here:
  1. Less textures to have to load
  2. Faster load times due to less texture to have to load
  3. Less memory usage. Packed textures will take up less memory
  4. Simplify sprite lists in memory (exporting is so much easier to manage)
Andreas has created a wonderful tool that runs on several systems. In my case I am using the PC version. The tool offers many options and my favourite has to be the Trim option. This will pack all your sprites as close as possible to each other, whether they be wide or tall or simply small. This creates a wonderful saving of memory and allows me to get more sprites into a single sprite sheet. As you will see in the next couple of example images of the texture packer itself, along with some of my Kal sprites from Hoopfighter for iPad.

In this image above you can see a number of the options available to this tool. In this case You also see Kals side on running animations all nicely laid out on this sprite sheet. Taking up a considerable amount of it as well.
Now this second image above us show what happens when I click the Trim button. It basically removes white space from the sprites, but will not overlap x or y of images. As you can clearly see, this has saved a lot of space on the sprite sheet. Leaving me with space for more haha!

As it happens this lovely tool come packed with several export options. Xml to specialized versions for various SDKs. It does Not however yet cover Marmalade, my SDK of choice. The other thing it doesn't do as yet is export the sprite atlas data to C++. Now  I would lvoe it to do marmalade natively, yet to be honest C++ is widely used and is not problem for me with Marmalade.

So what am I going to do about this? Use the Xml, well NO, I won't be doing that. Parsing something at run time is not my way when I know already what the assets are.  Something Rigid like assets for this game are not something I would want to parse every time it is run. So instead I really need something I could simply include into my code. the answer of course is to have a '.cpp' file created with all the appropriate data and structs or class built in.

To do that Andreas has created a Template style exporting system. Now I do not have any real instructions (I perused but never found them), but I am always game for playing with stuff. So I tracked down one of the otehr exporters I felt created soemthing close to what I would want to use. In the case I decided upon the BatteryTech_SDK exporter. and it exports a texture atlas that looks like this...
btx = 1.0
texture.assetname = test_bt.png
texture.width  = 2048
texture.height = 2048

image.assetname = Kal_Run_side_0000.png
image.uvs = 0.4072265625 0.6875 0.5390625 0.6875 0.5390625 0.90625 0.4072265625 0.90625
image.rotated = false
image.trimmed = true
image.origsize = 512 512
image.offset = 120 61
image.trimmedsize = 270 448

image.assetname = Kal_Run_side_0002.png
image.uvs = 0.16015625 0.6982421875 0.3095703125 0.6982421875 0.3095703125 0.921875 0.16015625 0.921875
image.rotated = false
image.trimmed = true
image.origsize = 512 512
image.offset = 91 50
image.trimmedsize = 306 458

Not exactly sterling C plus plus eh? Well if ya look again at the second image above, you will see that I am exporting the data using my new and shiny 'C Plus Plus' exporter. and what I get looks like this...
char tp_version[] = "cpp = 1.0";
char textureName[] = "test_batterytech.png";
int  textureWidth  = 2048;
int  textureHeight = 2048;

struct  sSPRITE_INFO
{
 char name[32];
 int size[2];
 float rotation;
 float texturePoints[4];
};

static const sSPRITE_INFO *test_batterytech.png[] =
{
  Kal_Run_side_0000.png,
  Kal_Run_side_0002.png,
  Kal_Run_side_0004.png,
  Kal_Run_side_0006.png,
  Kal_Run_side_0008.png,
  Kal_Run_side_0010.png,
  Kal_Run_side_0012.png,
  Kal_Run_side_0014.png,
  Kal_Run_side_0016.png,
  Kal_Run_side_0018.png,

  Kal_Run_side_0020.png,
  Kal_Run_side_0022.png,
};


sSPRITE_INFO  Kal_Run_side_0000.png = {
  "Kal_Run_side_0000.png", // name
 { 0.4072265625, 0.6875, 0.5390625, 0.90625 }, // TexturePoints
 false, // rotation
 { 270, 448 }, // size
};

sSPRITE_INFO  Kal_Run_side_0002.png = {
  "Kal_Run_side_0002.png", // name
 { 0.16015625, 0.6982421875, 0.3095703125, 0.921875 }, // TexturePoints
 false, // rotation
 { 306, 458 }, // size
};

Not yet correct, but getting along very nicely. As I see it I have a couple of real issues left.
  1. get rid of those .png suffixes all over the place. I will try this tomorrow anyway with those manually removed.
  2. Rotation is true or false, and yet I really need a rotation value, Degrees/Radians or whatever.
  3. As this will be going into the Sprite drawing helper routine I use for rendering sprites. I do not have to have a '.hpp' file, I can simply include this one directly. Not the best coding practice, but pretty darned efficient.
So I am very excited to do this. Andreas is very responsible and responsive and I am sure these last items on my list will be resolved very soon.

With that, I am going to bed,
Gnight all,
Da Voodoochief

1 comment:

  1. Good for you but would you share the export code? :D

    ReplyDelete