最近,编译了新版的osg和osgEarth库,发现在新版代码包中,osgQt模块已经单独剥离到一个项目中,不再和osg代码库一块发布了,而且osgQt目前基本已经很少更新,基本停留在之前的状态,对Qt5的支持也迟迟没有添加进来,但是实际使用中又需要将osg/osgEarth嵌入Qt窗体中使用,所以封装了QOSGViewerWidget类,可以很方便的将osgViewer嵌入Qt5中,放出来与大家分享,用法也很简单,直接将以下两个文件保存为头文件和源文件,引入工程中,在Designer中添加OpenGLWidget控件,并提升为QOSGViewerWidget类即可,初始加载可能看不到模型,这是由于类里边没有添加默认的CamaraManipulator,需要自行添加CameraManipulator。
#pragma once
#include <QOpenGLWidget>
#include <osgViewer/Viewer>
class QInputEvent;
class QOSGViewerWidget : public QOpenGLWidget, public osgViewer::Viewer
{
Q_OBJECT
public:
QOSGViewerWidget(QWidget *parent = 0);
~QOSGViewerWidget();
protected:
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 *);
protected:
virtual void paintGL();
private:
void init3D();
osg::ref_ptr<osg::Camera> createCamera(int x, int y, int w, int h);
private:
osgViewer::GraphicsWindow* _gw;
};
#pragma execution_character_set("utf-8")
#include "qosgviewerwidget.h"
#include <QInputEvent>
#include <osg/MatrixTransform>
#include <osgDB/ReadFile>
#include <osgGA/MultiTouchTrackballManipulator>
#include <osgGA/StateSetManipulator>
#include <osgViewer/ViewerEventHandlers>
#include <QApplication>
QOSGViewerWidget::QOSGViewerWidget(QWidget *parent)
: QOpenGLWidget(parent)
{
QSurfaceFormat format = QSurfaceFormat::defaultFormat();
format.setRenderableType(QSurfaceFormat::OpenGL);
format.setSamples(16);
setFormat(format);
init3D();
setMouseTracking(true);
setFocusPolicy(Qt::StrongFocus);
}
QOSGViewerWidget::~QOSGViewerWidget()
{
}
bool QOSGViewerWidget::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 = _gw->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 = _gw->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 = _gw->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 QOSGViewerWidget::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;
}
_gw->getEventQueue()->getCurrentEventState()->setModKeyMask(mask);
update();
}
void QOSGViewerWidget::keyPressEvent(QKeyEvent *event)
{
setKeyboardModifiers(event);
_gw->getEventQueue()->keyPress(event->key());
QOpenGLWidget::keyPressEvent(event);
update();
}
void QOSGViewerWidget::keyReleaseEvent(QKeyEvent *event)
{
setKeyboardModifiers(event);
_gw->getEventQueue()->keyRelease(event->key());
QOpenGLWidget::keyReleaseEvent(event);
update();
}
void QOSGViewerWidget::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);
_gw->getEventQueue()->mouseButtonPress(event->x(), event->y(), button);
update();
}
void QOSGViewerWidget::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);
_gw->getEventQueue()->mouseButtonRelease(event->x(), event->y(), button);
QOpenGLWidget::mouseReleaseEvent(event);
update();
}
void QOSGViewerWidget::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);
_gw->getEventQueue()->mouseDoubleButtonPress(event->x(), event->y(), button);
QOpenGLWidget::mouseDoubleClickEvent(event);
update();
}
void QOSGViewerWidget::mouseMoveEvent(QMouseEvent *event)
{
setKeyboardModifiers(event);
_gw->getEventQueue()->mouseMotion(event->x(), event->y());
QOpenGLWidget::mouseMoveEvent(event);
update();
}
void QOSGViewerWidget::wheelEvent(QWheelEvent *event)
{
setKeyboardModifiers(event);
_gw->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 QOSGViewerWidget::resizeEvent(QResizeEvent *event)
{
const QSize& size = event->size();
_gw->resized(x(), y(), size.width(), size.height());
_gw->getEventQueue()->windowResize(x(), y(), size.width(), size.height());
_gw->requestRedraw();
QOpenGLWidget::resizeEvent(event);
}
void QOSGViewerWidget::moveEvent(QMoveEvent *event)
{
const QPoint& pos = event->pos();
_gw->resized(pos.x(), pos.y(), width(), height());
_gw->getEventQueue()->windowResize(pos.x(), pos.y(), width(), height());
QOpenGLWidget::moveEvent(event);
}
void QOSGViewerWidget::timerEvent(QTimerEvent *)
{
update();
}
void QOSGViewerWidget::paintGL()
{
if (isVisibleTo(QApplication::activeWindow())) {
frame();
}
}
void QOSGViewerWidget::init3D()
{
osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
traits->windowDecoration = false;
traits->x = 0;
traits->y = 0;
traits->width = width();
traits->height = height();
traits->doubleBuffer = true;
traits->sharedContext = 0;
_gw = new osgViewer::GraphicsWindowEmbedded(traits);
realize();
auto camera = getCamera();
camera->setGraphicsContext(_gw);
camera->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));
camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
this->setThreadingModel(osgViewer::Viewer::SingleThreaded);
startTimer(20);
}
osg::ref_ptr<osg::Camera> QOSGViewerWidget::createCamera(int x, int y, int w, int h)
{
_gw = new osgViewer::GraphicsWindowEmbedded(x, y, w, h);
osg::ref_ptr<osg::Camera> camera = new osg::Camera;
camera->setGraphicsContext(_gw);
camera->setViewport(new osg::Viewport(0, 0,w, h));
camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
camera->setProjectionMatrixAsPerspective(
30.0f, double(w) / double(h), 1.0f, 10000.0f);
camera->setClearColor(osg::Vec4(0.3, 0.3, 0.6, 0.1));
return camera.release();
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...
Win10操作系统 MySQL版本一个为8.0另一个为5.7通过命令行直接进入MySQL8.0会报错:可能是因为系统分辨不出要进入哪一个MySQL(警告为在命令行里直接输入MySQL密码不安全,使用mysql -uroot -p敲回车再输入密码更安全。)正确打开的方法为进入安装MySQL文件夹下的bin目录,再敲上述代码:先cd一下MySQL8.0的安装目录再使用进入MySQL的命令,最好加上端口号(此处MySQL57版本的端口号是13306,而MySQL8版本的端口是3306):检查数_sql 4g文件
我们在使用html5的拖拽上传时,做法往往是监听一个控件范围内的drop事件。但是用户在操作的时候往往会出现文件没有进入到控件范围内就释放的情况,这种情况在以下浏览器中会出现不同的情况,下面是实验结果: chrome: 如果该文件是浏览器可浏览文件(图片等),浏览器会在当前窗口打开文件的预览;如果是不可浏览文件,则会触发浏览器的下载 fireFox:如果该文件是..._拖拽上传为什么要阻止默认事件
#在jsp页面使用富文本编辑器工具:MyEclipse(1)下载ueditor下载地址:http://ueditor.baidu.com/website/download.html(2)解压缩文件,并把文件夹名改为ueditorueditor\jsp\lib路径下有commons-codec-1.9.jar、commons-fileupload-1.3.1.jar、commons-i..._jsp页面文本编辑器
DSA算法和DSA指令概述DSA算法是美国国家标准的数字签名算法,只具备数字签名的功能不具备密钥交换的功能 生成DSA参数然后生成DSA密钥,DSA参数决定了DSA密钥的长度 三个指令 首先是dsaparam指令,该指令主要用来生成DSA密钥参数,并提供了一些格式转换、C代码生成等其他类似于dhparam指令的功能。一组DSA参数可以用来生成多个不同的DSA密钥,而不是仅仅对应于一个DSA密钥。 gendsa指令用来从现有的DSA参数中生成DSA密钥,使用相同的DSA参数可以生成不同的DSA密钥_dsa加密算法
直接附上代码,在resources文件家中存在预制物体就可以GameObject Prefab = (GameObject)Resources.Load("Prefabs/task1"); Prefab = Instantiate(Prefab); Prefab.transform.parent = parent; Prefab.transform.position = Vector3.zero; Prefab.transform.localScale = Vector3.one;将预制物体放在需要位置,_unity resouce.load 后需要实例化吗
研二 wifi嗅探项目 第一阶段 数据提取与分析#include #include #pragma comment(lib,"ws2_32.lib") int main(int argc, char* argv[]) { //一、WSAStartup函数初始化Winsock WORD sockVersion = MAKE
今天写一篇关于JTable有关的文章,包括:为JTable单元格设置字体颜色、为JTable单元格设置背景色、让JTable某一列设置为不可能编辑。代码很简单,请朋友们参考如下: package Java; import javax.swing.JFrame; import javax.swing.JTable; import javax.swi
def video2frames(video_path, newdir): cap = cv2.VideoCapture(video) count = 0 while (cap.isOpened()): ret, frame = cap.read() if True: if ret == True: # cv2.imshow('video2frames', frame) ...
查看linux源代码,经常会被其中一些程序的写法所迷惑,此种初始化写法并不是什么特殊的代码风格,而是所谓的C语言标记化结构初始化语法(designated initializer),而且还是一个ISO标准,C99注意:适用于GCC编译器,GCC能完美支持C99,VC2005支持C89,还不支持C99,只有能完美支持C99的编译器才能编译通过。GCC有扩展标记化结构初始化语法,写法是
同进程使用Service(一)比如,你做了一个音乐播放 app,里面有一个 MusicService 负责后台播放音乐,对外提供 play(),pause() 的接口你在一个 Activity 里想调用这个 Service 的 play(),怎么搞?必须在这个 Activity 里拿到刚才启动的 MusicService 的实例,但这是不可能的。Service 实例是由安卓OS维护的,你拿不到_java binder和wrapper对外部提供service接口
谈谈ConcurrentHashMap1.7和1.8的不同实现 HashMap vs ConcurrentHashMap引入ConcurrentHashMap是为了在同步集合HashTable之间有更好的选择,HashTable与HashMap、ConcurrentHashMap主要的区别在于HashMap不是同步的、线程不安全的和不适合应用于多线程并发环境下,而Co..._hashtable 同步1.7 1.8