2020-08-26 15:38:01 +08:00
|
|
|
#pragma once
|
2022-10-02 04:29:51 +08:00
|
|
|
#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
|
|
|
|
{
|
2021-01-01 05:43:23 +08:00
|
|
|
// Texture Packer, which takes source images and combines
|
2021-03-23 07:53:27 +08:00
|
|
|
// 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:
|
2021-03-21 08:33:04 +08:00
|
|
|
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
|
2021-03-21 08:33:04 +08:00
|
|
|
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.
|
2020-10-25 06:21:36 +08:00
|
|
|
int page;
|
2021-03-21 17:08:28 +08:00
|
|
|
|
|
|
|
// Whether the entry is empty
|
2020-10-25 06:21:36 +08:00
|
|
|
bool empty;
|
2021-03-21 17:08:28 +08:00
|
|
|
|
|
|
|
// Packed frame rectangle.
|
|
|
|
// This won't be set until after the packer has run.
|
2021-12-13 12:41:23 +08:00
|
|
|
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.
|
2021-12-13 12:41:23 +08:00
|
|
|
Recti packed;
|
2020-10-25 06:21:36 +08:00
|
|
|
|
2021-12-13 12:41:23 +08:00
|
|
|
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.
|
2020-10-25 06:21:36 +08:00
|
|
|
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
|
2021-03-21 08:33:04 +08:00
|
|
|
void add(u64 id, int width, int height, const Color* pixels);
|
2021-03-21 17:08:28 +08:00
|
|
|
|
|
|
|
// add a new entry
|
2021-03-21 08:33:04 +08:00
|
|
|
void add(u64 id, const Image& bitmap);
|
2020-08-26 15:38:01 +08:00
|
|
|
|
2021-04-12 11:57:09 +08:00
|
|
|
// add a new entry
|
2021-12-13 12:41:23 +08:00
|
|
|
void add(u64 id, const Image& bitmap, const Recti& source);
|
2021-04-12 11:57:09 +08:00
|
|
|
|
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;
|
2021-12-13 12:41:23 +08:00
|
|
|
Recti rect;
|
2020-08-26 15:38:01 +08:00
|
|
|
Node* right;
|
|
|
|
Node* down;
|
|
|
|
|
|
|
|
Node();
|
2022-01-10 05:51:23 +08:00
|
|
|
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
|
2020-12-24 16:19:58 +08:00
|
|
|
bool m_dirty;
|
2021-03-21 17:08:28 +08:00
|
|
|
|
|
|
|
// buffer of all the image data we will be packing
|
2020-12-24 16:19:58 +08:00
|
|
|
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
|
2021-12-13 12:41:23 +08:00
|
|
|
void add_entry(u64 id, int w, int h, const Color* pixels, const Recti& source);
|
2020-08-26 15:38:01 +08:00
|
|
|
};
|
|
|
|
}
|