HRESULT Mesh::Clean()

in Meshconvert/Mesh.cpp [388:536]


HRESULT Mesh::Clean() noexcept
{
    if (!mnFaces || !mIndices || !mnVerts || !mPositions)
        return E_UNEXPECTED;

    std::vector<uint32_t> dups;
    HRESULT hr = DirectX::Clean(mIndices.get(), mnFaces, mnVerts, mAdjacency.get(), mAttributes.get(), dups);
    if (FAILED(hr))
        return hr;

    if (dups.empty())
    {
        // No vertex duplication is needed for mesh clean
        return S_OK;
    }

    size_t nNewVerts = mnVerts + dups.size();

    std::unique_ptr<XMFLOAT3[]> pos(new (std::nothrow) XMFLOAT3[nNewVerts]);
    if (!pos)
        return E_OUTOFMEMORY;

    memcpy(pos.get(), mPositions.get(), sizeof(XMFLOAT3) * mnVerts);

    std::unique_ptr<XMFLOAT3[]> norms;
    if (mNormals)
    {
        norms.reset(new (std::nothrow) XMFLOAT3[nNewVerts]);
        if (!norms)
            return E_OUTOFMEMORY;

        memcpy(norms.get(), mNormals.get(), sizeof(XMFLOAT3) * mnVerts);
    }

    std::unique_ptr<XMFLOAT4[]> tans1;
    if (mTangents)
    {
        tans1.reset(new (std::nothrow) XMFLOAT4[nNewVerts]);
        if (!tans1)
            return E_OUTOFMEMORY;

        memcpy(tans1.get(), mTangents.get(), sizeof(XMFLOAT4) * mnVerts);
    }

    std::unique_ptr<XMFLOAT3[]> tans2;
    if (mBiTangents)
    {
        tans2.reset(new (std::nothrow) XMFLOAT3[nNewVerts]);
        if (!tans2)
            return E_OUTOFMEMORY;

        memcpy(tans2.get(), mBiTangents.get(), sizeof(XMFLOAT3) * mnVerts);
    }

    std::unique_ptr<XMFLOAT2[]> texcoord;
    if (mTexCoords)
    {
        texcoord.reset(new (std::nothrow) XMFLOAT2[nNewVerts]);
        if (!texcoord)
            return E_OUTOFMEMORY;

        memcpy(texcoord.get(), mTexCoords.get(), sizeof(XMFLOAT2) * mnVerts);
    }

    std::unique_ptr<XMFLOAT4[]> colors;
    if (mColors)
    {
        colors.reset(new (std::nothrow) XMFLOAT4[nNewVerts]);
        if (!colors)
            return E_OUTOFMEMORY;

        memcpy(colors.get(), mColors.get(), sizeof(XMFLOAT4) * mnVerts);
    }

    std::unique_ptr<XMFLOAT4[]> blendIndices;
    if (mBlendIndices)
    {
        blendIndices.reset(new (std::nothrow) XMFLOAT4[nNewVerts]);
        if (!blendIndices)
            return E_OUTOFMEMORY;

        memcpy(blendIndices.get(), mBlendIndices.get(), sizeof(XMFLOAT4) * mnVerts);
    }

    std::unique_ptr<XMFLOAT4[]> blendWeights;
    if (mBlendWeights)
    {
        blendWeights.reset(new (std::nothrow) XMFLOAT4[nNewVerts]);
        if (!blendWeights)
            return E_OUTOFMEMORY;

        memcpy(blendWeights.get(), mBlendWeights.get(), sizeof(XMFLOAT4) * mnVerts);
    }

    size_t j = mnVerts;
    for (auto it = dups.begin(); it != dups.end() && (j < nNewVerts); ++it, ++j)
    {
        assert(*it < mnVerts);

        pos[j] = mPositions[*it];

        if (norms)
        {
            norms[j] = mNormals[*it];
        }

        if (tans1)
        {
            tans1[j] = mTangents[*it];
        }

        if (tans2)
        {
            tans2[j] = mBiTangents[*it];
        }

        if (texcoord)
        {
            texcoord.get()[j] = mTexCoords[*it];
        }

        if (colors)
        {
            colors[j] = mColors[*it];
        }

        if (blendIndices)
        {
            blendIndices[j] = mBlendIndices[*it];
        }

        if (blendWeights)
        {
            blendWeights[j] = mBlendWeights[*it];
        }
    }

    mPositions.swap(pos);
    mNormals.swap(norms);
    mTangents.swap(tans1);
    mBiTangents.swap(tans2);
    mTexCoords.swap(texcoord);
    mColors.swap(colors);
    mBlendIndices.swap(blendIndices);
    mBlendWeights.swap(blendWeights);
    mnVerts = nNewVerts;

    return S_OK;
}