Skip to main content

History: BulletMeshStrider

Source of version: 3 (current)

Copy to clipboard
            {maketoc}

!Mesh Strider for [http://www.bulletphysics.com/|Bullet] physics engine
This is subclass of [http://www.continuousphysics.com/Bullet/BulletFull/classbtStridingMeshInterface.html|btStridingMeshInterface], which allows one to share the same geometry between both graphics and collision meshes

!!MeshStrider.h
{CODE(wrap="1", colors="c++")}#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__{CODE}

!!MeshStrider.cpp
{CODE(wrap="1", colors="c++")}#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 );
}
{CODE}