Page 1 of 1

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

Posted: Sat May 07, 2016 10:24 am
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);
                }
            }
        }
    }
}
 

Re: 32 bit index for COctreeTriangleSelector (Fixed)

Posted: Mon May 09, 2016 5:36 am
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.

Re: 32 bit index for COctreeTriangleSelector (Fixed)

Posted: Mon May 30, 2016 8:22 pm
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).