template<typename _Type>
static _Type *_FetchElementFromMultiView(const TMemoryView<const TStridedMemoryView<_Type> > &views, hh_u32 index)
{
hh_u32 base = 0;
for (hh_u32 i = 0; i < views.Count(); i++)
{
hh_u32 size = views[i].Count();
if (index >= base && index < base + size)
{
return &(views[i][index - base]);
}
base += size;
}
return null;
}
//----------------------------------------------------------------------------
template<typename _Type>
void _Test_MeshTriangleSorter(SUnitTestReport &__UT_report, const TMemoryView<const hh_u32> &indexPattern, hh_u32 vertexCount)
{
static const hh_u32 maxIndexCount = 4096;
static const hh_u32 maxFpCount = 4096;
static const hh_u32 kPosStrides[2] = { sizeof(CFloat3), sizeof(CFloat4) };
_Type *rawIndexBuffer = Mem::Alloc<_Type>(maxIndexCount, 0x10);
float *rawFp32Buffer = Mem::Alloc<float>(maxFpCount, 0x10);
CUtils::FillArrayRand(rawFp32Buffer, maxFpCount, -1000.0f, 1000.0f);
TStridedMemoryView<const CFloat3> positionsCollection[3];
CFloat3 sortDir = CFloat3(0.5f, 1.0f, -0.2f).Normalized();
hh_u32 maxPrimitiveCount = maxIndexCount / indexPattern.Count();
for (hh_u32 totalPrimitiveCount = 1; totalPrimitiveCount < maxPrimitiveCount; )
{
for (hh_u32 stride = 0; stride < 2; stride++)
{
hh_u32 pccount = 0;
hh_u32 primCount = totalPrimitiveCount;
hh_u32 pcount0 = primCount > 7 ? 7 : primCount;
primCount -= pcount0;
hh_u32 pcount1 = primCount > 49 ? 49 : primCount;
primCount -= pcount1;
hh_u32 pcount2 = primCount;
positionsCollection[pccount++] = TStridedMemoryView<const CFloat3>((const CFloat3*)((const hh_u8*)rawFp32Buffer), pcount0, kPosStrides[stride]);
if (pcount1 != 0)
{
positionsCollection[pccount++] = TStridedMemoryView<const CFloat3>((const CFloat3*)((const hh_u8*)rawFp32Buffer + pcount0 * kPosStrides[stride]), pcount1, kPosStrides[stride]);
if (pcount2 != 0)
{
positionsCollection[pccount++] = TStridedMemoryView<const CFloat3>((const CFloat3*)((const hh_u8*)rawFp32Buffer + pcount1 * kPosStrides[stride]), pcount2, kPosStrides[stride]);
}
}
TMemoryView<const TStridedMemoryView<const CFloat3> > positionsCollectionView(positionsCollection, pccount);
static const hh_u32 kClearTag = 0xCD;
_Type expandedClearTag;
memset(rawIndexBuffer, kClearTag, maxIndexCount * sizeof(*rawIndexBuffer));
memset(&expandedClearTag, kClearTag, sizeof(expandedClearTag));
CTriangleSorter:

ortPoints_AutogenIndices( indexPattern,
vertexCount,
rawIndexBuffer,
totalPrimitiveCount,
positionsCollectionView,
sortDir);
hh_u32 indexCountPerPrimitive = indexPattern.Count();
hh_u32 indexCount = totalPrimitiveCount * indexCountPerPrimitive;
// first, make sure the function didn't overflow the output buffer:
hh_u32 corrupt = 0;
for (hh_u32 i = indexCount; i < maxIndexCount; i++)
{
corrupt |= rawIndexBuffer[i] - expandedClearTag;
}
UT_TEST(corrupt == 0);
// now, make sure all the generated indices follow the correct index pattern:
float prevD = TNumericTraits<float>::NegativeInfinity();
for (hh_u32 i = 0; i < indexCount; i += indexCountPerPrimitive)
{
_Type baseId = rawIndexBuffer[i];
hh_u32 fuckedIndexPattern = 0;
for (hh_u32 j = 1; j < indexCountPerPrimitive; j++)
{
fuckedIndexPattern |= (rawIndexBuffer[i + j] - baseId) - indexPattern[j];
}
UT_TEST(fuckedIndexPattern == 0);
if (fuckedIndexPattern == 0)
{
// check these are ordered correctly
hh_u32 sourceId = baseId / vertexCount;
const CFloat3 *p = _FetchElementFromMultiView(positionsCollectionView, sourceId);
bool correctlySorted = false;
if (p != null)
{
float d = p->Dot(sortDir);
correctlySorted = d >= prevD;
prevD = d;
}
UT_TEST(correctlySorted);
}
}
}
if (totalPrimitiveCount < 36)
{
// for the first part, test with increments of 1
totalPrimitiveCount++;
}
else
{
// once we've reached large enough batches, test the next powers of two
totalPrimitiveCount = ((totalPrimitiveCount | (totalPrimitiveCount - 1)) + 1); // next power of two
}
}
Mem::Free(rawFp32Buffer);
Mem::Free(rawIndexBuffer);
}
//----------------------------------------------------------------------------
UT_DECLARE(Mesh_TriangleSorter16)
{
static const hh_u32 indexPattern0[] = { 0, 1, 2, 3, 4, 5 };
static const hh_u32 vertexCount0 = 6;
static const hh_u32 indexPattern1[] = { 0, 1, 2, 1, 0, 2 };
static const hh_u32 vertexCount1 = 4;
static const hh_u32 indexPattern2[] = { 0, 1 };
static const hh_u32 vertexCount2 = 2;
static const hh_u32 indexPattern3[] = { 0, 1, 2 };
static const hh_u32 vertexCount3 = 3;
static const hh_u32 indexPattern4[] = { 0, 1, 1, 0, 2, 2, 1, 2, 2, 2, 1, 1, 2, 0, 0, 1, 0, 0 };
static const hh_u32 vertexCount4 = 3;
static const hh_u32 indexPattern5[] = { 0, 1, 2, 1, 4, 2, 3, 5, 0, 2, 3, 0 };
static const hh_u32 vertexCount5 = 6;
_Test_MeshTriangleSorter<hh_u16>(__UT_report, indexPattern0, vertexCount0);
_Test_MeshTriangleSorter<hh_u16>(__UT_report, indexPattern1, vertexCount1);
_Test_MeshTriangleSorter<hh_u16>(__UT_report, indexPattern2, vertexCount2);
_Test_MeshTriangleSorter<hh_u16>(__UT_report, indexPattern3, vertexCount3);
_Test_MeshTriangleSorter<hh_u16>(__UT_report, indexPattern4, vertexCount4);
_Test_MeshTriangleSorter<hh_u16>(__UT_report, indexPattern5, vertexCount5);
}
//----------------------------------------------------------------------------
UT_DECLARE(Mesh_TriangleSorter32)
{
static const hh_u32 indexPattern0[6] = { 0, 1, 2, 3, 4, 5 };
static const hh_u32 vertexCount0 = 6;
static const hh_u32 indexPattern1[6] = { 0, 1, 2, 1, 0, 2 };
static const hh_u32 vertexCount1 = 4;
static const hh_u32 indexPattern2[] = { 0, 1 };
static const hh_u32 vertexCount2 = 2;
static const hh_u32 indexPattern3[] = { 0, 1, 2 };
static const hh_u32 vertexCount3 = 3;
static const hh_u32 indexPattern4[] = { 0, 1, 1, 0, 2, 2, 1, 2, 2, 2, 1, 1, 2, 0, 0, 1, 0, 0 };
static const hh_u32 vertexCount4 = 3;
static const hh_u32 indexPattern5[] = { 0, 1, 2, 1, 4, 2, 3, 5, 0, 2, 3, 0 };
static const hh_u32 vertexCount5 = 6;
_Test_MeshTriangleSorter<hh_u32>(__UT_report, indexPattern0, vertexCount0);
_Test_MeshTriangleSorter<hh_u32>(__UT_report, indexPattern1, vertexCount1);
_Test_MeshTriangleSorter<hh_u32>(__UT_report, indexPattern2, vertexCount2);
_Test_MeshTriangleSorter<hh_u32>(__UT_report, indexPattern3, vertexCount3);
_Test_MeshTriangleSorter<hh_u32>(__UT_report, indexPattern4, vertexCount4);
_Test_MeshTriangleSorter<hh_u32>(__UT_report, indexPattern5, vertexCount5);
}