HRESULT ValidateIndices()

in DirectXMesh/DirectXMeshValidate.cpp [39:254]


    HRESULT ValidateIndices(
        _In_reads_(nFaces * 3) const index_t* indices, _In_ size_t nFaces,
        _In_ size_t nVerts, _In_reads_opt_(nFaces * 3) const uint32_t* adjacency,
        _In_ VALIDATE_FLAGS flags, _In_opt_ std::wstring* msgs)
    {
        bool result = true;

        if (!adjacency)
        {
            if (flags & VALIDATE_BACKFACING)
            {
                if (msgs)
                    *msgs += L"Missing adjacency information required to check for BACKFACING\n";

                result = false;
            }

            if (flags & VALIDATE_ASYMMETRIC_ADJ)
            {
                if (msgs)
                    *msgs += L"Missing adjacency information required to check for ASYMMETRIC_ADJ\n";

                result = false;
            }

            if (!result)
                return E_INVALIDARG;
        }

        for (size_t face = 0; face < nFaces; ++face)
        {
            // Check for values in-range
            for (size_t point = 0; point < 3; ++point)
            {
                index_t i = indices[face * 3 + point];
                if (i >= nVerts && i != index_t(-1))
                {
                    if (!msgs)
                        return E_FAIL;

                    result = false;

                    wchar_t buff[128] = {};
                    swprintf_s(buff, L"An invalid index value (%u) was found on face %zu\n", i, face);
                    *msgs += buff;
                }

                if (adjacency)
                {
                    uint32_t j = adjacency[face * 3 + point];
                    if (j >= nFaces && j != UNUSED32)
                    {
                        if (!msgs)
                            return E_FAIL;

                        result = false;

                        wchar_t buff[128] = {};
                        swprintf_s(buff, L"An invalid neighbor index value (%u) was found on face %zu\n", j, face);
                        *msgs += buff;
                    }
                }
            }

            // Check for unused faces
            index_t i0 = indices[face * 3];
            index_t i1 = indices[face * 3 + 1];
            index_t i2 = indices[face * 3 + 2];
            if (i0 == index_t(-1)
                || i1 == index_t(-1)
                || i2 == index_t(-1))
            {
                if (flags & VALIDATE_UNUSED)
                {
                    if (i0 != i1
                        || i0 != i2
                        || i1 != i2)
                    {
                        if (!msgs)
                            return E_FAIL;

                        result = false;

                        wchar_t buff[128] = {};
                        swprintf_s(buff, L"An unused face (%zu) contains 'valid' but ignored vertices (%u,%u,%u)\n", face, i0, i1, i2);
                        *msgs += buff;
                    }

                    if (adjacency)
                    {
                        for (size_t point = 0; point < 3; ++point)
                        {
                            uint32_t k = adjacency[face * 3 + point];
                            if (k != UNUSED32)
                            {
                                if (!msgs)
                                    return E_FAIL;

                                result = false;

                                wchar_t buff[128] = {};
                                swprintf_s(buff, L"An unused face (%zu) has a neighbor %u\n", face, k);
                                *msgs += buff;
                            }
                        }
                    }
                }

                // ignore unused triangles for remaining tests
                continue;
            }

            // Check for degenerate triangles
            if (i0 == i1
                || i0 == i2
                || i1 == i2)
            {
                if (flags & VALIDATE_DEGENERATE)
                {
                    if (!msgs)
                        return E_FAIL;

                    result = false;

                    index_t bad;
                    if (i0 == i1)
                        bad = i0;
                    else if (i1 == i2)
                        bad = i2;
                    else
                        bad = i0;

                    wchar_t buff[128] = {};
                    swprintf_s(buff, L"A point (%u) was found more than once in triangle %zu\n", bad, face);
                    *msgs += buff;

                    if (adjacency)
                    {
                        for (size_t point = 0; point < 3; ++point)
                        {
                            uint32_t k = adjacency[face * 3 + point];
                            if (k != UNUSED32)
                            {
                                result = false;

                                swprintf_s(buff, L"A degenerate face (%zu) has a neighbor %u\n", face, k);
                                *msgs += buff;
                            }
                        }
                    }
                }

                // ignore degenerate triangles for remaining tests
                continue;
            }

            // Check for symmetric neighbors
            if ((flags & VALIDATE_ASYMMETRIC_ADJ) && adjacency)
            {
                for (size_t point = 0; point < 3; ++point)
                {
                    uint32_t k = adjacency[face * 3 + point];
                    if (k == UNUSED32)
                        continue;

                    assert(k < nFaces);

                    uint32_t edge = find_edge<uint32_t>(&adjacency[k * 3], uint32_t(face));
                    if (edge >= 3)
                    {
                        if (!msgs)
                            return E_FAIL;

                        result = false;

                        wchar_t buff[256] = {};
                        swprintf_s(buff, L"A neighbor triangle (%u) does not reference back to this face (%zu) as expected\n", k, face);
                        *msgs += buff;
                    }
                }
            }

            // Check for duplicate neighbor
            if ((flags & VALIDATE_BACKFACING) && adjacency)
            {
                uint32_t j0 = adjacency[face * 3];
                uint32_t j1 = adjacency[face * 3 + 1];
                uint32_t j2 = adjacency[face * 3 + 2];

                if ((j0 == j1 && j0 != UNUSED32)
                    || (j0 == j2 && j0 != UNUSED32)
                    || (j1 == j2 && j1 != UNUSED32))
                {
                    if (!msgs)
                        return E_FAIL;

                    result = false;

                    uint32_t bad;
                    if (j0 == j1 && j0 != UNUSED32)
                        bad = j0;
                    else if (j0 == j2 && j0 != UNUSED32)
                        bad = j0;
                    else
                        bad = j1;

                    wchar_t buff[256] = {};
                    swprintf_s(buff, L"A neighbor triangle (%u) was found more than once on triangle %zu\n"
                        L"\t(likley problem is that two triangles share same points with opposite direction)\n", bad, face);
                    *msgs += buff;
                }
            }
        }

        return result ? S_OK : E_FAIL;
    }