Skip to content

Commit

Permalink
Implement chart pack algorithm
Browse files Browse the repository at this point in the history
Chart pack algorithm: We guess a initial texture size based on the sum of chart areas, and try different methods then pick a best one, if pack failed because of texture size, we grow the size until it fit.
  • Loading branch information
huxingyi committed Oct 15, 2018
1 parent 13d6693 commit 8b720c6
Show file tree
Hide file tree
Showing 8 changed files with 1,134 additions and 18 deletions.
11 changes: 9 additions & 2 deletions simpleuv.pro
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,24 @@ CONFIG += release
DEFINES += NDEBUG

INCLUDEPATH += ./
INCLUDEPATH += ./thirdparty/libigl/include
INCLUDEPATH += ./thirdparty/eigen
INCLUDEPATH += thirdparty/libigl/include
INCLUDEPATH += thirdparty/eigen
INCLUDEPATH += thirdparty/squeezer

SOURCES += simpleuv/parametrize.cpp
HEADERS += simpleuv/parametrize.h

SOURCES += simpleuv/uvunwrapper.cpp
HEADERS += simpleuv/uvunwrapper.h

SOURCES += simpleuv/chartpacker.cpp
HEADERS += simpleuv/chartpacker.h

HEADERS += simpleuv/meshdatatype.h

SOURCES += thirdparty/squeezer/maxrects.c
HEADERS += thirdparty/squeezer/maxrects.h

QMAKE_CXXFLAGS += -std=c++11

target.path = ./
Expand Down
82 changes: 82 additions & 0 deletions simpleuv/chartpacker.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#include <simpleuv/chartpacker.h>
#include <cmath>
extern "C" {
#include <maxrects.h>
}

namespace simpleuv
{

void ChartPacker::setCharts(const std::vector<std::pair<float, float>> &chartSizes)
{
m_chartSizes = chartSizes;
}

const std::vector<std::tuple<float, float, float, float, bool>> &ChartPacker::getResult()
{
return m_result;
}

double ChartPacker::calculateTotalArea()
{
double totalArea = 0;
for (const auto &chartSize: m_chartSizes) {
totalArea += chartSize.first * chartSize.second;
}
return totalArea;
}

bool ChartPacker::tryPack(float textureSize)
{
std::vector<maxRectsSize> rects;
int width = textureSize * m_floatToIntFactor;
int height = width;
for (const auto &chartSize: m_chartSizes) {
maxRectsSize r;
r.width = chartSize.first * m_floatToIntFactor;
r.height = chartSize.second * m_floatToIntFactor;
rects.push_back(r);
}
const maxRectsFreeRectChoiceHeuristic methods[] = {
rectBestShortSideFit,
rectBestLongSideFit,
rectBestAreaFit,
rectBottomLeftRule,
rectContactPointRule
};
float occupancy = 0;
float bestOccupancy = 0;
std::vector<maxRectsPosition> bestResult;
for (size_t i = 0; i < sizeof(methods) / sizeof(methods[0]); ++i) {
std::vector<maxRectsPosition> result(rects.size());
if (!maxRects(width, height, rects.size(), rects.data(), methods[i], true, result.data(), &occupancy)) {
continue;
}
if (occupancy >= bestOccupancy) {
bestResult = result;
bestOccupancy = occupancy;
}
}
if (bestResult.size() != rects.size())
return false;
m_result.resize(bestResult.size());
for (decltype(bestResult.size()) i = 0; i < bestResult.size(); ++i) {
const auto &result = bestResult[i];
const auto &rect = rects[i];
m_result[i] = {result.left / textureSize, result.top / textureSize, rect.width / textureSize, rect.height / textureSize, result.rotated};
}
return true;
}

void ChartPacker::pack()
{
float initialGuessSize = std::sqrt(calculateTotalArea() * m_initialAreaGuessFactor);
float textureSize = initialGuessSize;
while (true) {
if (tryPack(textureSize))
break;
textureSize *= 1.0 + m_textureSizeGrowFactor;
}
}

}
29 changes: 29 additions & 0 deletions simpleuv/chartpacker.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#ifndef SIMPLEUV_CHART_PACKER_H
#define SIMPLEUV_CHART_PACKER_H
#include <vector>

namespace simpleuv
{

class ChartPacker
{
public:
void setCharts(const std::vector<std::pair<float, float>> &chartSizes);
const std::vector<std::tuple<float, float, float, float, bool>> &getResult();
void pack();
bool tryPack(float textureSize);

private:
double calculateTotalArea();

std::vector<std::pair<float, float>> m_chartSizes;
std::vector<std::tuple<float, float, float, float, bool>> m_result;
float m_initialAreaGuessFactor = 1.0;
float m_textureSizeGrowFactor = 0.1;
float m_floatToIntFactor = 100;
};

}

#endif

2 changes: 1 addition & 1 deletion simpleuv/meshdatatype.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ struct Vertex

struct Face
{
int indicies[3];
size_t indicies[3];
};

struct TextureCoord
Expand Down
Loading

0 comments on commit 8b720c6

Please sign in to comment.