in UVAtlas/isochart/UVAtlasRepacker.cpp [825:997]
HRESULT CUVAtlasRepacker::GenerateNewBuffers()
{
// create an attribute buffer
m_vAttributeBuffer.resize(m_iNumFaces);
auto pAB = m_vAttributeBuffer.data();
for (size_t i = 0; i < m_iNumFaces; i++)
pAB[i] = uint32_t(-1);
try
{
m_NewAdjacentInfo.resize(m_iNumFaces * 3);
m_VertexBuffer.reserve(m_iNumVertices);
m_IndexBuffer.reserve(m_iNumFaces * 3);
m_IndexPartition.resize(m_iNumVertices);
for (size_t i = 0; i < m_iNumVertices; i++)
m_IndexPartition[i] = uint32_t(-1);
auto pVB = reinterpret_cast<const uint8_t*>(m_pvVertexBuffer->data());
auto pIB = reinterpret_cast<const uint8_t*>(m_pvIndexBuffer->data());
UVATLASATTRIBUTERANGE ar;
std::unique_ptr<bool[]> bUsedFace(new (std::nothrow) bool[m_iNumFaces]);
if (!bUsedFace)
return E_OUTOFMEMORY;
memset(bUsedFace.get(), 0, sizeof(bool) * m_iNumFaces);
std::vector<uint32_t> ab;
uint32_t num = 0;
uint32_t indexnum = 0;
uint32_t facestart = 0;
for (uint32_t i = 0; i < m_iNumFaces; i++)
{
if (pAB[i] == uint32_t(-1))
{
ab.clear();
if (!bUsedFace[i])
{
ab.push_back(i);
bUsedFace[i] = true;
}
size_t t = 0;
// use broad-first search algorithm to find chart
// store the result into m_pAttributeBuffer
if (m_pPartitionAdj)
{
while (t < ab.size())
{
pAB[ab[t]] = uint32_t(num);
for (uint32_t j = 0; j < 3; j++)
{
uint32_t index = 3 * ab[t] + j;
if (m_AdjacentInfo[index] != uint32_t(-1) && !bUsedFace[m_AdjacentInfo[index]])
{
ab.push_back(m_AdjacentInfo[index]);
bUsedFace[m_AdjacentInfo[index]] = true;
}
}
t++;
}
}
else
{
while (t < ab.size())
{
pAB[ab[t]] = uint32_t(num);
for (size_t j = 0; j < 3; j++)
{
uint32_t index = *reinterpret_cast<const T*>(pIB + (3 * ab[t] + j) * sizeof(T));
for (size_t k = 0; k < m_VertexAdjInfo[index].size(); k++)
if (!bUsedFace[m_VertexAdjInfo[index][k]])
{
ab.push_back(m_VertexAdjInfo[index][k]);
bUsedFace[m_VertexAdjInfo[index][k]] = true;
}
}
t++;
}
}
// after found a set of vertices that belong to the same chart we store them
// continuously in new vertex buffers.
ar.VertexStart = uint32_t(m_VertexBuffer.size());
// iterate every triangle in the same chart
for (size_t j = 0; j < ab.size(); j++)
{
// find the original index of the triangle's vertex
uint32_t index1 = *reinterpret_cast<const T*>(pIB + 3 * ab[j] * sizeof(T));
uint32_t index2 = *reinterpret_cast<const T*>(pIB + (3 * ab[j] + 1) * sizeof(T));
uint32_t index3 = *reinterpret_cast<const T*>(pIB + (3 * ab[j] + 2) * sizeof(T));
// copy the original adjacent information continuously in new adjacent buffer
memcpy(&m_NewAdjacentInfo[j * 3 + facestart * 3],
&m_AdjacentInfo[3 * ab[j]], sizeof(uint32_t) * 3);
// copy the original index information continuously in new index buffer
m_IndexBuffer.push_back(index1);
m_IndexBuffer.push_back(index2);
m_IndexBuffer.push_back(index3);
// find the original UV coordinates of each vertex
auto p1 = reinterpret_cast<const XMFLOAT2*>(pVB + index1 * m_iNumBytesPerVertex + m_TexCoordOffset);
auto p2 = reinterpret_cast<const XMFLOAT2*>(pVB + index2 * m_iNumBytesPerVertex + m_TexCoordOffset);
auto p3 = reinterpret_cast<const XMFLOAT2*>(pVB + index3 * m_iNumBytesPerVertex + m_TexCoordOffset);
// find the original 3D coordinates of each vertex
auto pp1 = reinterpret_cast<const XMFLOAT3*>(pVB + index1 * m_iNumBytesPerVertex);
auto pp2 = reinterpret_cast<const XMFLOAT3*>(pVB + index2 * m_iNumBytesPerVertex);
auto pp3 = reinterpret_cast<const XMFLOAT3*>(pVB + index3 * m_iNumBytesPerVertex);
// create an index partition buffer which store each vertex's original position
// to recover the vertex buffer after repacking.
if (m_IndexPartition[index1] == uint32_t(-1))
{
m_IndexPartition[index1] = indexnum++;
UVAtlasVertex vert;
vert.pos.x = pp1->x;
vert.pos.y = pp1->y;
vert.pos.z = pp1->z;
vert.uv.x = p1->x;
vert.uv.y = p1->y;
m_VertexBuffer.push_back(vert);
}
if (m_IndexPartition[index2] == uint32_t(-1))
{
m_IndexPartition[index2] = indexnum++;
UVAtlasVertex vert;
vert.pos.x = pp2->x;
vert.pos.y = pp2->y;
vert.pos.z = pp2->z;
vert.uv.x = p2->x;
vert.uv.y = p2->y;
m_VertexBuffer.push_back(vert);
}
if (m_IndexPartition[index3] == uint32_t(-1))
{
m_IndexPartition[index3] = indexnum++;
UVAtlasVertex vert;
vert.pos.x = pp3->x;
vert.pos.y = pp3->y;
vert.pos.z = pp3->z;
vert.uv.x = p3->x;
vert.uv.y = p3->y;
m_VertexBuffer.push_back(vert);
}
}
// store the newly found chart's information into m_AttrTable which
// represent the attribute table
ar.VertexCount = static_cast<uint32_t>(m_VertexBuffer.size() - ar.VertexStart);
ar.FaceCount = static_cast<uint32_t>(ab.size());
ar.FaceStart = facestart;
ar.AttribId = num;
facestart += static_cast<uint32_t>(ab.size());
m_AttrTable.push_back(ar);
num++;
}
}
m_iNumCharts = size_t(num);
}
catch (...)
{
return E_OUTOFMEMORY;
}
return S_OK;
}