学习了下OGRE中文网上的那篇中级教程后,跟据自己的情况封了一个鼠标选择类。
Selection.h
//=============================================================================
//class: 框选矩形类
//Desc: 显示鼠标框选矩形
//day: 2008/06/30
//author: 苗琳
//=============================================================================
class SelectionRectangle : public ManualObject
{
public:
SelectionRectangle(const String &name)
: ManualObject(name)
{
setRenderQueueGroup(RENDER_QUEUE_OVERLAY); //设置该渲染队列为所有层之上
setUseIdentityProjection(true); //使用单位化投影矩阵
setUseIdentityView(true); //使用单位化视图矩阵
setQueryFlags(0);
}
//-----------------------------------------------------------------------------
// name: 绘制矩形框
// Desc:
//-----------------------------------------------------------------------------
void DrawRectangle(float left, float top, float right, float bottom)
{
//转换坐标为-1 到 +1之间
left = left * 2 - 1;
right = right * 2 - 1;
top = 1 - top * 2;
bottom = 1 - bottom * 2;
//清除以前绘制的所有点
clear();
//开始绘制线带
begin("", RenderOperation::OT_LINE_STRIP);
position(left, top, -1);
position(right, top, -1);
position(right, bottom, -1);
position(left, bottom, -1);
position(left, top, -1);
end();
}
void DrawRectangle(const Vector2 &topLeft, const Vector2 &bottomRight)
{
DrawRectangle(topLeft.x, topLeft.y, bottomRight.x, bottomRight.y);
}
};
//=============================================================================
//class: 选择物体类
//Desc: 对用户选择物体的处理 , 包括框选,点选等
//day: 2008/06/30
//author: 苗琳
//=============================================================================
class CSelection
{
public:
CSelection(SceneManager* pSceneMgr , Camera* pCamera);
~CSelection(void);
//不选择所有物体
void deselectObjects();
//选择一个物体
void selectObject(MovableObject *obj);
//执行查询
void performSelection(const Vector2 &first, const Vector2 &second);
public:
Vector2 mStart, mStop; //框选开始点/结束点
SceneManager *mSceneMgr; //场景管理者
Camera* m_pCamera; //摄像机
PlaneBoundedVolumeListSceneQuery *mVolQuery; //平面体积查询器
RaySceneQuery* m_pRaySceneQuery; //射线场景查询器
std::list mSelected; //当前选择的物体列表
SelectionRectangle *mRect; //框选矩形显示类
bool mSelecting; //是否正在框选
};
Selection.cpp
//=============================================================================
//class: 选择物体类
//Desc: 对用户选择物体的处理 , 包括框选,点选等
//day: 2008/06/30
//author: 苗琳
//=============================================================================
#include "Selection.h"
//-----------------------------------------------------------------------------
// name: 构造函数
// Desc:
//-----------------------------------------------------------------------------
CSelection::CSelection(SceneManager* pSceneMgr , Camera* pCamera) : mRect(0) , mSceneMgr(pSceneMgr) , m_pCamera(pCamera)
{
//初始化框选矩形
mRect = new SelectionRectangle("SelectionRectangle");
mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(mRect);
//初始化框选/点选查询器
mVolQuery = mSceneMgr->createPlaneBoundedVolumeQuery(PlaneBoundedVolumeList()); //初始化平面体积查询器
m_pRaySceneQuery=mSceneMgr->createRayQuery(Ray()); //初始化射线场景查询器
//初始化选择状态
mSelecting = false;
mRect->setVisible(false);
}
//-----------------------------------------------------------------------------
// name: 析构函数
// Desc:
//-----------------------------------------------------------------------------
CSelection::~CSelection(void)
{
//删除查询器
mSceneMgr->destroyQuery(mVolQuery);
mSceneMgr->destroyQuery(m_pRaySceneQuery);
SafeDelete(mRect);
}
//-----------------------------------------------------------------------------
// name: 不选择所有物体
// Desc: 设置所有被选物体的包围盒清空被选物体数组
//-----------------------------------------------------------------------------
void CSelection::deselectObjects()
{
std::list::iterator itr;
for (itr = mSelected.begin(); itr != mSelected.end(); ++itr)
(*itr)->getParentSceneNode()->showBoundingBox(false);
mSelected.clear();
}
//-----------------------------------------------------------------------------
// name: 选择一个物体
// Desc: 添加一个物体到被选数组里,并且显示这个物体的包围盒
//-----------------------------------------------------------------------------
void CSelection::selectObject(MovableObject *obj)
{
obj->getParentSceneNode()->showBoundingBox(true);
mSelected.push_back(obj);
}
//-----------------------------------------------------------------------------
// name: 进行框选查询
// Desc: 在用户框选完成后调用
//-----------------------------------------------------------------------------
void CSelection::performSelection(const Vector2 &first, const Vector2 &second)
{
float left = first.x, right = second.x,
top = first.y, bottom = second.y;
//如果用户是反着框的话,转换一下坐标
if (left > right)
swap(left, right);
if (top > bottom)
swap(top, bottom);
//跟据用户框选的范围大小,判断是框选还是点选
if ((right - left) * (bottom - top) < 0.0001)
{
//right+=0.002;
//bottom+=0.002;
Ray selectRay = m_pCamera->getCameraToViewportRay(left, top);
m_pRaySceneQuery->setRay(selectRay);
m_pRaySceneQuery->setSortByDistance(true);
RaySceneQueryResult result = m_pRaySceneQuery->execute();
deselectObjects();
RaySceneQueryResult::iterator itr;
for ( itr = result.begin(); itr != result.end(); itr++ )
{
//筛选掉一些非选择性物体
if (itr->movable->getParentSceneNode()->getName()=="" ||
itr->movable->getParentSceneNode()->getName()=="eye" ||
itr->movable->getName()=="entBrush" ||
itr->movable->getName()=="Axis" ||
itr->movable->getName()=="ETTerrain/Terrain/Tile[0][0]" ||
itr->movable->getName()=="ETTerrain/Terrain/Tile[1][0]" ||
itr->movable->getName()=="ETTerrain/Terrain/Tile[0][1]" ||
itr->movable->getName()=="ETTerrain/Terrain/Tile[1][1]")
{
continue;
}
selectObject(itr->movable);
}
}
else
{
//由选择框产生四条射线,分别从选择框四个角发射
Ray topLeft = m_pCamera->getCameraToViewportRay(left, top);
Ray topRight = m_pCamera->getCameraToViewportRay(right, top);
Ray bottomLeft = m_pCamera->getCameraToViewportRay(left, bottom);
Ray bottomRight = m_pCamera->getCameraToViewportRay(right, bottom);
//以下平面定义了一个在摄像机前无限伸展的“开放锥体”
PlaneBoundedVolume vol;
vol.planes.push_back(Plane(topLeft.getPoint(3), topRight.getPoint(3), bottomRight.getPoint(3))); // 前平面
vol.planes.push_back(Plane(topLeft.getOrigin(), topLeft.getPoint(100), topRight.getPoint(100))); // 顶平面
vol.planes.push_back(Plane(topLeft.getOrigin(), bottomLeft.getPoint(100), topLeft.getPoint(100))); // 左平面
vol.planes.push_back(Plane(topLeft.getOrigin(), bottomRight.getPoint(100), bottomLeft.getPoint(100))); // 底平面
vol.planes.push_back(Plane(topLeft.getOrigin(), topRight.getPoint(100), bottomRight.getPoint(100))); // 右平面
//增加上面定义的盒子到平面体积查询中
PlaneBoundedVolumeList volList;
volList.push_back(vol);
mVolQuery->setVolumes(volList);
SceneQueryResult result = mVolQuery->execute();
//显示查询结果
deselectObjects();
SceneQueryResultMovableList::iterator itr;
for (itr = result.movables.begin(); itr != result.movables.end(); ++itr)
{
//筛选掉一些非选择性物体
if ((*itr)->getParentSceneNode()->getName()=="" ||
(*itr)->getParentSceneNode()->getName()=="eye" ||
(*itr)->getName()=="entBrush" ||
(*itr)->getName()=="Axis" )
{
continue;
}
selectObject(*itr);
}
}
}
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/miaolinvip/archive/2008/07/20/2680507.aspx