Ogre-在三维空间中移动实体
在三维空间中,我们可能想要通过鼠标拖动实体,从而改变实体在世界坐标系中的位置。
由于鼠标的移动是在二位平面上,缺乏深度信息,如果通过鼠标的位移量来和实体的移动做一个简单的映射的话,也可以达到移动实体的目的,但是,效果可能不是我们想要的。我们想要的应该是"指哪打哪",就是说,鼠标移动到哪儿,实体就应该移动到哪。 那么,如何实现这样的功能呢?首先,我们需要选定一个参考面,实体在三维空间中的移动通常是基于一个参考面实现的,每次我们移动实体,只能在这个参考面进行。接下来,我们以鼠标所在屏幕上的点为原点,向垂直于视口方向引一条射线,该射线与参考面的交点即是实体最后应该放置的位置。 以下是具体实现方法的代码片段:
void translateEntityByMouse(Ogre::Entity* entity, Ogre::String referencePlane, const OIS::MouseEvent &endArg)
{
if (entity)
{
//获取垂直于屏幕的射线
Ogre::Ray mouseRay = mSceneMgr->getCamera("DefaultCamera")->getCameraToViewportRay(
endArg.state.X.abs / (float)endArg.state.width, endArg.state.Y.abs / (float) endArg.state.height );
Ogre::Vector3 normal;
Ogre::Real d = 0;
//选择参考平面
if (referencePlane == "XZ")
{
normal = Ogre::Vector3::UNIT_Y;
}else if (referencePlane == "XY")
{
normal = Ogre::Vector3::UNIT_Z;
}else if (referencePlane == "YZ")
{
normal = Ogre::Vector3::UNIT_X;
}
//计算射线与平面的交点
Ogre::Real nom;
Ogre::Real t;
Ogre::Real denom = normal.dotProduct(mouseRay.getDirection());
if (Ogre::Math::Abs(denom) < std::numeric_limits<Ogre::Real>::epsilon())
{
//直线与平面平行
return;
}else{
nom = normal.dotProduct(mouseRay.getOrigin()) + d;
t = -(nom / denom);
}
//计算交点
Ogre::Vector3 intersectPoint = mouseRay.getOrigin() + t * mouseRay.getDirection();
//该交点即为实体的新位置
entity->getParentNode()->setPosition(intersectPoint);
}
}
Written on April 21, 2014