HRESULT __cdecl DirectX::UVAtlasComputeIMTFromPerVertexSignal()

in UVAtlas/isochart/UVAtlas.cpp [728:843]


HRESULT __cdecl DirectX::UVAtlasComputeIMTFromPerVertexSignal(
    const XMFLOAT3* positions,
    size_t nVerts,
    const void* indices,
    DXGI_FORMAT indexFormat,
    size_t nFaces,
    const float* pVertexSignal,
    size_t signalDimension,
    size_t signalStride,
    std::function<HRESULT __cdecl(float percentComplete)> statusCallBack,
    float* pIMTArray)
{
    if (!positions || !nVerts || !indices || !nFaces || !pVertexSignal || !pIMTArray)
        return E_INVALIDARG;

    if (!signalStride || (signalStride % sizeof(float)))
    {
        DPF(0, "UVAtlasComputeIMT: signalStride (%zu) must be a multiple of %zu.", signalStride, sizeof(float));
        return E_INVALIDARG;
    }

    if ((signalStride / sizeof(float)) < signalDimension)
    {
        DPF(0, "UVAtlasComputeIMT: signalStride (%zu) must accommodate signal dimension float values (%zu)\n", signalStride, signalDimension);
        return E_INVALIDARG;
    }

    switch (indexFormat)
    {
    case DXGI_FORMAT_R16_UINT:
        if (nVerts >= UINT16_MAX)
            return E_INVALIDARG;
        break;

    case DXGI_FORMAT_R32_UINT:
        if (nVerts >= UINT32_MAX)
            return E_INVALIDARG;
        break;

    default:
        return E_INVALIDARG;
    }

    if ((uint64_t(signalDimension) * 3) >= UINT32_MAX)
        return HRESULT_E_ARITHMETIC_OVERFLOW;

    std::unique_ptr<float[]> signalData(new (std::nothrow) float[3 * signalDimension]);
    if (!signalData)
        return E_OUTOFMEMORY;

    float* pfSignalData = signalData.get();

    auto pdwIndexData = reinterpret_cast<const uint32_t*>(indices);
    auto pwIndexData = reinterpret_cast<const uint16_t*>(indices);

    float* pfIMTData = pIMTArray;

    HRESULT hr;

    for (size_t i = 0; i < nFaces; i++)
    {
        if (statusCallBack && ((i % 64) == 0))
        {
            float fPct = float(i) / float(nFaces);
            hr = statusCallBack(fPct);
            if (FAILED(hr))
                return E_ABORT;
        }

        XMFLOAT3 pos[3] = {};
        for (size_t j = 0; j < 3; j++)
        {
            uint32_t dwId;
            if (indexFormat == DXGI_FORMAT_R16_UINT)
            {
                dwId = pwIndexData[3 * i + j];
            }
            else
            {
                dwId = pdwIndexData[3 * i + j];
            }

            if (dwId >= nVerts)
            {
                DPF(0, "UVAtlasComputeIMT: Vertex ID out of range.");
                return E_FAIL;
            }

            pos[j] = positions[dwId];

            for (size_t k = 0; k < signalDimension; k++)
            {
                pfSignalData[j * signalDimension + k] = pVertexSignal[dwId * (signalStride / sizeof(float)) + k];
            }
        }

        hr = IMTFromPerVertexSignal(pos,
            pfSignalData,
            signalDimension,
            reinterpret_cast<FLOAT3*>(pfIMTData + 3 * i));
        if (FAILED(hr))
        {
            DPF(0, "UVAtlasComputeIMT: IMT data calculation failed.");
            return hr;
        }
    }

    if (statusCallBack)
    {
        hr = statusCallBack(1.0f);
        if (FAILED(hr))
            return E_ABORT;
    }

    return S_OK;
}