Browse Source

TextureTools: use a Pair instead of Vector3i in the internals.

The z() element was input offset and not a layer. Rather confusing in an
atlas algorithm that operates with texture arrays-
pull/168/head
Vladimír Vondruš 3 years ago
parent
commit
752acbdc3e
  1. 19
      src/Magnum/TextureTools/Atlas.cpp

19
src/Magnum/TextureTools/Atlas.cpp

@ -77,14 +77,13 @@ Containers::Pair<Int, Containers::Array<Vector3i>> atlasArrayPowerOfTwo(const Ve
/* Copy the input to a sorted array, together with a mapping to the
original order stored in Z. Can't really reuse the output allocation
as it would be overwritten in random order. */
Containers::Array<Vector3i> sortedSizes{NoInit, sizes.size()};
Containers::Array<Containers::Pair<Vector2i, UnsignedInt>> sortedSizes{NoInit, sizes.size()};
for(std::size_t i = 0; i != sizes.size(); ++i) {
const Vector2i size = sizes[i];
CORRADE_ASSERT(size.product() && size.x() == size.y() && (size & (size - Vector2i{1})).isZero() && size <= layerSize,
"TextureTools::atlasArrayPowerOfTwo(): expected size" << i << "to be a non-zero power-of-two square not larger than" << Debug::packed << layerSize << "but got" << Debug::packed << size, {});
sortedSizes[i].xy() = size;
sortedSizes[i].z() = i;
sortedSizes[i] = {size, UnsignedInt(i)};
}
/* Sort to have the biggest size first. Assuming the items are square,
@ -93,15 +92,15 @@ Containers::Pair<Int, Containers::Array<Vector3i>> atlasArrayPowerOfTwo(const Ve
consistent across platforms. */
/** @todo stable_sort allocates, would be great if i could make it reuse
the memory allocated for output */
std::stable_sort(sortedSizes.begin(), sortedSizes.end(), [](const Vector3i& a, const Vector3i& b) {
return a.x() > b.x();
std::stable_sort(sortedSizes.begin(), sortedSizes.end(), [](const Containers::Pair<Vector2i, UnsignedInt>& a, const Containers::Pair<Vector2i, UnsignedInt>& b) {
return a.first().x() > b.first().x();
});
/* Start with the whole first layer free */
Int layer = 0;
UnsignedInt free = 1;
Vector2i previousSize = layerSize;
for(const Vector3i& size: sortedSizes) {
for(const Containers::Pair<Vector2i, UnsignedInt>& size: sortedSizes) {
/* No free slots left, go to the next layer. Then, what's free, is one
whole layer. */
if(!free) {
@ -114,11 +113,11 @@ Containers::Pair<Int, Containers::Array<Vector3i>> atlasArrayPowerOfTwo(const Ve
size. If the size is the same, nothing changes. */
/** @todo there's definitely some bit trick for dividing power-of-two
numbers, use it */
free *= (previousSize/size.xy()).product();
free *= (previousSize/size.first()).product();
/* Slot index as if the whole layer was consisting just of slots of
this size. */
const UnsignedInt sideSlotCount = layerSize.x()/size.x();
const UnsignedInt sideSlotCount = layerSize.x()/size.first().x();
const UnsignedInt layerDepth = Math::log2(sideSlotCount);
const UnsignedInt slotIndex = sideSlotCount*sideSlotCount - free;
@ -132,8 +131,8 @@ Containers::Pair<Int, Containers::Array<Vector3i>> atlasArrayPowerOfTwo(const Ve
}
/* Save to the output in the original order */
output[size.z()] = {coordinates, layer};
previousSize = size.xy();
output[size.second()] = {coordinates, layer};
previousSize = size.first();
--free;
}

Loading…
Cancel
Save