[fixed?]32 bit index for COctreeTriangleSelector (Fixed)

You discovered a bug in the engine, and you are sure that it is not a problem of your code? Just post it in here. Please read the bug posting guidelines first.
Post Reply
Wol101
Posts: 9
Joined: Sat Apr 23, 2016 6:39 am

[fixed?]32 bit index for COctreeTriangleSelector (Fixed)

Post by Wol101 »

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);
                }
            }
        }
    }
}
 
chronologicaldot
Competition winner
Posts: 684
Joined: Mon Sep 10, 2012 8:51 am

Re: 32 bit index for COctreeTriangleSelector (Fixed)

Post by chronologicaldot »

edit: I see what you did there. lol

But speaking of docs, the poor wiki is sorely lacking... *sigh* Maybe we'll get back to it someday.
CuteAlien
Admin
Posts: 9628
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: 32 bit index for COctreeTriangleSelector (Fixed)

Post by CuteAlien »

I added a patch to trunk. Should work in theory... but not yet really tested with 32-bit meshes (have to find one first... not sure right now if I got any). And also should be faster (code looks more horrible now, but I think it's worth it in this case).
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Post Reply