Repo created
This commit is contained in:
parent
4af19165ec
commit
68073add76
12458 changed files with 12350765 additions and 2 deletions
182
libs/geometry/packer.cpp
Normal file
182
libs/geometry/packer.cpp
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
#include "geometry/packer.hpp"
|
||||
|
||||
#include "base/assert.hpp"
|
||||
#include "base/logging.hpp"
|
||||
|
||||
namespace m2
|
||||
{
|
||||
Packer::Packer()
|
||||
: m_currentX(0)
|
||||
, m_currentY(0)
|
||||
, m_yStep(0)
|
||||
, m_width(0)
|
||||
, m_height(0)
|
||||
, m_currentHandle(0)
|
||||
, m_maxHandle(0)
|
||||
, m_invalidHandle(0x00FFFFFF)
|
||||
{}
|
||||
|
||||
Packer::Packer(unsigned width, unsigned height, uint32_t maxHandle)
|
||||
: m_currentX(0)
|
||||
, m_currentY(0)
|
||||
, m_yStep(0)
|
||||
, m_width(width)
|
||||
, m_height(height)
|
||||
, m_currentHandle(0)
|
||||
, m_maxHandle(maxHandle)
|
||||
, m_invalidHandle(0x00FFFFFF)
|
||||
{}
|
||||
|
||||
uint32_t Packer::invalidHandle() const
|
||||
{
|
||||
return m_invalidHandle;
|
||||
}
|
||||
|
||||
Packer::handle_t Packer::pack(unsigned width, unsigned height)
|
||||
{
|
||||
ASSERT(width <= m_width, ());
|
||||
ASSERT(height <= m_height, ());
|
||||
|
||||
if ((width > m_width) || (height > m_height))
|
||||
return m_invalidHandle;
|
||||
|
||||
/// checking whether there is enough space on X axis
|
||||
|
||||
if (m_currentX + width > m_width)
|
||||
{
|
||||
m_currentY += m_yStep;
|
||||
m_currentX = 0;
|
||||
m_yStep = 0;
|
||||
}
|
||||
|
||||
/// checking whether there is enough space on Y axis
|
||||
if (m_currentY + height > m_height)
|
||||
{
|
||||
/// texture overflow detected. all packed rects should be forgotten.
|
||||
callOverflowFns();
|
||||
reset();
|
||||
}
|
||||
/// check handleOverflow
|
||||
if (m_currentHandle == m_maxHandle)
|
||||
{
|
||||
/// handles overflow detected. all packed rects should be forgotten.
|
||||
callOverflowFns();
|
||||
reset();
|
||||
m_currentHandle = 0;
|
||||
}
|
||||
|
||||
/// can pack
|
||||
m_yStep = std::max(height, m_yStep);
|
||||
handle_t curHandle = m_currentHandle++;
|
||||
m_rects[curHandle] = m2::RectU(m_currentX, m_currentY, m_currentX + width, m_currentY + height);
|
||||
m_currentX += width;
|
||||
|
||||
return curHandle;
|
||||
}
|
||||
|
||||
Packer::handle_t Packer::freeHandle()
|
||||
{
|
||||
if (m_currentHandle == m_maxHandle)
|
||||
{
|
||||
callOverflowFns();
|
||||
reset();
|
||||
m_currentHandle = 0;
|
||||
}
|
||||
|
||||
return m_currentHandle++;
|
||||
}
|
||||
|
||||
bool Packer::hasRoom(unsigned width, unsigned height) const
|
||||
{
|
||||
return ((m_width >= width) && (m_height - m_currentY - m_yStep >= height)) ||
|
||||
((m_width - m_currentX >= width) && (m_height - m_currentY >= height));
|
||||
}
|
||||
|
||||
bool Packer::hasRoom(m2::PointU const * sizes, size_t cnt) const
|
||||
{
|
||||
unsigned currentX = m_currentX;
|
||||
unsigned currentY = m_currentY;
|
||||
unsigned yStep = m_yStep;
|
||||
|
||||
for (unsigned i = 0; i < cnt; ++i)
|
||||
{
|
||||
unsigned width = sizes[i].x;
|
||||
unsigned height = sizes[i].y;
|
||||
|
||||
if (width <= m_width - currentX)
|
||||
{
|
||||
if (height <= m_height - currentY)
|
||||
{
|
||||
yStep = std::max(height, yStep);
|
||||
currentX += width;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentX = 0;
|
||||
currentY += yStep;
|
||||
yStep = 0;
|
||||
|
||||
if (width <= m_width - currentX)
|
||||
{
|
||||
if (height <= m_height - currentY)
|
||||
{
|
||||
yStep = std::max(height, yStep);
|
||||
currentX += width;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Packer::isPacked(handle_t handle)
|
||||
{
|
||||
return m_rects.find(handle) != m_rects.end();
|
||||
}
|
||||
|
||||
Packer::find_result_t Packer::find(handle_t handle) const
|
||||
{
|
||||
rects_t::const_iterator it = m_rects.find(handle);
|
||||
std::pair<bool, m2::RectU> res;
|
||||
res.first = (it != m_rects.end());
|
||||
if (res.first)
|
||||
res.second = it->second;
|
||||
return res;
|
||||
}
|
||||
|
||||
void Packer::remove(handle_t handle)
|
||||
{
|
||||
m_rects.erase(handle);
|
||||
}
|
||||
|
||||
void Packer::reset()
|
||||
{
|
||||
m_rects.clear();
|
||||
m_currentX = 0;
|
||||
m_currentY = 0;
|
||||
m_yStep = 0;
|
||||
m_currentHandle = 0;
|
||||
}
|
||||
|
||||
void Packer::addOverflowFn(overflowFn fn, int priority)
|
||||
{
|
||||
m_overflowFns.push(std::pair<size_t, overflowFn>(priority, fn));
|
||||
}
|
||||
|
||||
void Packer::callOverflowFns()
|
||||
{
|
||||
LOG(LDEBUG, ("Texture|Handles Overflow"));
|
||||
overflowFns handlersCopy = m_overflowFns;
|
||||
while (!handlersCopy.empty())
|
||||
{
|
||||
handlersCopy.top().second();
|
||||
handlersCopy.pop();
|
||||
}
|
||||
}
|
||||
} // namespace m2
|
||||
Loading…
Add table
Add a link
Reference in a new issue