What are you really want to achieve? btMotionState is just a two-funcs interfaces: one for getting "user" matrix from user to physics (usually kinematic objects), and one for setting it from physics to user (dynamic objects).
Obviously it's better to extend/wrap this class for additional functionality. I'm using such class for a subscription-based notifications. Subscribers that want physics->user transform update notification are inherit from IMotionStateCallback . Small note: I'm using Marmalade SDK CIwArray container here, you should update this code for STL or other containers a bit.
Code:
//===========================================================================
class IMotionStateCallback
{
public:
virtual void OnMotionStateChanged ( const btTransform& worldTrans ) = 0;
};
//===========================================================================
class MotionState : public btMotionState
{
public:
MotionState ( const btTransform& startTrans = btTransform::getIdentity())
: worldTrans_ ( startTrans )
, stateChangedCallbacks_ ()
{ }
//---------------------------------------------------------------------------
// btMotionState interface.
/// Synchronizes world transform from user to physics
virtual void getWorldTransform ( btTransform& centerOfMassWorldTrans ) const
{
centerOfMassWorldTrans = worldTrans_;
}
///synchronizes world transform from physics to user
///Bullet only calls the update of worldtransform for active objects
virtual void setWorldTransform ( const btTransform& centerOfMassWorldTrans )
{
worldTrans_ = centerOfMassWorldTrans;
if (!stateChangedCallbacks_.empty())
{
for (MotionStateCallbacks_t::const_iterator it = stateChangedCallbacks_.begin(),
it_end = stateChangedCallbacks_.end(); it != it_end; ++it)
{
(*it)->OnMotionStateChanged (worldTrans_);
}
}
}
// Internal interface.
const btTransform& getWorldTransform () const
{
return worldTrans_;
}
void setWorldTransform ( const btTransform& centerOfMassWorldTrans
, bool invokeCallbacks = true )
{
worldTrans_ = centerOfMassWorldTrans;
if (invokeCallbacks && !stateChangedCallbacks_.empty())
{
for (MotionStateCallbacks_t::const_iterator it = stateChangedCallbacks_.begin(),
it_end = stateChangedCallbacks_.end(); it != it_end; ++it)
{
(*it)->OnMotionStateChanged (worldTrans_);
}
}
}
void AddMotionStateCallback ( IMotionStateCallback* callback )
{
IwAssert(PHYSICS, stateChangedCallbacks_.find ( callback ) < 0);
stateChangedCallbacks_.push_back ( callback );
}
void RemoveMotionStateCallback ( IMotionStateCallback* callback )
{
IwAssert(PHYSICS, stateChangedCallbacks_.find (callback) >= 0);
stateChangedCallbacks_.find_and_remove_fast ( callback );
}
private:
typedef CIwArray<IMotionStateCallback*> MotionStateCallbacks_t;
btTransform worldTrans_;
MotionStateCallbacks_t stateChangedCallbacks_;
};