在第四课基础上继续。第四课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(); }