HRESULT __cdecl DirectX::UVAtlasComputeIMTFromTexture()

in UVAtlas/isochart/UVAtlas.cpp [1239:1367]


HRESULT __cdecl DirectX::UVAtlasComputeIMTFromTexture(
    const XMFLOAT3* positions,
    const XMFLOAT2* texcoords,
    size_t nVerts,
    const void* indices,
    DXGI_FORMAT indexFormat,
    size_t nFaces,
    const float* pTexture,
    size_t width,
    size_t height,
    UVATLAS_IMT options,
    std::function<HRESULT __cdecl(float percentComplete)> statusCallBack,
    float* pIMTArray)
{
    if (!positions || !texcoords || !nVerts || !indices || !nFaces || !pTexture || !pIMTArray)
        return E_INVALIDARG;

    if (!width || !height)
        return E_INVALIDARG;

    if ((width > UINT32_MAX) || (height > UINT32_MAX))
        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(nFaces) * 3) >= UINT32_MAX)
        return HRESULT_E_ARITHMETIC_OVERFLOW;

    LPIMTSIGNALCALLBACK pSignalCallback = nullptr;
    if ((options & UVATLAS_IMT_WRAP_UV) == UVATLAS_IMT_WRAP_UV)
    {
        pSignalCallback = IMTTextureCbWrapUV;
    }
    else if (options & UVATLAS_IMT_WRAP_U)
    {
        pSignalCallback = IMTTextureCbWrapU;
    }
    else if (options & UVATLAS_IMT_WRAP_V)
    {
        pSignalCallback = IMTTextureCbWrapV;
    }
    else
    {
        pSignalCallback = IMTTextureCbWrapNone;
    }

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

    IMTTextureDesc TextureDesc;
    TextureDesc.pTexture = reinterpret_cast<const XMFLOAT4*>(pTexture);
    TextureDesc.uWidth = width;
    TextureDesc.uHeight = height;

    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] = {};
        XMFLOAT2 uv[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];
            uv[j] = texcoords[dwId];
        }

        hr = IMTFromTextureMapEx(pos,
            uv,
            i,
            4, // dimension 4, rgba, can be zeroes if less than 4
            pSignalCallback,
            &TextureDesc,
            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;
}