[fixed?]32 bit index for COctreeTriangleSelector (Fixed)
Posted: Sat May 07, 2016 10:24 am
I recently needed to use a big mesh loaded it into a CDynamicMeshBuffer with the EIT_32BIT setting. I thought the COctreeTriangleSelector ought to work OK but it actually doesn't cope with 32 bit indices - not a bug as such but not documented. I tracked the problem down and it isn't COctreeTriangleSelector, it is actually the underlying CTriangleSelector that only works with 16 bit indices. That makes a bit more sense, but actually the fix is very straightforward and I doubt will impact performance. All you need to do is use getIndexType() and change the pointer to the indices to 32 bit if that's the one you need. The attached code illustrates one way of doing it. It really just changes "const u16* indices = buf->getIndices();" to "const u32* indices = (u32*)buf->getIndices();" when you have EIT_32BIT drivers. Collision detection then works fine with >8 million polygons in my biggest mesh!
Code: Select all
void CTriangleSelector32bit::updateFromMesh(const IMesh* mesh) const
{
if (!mesh)
return;
bool skinnnedMesh = mesh->getMeshType() == EAMT_SKINNED;
u32 meshBuffers = mesh->getMeshBufferCount();
u32 triangleCount = 0;
BoundingBox.reset(0.f, 0.f, 0.f);
for (u32 i = 0; i < meshBuffers; ++i)
{
IMeshBuffer* buf = mesh->getMeshBuffer(i);
u32 idxCnt = buf->getIndexCount();
if (buf->getIndexType() == video::EIT_16BIT)
{
const u16* indices = buf->getIndices();
if ( skinnnedMesh )
{
const core::matrix4& bufferTransform = ((scene::SSkinMeshBuffer*)buf)->Transformation;
for (u32 index = 0; index < idxCnt; index += 3)
{
core::triangle3df& tri = Triangles[triangleCount++];
bufferTransform.transformVect(tri.pointA, buf->getPosition(indices[index + 0]));
bufferTransform.transformVect(tri.pointB, buf->getPosition(indices[index + 1]));
bufferTransform.transformVect(tri.pointC, buf->getPosition(indices[index + 2]));
BoundingBox.addInternalPoint(tri.pointA);
BoundingBox.addInternalPoint(tri.pointB);
BoundingBox.addInternalPoint(tri.pointC);
}
}
else
{
for (u32 index = 0; index < idxCnt; index += 3)
{
core::triangle3df& tri = Triangles[triangleCount++];
tri.pointA = buf->getPosition(indices[index + 0]);
tri.pointB = buf->getPosition(indices[index + 1]);
tri.pointC = buf->getPosition(indices[index + 2]);
BoundingBox.addInternalPoint(tri.pointA);
BoundingBox.addInternalPoint(tri.pointB);
BoundingBox.addInternalPoint(tri.pointC);
}
}
}
else if (buf->getIndexType() == video::EIT_32BIT)
{
const u32* indices = (u32*)buf->getIndices();
if ( skinnnedMesh )
{
const core::matrix4& bufferTransform = ((scene::SSkinMeshBuffer*)buf)->Transformation;
for (u32 index = 0; index < idxCnt; index += 3)
{
core::triangle3df& tri = Triangles[triangleCount++];
bufferTransform.transformVect(tri.pointA, buf->getPosition(indices[index + 0]));
bufferTransform.transformVect(tri.pointB, buf->getPosition(indices[index + 1]));
bufferTransform.transformVect(tri.pointC, buf->getPosition(indices[index + 2]));
BoundingBox.addInternalPoint(tri.pointA);
BoundingBox.addInternalPoint(tri.pointB);
BoundingBox.addInternalPoint(tri.pointC);
}
}
else
{
for (u32 index = 0; index < idxCnt; index += 3)
{
core::triangle3df& tri = Triangles[triangleCount++];
tri.pointA = buf->getPosition(indices[index + 0]);
tri.pointB = buf->getPosition(indices[index + 1]);
tri.pointC = buf->getPosition(indices[index + 2]);
BoundingBox.addInternalPoint(tri.pointA);
BoundingBox.addInternalPoint(tri.pointB);
BoundingBox.addInternalPoint(tri.pointC);
}
}
}
}
}