Allegro.cc - Online Community

Allegro.cc Forums » The Depot » Atlas texture atlas library for Allegro 5

This thread is locked; no one can reply to it. rss feed Print
Atlas texture atlas library for Allegro 5
Trent Gamblin
Member #261
April 2000
avatar

I wrote this texture atlas creating library for a level editor I'm making and I think it's generally useful so Here's a link to it:

http://www.nooskewl.com/stuff/downloads/atlas-1.0.zip

There's an example that comes with it that shows how to use it (it's pretty simple). Basically you just create an atlas, feed it whatever images you have, then finish the atlas and it'll put everything into sheets (the size of which you tell it). It's not nearly an optimal algorithm spacing saving wise, but it does ok. I gave it a few hundred images and it made about 5 sheets without much wasted space.

Matthew Leverton
Supreme Loser
January 1999
avatar

Can you paste a code example? (Too lazy to look at the the zip.)

I was going to build something like this for my GUI.

Trent Gamblin
Member #261
April 2000
avatar

Here's ex_atlas:

#SelectExpand
1 2#include <allegro5/allegro.h> 3#include <allegro5/allegro_image.h> 4#include "atlas.h" 5#include "atlas_internal.h" 6#include <stdio.h> 7 8int main(int argc, char **argv) 9{ 10 int i; 11 12 al_init(); 13 al_init_image_addon(); 14 al_install_keyboard(); 15 16 ALLEGRO_DISPLAY *display = al_create_display(512, 512); 17 ALLEGRO_EVENT_QUEUE *queue = al_create_event_queue(); 18 al_register_event_source(queue, al_get_keyboard_event_source()); 19 20 ATLAS *atlas = atlas_create(512, 512, 2, true); 21 22 for (i = 1; i < argc; i++) { 23 ALLEGRO_BITMAP *b = al_load_bitmap(argv[i]); 24 if (b) { 25 atlas_add(atlas, b, i-1); 26 } 27 } 28 29 atlas_finish(atlas); 30 31 bool done = false; 32 int sheet = 0; 33 34 while (!done) { 35 al_set_target_backbuffer(display); 36 al_clear_to_color(al_map_rgb(0, 0, 0)); 37 al_draw_bitmap(atlas_get_sheet(atlas, sheet), 0, 0, 0); 38 al_flip_display(); 39 ALLEGRO_EVENT event; 40 al_wait_for_event(queue, &event); 41 if (event.type == ALLEGRO_EVENT_KEY_DOWN) { 42 if (event.keyboard.keycode == ALLEGRO_KEY_ESCAPE) 43 done = true; 44 else if (event.keyboard.keycode == ALLEGRO_KEY_LEFT) { 45 if (sheet > 0) sheet--; 46 } 47 else if (event.keyboard.keycode == ALLEGRO_KEY_RIGHT) { 48 if (sheet < atlas_get_num_sheets(atlas)-1) sheet++; 49 } 50 } 51 } 52 53 return 0; 54}

Lines 20 to 29 are the business stuff. 512, 512 is the size of the sheets you want and 2 is the border.

Matthew Leverton
Supreme Loser
January 1999
avatar

Posting the API:

#SelectExpand
1#ifndef TEXATLAS_H 2#define TEXATLAS_H 3 4#ifdef __cplusplus 5extern "C" { 6#endif 7 8typedef struct ATLAS ATLAS; 9typedef struct ATLAS_ITEM ATLAS_ITEM; 10 11/* Main api */ 12ATLAS *atlas_create(int width, int height, int border, bool destroy_bmps); 13bool atlas_add(ATLAS *atlas, ALLEGRO_BITMAP *bitmap, int id); 14int atlas_finish(ATLAS *atlas); 15void atlas_destroy(ATLAS *atlas); 16 17/* Structure accessors */ 18 /* ATLAS */ 19int atlas_get_width(ATLAS *atlas); 20int atlas_get_height(ATLAS *atlas); 21int atlas_get_border(ATLAS *atlas); 22int atlas_get_destroy_bmps(ATLAS *atlas); 23int atlas_get_num_items(ATLAS *atlas); 24ATLAS_ITEM *atlas_get_item_by_id(ATLAS *atlas, int id); 25ATLAS_ITEM *atlas_get_item_by_index(ATLAS *atlas, int index); 26int atlas_get_num_sheets(ATLAS *atlas); 27ALLEGRO_BITMAP *atlas_get_sheet(ATLAS *atlas, int index); 28 /* ATLAS_ITEM */ 29ALLEGRO_BITMAP *atlas_get_item_sub_bitmap(ATLAS_ITEM *item); 30int atlas_get_item_sheet(ATLAS_ITEM *item); 31int atlas_get_item_x(ATLAS_ITEM *item); 32int atlas_get_item_y(ATLAS_ITEM *item); 33int atlas_get_item_id(ATLAS_ITEM *item); 34 35#ifdef __cplusplus 36} 37#endif 38 39#endif

I would kind of like:

bitmap = atlas_add_and_return_sub_bitmap(atlas, bitmap, id);

That is, I add the bitmap and it takes ownership of it (including destroying the original bitmap), and returns a pointer to the bitmap. I no longer have any control over it, although I could remove it later by id. At least that was how I was thinking about doing it.

It might not fit with your design... (Do you destroy the bitmap?) And perhaps it is a bad idea; I didn't think about it much.

Edit: I suppose since you have atlas_finish it wouldn't really be possible at that time.

Trent Gamblin
Member #261
April 2000
avatar

Ya, it's not possible to return sub bitmaps at that point.

About destroying bitmaps, the final parameter of atlas_create tells the lib whether or not to destroy bitmaps when calling atlas_destroy.

Edit:
The reason for finish is the algorithm performs much better space wise if the bitmaps are sorted by size.

Matthew Leverton
Supreme Loser
January 1999
avatar

The reason for finish is the algorithm performs much better space wise if the bitmaps are sorted by size.

Yeah, in my use case, it would be dynamic. There would be no use for a finish because I'd be adding and removing.

Perhaps a better (or simply different) set up would be to have an optimize method (instead of finish) that you could call at any time. Obviously it would invalidate the previously returned pointers, but at least it would allow for both usage types.

Trent Gamblin
Member #261
April 2000
avatar

Yeah, it really depends on how you're going to use it. For me it's simply to display tiles for the level editor (they can be any size) in a big grid instead of in rows or something like that. I'm not going to make it dynamic but patches for that would certainly be considered (though it's pretty simple, you could probably make your own without much trouble).

Elias
Member #358
May 2000

Now we would need a function in Allegro to move a sub-bitmap. Then you actually could return it, just later change its parent and position.

--
"Either help out or stop whining" - Evert

Thomas Fjellstrom
Member #476
June 2000
avatar

Regardless of the ATLAS stuff, being able to move a sub bitmap is probably useful.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Pho75_
Member #12,377
November 2010

Good stuff:
Here is a link to recursive bin-packing C++ source.
This might be more space-efficient.
The author released it as public domain.
It ports very easily to C.

http://clb.demon.fi/projects/rectangle-bin-packing

Cheers.

Go to: