blah/include/blah_packer.h

120 lines
2.6 KiB
C
Raw Normal View History

2020-08-26 15:38:01 +08:00
#pragma once
#include <blah_common.h>
#include <blah_image.h>
#include <blah_color.h>
#include <blah_spatial.h>
#include <blah_string.h>
#include <blah_vector.h>
#include <blah_stream.h>
#include <blah_filesystem.h>
2020-08-26 15:38:01 +08:00
namespace Blah
{
// Texture Packer, which takes source images and combines
// them into a single large texture. Useful for 2D sprite batching.
2020-08-26 15:38:01 +08:00
class Packer
{
public:
2021-03-21 17:08:28 +08:00
// Packer Entry, which stores information about the resulting packed texture
2020-08-26 15:38:01 +08:00
class Entry
{
friend class Packer;
private:
i64 memory_index;
2021-03-21 17:08:28 +08:00
2020-08-26 15:38:01 +08:00
public:
2021-03-21 17:08:28 +08:00
// entry ID
u64 id;
2021-03-21 17:08:28 +08:00
// Texture Page that it was packed into.
// This won't be set until after the packer has run.
int page;
2021-03-21 17:08:28 +08:00
// Whether the entry is empty
bool empty;
2021-03-21 17:08:28 +08:00
// Packed frame rectangle.
// This won't be set until after the packer has run.
Recti frame;
2021-03-21 17:08:28 +08:00
// Packed position and size.
// This won't be set until after the packer has run.
Recti packed;
Entry(u64 id, const Recti& frame)
2021-03-21 17:08:28 +08:00
: memory_index(0)
, id(id)
, page(0)
, empty(true)
, frame(frame)
, packed(0, 0, 0, 0) {}
2020-08-26 15:38:01 +08:00
};
2021-03-21 17:08:28 +08:00
// maximum width / height of the generated texture
2020-08-26 15:38:01 +08:00
int max_size;
2021-03-21 17:08:28 +08:00
// whether the generated texture must be a power of 2
2020-08-26 15:38:01 +08:00
bool power_of_two;
2021-03-21 17:08:28 +08:00
// spacing between each packed subtexture
2020-08-26 15:38:01 +08:00
int spacing;
2021-03-21 17:08:28 +08:00
// padding on each subtexture (extrudes their borders outwards)
2020-08-26 15:38:01 +08:00
int padding;
2021-03-21 17:08:28 +08:00
// generated textures. There can be more than one if the packer was
2022-11-19 22:29:18 +08:00
// unable to fit all the provided subtextures into the max_size.
Vector<Image> pages;
2020-08-26 15:38:01 +08:00
Packer();
Packer(int max_size, int spacing, bool power_of_two);
2021-03-21 17:08:28 +08:00
// add a new entry
void add(u64 id, int width, int height, const Color* pixels);
2021-03-21 17:08:28 +08:00
// add a new entry
void add(u64 id, const Image& bitmap);
2020-08-26 15:38:01 +08:00
// add a new entry
void add(u64 id, const Image& bitmap, const Recti& source);
2021-03-21 17:08:28 +08:00
// add a new entry
void add(u64 id, const FilePath& path);
// returns a vector of all the resulting entries
const Vector<Entry>& entries() const;
// perform the packing
2020-08-26 15:38:01 +08:00
void pack();
2021-03-21 17:08:28 +08:00
// clear the current packer data
2020-08-26 15:38:01 +08:00
void clear();
2021-03-21 17:08:28 +08:00
2020-08-26 15:38:01 +08:00
private:
struct Node
{
bool used;
Recti rect;
2020-08-26 15:38:01 +08:00
Node* right;
Node* down;
Node();
Node* find(int w, int h);
Node* reset(const Recti& rect);
2020-08-26 15:38:01 +08:00
};
2021-03-21 17:08:28 +08:00
// whether the packer has any changes that require it to run again
bool m_dirty;
2021-03-21 17:08:28 +08:00
// buffer of all the image data we will be packing
BufferStream m_buffer;
2020-08-26 15:38:01 +08:00
2021-03-21 17:08:28 +08:00
// Entries to pack & their resulting data
Vector<Entry> m_entries;
// adds a new entry
void add_entry(u64 id, int w, int h, const Color* pixels, const Recti& source);
2020-08-26 15:38:01 +08:00
};
}