BulletMeshStrider         A subclass of btStridingMeshInterface which allows one to share the same geometry between both graphics and collision meshes

Table of contents

Mesh Strider for Bullet physics engine

This is subclass of btStridingMeshInterface, which allows one to share the same geometry between both graphics and collision meshes

MeshStrider.h

#ifndef MeshStrider_h__
#define MeshStrider_h__

#include "..\common.h"

/// Shares vertices/indexes between Ogre and Bullet
class MeshStrider : public btStridingMeshInterface{

public:
    MeshStrider( Ogre::Mesh * m = 0 ):mMesh(m){}

    void set( Ogre::Mesh * m ) { ASSERT(m); mMesh = m; }
    // inherited interface
    virtual int        getNumSubParts() const;

    virtual void    getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0);
    virtual void    getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0) const;

    virtual void    unLockVertexBase(int subpart);
    virtual void    unLockReadOnlyVertexBase(int subpart) const;

    virtual void    preallocateVertices(int numverts);
    virtual void    preallocateIndices(int numindices);
private:
    Ogre::Mesh * mMesh;
};

#endif // MeshStrider_h__

MeshStrider.cpp

#include "common.h"

#include "MeshStrider.h"

int MeshStrider::getNumSubParts() const
{
    int ret = mMesh->getNumSubMeshes();
    ASSERT( ret > 0 );
    return ret;
}

void MeshStrider::getLockedReadOnlyVertexIndexBase( 
    const unsigned char **vertexbase, 
    int& numverts,
    PHY_ScalarType& type, 
    int& stride,
    const unsigned char **indexbase,
    int & indexstride,
    int& numfaces,
    PHY_ScalarType& indicestype,
    int subpart/*=0*/ ) const
{
    Ogre::SubMesh* submesh = mMesh->getSubMesh(subpart);

    Ogre::VertexData* vertex_data = submesh->useSharedVertices ? mMesh->sharedVertexData : submesh->vertexData;

    const Ogre::VertexElement* posElem =
        vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);

    Ogre::HardwareVertexBufferSharedPtr vbuf =
        vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());

    *vertexbase =
        reinterpret_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
    // There is _no_ baseVertexPointerToElement() which takes an Ogre::Real or a double
    //  as second argument. So make it float, to avoid trouble when Ogre::Real will
    //  be comiled/typedefed as double:
    //Ogre::Real* pReal;
    float* pReal;
    posElem->baseVertexPointerToElement((void*) *vertexbase, &pReal);
    *vertexbase = (unsigned char*) pReal;

    stride = (int) vbuf->getVertexSize();

    numverts = (int) vertex_data->vertexCount;
    ASSERT( numverts );

    type = PHY_FLOAT;

    Ogre::IndexData* index_data = submesh->indexData;
    Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;

    if (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT){
        indicestype = PHY_INTEGER;
    }
    else{
        ASSERT(ibuf->getType() == Ogre::HardwareIndexBuffer::IT_16BIT);
        indicestype = PHY_SHORT;
    }

    if ( submesh->operationType == Ogre::RenderOperation::OT_TRIANGLE_LIST ){
        numfaces = (int) index_data->indexCount / 3;
        indexstride = (int) ibuf->getIndexSize()*3;
    }
    else
    if ( submesh->operationType == Ogre::RenderOperation::OT_TRIANGLE_STRIP ){
        numfaces = (int) index_data->indexCount -2;
        indexstride = (int) ibuf->getIndexSize();
    }
    else{
        ASSERT( 0 ); // not supported
    }
    
    *indexbase = reinterpret_cast<unsigned char*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
}

void MeshStrider::getLockedVertexIndexBase( unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart/*=0*/ )
{
    ASSERT( 0 );
}

void MeshStrider::unLockReadOnlyVertexBase( int subpart ) const
{
    Ogre::SubMesh* submesh = mMesh->getSubMesh(subpart);

    Ogre::VertexData* vertex_data = submesh->useSharedVertices ? mMesh->sharedVertexData : submesh->vertexData;

    const Ogre::VertexElement* posElem =
        vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);

    Ogre::HardwareVertexBufferSharedPtr vbuf =
        vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());
    
    vbuf->unlock();

    Ogre::IndexData* index_data = submesh->indexData;
    Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;
    ibuf->unlock();
}

void MeshStrider::unLockVertexBase( int subpart )
{
    ASSERT( 0 );
}

void MeshStrider::preallocateVertices( int numverts )
{
    ASSERT( 0 );
}

void MeshStrider::preallocateIndices( int numindices )
{
    ASSERT( 0 );
}