在第四课基础上继续。第四课src链接
参考《OSG三维渲染引擎编程指南》显示位置及拾取示例
HUD和Camera可能冲突,还不懂怎么设置两个Camera,目前程序还有问题。学习之后再回来解决
添加CPickHandler事件处理类,选择内联,公有继承osgGA::GUIEventHandler
添加保护成员变量
protected:
//得到当前视图矩阵
osg::Vec3 position;
osg::Vec3 center;
osg::Vec3 up;
//传递一个文字对象
osg::ref_ptr<osgText::Text> _updateText;
添加内联函数
// 设置显示内容
void SetLabel(const std::string& name)
{
_updateText->setText(name);
}
//构造函数
CPickHandler(osg::ref_ptr<osgText::Text> updateText):_updateText(updateText)
{
}
~CPickHandler(void)
{
}
添加PICK拾取动作 鼠标点中时显示世界坐标系中的位置
// 选择动作
void CPickHandler::Pick(osg::ref_ptr<osgViewer::Viewer> viewer ,const osgGA::GUIEventAdapter& ea)
{
// 创建一个线段交集检测对象
osgUtil::LineSegmentIntersector::Intersections intersections;
std::string gdlist = "";
// 申请一个流
std::ostringstream os;
//得到鼠标的位置
float x = ea.getX();
float y = ea.getY();
//如果没有发生交集运算或鼠标没有点中物体
if (viewer->computeIntersections(x, y, intersections))
{
for (osgUtil::LineSegmentIntersector::Intersections::iterator hitr = intersections.begin();
hitr != intersections.end();
hitr++)
{
//
os<<"Mouse int World X:" << hitr->getWorldIntersectPoint().x()<<
"Y:" << hitr->getWorldIntersectPoint().y()<<
"Z:" << hitr->getWorldIntersectPoint().z()<<std::endl;
}
} // end viewer computeIntersections
//
os<<"Viewer Position X:"<<position[0]<<"Y:"<<position[1]<<"Z:"<<position[2]<<std::endl;
gdlist += os.str();
//设置显示内容
SetLabel(gdlist);
}
在InitSceneGraph中添加
updatetext = new osgText::Text();
hudText = new CCreateHUD;
//把模型加入到场景中
mRoot->addChild(mModel.get());
mRoot->addChild(hudText->createHUD(updatetext.get()));
添加事件处理虚函数handle,注意aa前不加const,才能利用dynamic_cast 进行动态转换
GUIEventAdapter是事件适配器
GUIActionAdapter是动作适配器,主要包含系统执行的动作
// 事件处理
bool CPickHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
{
switch(ea.getEventType())
{
//每一帧
case (osgGA::GUIEventAdapter::FRAME):
{
osg::ref_ptr<osgViewer::Viewer> viewer = dynamic_cast<osgViewer::Viewer*>(&aa);
//得到视图矩阵
viewer->getCamera()->getViewMatrixAsLookAt(position,center,up);
if (viewer)
{
//执行pick动作
Pick(viewer.get(),ea);
}
return false;
}
default:
return false;
}
return false;
}
在CoreOSG.cpp中包含PICK头文件
#include "PickHandler.h"
并添加事件
//设置数据
mViewer->setSceneData(mRoot.get());
//添加事件
mViewer->addEventHandler(new CArchieHandler(mRoot.get()));
//PICK
mViewer->addEventHandler(new CPickHandler(updatetext.get()));
修改初始文档名
CMy3DVisionDoc::CMy3DVisionDoc()
{
// 定义一个默认打开文件
m_csFileName="lz.osg";
}
在PickHandler.h中创建HUD
HUD is short for Heads Up Display平视显示器
HUD是利用光学反射的原理,将重要的相关资讯投射在眼睛前方的一片玻璃上面,高度大致与眼睛成水平,投射的文字和影像调整在焦距无限远的距离上面,飞行员透过HUD往前方看的时候,能够轻易的将外界的景象与HUD显示的资料融合在一起。
//创建HUD
osg::ref_ptr<osg::Node> createHUD(osg::ref_ptr<osgText::Text> updateText)
{
//创建一个相机
osg::ref_ptr<osg::Camera> hudCamera = new osg::Camera;
//设置绝对帧引用
hudCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
//设置正投影矩阵
hudCamera->setProjectionMatrixAsOrtho2D(0,1440,0,900);
//设置视图矩阵
hudCamera->setViewMatrix(osg::Matrix::identity());
//设置渲染顺序为POST
hudCamera->setRenderOrder(osg::Camera::POST_RENDER);
//清除深度缓存
hudCamera->setClearMask(GL_DEPTH_BUFFER_BIT);
//设置字体
std::string timesFont("fonts//cour.ttf");//注意要添加此字体
//设置位置
osg::Vec3 position = osg::Vec3(700,900,0.0);
osg::ref_ptr<osg::Geode> geode = new osg::Geode();
osg::ref_ptr<osg::StateSet> stateset = geode->getOrCreateStateSet();
//关闭光照
stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
//关闭深度测试
stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
geode->addDrawable(updateText.get());
hudCamera->addChild(geode.get());
updateText->setCharacterSize(20.0f);
updateText->setFont(timesFont);
updateText->setColor(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
updateText->setText("");
updateText->setPosition(position);
//设置数据变量为DYNAMIC
updateText->setDataVariance(osg::Object::DYNAMIC);
return hudCamera.get();
}