OSG学习二

OSG学习记录二

前言

上一节主要讲了,在编译OSG过程中遇到的一些问题,希望能对大家在编译OSG有所帮助。还顺便简单提了一下如何在Qt中嵌入OSG。

嵌入OSG

先上代码吧!
头文件

// OSGViewWidget.h
#ifndef __OSG_VIEW_WIDGET_H__
#define __OSG_VIEW_WIDGET_H__

#include <osgQt/GraphicsWindowQt>
#include <osgViewer/Viewer>
#include "TravelManipulator.h"

class OSGViewWidget : public osgQt::GLWidget, public osgViewer::Viewer
{
    Q_OBJECT

public:
    OSGViewWidget(QWidget* parent = 0);
    ~OSGViewWidget(void);

public:
    osg::ref_ptr<TM::TravelManipulator> GetCurrentManipulator() {return m_pTravelManipulator;}

protected:
    virtual void resizeEvent( QResizeEvent* event );
    virtual void paintEvent(QPaintEvent* event);

private:
    osg::ref_ptr<TM::TravelManipulator> m_pTravelManipulator;


};

#endif // __OSG_VIEW_WIDGET_H__

Cpp文件

// OSGViewWidget.cpp
#include "OSGViewWidget.h"
#include <osgGA/TrackballManipulator>


OSGViewWidget::OSGViewWidget(QWidget* parent /*= 0*/)
    :osgQt::GLWidget(parent),
    m_pTravelManipulator(NULL)
{
    this->setThreadingModel(osgViewer::ViewerBase::SingleThreaded);
    this->_gw = new osgQt::GraphicsWindowQt(this);

//     osg::ref_ptr<osg::Camera> camera = new osg::Camera;
//     camera->setGraphicsContext(this->_gw);
//     camera->setClearColor( osg::Vec4(0.2, 0.2, 0.6, 1.0) );
//     camera->setClearDepth(1.0);
//     camera->setViewport( new osg::Viewport(0, 0, _gw->getTraits()->width, _gw->getTraits()->height) );
//     GLenum buffer = _gw->getTraits()->doubleBuffer ? GL_BACK : GL_FRONT;
//     camera->setDrawBuffer(buffer);
//     camera->setReadBuffer(buffer);
//     camera->setProjectionMatrixAsPerspective(30.f,
//         static_cast<double>(_gw->getTraits()->width)/static_cast<double>(_gw->getTraits()->height),
//         10.0f, 10000.0f );
//     // 对比两种设置Camera方式,调用setGlobalDefaults()的图像区别比较大
//     camera->getOrCreateStateSet()->setGlobalDefaults();
//     this->setCamera(camera.get());

    this->getCamera()->setGraphicsContext(_gw);
    this->getCamera()->setViewport( new osg::Viewport(0, 0, _gw->getTraits()->width, _gw->getTraits()->height));
    this->getCamera()->setClearColor(osg::Vec4(0.2,0.2,0.6, 1.0f));
    GLenum buffer = _gw->getTraits()->doubleBuffer ? GL_BACK : GL_FRONT;
    getCamera()->setDrawBuffer(buffer);
    getCamera()->setReadBuffer(buffer);
    getCamera()->setClearDepth(1.0);

    osgGA::TrackballManipulator* trackBallMpl = new osgGA::TrackballManipulator();
    setCameraManipulator(trackBallMpl);
//     m_pTravelManipulator = TM::TravelManipulator::CreateManipulator(this);
// 
//     setCameraManipulator(m_pTravelManipulator.get());

}


OSGViewWidget::~OSGViewWidget(void)
{
}

void OSGViewWidget::resizeEvent(QResizeEvent* event)
{
    GLWidget::resizeEvent(event);

    if (_gw->getTraits()->height > 0)
    {
        getCamera()->setViewport(0 ,0, _gw->getTraits()->width, _gw->getTraits()->height);
        // 分析OSG源码后,相机的坐标系统影响home初始化
        getCamera()->setProjectionMatrixAsPerspective(
            60.f, static_cast<double>(_gw->getTraits()->width)/static_cast<double>(_gw->getTraits()->height), 1.0f, 10000.0f );
    }

    frame();
}

void OSGViewWidget::paintEvent(QPaintEvent* event)
{
    frame();

    update();
}
Created with Raphaël 2.1.2 osgQt::GLWidget与QGLWidget继承关系 osgQt_GLWidget osgQt_GLWidget QGLWidget QGLWidget osgQt::GLWidget继承于QGLWidget
Created with Raphaël 2.1.2 osgQt:GraphicsWindowQt与osgViewer:GraphicsWindow继承关系 osgQt_GraphicsWindowQt osgQt_GraphicsWindowQt osgViewer_GraphicsWindow osgViewer_GraphicsWindow osg_GraphicsContext osg_GraphicsContext osgQt::GraphicsWindowQt继承于osgViewer::GraphicsWindow osgViewer::GraphicsWindow继承于osg::GraphicsContext

首先声明一个OSGViewWidget继承osgQt::GLWidget和osgViewer::Viewer,在Qt中嵌入OSG主要就是使用该类进行显示OSG的三维图像。在OSGViewWidget中配置osgViewer::Viewer的相机参数以及漫游方式,配置osgViewer::Viewer的相机有两种方式
1. 自己new一个Camera后,然后配置Camera的基本配置,最后通过setCamera将相机设置到osgViewer::Viewer中;
2. 通过调用getCamera()函数来创建默认的Camera,然后配置Camera参数;

通过阅读osgViewerQt例子中的代码可知,在Qt5.0以后的版本中必须使用单线程模式,所以在osgViewer::Viewer中必须设置this->setThreadingModel(osgViewer::ViewerBase::SingleThreaded);

我们要将OSG显示在Qt中除了需要构建一个Widget之外,还必须构建osg::GraphicsContext,这样才能将osg显示在窗口中,GraphicsContext顾名思义则是图像上下文。

在Camera类的成员函数中,setGraphicContext()函数的工作是设置相机对应的图形设备对象,换句话说,下面要介绍的GraphicsContext类就是图形设备对象的载体。用一句话来描述的话,GraphicsContext是任意图形子系统的抽象层接口,它提供了统一的图形设备操作函数,用来实现渲染结果和底层设备的交互;同时它还具有平台无关性,因而将OSG的渲染过程与操作系统平台剥离开来,使两者相互独立。用户即可以将渲染的内容传递给Windows或者X11的窗口与像素缓存对象,也可以自定义一个支持OpenGL的图形设备,并将结果反映在其上。

图形设备对象的主要工作是提供场景渲染结果的载体,这个载体可以显示缓存,进而绘制到一个图像窗口中,也可以是其他特殊的缓存对象,从而实现复杂的渲染和图像多次曝光等功能,创建一个图像设备不能简单地使用new运算符,因为GraphicContext类是一个不能被实例化的抽象类(这个体现在valid()等一大批纯虚函数上);通常应当使用createContext()静态函数,自动根据当前的用户环境和特性参数traits,构建一个平台相关的图形设备对象。

所以我们在代码中必须要this->_gw = new osgQt::GraphicsWindowQt(this),然后将_gw设置到Camera中。

Qt的Widget在显示时,必须调用paint来将控件和图像绘制到屏幕上,所以在widget中显示OSG图像时也必须不停的绘制OSG,所以我们必须在虚函数paintevent中不停的调用osgViewer的frame()函数,来实时的绘制osg图像。

当widget改变窗口大小时,我们也必须实时的修改Camera的视口范围,否则改变Widget大小后osg的图像无法跟着一起改变,所以我们必须在resizeEvent中重新更新OSGViewer::Viewer的Camera视口大小以及Camera的投影坐标。

到这一步,我们已经完成在Qt中嵌入OSG的核心代码,后面调用OSG时只需add这个Widget即可,如下所示:

ui.setupUi(this);
m_pOSGWidget = new OSGViewWidget(this);
ui.gridLayout->addWidget(m_pOSGWidget);

后面即可在Qt中添加相应的模型内容。

代码

所有代码见(https://github.com/Timo-China/OSGQtDemo)[https://github.com/Timo-China/OSGQtDemo]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值