在调用ogre的命令做与包围盒的选取时,有两种比较快速的方法,适合在不同需求下使用。这里选取主要是指点选。
m_windowWidth,m_windowHeight 分别指窗口的宽度和高度。
1. 射线选取:
// get camera ray
Ogre::Ray cameraRay = m_camera->getCameraToViewportRay(point.x /m_windowWidth, point.y / m_windowHeight);
Ogre::Vector3 vecPoint1 = cameraRay.getOrigin();
Ogre::Vector3 vecPoint2 = cameraRay.getPoint(300000);
vecPoint2 = vecPoint2 - vecPoint1;
vecPoint2.normalise();
// get the ray Ogre::Ray ray;
ray.setDirection(vecPoint2);
ray.setOrigin(vecPoint1);
Ogre::AxisAlignedBox box = getPickBoundingBox(); // 获取物体包围盒
if (ray.intersects(box).first)
{
return true;
}
注释:point 是鼠标在屏幕上的点,是屏幕坐标。 主要思路是:首先把屏幕坐标点转化为ogre的射线,然后调用ogre射线的命令直接与包围盒求交。 如果有交点,就会返回true。
2. 视图选取:
Ogre::Real screenLeft = (mousePoint.x - m_SelectTolerance)/m_windowWidth;
Ogre::Real screenTop = (mousePoint.y - m_SelectTolerance)/m_windowHeight;
Ogre::Real screenRight = (mousePoint.x + m_SelectTolerance)/m_windowWidth;
Ogre::Real screenBottom = (mousePoint.y + m_SelectTolerance)/m_windowHeight;
Ogre::PlaneBoundedVolume= m_camera->getCameraToViewportBoxVolume(screenLeft,screenTop, screenRight,screenBottom,false); Ogre::AxisAlignedBox box = getPickBoundingBox(); // 获取物体包围盒
if (toleranceView.intersects(box))
{
return true;
}
注释: 该方法是根据屏幕坐标点mousePoint,以及选取设置tolerance, 可以计算出在点mousePoint的tolerance范围的屏幕绝对坐标单位化值。然后调用 m_camera->getCameraToViewportBoxVolume,根据这四个坐标值,可以由camera处获得一个包围面体,然后 判断包围盒是否与这个包围面体相交。
比较两种方法的优缺点:
前者(射线选取)可以很精确的选择包围盒,速度会更快,但是不能有tolerance设置。 后者(视图选取)速度稍微差一点,但是可以设置tolerance。 故可根据具体需要,选用不同的判断方法。
另外,我自己最初在设置tolerance时,使用了一种比较笨的方法,首先把包围盒的八个点都投影到屏幕上,找到在屏幕上的最小坐标点和最大坐标 点,根据这两个点组成一个与屏幕平行的四边形,判断鼠标点是否在这个四边形的tolerance内。这样虽然可以选取,但是由于对包围盒做了粗放的估计,选取不准确,导致进一步做图元的选取,使得总体的速度大大下降。