Implementing Convex Decomposition

Mako_energy02
Posts: 171
Joined: Sun Jan 17, 2010 4:47 am

Implementing Convex Decomposition

Post by Mako_energy02 »

I am attempting it, and not having much luck. I'm using the code provided in the extra's folder with the SDK and compiling as a static lib. In all honesty, I don't really have the best of idea's regarding what I am doing...so please call me out if I'm doing something wrong, but also please tell me how to do it right.

What I am trying to do overall, is take mesh data from an already loaded Ogre mesh, and perform convex decomposition with that data. As a result I don't need or want anything to do with Wavefront object files, so I cut that part out, but the rest is pretty much copy pasta from the Convex Decomp Demo files.

Part of my Interface class:

Code: Select all

void PhysConvexDecomposition::ConvexDecompResult(ConvexDecomposition::ConvexResult &result)
        {
            btTriangleMesh* trimesh = new btTriangleMesh();

            btVector3 localScaling(1.f,1.f,1.f);

            //calc centroid, to shift vertices around center of mass
            btVector3 centroid;
            centroid.setValue(0,0,0);

            btAlignedObjectArray<btVector3> vertices;

            //const unsigned int *src = result.mHullIndices;
            for (unsigned int i=0; i<result.mHullVcount; i++)
            {
                    btVector3 vertex(result.mHullVertices[i*3],result.mHullVertices[i*3+1],result.mHullVertices[i*3+2]);
                    vertex *= localScaling;
                    centroid += vertex;
            }

            centroid *= 1.f/(float(result.mHullVcount) );

            //const unsigned int *src = result.mHullIndices;
            for (unsigned int i=0; i<result.mHullVcount; i++)
            {
                btVector3 vertex(result.mHullVertices[i*3],result.mHullVertices[i*3+1],result.mHullVertices[i*3+2]);
                vertex *= localScaling;
                vertex -= centroid ;
                vertices.push_back(vertex);
            }
            const unsigned int *src = result.mHullIndices;
            for (unsigned int i=0; i<result.mHullTcount; i++)
            {
                unsigned int index0 = *src++;
                unsigned int index1 = *src++;
                unsigned int index2 = *src++;

                btVector3 vertex0(result.mHullVertices[index0*3], result.mHullVertices[index0*3+1],result.mHullVertices[index0*3+2]);
                btVector3 vertex1(result.mHullVertices[index1*3], result.mHullVertices[index1*3+1],result.mHullVertices[index1*3+2]);
                btVector3 vertex2(result.mHullVertices[index2*3], result.mHullVertices[index2*3+1],result.mHullVertices[index2*3+2]);
                vertex0 *= localScaling;
                vertex1 *= localScaling;
                vertex2 *= localScaling;

                vertex0 -= centroid;
                vertex1 -= centroid;
                vertex2 -= centroid;

                trimesh->addTriangle(vertex0,vertex1,vertex2);

                index0+=mBaseCount;
                index1+=mBaseCount;
                index2+=mBaseCount;
            }

            btConvexHullShape* convexShape = new btConvexHullShape(&(vertices[0].getX()),vertices.size());

            convexShape->setMargin(0.01f);
            m_convexShapes.push_back(convexShape);
            m_convexCentroids.push_back(centroid);
            mBaseCount+=result.mHullVcount; // advance the 'base index' counter.
        }
And here is the function that'll do all the other important convex decomp stuff:

Code: Select all

void ActorRigid::PerformConvexDecomposition(unsigned int depth, float cpercent, float ppercent)
    {
        Ogre::MeshPtr myMesh = entity->getMesh();
        Ogre::SubMesh* subMesh = myMesh->getSubMesh(0);
        Ogre::IndexData*  indexData = subMesh->indexData;
        Ogre::VertexData* vertexData = subMesh->vertexData;

        const Ogre::VertexElement* posElem = vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
        Ogre::HardwareVertexBufferSharedPtr vBuffer = vertexData->vertexBufferBinding->getBuffer(posElem->getSource());
        Ogre::HardwareIndexBufferSharedPtr iBuffer = indexData->indexBuffer;

        unsigned int triCount = indexData->indexCount/3;
        Ogre::Real* vertices = new Ogre::Real[vertexData->vertexCount*3];
        unsigned int* indices = new unsigned int[indexData->indexCount];
        unsigned char* vertex = static_cast<unsigned char*>(vBuffer->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
        int vcount=0;
        float* pReal = NULL;
        for (size_t j = 0; j < vertexData->vertexCount; j+=3, vertex += vBuffer->getVertexSize() )
        {
            posElem->baseVertexPointerToElement(vertex, &pReal);
            vertices[j] = pReal[0];
            vertices[j+1] = pReal[1];
            vertices[j+2] = pReal[2];
            vcount+=3;
        }
        vBuffer->unlock();
        size_t index_offset = 0;
        bool use32bitindexes = (iBuffer->getType() == Ogre::HardwareIndexBuffer::IT_32BIT);

        unsigned long* pLong = static_cast<unsigned long*>(iBuffer->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
        unsigned short* pShort = reinterpret_cast<unsigned short*>(pLong);

        if (use32bitindexes)
        {
            for (size_t k = 0; k < triCount*3; ++k)
            {
                indices[index_offset++] = pLong[k];
            }
        }
        else
        {
            for (size_t k = 0; k < triCount*3; ++k)
            {
                indices[index_offset++] = static_cast<unsigned long>(pShort[k]);
            }
        }
        iBuffer->unlock();

        ConvexDecomposition::DecompDesc desc;
        desc.mVcount = vcount;
        desc.mTcount = triCount;
        desc.mVertices = &vertices[0];
        desc.mIndices = &indices[0];
        unsigned int maxv  = 16;
        float skinWidth    = 0.0;
        desc.mDepth        = depth;
		desc.mCpercent     = cpercent;
		desc.mPpercent     = ppercent;
		desc.mMaxVertices  = maxv;
		desc.mSkinWidth    = skinWidth;

        internal::PhysConvexDecomposition decomp;
        desc.mCallback = &decomp;

        ConvexBuilder cb(desc.mCallback);
        cb.process(desc);

        btCompoundShape* compound = new btCompoundShape(false);
        btTransform trans;
        trans.setIdentity();
        for (int i=0;i<decomp.m_convexShapes.size();i++)
        {
            btVector3 centroid = decomp.m_convexCentroids[i];
            trans.setOrigin(centroid);
            btConvexHullShape* convexShape = decomp.m_convexShapes[i];
            compound->addChildShape(trans,convexShape);
        }
        Shape=compound;
        this->physrigidbody->setCollisionShape(this->Shape);

        delete[] vertices;
        delete[] indices;

        return;
The other relevant stuff like the calculating local inertia I do elsewhere, but it is getting taken care of.

The problem right now is that in windows, this will cause an Assertion fail from line 502 of cd_hull.cpp . If I run it through with GDB (MinGW debugger) then it won't throw an assert at all, instead it'll not fill the mChulls vector and skip over most of the code in the process function, thus not actually perform any decomposition and not give the object any shape causing objects to fall through each other. In linux, the same code will cause a seg fault in btAxisSweep.h on line 1004, rather then either of the windows behaviors. This also only happens when we enable Convex decomp in our code. We have it creating regular convex hulls and gimpact shapes just fine.

If anyone can help, or post a code snippet to get me on the right track, I would greatly appreciate it.
Mako_energy02
Posts: 171
Joined: Sun Jan 17, 2010 4:47 am

Re: Implementing Convex Decomposition

Post by Mako_energy02 »

Update:

The linux crash turned out to be another unrelated issue, now the linux version behaves the same way as the debugger on the windows side. No crashes or asserts, it just doesn't perform convex decomposition and thus our body doesn't get any collision shape.

When debugging I saw that the vector "mChulls" in the convex builder class simply wasn't being populated...the function that populates it simply never gets called. So almost all of the library gets skipped over and nothing gets done. However I have compiled the demo and it works just fine, and I've tried copying everything I could from it to get a basic working version and I don't. So now I know for a fact I am missing something, but don't have a single clue as to what that is.
Mako_energy02
Posts: 171
Joined: Sun Jan 17, 2010 4:47 am

Re: Implementing Convex Decomposition

Post by Mako_energy02 »

Erwin...I'm pretty sure you can answer this question. If you didn't make the demo then at least please give me the name of the person that did so I may contact them and figure this out.

Looking at the Demo simply doesn't make sense. In the Process function of ConvexBuilder it expects mChulls to be populated by the time it combines hulls, there is only one function that is called before that and it doesn't do anything to populate that vector. Large portions of code are skipped without it resulting in no collision shapes. However I have compiled the demo and it works properly. Why? It simply doesn't make any sense the way it's written as is...and the demo does NOT make it any clearer. I've posted my code, if you need more then let me know.