天天看点

Archie OSG Step By Step⑤ 显示位置及拾取

在第四课基础上继续。第四课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);
    }
           
Archie OSG Step By Step⑤ 显示位置及拾取
//构造函数
    CPickHandler(osg::ref_ptr<osgText::Text> updateText):_updateText(updateText)
    {
    }

    ~CPickHandler(void)
    {
    }
    
           

添加PICK拾取动作 鼠标点中时显示世界坐标系中的位置

Archie OSG Step By Step⑤ 显示位置及拾取
// 选择动作
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();

    }