Cylinder 之 osg:
osg::Cylinder* cylinder = new osg::Cylinder();
圆柱Cylinder:质心(0.0, 0.0, 0.0),半径和高1.0,圆柱的轴与z平行。
osg::Cylinder* cylinder = new osg::Cylinder(osg::Vec3(1.0f, 0.0f, 0.0f), radius * 0.5, height * 1.0);
cylinder->setRotation(osg::Quat(osg::PI_4, osg::Vec3(0.0, 1.0, 0.0)));
可见cylinder可以通过矩阵变换接口对圆柱原始顶点做平移与旋转操作,且顺序为先旋转后平移。
Cylinder 之 bullet
bullet中btCylinderShapeZ(btVector3(0.5, 0.5, 0.5))与osg::Cylinder()等价,区别在于bullet没有提供初始矩阵去修改碰撞模型的原始顶点,为了达到这一效果我们可以继承btMotionState类通过重写矩阵接口,添加相应的初始矩阵
class KinematicMatrixTransform: public osg::MatrixTransform, public btMotionState
{
typedef osg::MatrixTransform inherited;
typedef btMotionState inheritedbt;
public:
KinematicMatrixTransform(osg::Matrix start = osg::Matrix::identity(), osg::Matrix offset = osg::Matrix::identity())
:mWorldTrans(tobtMatrix(start)), mOffsetTrans(tobtMatrix(offset)){}
void setMatrix(const osg::Matrix& mat)
{
inherited::setMatrix(mat);
setWorldTransform(tobtMatrix(mat));
}
virtual void getWorldTransform(btTransform & worldTrans) const
{
worldTrans = mWorldTrans * mOffsetTrans;
}
virtual void setWorldTransform(const btTransform& worldTrans)
{
mWorldTrans = worldTrans;
}
private:
osg::Matrix toMatrix(const btTransform& t)
{
btScalar ogl[16];
t.getOpenGLMatrix(ogl);
osg::Matrix m(ogl);
return m;
}
btTransform tobtMatrix(osg::Matrix m)
{
const osg::Matrix::value_type* oPtr = m.ptr();
btScalar bPtr[16];
int idx;
for (idx=0; idx<16; idx++)
bPtr[idx] = oPtr[idx];
btTransform t;
t.setFromOpenGLMatrix(bPtr);
return t;
}
private:
btTransform mWorldTrans;
btTransform mOffsetTrans;
};
该类重点在于对btMotionState虚函数:getWorldTransform、setWorldTransform的实现;成员变量mOffsetTrans用于存储osg::Cylinder的 rotate * translate矩阵。
-------------------------------------------------------注意事项!---------------------------------------------------------------
bullet中总共有三种刚体Static, Dynamic and Kinematic ,KinematicMatrixTransform主要用于解决Kinematic类型与osg可视化模型的匹配,由于Dynamic和static类型的刚体getWorldTransform只会在bullet初始化时调用一次,所以并不适用。