Qt 中嵌套 OSG 窗口(两种思路带源码)
文章目录说明Demo说明网上大部分操作介绍都讲得很繁琐,并且编译未必能过在网上找到这么一个讲解,感觉很好链接:Step-by-step on how to set up your CMake, Qt and OSG in draw-on-demand mode(分为1和2)两个部分Demo/** =======================================...
·
说明
- 网上大部分操作介绍都讲得很繁琐,并且编译未必能过
- 经我全网搜索与测试,最终总结出以下两种方法,两种方法均编译通过且完整运行
方法一:继承于 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 <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <QApplication>
#include <QMainWindow>
#include <QOpenGLWidget>
#include <QMouseEvent>
#include <QWheelEvent>
#include <QDesktopWidget>
#include <QScreen>
#include <QtGlobal>
#include <QWindow>
#include <osg/ref_ptr>
#include <osgViewer/GraphicsWindow>
#include <osgViewer/Viewer>
#include <osg/Camera>
#include <osg/ShapeDrawable>
#include <osg/StateSet>
#include <osg/Material>
#include <osgGA/EventQueue>
#include <osgGA/TrackballManipulator>
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<float>( this->width()) / static_cast<float>( 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<osg::Geode *>(_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<osgViewer::GraphicsWindowEmbedded> _mGraphicsWindow;
osg::ref_ptr<osgViewer::Viewer> _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
链接直达
源码(分三部分,OsgContainer.h,OsgContainer.cpp,main.cpp)
1. OsgContainer.h
#ifndef OSGCONTAINER_H
#define OSGCONTAINER_H
#include <QOpenGLWidget>
#include <osgViewer/Viewer>
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<osg::Camera> createCamera(int x, int y, int w, int h);
private:
osg::ref_ptr<osg::Group> root;
osgViewer::GraphicsWindow *window;
};
#endif // OSGCONTAINER_H
2. OsgContainer.cpp
#include "OsgContainer.h"
#include <QInputEvent>
#include <osg/MatrixTransform>
#include <osgDB/ReadFile>
#include <osgGA/MultiTouchTrackballManipulator>
#include <osgGA/StateSetManipulator>
#include <osgViewer/ViewerEventHandlers>
#include <QApplication>
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<QTouchEvent::TouchPoint> touchPoints = static_cast<QTouchEvent *>(event)->touchPoints();
unsigned int id = 0;
unsigned int tapCount = touchPoints.size();
osg::ref_ptr<osgGA::GUIEventAdapter> 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<osgGA::TrackballManipulator> 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<osg::Camera> 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<osg::GraphicsContext::Traits> 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<osg::Camera> 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 <QtWidgets/QApplication>
#include <QMainWindow>
#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自定义控件以及控件的提升
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
已为社区贡献5条内容
所有评论(0)