yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
texture_atlas.cc
Go to the documentation of this file.
1#include "texture_atlas.h"
2
3#include "util/log.h"
4
5namespace yaze {
6namespace gfx {
7
8TextureAtlas::TextureAtlas(int width, int height)
9 : width_(width), height_(height) {
10 // Create atlas bitmap with initial empty data
11 std::vector<uint8_t> empty_data(width * height, 0);
12 atlas_bitmap_ = Bitmap(width, height, 8, empty_data);
13 LOG_DEBUG("[TextureAtlas]", "Created %dx%d atlas", width, height);
14}
15
16TextureAtlas::AtlasRegion* TextureAtlas::AllocateRegion(int source_id, int width, int height) {
17 // Simple linear packing algorithm
18 // TODO: Implement more efficient rect packing (shelf, guillotine, etc.)
19
20 int pack_x, pack_y;
21 if (!TryPackRect(width, height, pack_x, pack_y)) {
22 LOG_DEBUG("[TextureAtlas]", "Failed to allocate %dx%d region for source %d (atlas full)",
23 width, height, source_id);
24 return nullptr;
25 }
26
27 AtlasRegion region;
28 region.x = pack_x;
29 region.y = pack_y;
30 region.width = width;
31 region.height = height;
32 region.source_id = source_id;
33 region.in_use = true;
34
35 regions_[source_id] = region;
36
37 LOG_DEBUG("[TextureAtlas]", "Allocated region (%d,%d,%dx%d) for source %d",
38 pack_x, pack_y, width, height, source_id);
39
40 return &regions_[source_id];
41}
42
43absl::Status TextureAtlas::PackBitmap(const Bitmap& src, const AtlasRegion& region) {
44 if (!region.in_use) {
45 return absl::FailedPreconditionError("Region not allocated");
46 }
47
48 if (!src.is_active() || src.width() == 0 || src.height() == 0) {
49 return absl::InvalidArgumentError("Source bitmap not active");
50 }
51
52 if (region.width < src.width() || region.height < src.height()) {
53 return absl::InvalidArgumentError("Region too small for bitmap");
54 }
55
56 // TODO: Implement pixel copying from src to atlas_bitmap_ at region coordinates
57 // For now, just return OK (stub implementation)
58
59 LOG_DEBUG("[TextureAtlas]", "Packed %dx%d bitmap into region at (%d,%d) for source %d",
60 src.width(), src.height(), region.x, region.y, region.source_id);
61
62 return absl::OkStatus();
63}
64
65absl::Status TextureAtlas::DrawRegion(int source_id, int /*dest_x*/, int /*dest_y*/) {
66 auto it = regions_.find(source_id);
67 if (it == regions_.end() || !it->second.in_use) {
68 return absl::NotFoundError("Region not found or not in use");
69 }
70
71 // TODO: Integrate with renderer to draw atlas region at (dest_x, dest_y)
72 // For now, just return OK (stub implementation)
73
74 return absl::OkStatus();
75}
76
77void TextureAtlas::FreeRegion(int source_id) {
78 auto it = regions_.find(source_id);
79 if (it != regions_.end()) {
80 it->second.in_use = false;
81 LOG_DEBUG("[TextureAtlas]", "Freed region for source %d", source_id);
82 }
83}
84
86 regions_.clear();
87 next_x_ = 0;
88 next_y_ = 0;
89 row_height_ = 0;
90 LOG_DEBUG("[TextureAtlas]", "Cleared all regions");
91}
92
94 auto it = regions_.find(source_id);
95 if (it != regions_.end() && it->second.in_use) {
96 return &it->second;
97 }
98 return nullptr;
99}
100
102 AtlasStats stats;
103 stats.total_pixels = width_ * height_;
104 stats.total_regions = regions_.size();
105
106 for (const auto& [id, region] : regions_) {
107 if (region.in_use) {
108 stats.used_regions++;
109 stats.used_pixels += region.width * region.height;
110 }
111 }
112
113 if (stats.total_pixels > 0) {
114 stats.utilization = static_cast<float>(stats.used_pixels) / stats.total_pixels * 100.0f;
115 }
116
117 return stats;
118}
119
120bool TextureAtlas::TryPackRect(int width, int height, int& out_x, int& out_y) {
121 // Simple shelf packing algorithm
122 // Try to pack in current row
123 if (next_x_ + width <= width_) {
124 // Fits in current row
125 out_x = next_x_;
126 out_y = next_y_;
127 next_x_ += width;
128 row_height_ = std::max(row_height_, height);
129 return true;
130 }
131
132 // Move to next row
133 next_x_ = 0;
135 row_height_ = 0;
136
137 // Check if fits in new row
138 if (next_y_ + height <= height_ && width <= width_) {
139 out_x = next_x_;
140 out_y = next_y_;
141 next_x_ += width;
143 return true;
144 }
145
146 // Atlas is full
147 return false;
148}
149
150} // namespace gfx
151} // namespace yaze
152
Represents a bitmap image optimized for SNES ROM hacking.
Definition bitmap.h:66
bool is_active() const
Definition bitmap.h:264
int height() const
Definition bitmap.h:254
int width() const
Definition bitmap.h:253
AtlasStats GetStats() const
const AtlasRegion * GetRegion(int source_id) const
Get region for a specific source.
absl::Status PackBitmap(const Bitmap &src, const AtlasRegion &region)
Pack a bitmap into an allocated region.
void FreeRegion(int source_id)
Free a region and mark it as available.
int width() const
Get atlas dimensions.
TextureAtlas(int width=2048, int height=2048)
Construct texture atlas with specified dimensions.
void Clear()
Clear all regions and reset atlas.
absl::Status DrawRegion(int source_id, int dest_x, int dest_y)
Draw a region from the atlas to screen coordinates.
AtlasRegion * AllocateRegion(int source_id, int width, int height)
Allocate a region in the atlas for a source texture.
bool TryPackRect(int width, int height, int &out_x, int &out_y)
std::map< int, AtlasRegion > regions_
#define LOG_DEBUG(category, format,...)
Definition log.h:104
Main namespace for the application.
Region within the atlas texture.
Get atlas utilization statistics.