标签:
OSG提供了几种manipulator(操作器),已经能胜任很多场合了。但玩过射击类游戏的都比较熟悉使用按键的方式控制人物角色的移动,自己也想来实现一个,于是参考了OSG程序设计 一书,进行实现。
1、视口矩阵的运算方式:
osg::Matrixd CustomManipulator::getMatrix() const
{
// 返回视口的矩阵
osg::Matrixd mat;
mat.makeRotate(m_vecRotation._v[0], osg::Vec3d(1.0, 0.0, 0.0),
m_vecRotation._v[1], osg::Vec3d(0.0, 1.0, 0.0),
m_vecRotation._v[2], osg::Vec3d(0.0, 0.0, 1.0));
return mat * osg::Matrixd::translate(m_vecPosition);
}
2、视口矩阵的逆矩阵:这个就比较好求了,直接对视口矩阵求逆
osg::Matrixd CustomManipulator::getInverseMatrix() const
{
osg::Matrixd mat;
mat.makeRotate(m_vecRotation._v[0], osg::Vec3d(1.0, 0.0, 0.0),
m_vecRotation._v[1], osg::Vec3d(0.0, 1.0, 0.0),
m_vecRotation._v[2], osg::Vec3d(0.0, 0.0, 1.0));
// 返回视口的逆矩阵
return osg::Matrixd::inverse(mat * osg::Matrixd::translate(m_vecPosition));
}
3、移动过程中的碰撞检测
使用的是比较简单的十字交叉方式进行碰撞检测,在实际运用中,我们需要使用包围盒的方式,也就是需要十二条线进行碰撞检测。
osg::Vec3d newPos = m_vecPosition + delta;
osgUtil::IntersectVisitor iv;
osg::ref_ptr<osg::LineSegment> lineWidth = new osg::LineSegment(newPos, m_vecPosition);
osg::ref_ptr<osg::LineSegment> lineHeight = new osg::LineSegment(
newPos + osg::Vec3d(0, 0, m_dSpeed), newPos - osg::Vec3d(0, 0, m_dSpeed));
iv.addLineSegment(lineWidth);
iv.addLineSegment(lineHeight);
m_pCollisionNode->accept(iv);
if (!iv.hits())
{
// 碰撞检测失败,可以移动
m_vecPosition += delta;
}
所有完整代码已上传到我的GitHub, 传送门在此OSG漫游。
PS:里面不光有漫游的代码,也有前面博客中提及的所有代码。
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/chlk118/article/details/47261543