Qt 中嵌套 OSG 窗口(两种思路带源码)

Qt 中嵌套 OSG 窗口(两种思路带源码)

文章目录

说明方法一:继承于 QOpenGLWidget方法二:继承 QOpenGLWidget 和 osgViewer::Viewer其它实现更灵活的嵌套使用

说明

网上大部分操作介绍都讲得很繁琐,并且编译未必能过经我全网搜索与测试,最终总结出以下两种方法,两种方法均编译通过且完整运行

方法一:继承于 QOpenGLWidget

链接直达

Step-by-step on how to set up your CMake, Qt and OSG in draw-on-demand mode(分为1和2)两个部分

源码(就一个 main.cpp)

/*

* =====================================================================================

*

* Filename: main.cpp

*

* Description: Minimalistic project example that uses both Qt and OpenSceneGraph libraries.

*

* Version: 1.0

* Created: 30-Jun-16 10:23:06 AM

* Revision: none

* Compiler: gcc

*

* Author: Victoria Rudakova (vicrucann@gmail.com),

* Organization: vicrucann.github.io

*

* =====================================================================================

*/

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

class QtOSGWidget : public QOpenGLWidget {

public:

QtOSGWidget(QWidget *parent = 0)

: QOpenGLWidget(parent)

, _mGraphicsWindow(new osgViewer::GraphicsWindowEmbedded( this->x(), this->y(),

this->width(), this->height() ) )

, _mViewer(new osgViewer::Viewer)

// take care of HDPI screen, e.g. Retina display on Mac

, m_scale(QApplication::desktop()->devicePixelRatio()) {

osg::Cylinder *cylinder = new osg::Cylinder( osg::Vec3( 0.f, 0.f, 0.f ), 0.25f, 0.5f );

osg::ShapeDrawable *sd = new osg::ShapeDrawable( cylinder );

sd->setColor( osg::Vec4( 0.8f, 0.5f, 0.2f, 1.f ) );

osg::Geode *geode = new osg::Geode;

geode->addDrawable(sd);

osg::Camera *camera = new osg::Camera;

camera->setViewport( 0, 0, this->width(), this->height() );

camera->setClearColor( osg::Vec4( 0.9f, 0.9f, 1.f, 1.f ) );

float aspectRatio = static_cast( this->width()) / static_cast( this->height() );

camera->setProjectionMatrixAsPerspective( 30.f, aspectRatio, 1.f, 1000.f );

camera->setGraphicsContext( _mGraphicsWindow );

_mViewer->setCamera(camera);

_mViewer->setSceneData(geode);

osgGA::TrackballManipulator *manipulator = new osgGA::TrackballManipulator;

manipulator->setAllowThrow( false );

this->setMouseTracking(true);

_mViewer->setCameraManipulator(manipulator);

_mViewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);

_mViewer->realize();

}

virtual ~QtOSGWidget() {}

protected:

virtual void paintGL() {

_mViewer->frame();

}

virtual void resizeGL( int width, int height ) {

this->getEventQueue()->windowResize(this->x()*m_scale, this->y() * m_scale, width * m_scale, height * m_scale);

_mGraphicsWindow->resized(this->x()*m_scale, this->y() * m_scale, width * m_scale, height * m_scale);

osg::Camera *camera = _mViewer->getCamera();

camera->setViewport(0, 0, this->width()*m_scale, this->height()* m_scale);

}

virtual void initializeGL() {

osg::Geode *geode = dynamic_cast(_mViewer->getSceneData());

osg::StateSet *stateSet = geode->getOrCreateStateSet();

osg::Material *material = new osg::Material;

material->setColorMode( osg::Material::AMBIENT_AND_DIFFUSE );

stateSet->setAttributeAndModes( material, osg::StateAttribute::ON );

stateSet->setMode( GL_DEPTH_TEST, osg::StateAttribute::ON );

}

virtual void mouseMoveEvent(QMouseEvent *event) {

this->getEventQueue()->mouseMotion(event->x()*m_scale, event->y()*m_scale);

}

virtual void mousePressEvent(QMouseEvent *event) {

unsigned int button = 0;

switch (event->button()) {

case Qt::LeftButton:

button = 1;

break;

case Qt::MiddleButton:

button = 2;

break;

case Qt::RightButton:

button = 3;

break;

default:

break;

}

this->getEventQueue()->mouseButtonPress(event->x()*m_scale, event->y()*m_scale, button);

}

virtual void mouseReleaseEvent(QMouseEvent *event) {

unsigned int button = 0;

switch (event->button()) {

case Qt::LeftButton:

button = 1;

break;

case Qt::MiddleButton:

button = 2;

break;

case Qt::RightButton:

button = 3;

break;

default:

break;

}

this->getEventQueue()->mouseButtonRelease(event->x()*m_scale, event->y()*m_scale, button);

}

virtual void wheelEvent(QWheelEvent *event) {

int delta = event->delta();

osgGA::GUIEventAdapter::ScrollingMotion motion = delta > 0 ?

osgGA::GUIEventAdapter::SCROLL_UP : osgGA::GUIEventAdapter::SCROLL_DOWN;

this->getEventQueue()->mouseScroll(motion);

}

virtual bool event(QEvent *event) {

bool handled = QOpenGLWidget::event(event);

this->update();

return handled;

}

private:

osgGA::EventQueue *getEventQueue() const {

osgGA::EventQueue *eventQueue = _mGraphicsWindow->getEventQueue();

return eventQueue;

}

osg::ref_ptr _mGraphicsWindow;

osg::ref_ptr _mViewer;

qreal m_scale;

};

int main(int argc, char **argv) {

#if QT_VERSION >= QT_VERSION_CHECK(5,6,0)

QApplication::setAttribute(Qt::AA_DisableHighDpiScaling);

#else

qputenv("QT_DEVICE_PIXEL_RATIO", QByteArray("1"));

#endif

QApplication qapp(argc, argv);

QMainWindow window;

QtOSGWidget *widget = new QtOSGWidget(&window);

window.setCentralWidget(widget);

window.show();

return qapp.exec();

}

效果

方法二:继承 QOpenGLWidget 和 osgViewer::Viewer

链接直达

Qt中嵌入OSG控件的方法

源码(分三部分,OsgContainer.h,OsgContainer.cpp,main.cpp)

1. OsgContainer.h

#ifndef OSGCONTAINER_H

#define OSGCONTAINER_H

#include

#include

class QInputEvent;

class OsgContainer : public QOpenGLWidget, public osgViewer::Viewer {

Q_OBJECT

public:

OsgContainer(QWidget *parent = 0);

~OsgContainer();

bool event(QEvent *event);

void setKeyboardModifiers(QInputEvent *event);

void keyPressEvent(QKeyEvent *event);

void keyReleaseEvent(QKeyEvent *event);

void mousePressEvent(QMouseEvent *event);

void mouseReleaseEvent(QMouseEvent *event);

void mouseDoubleClickEvent(QMouseEvent *event);

void mouseMoveEvent(QMouseEvent *event);

void wheelEvent(QWheelEvent *event);

void resizeEvent(QResizeEvent *event);

void moveEvent(QMoveEvent *event);

void timerEvent(QTimerEvent *);

osgViewer::Viewer *getOSGViewer() {

return this;

}

osg::Group *getRoot() {

return root;

}

protected:

virtual void paintGL();

private:

void init3D();

osg::ref_ptr createCamera(int x, int y, int w, int h);

private:

osg::ref_ptr root;

osgViewer::GraphicsWindow *window;

};

#endif // OSGCONTAINER_H

2. OsgContainer.cpp

#include "OsgContainer.h"

#include

#include

#include

#include

#include

#include

#include

OsgContainer::OsgContainer(QWidget *parent)

: QOpenGLWidget(parent) {

init3D();

setMouseTracking(true);

setFocusPolicy(Qt::StrongFocus);

}

OsgContainer::~OsgContainer() {

}

bool OsgContainer::event(QEvent *event) {

switch (event->type()) {

case QEvent::TouchBegin:

case QEvent::TouchEnd:

case QEvent::TouchUpdate: {

QList touchPoints = static_cast(event)->touchPoints();

unsigned int id = 0;

unsigned int tapCount = touchPoints.size();

osg::ref_ptr osgEvent(NULL);

osgGA::GUIEventAdapter::TouchPhase phase = osgGA::GUIEventAdapter::TOUCH_UNKNOWN;

foreach(const QTouchEvent::TouchPoint &touchPoint, touchPoints) {

if (!osgEvent) {

if (event->type() == QEvent::TouchBegin) {

phase = osgGA::GUIEventAdapter::TOUCH_BEGAN;

osgEvent = window->getEventQueue()->touchBegan(id, osgGA::GUIEventAdapter::TOUCH_BEGAN, touchPoint.pos().x(), touchPoint.pos().y());

} else if (event->type() == QEvent::TouchEnd) {

phase = osgGA::GUIEventAdapter::TOUCH_ENDED;

osgEvent = window->getEventQueue()->touchEnded(id, osgGA::GUIEventAdapter::TOUCH_ENDED, touchPoint.pos().x(), touchPoint.pos().y(), tapCount);

} else if (event->type() == QEvent::TouchUpdate) {

phase = osgGA::GUIEventAdapter::TOUCH_MOVED;

osgEvent = window->getEventQueue()->touchMoved(id, osgGA::GUIEventAdapter::TOUCH_MOVED, touchPoint.pos().x(), touchPoint.pos().y());

}

} else {

osgEvent->addTouchPoint(id, osgGA::GUIEventAdapter::TOUCH_ENDED, touchPoint.pos().x(), touchPoint.pos().y());

osgEvent->addTouchPoint(id, phase, touchPoint.pos().x(), touchPoint.pos().y());

}

id++;

}

break;

}

default:

break;

}

return QOpenGLWidget::event(event);

}

void OsgContainer::setKeyboardModifiers(QInputEvent *event) {

int modkey = event->modifiers() & (Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier);

unsigned int mask = 0;

if (modkey & Qt::ShiftModifier) {

mask |= osgGA::GUIEventAdapter::MODKEY_SHIFT;

}

if (modkey & Qt::ControlModifier) {

mask |= osgGA::GUIEventAdapter::MODKEY_CTRL;

}

if (modkey & Qt::AltModifier) {

mask |= osgGA::GUIEventAdapter::MODKEY_ALT;

}

window->getEventQueue()->getCurrentEventState()->setModKeyMask(mask);

update();

}

void OsgContainer::keyPressEvent(QKeyEvent *event) {

setKeyboardModifiers(event);

window->getEventQueue()->keyPress(event->key());

QOpenGLWidget::keyPressEvent(event);

update();

}

void OsgContainer::keyReleaseEvent(QKeyEvent *event) {

setKeyboardModifiers(event);

window->getEventQueue()->keyRelease(event->key());

QOpenGLWidget::keyReleaseEvent(event);

update();

}

void OsgContainer::mousePressEvent(QMouseEvent *event) {

int button = 0;

switch (event->button()) {

case Qt::LeftButton: button = 1; break;

case Qt::MidButton: button = 2; break;

case Qt::RightButton: button = 3; break;

case Qt::NoButton: button = 0; break;

default: button = 0; break;

}

setKeyboardModifiers(event);

window->getEventQueue()->mouseButtonPress(event->x(), event->y(), button);

update();

}

void OsgContainer::mouseReleaseEvent(QMouseEvent *event) {

int button = 0;

switch (event->button()) {

case Qt::LeftButton: button = 1; break;

case Qt::MidButton: button = 2; break;

case Qt::RightButton: button = 3; break;

case Qt::NoButton: button = 0; break;

default: button = 0; break;

}

setKeyboardModifiers(event);

window->getEventQueue()->mouseButtonRelease(event->x(), event->y(), button);

QOpenGLWidget::mouseReleaseEvent(event);

update();

}

void OsgContainer::mouseDoubleClickEvent(QMouseEvent *event) {

int button = 0;

switch (event->button()) {

case Qt::LeftButton: button = 1; break;

case Qt::MidButton: button = 2; break;

case Qt::RightButton: button = 3; break;

case Qt::NoButton: button = 0; break;

default: button = 0; break;

}

setKeyboardModifiers(event);

window->getEventQueue()->mouseDoubleButtonPress(event->x(), event->y(), button);

QOpenGLWidget::mouseDoubleClickEvent(event);

update();

}

void OsgContainer::mouseMoveEvent(QMouseEvent *event) {

setKeyboardModifiers(event);

window->getEventQueue()->mouseMotion(event->x(), event->y());

QOpenGLWidget::mouseMoveEvent(event);

update();

}

void OsgContainer::wheelEvent(QWheelEvent *event) {

setKeyboardModifiers(event);

window->getEventQueue()->mouseScroll(

event->orientation() == Qt::Vertical ?

(event->delta() > 0 ? osgGA::GUIEventAdapter::SCROLL_UP : osgGA::GUIEventAdapter::SCROLL_DOWN) :

(event->delta() > 0 ? osgGA::GUIEventAdapter::SCROLL_LEFT : osgGA::GUIEventAdapter::SCROLL_RIGHT));

QOpenGLWidget::wheelEvent(event);

update();

}

void OsgContainer::resizeEvent(QResizeEvent *event) {

const QSize &size = event->size();

window->resized(x(), y(), size.width(), size.height());

window->getEventQueue()->windowResize(x(), y(), size.width(), size.height());

window->requestRedraw();

// const QSize& oldSize = event->oldSize();

// int oldWidth = oldSize.width();

// int oldHeight = oldSize.height();

// int newWidth = size.width();

// int newHeight = size.height();

// double widthChangeRatio = double(newWidth) / double(oldWidth);

// double heigtChangeRatio = double(newHeight) / double(oldHeight);

// double aspectRatioChange = widthChangeRatio / heigtChangeRatio;

QOpenGLWidget::resizeEvent(event);

}

void OsgContainer::moveEvent(QMoveEvent *event) {

const QPoint &pos = event->pos();

window->resized(pos.x(), pos.y(), width(), height());

window->getEventQueue()->windowResize(pos.x(), pos.y(), width(), height());

QOpenGLWidget::moveEvent(event);

}

void OsgContainer::timerEvent(QTimerEvent *) {

update();

}

void OsgContainer::paintGL() {

if (isVisibleTo(QApplication::activeWindow())) {

frame();

}

}

void OsgContainer::init3D() {

root = new osg::Group;

root->setName("Root");

setCamera(createCamera(0, 0, width(), height()));

osg::ref_ptr manipulator = new osgGA::TrackballManipulator;

setCameraManipulator(manipulator);

addEventHandler(new osgViewer::StatsHandler);

addEventHandler(new osgViewer::ThreadingHandler());

addEventHandler(new osgViewer::HelpHandler);

addEventHandler(new osgGA::StateSetManipulator(this->getCamera()->getOrCreateStateSet()));

setThreadingModel(osgViewer::Viewer::SingleThreaded);

root->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::ON);

root->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);

setSceneData(root);

// setRunFrameScheme(ON_DEMAND);

startTimer(10);

}

osg::ref_ptr OsgContainer::createCamera(int x, int y, int w, int h) {

window = new osgViewer::GraphicsWindowEmbedded(x, y, w, h);

// osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();

osg::ref_ptr traits = new osg::GraphicsContext::Traits;

traits->windowDecoration = true;

traits->x = x;

traits->y = y;

traits->width = w;

traits->height = h;

traits->doubleBuffer = true;

traits->sharedContext = 0;

osg::ref_ptr camera = new osg::Camera;

camera->setGraphicsContext(window);

camera->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));

camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

camera->setProjectionMatrixAsPerspective(

30.0f, double(traits->width) / double(traits->height), 1.0f, 10000.0f);

camera->setClearColor(osg::Vec4(0.3, 0.3, 0.6, 0.1));

return camera.release();

}

3. main.cpp

#include "QtOSG3.h"

#include

#include

#include "OsgContainer.h"

int main(int argc, char *argv[]) {

QApplication a(argc, argv);

QMainWindow window;

OsgContainer *osgViewer = new OsgContainer(&window); //(记得提前声明哦)

window.setCentralWidget(osgViewer);

window.show();

return a.exec();

}

效果

其它实现

以下实现方法或多或少有些问题

Qt中嵌入OSG,结论:编译通过并且可以运行,但是窗口会一闪而过,且不好控制OSG 与QT 结合,结论:编译不过,错误 14 error LNK2001: 无法解析的外部符号 “public: virtual void __cdecl QGLWidget::updateOverlayGL(void)” (?updateOverlayGL@QGLWidget@@UEAAXXZ) F:\Project_CPlus\QtOSG2\QtOSG2\main.obj QtOSG2将OSG嵌入QT窗口系统中,实现拖拽界面,结论:编译不过,提示缺少 OsgLib.h,我也不知道这个文件是自带的还是自己写的…osg与Qt结合编程,结论:编译不过其它…

更灵活的嵌套使用

为了能够更加灵活方便的使用嵌套窗口,我们可以在 QtCreator 中拖拽 QOpenGLWidget ,然后将其提升为自己定义的 OSGWidget

eg 友情参考链接:Qt自定义控件以及控件的提升

评论留言