@@ -29,8 +29,8 @@ The BorderedImageData concept:
29
29
30
30
// / @brief Holds maximum size restrictions of the texture atlas.
31
31
struct TextureAtlasLimits {
32
- GLsizei max_texture_size;
33
- GLsizei max_layer_count;
32
+ std:: size_t max_texture_size;
33
+ std:: size_t max_layer_count;
34
34
};
35
35
36
36
// / @brief Can store a large number of texture tiles in multiple layers of grids.
@@ -43,25 +43,25 @@ class TextureAtlasTiles {
43
43
44
44
// / @brief A function that is called with required size (width and height), layers and mipmap levels.
45
45
// / @remark Returns whether actual resizing occurred.
46
- using TextureResizeFunction = std::function<bool (GLsizei, GLsizei, GLsizei )>;
46
+ using TextureResizeFunction = std::function<bool (std:: size_t , std:: size_t , std:: size_t )>;
47
47
48
48
// / @brief A function that uploads the image to a specific position and mipmap level of a texture.
49
- using TextureModifyFunction = std::function<void (const BorderedImageData&, ivec3, GLint )>;
49
+ using TextureModifyFunction = std::function<void (const BorderedImageData&, dmath::svec3, std:: size_t )>;
50
50
51
51
class TileHandle ;
52
52
53
53
private:
54
54
// / @brief Atlas information which is stored in a unique_ptr, so that it can be shared with all TileData instances.
55
55
struct AtlasInfo {
56
- GLsizei atlas_size;
56
+ std:: size_t atlas_size;
57
57
};
58
58
59
59
// / @brief Information about the placement of a tile, including whether it has been written to the texture yet.
60
60
struct TilePlacement {
61
61
// / @brief The index of this tile in the layer.
62
62
std::size_t index = 0 ;
63
63
// / @brief The position where the write this tile in the array texture.
64
- svec3 position;
64
+ dmath:: svec3 position;
65
65
// / @brief Whether this tile has been written to the array texture yet.
66
66
bool written = false ;
67
67
@@ -70,19 +70,19 @@ class TextureAtlasTiles {
70
70
// / @param index The index of this tile in the layer.
71
71
// / @param layer The index of the layer itself, determining the z position.
72
72
// / @param position The x and y coordinates of the position.
73
- TilePlacement (std::size_t index, svec2 position, GLsizei layer)
73
+ TilePlacement (std::size_t index, dmath:: svec2 position, std:: size_t layer)
74
74
: index(index)
75
75
, position(position.x(), position.y(), layer)
76
76
{}
77
77
78
78
// / @brief The position on the given mipmap layer.
79
- auto pixelPos (GLsizei mipmap_layer = 0 ) const { return position.xy () >> mipmap_layer; }
79
+ auto pixelPos (std:: size_t mipmap_layer = 0 ) const { return position.xy () >> mipmap_layer; }
80
80
81
81
// / @brief The position and atlas layer on the given mipmap layer.
82
- auto pixelPosAndLayer (GLsizei mipmap_layer = 0 ) const
82
+ auto pixelPosAndLayer (std:: size_t mipmap_layer = 0 ) const
83
83
{
84
84
auto [x, y] = pixelPos (mipmap_layer);
85
- return svec3{ x, y, position.z ()} ;
85
+ return dmath:: svec3( x, y, position.z ()) ;
86
86
}
87
87
};
88
88
@@ -108,7 +108,7 @@ class TextureAtlasTiles {
108
108
class Layer {
109
109
public:
110
110
// / @brief Creates a new layer with the given tile size, specified as log2.
111
- explicit Layer (const svec2& tile_size_log2, std::size_t max_texture_size)
111
+ explicit Layer (const dmath:: svec2& tile_size_log2, std::size_t max_texture_size)
112
112
: tile_size_log2_(tile_size_log2)
113
113
, max_tiles_(calculateMaxTiles(max_texture_size))
114
114
{}
@@ -119,22 +119,25 @@ class TextureAtlasTiles {
119
119
Layer& operator =(Layer&&) = default ;
120
120
121
121
// / @brief Returns the log2 of the pixel size of a tile.
122
- svec2 tileSizeLog2 () const { return tile_size_log2_; }
122
+ dmath:: svec2 tileSizeLog2 () const { return tile_size_log2_; }
123
123
// / @brief Returns the pixel size of a single tile.
124
- svec2 tileSize () const { return {GLsizei{1 } << tile_size_log2_.x (), GLsizei{1 } << tile_size_log2_.y ()}; }
124
+ dmath::svec2 tileSize () const
125
+ {
126
+ return {std::size_t {1 } << tile_size_log2_.x (), std::size_t {1 } << tile_size_log2_.y ()};
127
+ }
125
128
126
129
// / @brief Calculates the required grid size (for the longer side) to fit all tiles.
127
- GLsizei requiredGridSizeLog2 () const
130
+ std:: size_t requiredGridSizeLog2 () const
128
131
{
129
132
if (tiles_.empty ())
130
133
return 0 ;
131
- auto diff_log2 = std::abs (tile_size_log2_.x () - tile_size_log2_.y ());
134
+ auto diff_log2 = dutils::absoluteDifference (tile_size_log2_.x (), tile_size_log2_.y ());
132
135
auto square_tiles = ((tiles_.size () - 1 ) >> diff_log2) + 1 ;
133
136
return (dutils::ilog2ceil (square_tiles) + 1 ) >> 1 ;
134
137
}
135
138
136
139
// / @brief Calculates the required texture size to fit all tiles.
137
- GLsizei requiredTextureSize () const { return tileSize ().maxValue () << requiredGridSizeLog2 (); }
140
+ std:: size_t requiredTextureSize () const { return tileSize ().maxValue () << requiredGridSizeLog2 (); }
138
141
139
142
// / @brief Whether the grid is empty.
140
143
bool empty () const { return tiles_.empty (); }
@@ -143,7 +146,7 @@ class TextureAtlasTiles {
143
146
bool full () const { return first_free_tile_ == max_tiles_; }
144
147
145
148
// / @brief Places a single tile in the grid, filling potential gaps that appeared after removing tiles.
146
- void addTile (TileData& tile, GLsizei layer)
149
+ void addTile (TileData& tile, std:: size_t layer)
147
150
{
148
151
assert (!full ());
149
152
tile.placement = TilePlacement (first_free_tile_, tileSize () * indexToPosition (first_free_tile_), layer);
@@ -199,8 +202,7 @@ class TextureAtlasTiles {
199
202
// / @brief Draws a single tile onto the texture.
200
203
void drawTile (TileData& tile, const TextureModifyFunction& modify) const
201
204
{
202
- for (GLint mipmap_level = 0 ; mipmap_level < static_cast <GLint>(tile.mipmap_levels .count ());
203
- mipmap_level++) {
205
+ for (std::size_t mipmap_level = 0 ; mipmap_level < tile.mipmap_levels .count (); mipmap_level++) {
204
206
const auto & bordered_image = tile.mipmap_levels [mipmap_level];
205
207
assert (bordered_image);
206
208
modify (bordered_image, tile.placement .pixelPosAndLayer (mipmap_level), mipmap_level);
@@ -211,38 +213,38 @@ class TextureAtlasTiles {
211
213
// / @brief Returns the maximum number of tiles, that can fit in a square texture of the given size.
212
214
std::size_t calculateMaxTiles (std::size_t max_texture_size) const
213
215
{
214
- assert (static_cast <std:: size_t >( tileSize ().maxValue () ) <= max_texture_size);
216
+ assert (tileSize ().maxValue () <= max_texture_size);
215
217
auto x_tiles = std::size_t {1 } << dutils::ilog2 (max_texture_size >> tile_size_log2_.x ());
216
218
auto y_tiles = std::size_t {1 } << dutils::ilog2 (max_texture_size >> tile_size_log2_.y ());
217
219
return x_tiles * y_tiles;
218
220
}
219
221
220
222
// / @brief Inverse pairing function, returning only even/odd bits as x/y.
221
- svec2 indexToPosition (std::size_t index)
223
+ dmath:: svec2 indexToPosition (std::size_t index)
222
224
{
223
- auto size_diff_log2 = std::abs (tile_size_log2_.x () - tile_size_log2_.y ());
225
+ auto size_diff_log2 = dutils::absoluteDifference (tile_size_log2_.x (), tile_size_log2_.y ());
224
226
auto flip = tile_size_log2_.x () < tile_size_log2_.y ();
225
- auto x = static_cast <GLsizei>( dutils::removeOddBits (index >> size_diff_log2) );
226
- auto y = static_cast <GLsizei>( dutils::removeOddBits (index >> (size_diff_log2 + 1 ) ));
227
+ auto x = dutils::removeOddBits (index >> size_diff_log2);
228
+ auto y = dutils::removeOddBits (index >> (size_diff_log2 + 1 ));
227
229
y <<= size_diff_log2;
228
230
y |= index & ~(~std::size_t {0 } << size_diff_log2);
229
- return flip ? svec2 (y, x) : svec2 (x, y);
231
+ return flip ? dmath:: svec2 (y, x) : dmath:: svec2 (x, y);
230
232
}
231
233
232
234
// / @brief Pairing function, interleaving x/y as odd/even bits of the resulting integer.
233
- std::size_t positionToIndex (svec2 position)
235
+ std::size_t positionToIndex (dmath:: svec2 position)
234
236
{
235
237
auto size_diff_log2 = std::abs (tile_size_log2_.x () - tile_size_log2_.y ());
236
238
auto flip = tile_size_log2_.x () < tile_size_log2_.y ();
237
239
position = flip ? position.yx () : position;
238
240
auto result = position.y () & ~(~std::size_t {0 } << size_diff_log2);
239
241
position.y () >>= size_diff_log2;
240
- result |= dutils::interleaveZeros (static_cast <std:: size_t >( position.x () )) << size_diff_log2;
241
- result |= dutils::interleaveZeros (static_cast <std:: size_t >( position.y () )) << (size_diff_log2 + 1 );
242
+ result |= dutils::interleaveZeros (position.x ()) << size_diff_log2;
243
+ result |= dutils::interleaveZeros (position.y ()) << (size_diff_log2 + 1 );
242
244
return result;
243
245
}
244
246
245
- svec2 tile_size_log2_;
247
+ dmath:: svec2 tile_size_log2_;
246
248
std::vector<TileData*> tiles_;
247
249
std::size_t first_free_tile_ = 0 ;
248
250
std::size_t max_tiles_;
@@ -271,30 +273,27 @@ class TextureAtlasTiles {
271
273
return !(lhs == rhs);
272
274
}
273
275
274
- auto atlasPixelSize (GLsizei mipmap_layer = 0 ) const
276
+ auto atlasPixelSize (std:: size_t mipmap_layer = 0 ) const
275
277
{
276
278
return dataOrThrow ().atlas_info ->atlas_size >> mipmap_layer;
277
279
}
278
280
279
- auto pixelPos (GLsizei mipmap_layer = 0 ) const { return dataOrThrow ().placement .pixelPos (mipmap_layer); }
281
+ auto pixelPos (std:: size_t mipmap_layer = 0 ) const { return dataOrThrow ().placement .pixelPos (mipmap_layer); }
280
282
281
- auto pixelSize (GLsizei mipmap_layer = 0 ) const
282
- {
283
- return dataOrThrow ().mipmap_levels [static_cast <std::size_t >(mipmap_layer)].size ();
284
- }
283
+ auto pixelSize (std::size_t mipmap_layer = 0 ) const { return dataOrThrow ().mipmap_levels [mipmap_layer].size (); }
285
284
286
- auto pixelPosAndLayer (GLsizei mipmap_layer = 0 ) const
285
+ auto pixelPosAndLayer (std:: size_t mipmap_layer = 0 ) const
287
286
{
288
287
return dataOrThrow ().placement .pixelPosAndLayer (mipmap_layer);
289
288
}
290
289
291
- auto pos () const { return static_cast <vec2>(pixelPos ()) / vec2 ( static_cast <GLfloat >(atlasPixelSize () )); }
292
- auto size () const { return static_cast <vec2>(pixelSize ()) / vec2 ( static_cast <GLfloat >(atlasPixelSize () )); }
290
+ auto pos () const { return static_cast <dmath:: vec2>(pixelPos ()) / static_cast <float >(atlasPixelSize ()); }
291
+ auto size () const { return static_cast <dmath:: vec2>(pixelSize ()) / static_cast <float >(atlasPixelSize ()); }
293
292
294
293
bounds2 bounds () const
295
294
{
296
- auto padding = dataOrThrow ().mipmap_levels . front () .padding ();
297
- auto inset = static_cast <vec2>(padding) / (2 .0f * atlasPixelSize ());
295
+ auto padding = dataOrThrow ().mipmap_levels [ 0 ] .padding ();
296
+ auto inset = static_cast <dmath:: vec2>(padding) / (2 .0f * atlasPixelSize ());
298
297
auto top_left = pos ();
299
298
auto bottom_right = top_left + size ();
300
299
return bounds2 (top_left, bottom_right).inset (inset);
@@ -323,12 +322,7 @@ class TextureAtlasTiles {
323
322
// / @exception std::invalid_argument if either maximum is less than zero.
324
323
TextureAtlasTiles (const TextureAtlasLimits& limits)
325
324
: limits_(limits)
326
- {
327
- if (limits.max_texture_size < 0 )
328
- throw std::invalid_argument (" Maximum texture size cannot be negative." );
329
- if (limits.max_layer_count < 0 )
330
- throw std::invalid_argument (" Maximum layer count cannot be negative." );
331
- }
325
+ {}
332
326
333
327
TextureAtlasTiles (const TextureAtlasTiles&) = delete ;
334
328
TextureAtlasTiles (TextureAtlasTiles&&) = default ;
@@ -402,18 +396,20 @@ class TextureAtlasTiles {
402
396
void ensureTextureSize (const TextureResizeFunction& resize)
403
397
{
404
398
auto required_size = maxLayerSize ();
405
- auto layers = static_cast <GLsizei>(layers_.size ());
406
- auto mipmap_levels = static_cast <GLsizei>(maxMipmapLevels (static_cast <std::size_t >(required_size)));
399
+ if (required_size == 0 )
400
+ return ;
401
+ auto layers = layers_.size ();
402
+ auto mipmap_levels = maxMipmapLevels (required_size);
407
403
if (!resize (required_size, layers, mipmap_levels))
408
404
return ;
409
405
for (const auto & tile : tiles_)
410
406
tile->placement .written = false ;
411
407
}
412
408
413
409
// / @brief Finds the maximum layer size.
414
- GLsizei maxLayerSize () const
410
+ std:: size_t maxLayerSize () const
415
411
{
416
- GLsizei result = 0 ;
412
+ std:: size_t result = 0 ;
417
413
for (auto & layer : layers_)
418
414
result = std::max (result, layer.requiredTextureSize ());
419
415
return result;
@@ -423,16 +419,14 @@ class TextureAtlasTiles {
423
419
424
420
// / @brief Returns a pointer to a (possibly newly created) layer for the given tile size and its index.
425
421
// / @remark The pointer can be null, in which case a new layer would have exceeded the maximum layer count.
426
- LayerResult layerForTile (const svec2& size)
422
+ LayerResult layerForTile (const dmath:: svec2& size)
427
423
{
428
- auto unsigned_width = static_cast <std::make_unsigned_t <GLsizei>>(size.x ());
429
- auto unsigned_height = static_cast <std::make_unsigned_t <GLsizei>>(size.y ());
430
- auto tile_size_log2 = svec2 (static_cast <GLsizei>(dutils::ilog2ceil (unsigned_width)),
431
- static_cast <GLsizei>(dutils::ilog2ceil (unsigned_height)));
424
+ auto tile_size_log2 = dmath::svec2 (static_cast <std::size_t >(dutils::ilog2ceil (size.x ())),
425
+ static_cast <std::size_t >(dutils::ilog2ceil (size.y ())));
432
426
auto layer_iter = std::find_if (begin (layers_), end (layers_), [&](const Layer& layer) {
433
427
return !layer.full () && layer.tileSizeLog2 () == tile_size_log2;
434
428
});
435
- auto layer_index = std::distance (begin (layers_), layer_iter);
429
+ auto layer_index = static_cast < std::size_t >( std:: distance (begin (layers_), layer_iter) );
436
430
if (layer_iter != end (layers_))
437
431
return {&*layer_iter, layer_index};
438
432
if (layer_index >= limits_.max_layer_count )
@@ -455,13 +449,13 @@ class TextureAtlasTiles {
455
449
throw std::invalid_argument (" Image is too big for texture atlas. (" + size.format () + " > " +
456
450
std::to_string (limits_.max_texture_size ) + " )" );
457
451
458
- auto [layer, index] = layerForTile (static_cast <svec2>( size) );
452
+ auto [layer, index] = layerForTile (size);
459
453
if (!layer)
460
454
throw std::length_error (" Too many texture atlas layers. (max " + std::to_string (limits_.max_layer_count ) +
461
455
" )" );
462
456
463
- const auto & tile = tiles_.emplace_back (std::make_shared<TileData>(std::move (bordered_image_data ), atlas_info_));
464
- layer->addTile (*tile, static_cast <GLsizei>( index) );
457
+ const auto & tile = tiles_.emplace_back (std::make_shared<TileData>(std::move (mipmap_levels ), atlas_info_));
458
+ layer->addTile (*tile, index);
465
459
atlas_info_->atlas_size = maxLayerSize ();
466
460
return tile;
467
461
}
0 commit comments