in DirectXMesh/DirectXMeshRemap.cpp [707:835]
HRESULT DirectX::FinalizeVBAndPointReps(
const void* vbin,
size_t stride,
size_t nVerts,
const uint32_t* prin,
const uint32_t* dupVerts,
size_t nDupVerts,
const uint32_t* vertexRemap,
void* vbout,
uint32_t* prout) noexcept
{
if (!vbin || !stride || !nVerts || !prin || !vbout || !prout)
return E_INVALIDARG;
if (!dupVerts && !vertexRemap)
return E_INVALIDARG;
if (dupVerts && !nDupVerts)
return E_INVALIDARG;
if (!dupVerts && nDupVerts > 0)
return E_INVALIDARG;
if (nVerts >= UINT32_MAX)
return E_INVALIDARG;
if (stride > c_MaxStride)
return E_INVALIDARG;
if ((uint64_t(nVerts) + uint64_t(nDupVerts)) >= UINT32_MAX)
return HRESULT_E_ARITHMETIC_OVERFLOW;
if (vbin == vbout)
return HRESULT_E_NOT_SUPPORTED;
size_t newVerts = nVerts + nDupVerts;
std::unique_ptr<uint32_t[]> vertexRemapInverse;
if (vertexRemap)
{
vertexRemapInverse.reset(new (std::nothrow) uint32_t[newVerts]);
if (!vertexRemapInverse)
return E_OUTOFMEMORY;
memset(vertexRemapInverse.get(), 0xff, sizeof(uint32_t) * newVerts);
for (uint32_t j = 0; j < newVerts; ++j)
{
if (vertexRemap[j] != UNUSED32)
{
if (vertexRemap[j] >= newVerts)
return E_INVALIDARG;
vertexRemapInverse[vertexRemap[j]] = j;
}
}
}
auto sptr = static_cast<const uint8_t*>(vbin);
auto dptr = static_cast<uint8_t*>(vbout);
#ifdef _DEBUG
memset(vbout, 0, newVerts * stride);
#endif
std::unique_ptr<uint32_t[]> pointRep(new (std::nothrow) uint32_t[nVerts + nDupVerts]);
if (!pointRep)
return E_OUTOFMEMORY;
memcpy(pointRep.get(), prin, sizeof(uint32_t) * nVerts);
for (size_t i = 0; i < nDupVerts; ++i)
{
pointRep[i + nVerts] = prin[dupVerts[i]];
}
for (size_t j = 0; j < newVerts; ++j)
{
uint32_t src = (vertexRemap) ? vertexRemap[j] : uint32_t(j);
if (src == UNUSED32)
{
// remap entry is unused
}
else if (src >= newVerts)
{
return E_FAIL;
}
else if (src < nVerts)
{
memcpy(dptr, sptr + src * stride, stride);
uint32_t pr = pointRep[src];
if (pr < newVerts)
{
prout[j] = (vertexRemapInverse) ? vertexRemapInverse[pr] : pr;
}
}
else if (dupVerts)
{
uint32_t dup = dupVerts[src - nVerts];
memcpy(dptr, sptr + dup * stride, stride);
uint32_t pr = pointRep[src];
if (pr < newVerts)
{
prout[j] = (vertexRemapInverse) ? vertexRemapInverse[pr] : pr;
}
}
else
return E_FAIL;
dptr += stride;
}
if (vertexRemap)
{
// clean up point reps for any removed vertices
for (uint32_t i = 0; i < newVerts; ++i)
{
if (vertexRemap[i] == UNUSED32)
{
pointRep[i] = UNUSED32;
}
}
}
return S_OK;
}