in UVAtlas/isochart/mergecharts.cpp [305:482]
HRESULT CIsochartMesh::MergeAdjacentChart(
ISOCHARTMESH_ARRAY& children,
uint32_t dwMainChartID,
size_t dwTotalFaceNumber,
bool* pbMergeFlag,
XMFLOAT3* pChartNormal,
bool& bMerged)
{
HRESULT hr = S_OK;
bMerged = false;
CIsochartMesh* pMainChart = children[dwMainChartID];
auto& adjacentChartList = pMainChart->m_adjacentChart;
size_t dwAdjacentChartNumber = adjacentChartList.size();
if (dwAdjacentChartNumber == 0)
{
return hr;
}
// 1. Sort adjacent sub-charts according to the average normal
// alwasy try to merge charts having approximate normals firstly
for (size_t i = 0; i < dwAdjacentChartNumber - 1; i++)
{
if (!children[adjacentChartList[i]])
{
continue;
}
for (size_t j = i + 1; j < dwAdjacentChartNumber; j++)
{
if (!children[adjacentChartList[j]])
{
continue;
}
float fTemp1, fTemp2;
fTemp1 = XMVectorGetX(XMVector3Dot(
XMLoadFloat3(pChartNormal + dwMainChartID), XMLoadFloat3(pChartNormal + adjacentChartList[i])));
fTemp2 = XMVectorGetX(XMVector3Dot(
XMLoadFloat3(pChartNormal + dwMainChartID), XMLoadFloat3(pChartNormal + adjacentChartList[j])));
if (fTemp1 < fTemp2)
{
uint32_t dwTemp = adjacentChartList[i];
adjacentChartList[i] = adjacentChartList[j];
adjacentChartList[j] = dwTemp;
}
}
}
// 2 . Try to merge current chart to its adjacent charts.
uint32_t dwAdditionalChartID = INVALID_INDEX;
CIsochartMesh* pMergedChart = nullptr;
CIsochartMesh* pAddjacentChart = nullptr;
size_t dwMaxFaceNumAfterMerging
= std::max<size_t>(size_t(float(dwTotalFaceNumber) * MAX_MERGE_RATIO),
size_t(MAX_MERGE_FACE_NUMBER));
for (size_t i = 0; i < dwAdjacentChartNumber; i++)
{
uint32_t dwAdjacentChartID = adjacentChartList[i];
// 2.1. Don't try merage this chart, if its has failed to merage other charts
if (!pbMergeFlag[dwAdjacentChartID])
{
continue;
}
pAddjacentChart = children[dwAdjacentChartID];
if (!pAddjacentChart)
{
continue;
}
if (0 == pAddjacentChart->GetChart3DArea())
{
continue;
}
// 2.2. Don't try to get a very large chart
size_t dwMergedFaceNumber = pMainChart->GetFaceNumber() + pAddjacentChart->GetFaceNumber();
if (dwMergedFaceNumber > dwMaxFaceNumAfterMerging)
{
continue;
}
// 2.3. try to merge.
FAILURE_RETURN(
TryMergeChart(children, pMainChart, pAddjacentChart, &pMergedChart));
if (!pMergedChart)
{
continue;
}
// 2.4 try to get right initial parameterization
bool bParameterSucceed = false;
if (FAILED(hr = pMergedChart->TryParameterize(bParameterSucceed)))
{
delete pMergedChart;
pMergedChart = nullptr;
return hr;
}
if (!bParameterSucceed)
{
delete pMergedChart;
pMergedChart = nullptr;
continue;
}
// 2.5 Check if the meraged chart also satisfied the stretch
bool bCanMerge = true;
if (FAILED(hr = CheckMergeResult(
children,
pMainChart,
pAddjacentChart,
pMergedChart,
bCanMerge)))
{
delete pMergedChart;
pMergedChart = nullptr;
continue;
}
if (bCanMerge)
{
dwAdditionalChartID = dwAdjacentChartID;
break;
}
else
{
delete pMergedChart;
pMergedChart = nullptr;
}
}
if (!pMergedChart)
{
pbMergeFlag[dwMainChartID] = false;
bMerged = false;
return S_OK;
}
// 3. Adjust the adjacence of merged charts and other charts
for (size_t i = 0; i < pMergedChart->m_adjacentChart.size(); i++)
{
pAddjacentChart = children[pMergedChart->m_adjacentChart[i]];
if (!pAddjacentChart)
{
continue;
}
removeItem(pAddjacentChart->m_adjacentChart, dwAdditionalChartID);
if (!addNoduplicateItem(pAddjacentChart->m_adjacentChart,
dwMainChartID))
{
delete pMergedChart;
return E_OUTOFMEMORY;
}
}
// Delete the two sub-charts that joined the merging.
if (children[dwAdditionalChartID]->m_bIsInitChart)
children[dwAdditionalChartID] = nullptr;
else
{
delete children[dwAdditionalChartID];
children[dwAdditionalChartID] = nullptr;
}
if (!pMainChart->m_bIsInitChart)
delete pMainChart;
// Assign merged chart to main chart, caculate the normal of the new chart.
children[dwMainChartID] = pMergedChart;
pMergedChart->CalculateAveragNormal(pChartNormal + dwMainChartID);
bMerged = true;
return hr;
}