in UVAtlas/isochart/packingcharts.cpp [2504:2798]
HRESULT CIsochartMesh::PackingOneChart(
CIsochartMesh* pChart,
ATLASINFO& atlasInfo,
size_t dwIteration)
{
HRESULT hr = S_OK;
auto pPackingInfo = pChart->GetPackingInfoBuffer();
// 1. If current chart's area is zero, don't pack it, just put it at (0, 0).
if (IsInZeroRange2(pChart->m_fChart2DArea))
{
PackingZeroAreaChart(pChart);
return hr;
}
// 2. Rotate current chart and Calculate the borders of the chart in all directions
// This function rotate current chart in CHART_ROTATION_NUMBER direction, Calculate
// left, right, top and bottom borders of in each direction. Calculate bounding box
// of current chart in each direction.
FAILURE_RETURN(pChart->CalculateChartBordersOfAllDirection(atlasInfo));
// 3. Packing one chart
size_t dwMinRotationId = 0;
size_t dwDirMinRotationId[PACKING_DIRECTION_NUMBER];
float fAreaLost = 0;
float fMinAreaLost = 0;
float fDirMinAreaLost[PACKING_DIRECTION_NUMBER];
float fBetweenArea;
float fMinBetweenArea[PACKING_DIRECTION_NUMBER];
XMFLOAT2 dirOrg[PACKING_DIRECTION_NUMBER];
XMFLOAT2 newOrgin;
/*
//if ((dwIteration > 0 && dwIteration < 12) ||dwIteration > 12 )
if (dwIteration > 1 )
{
for (size_t i=0; i<pChart->m_dwVertNumber; i++)
{
pChart->m_pVerts[i].uv.x = pChart->m_pVerts[i].uv.y = 0;
}
return hr;
}
*/
// 3.1 If current chart is the first chart to be packed,
// initialize the UV-atlas by putting the first chart into it.
if (0 == dwIteration || atlasInfo.fPackedChartArea == 0)
{
// Find one direction with smallest area lost rate.
atlasInfo.fPackedChartArea = pChart->m_fChart2DArea;
fMinAreaLost = FLT_MAX;
for (size_t i = 0; i < CHART_ROTATION_NUMBER; i++)
{
fAreaLost =
1.0f - atlasInfo.fPackedChartArea /
(pPackingInfo->fUVWidth[i] * pPackingInfo->fUVHeight[i]);
if (fAreaLost < fMinAreaLost)
{
fMinAreaLost = fAreaLost;
dwMinRotationId = i;
}
}
// Rotate chart to the direction gotten by above step
pChart->RotateChartAroundCenter(dwMinRotationId, false);
// Initialize atlas after packing the first chart.
FAILURE_RETURN(
Initializeatlas(
atlasInfo,
*pPackingInfo,
dwMinRotationId));
}
// 3.2 Add charts into current atlas
else
{
ISOCHARTVERTEX* pVex;
atlasInfo.fPackedChartArea += pChart->m_fChart2DArea;
for (size_t i = 0; i < PACKING_DIRECTION_NUMBER; i++)
{
fDirMinAreaLost[i] = FLT_MAX;
fMinBetweenArea[i] = FLT_MAX;
dwDirMinRotationId[i] = INVALID_INDEX;
}
atlasInfo.fExpectedAtlasWidth =
(atlasInfo.fBoxTop - atlasInfo.fBoxBottom) * atlasInfo.fWidthHeightRatio;
// 3.1.1 Need to add chart in horizon direction to increase width of atlas
if (atlasInfo.fExpectedAtlasWidth
> atlasInfo.fBoxRight - atlasInfo.fBoxLeft)
{
for (size_t i = 0; i < CHART_ROTATION_NUMBER; i++)
{
ISOCHARTVERTEX* pOneBorderVertex = pPackingInfo->leftBorder[i][1];
if (INVALID_VERT_ID == pOneBorderVertex->dwIDInRootMesh)
{
for (size_t j = 0; j < 4; j++)
{
pPackingInfo->pStandardVirtualCorner[j] = pOneBorderVertex[j].uv;
}
}
else
{
pChart->RotateBordersAroundCenter(i);
pVex = pChart->GetVertexBuffer();
for (size_t j = 0; j < pChart->GetVertexNumber(); j++)
{
pPackingInfo->pStandardUV[j] = pVex->uv;
pVex++;
}
}
//Try packing from right
FAILURE_RETURN(
FindChartPosition(
FromRight,
atlasInfo,
pPackingInfo,
i,
newOrgin,
fBetweenArea,
fAreaLost));
UpdateAreaLostInfo(
FromRight,
dwDirMinRotationId,
i,
dirOrg,
newOrgin,
fDirMinAreaLost,
fAreaLost,
fMinBetweenArea,
fBetweenArea);
//Try packing from left
FAILURE_RETURN(
FindChartPosition(
FromLeft,
atlasInfo,
pPackingInfo,
i,
newOrgin,
fBetweenArea,
fAreaLost));
UpdateAreaLostInfo(
FromLeft,
dwDirMinRotationId,
i,
dirOrg,
newOrgin,
fDirMinAreaLost,
fAreaLost,
fMinBetweenArea,
fBetweenArea);
}
}
// 3.1.2 Need to add chart in vertical direction to increase height of atlas
else
{
for (size_t i = 0; i < CHART_ROTATION_NUMBER; i++)
{
ISOCHARTVERTEX* pOneBorderVertex = pPackingInfo->topBorder[i][1];
if (INVALID_VERT_ID == pOneBorderVertex->dwIDInRootMesh)
{
for (size_t j = 0; j < 4; j++)
{
pPackingInfo->pStandardVirtualCorner[j] = pOneBorderVertex[j].uv;
}
}
else
{
pChart->RotateBordersAroundCenter(i);
pVex = pChart->GetVertexBuffer();
for (size_t j = 0; j < pChart->GetVertexNumber(); j++)
{
pPackingInfo->pStandardUV[j] = pVex->uv;
pVex++;
}
}
//Try packing from top
FAILURE_RETURN(
FindChartPosition(
FromTop,
atlasInfo,
pPackingInfo,
i,
newOrgin,
fBetweenArea,
fAreaLost));
UpdateAreaLostInfo(
FromTop,
dwDirMinRotationId,
i,
dirOrg,
newOrgin,
fDirMinAreaLost,
fAreaLost,
fMinBetweenArea,
fBetweenArea);
//Try packing from bottom
FAILURE_RETURN(
FindChartPosition(
FromBottom,
atlasInfo,
pPackingInfo,
i,
newOrgin,
fBetweenArea,
fAreaLost));
UpdateAreaLostInfo(
FromBottom,
dwDirMinRotationId,
i,
dirOrg,
newOrgin,
fDirMinAreaLost,
fAreaLost,
fMinBetweenArea,
fBetweenArea);
}
}
// 3.2 Find the approach which causes less area lost
size_t dwPackDirection = FromRight;
for (size_t j = 1; j < PACKING_DIRECTION_NUMBER; j++)
{
if (fDirMinAreaLost[j] < fDirMinAreaLost[dwPackDirection])
{
dwPackDirection = j;
}
}
if (dwDirMinRotationId[dwPackDirection] == INVALID_INDEX)
{
DPF(0, "2d area %f", double(pChart->m_fChart2DArea));
DPF(0, "3d area %f", double(pChart->m_fChart3DArea));
DPF(0, "Face number %zu", pChart->m_dwFaceNumber);
DPF(0, "Vert number %zu", pChart->m_dwVertNumber);
for (size_t ii = 0; ii < pChart->m_dwVertNumber; ii++)
{
DPF(0, "(%f, %f)", double(pChart->m_pVerts[ii].uv.x), double(pChart->m_pVerts[ii].uv.y));
}
}
assert(dwDirMinRotationId[dwPackDirection] != INVALID_INDEX);
// 3.3 Use the method gotten by last step to pack current chart
pChart->RotateChartAroundCenter(dwDirMinRotationId[dwPackDirection], false);
newOrgin = dirOrg[dwPackDirection];
pVex = pChart->GetVertexBuffer();
for (size_t i = 0; i < pChart->GetVertexNumber(); i++)
{
pVex->uv.x += newOrgin.x;
pVex->uv.y += newOrgin.y;
pVex++;
}
ISOCHARTVERTEX* pOneBorderVertex
= pPackingInfo->leftBorder[dwDirMinRotationId[dwPackDirection]][1];
if (INVALID_VERT_ID == pOneBorderVertex->dwIDInRootMesh)
{
pVex = pChart->GetVertexBuffer();
AdjustCornerBorder(
pOneBorderVertex,
pVex,
pChart->GetVertexNumber());
}
// 3.4 Update current horizon lines.
FAILURE_RETURN(
UpdateAtlas(
atlasInfo,
*pPackingInfo,
newOrgin,
dwDirMinRotationId[dwPackDirection]));
}
return hr;
}