OSG 使用Qt的QOpenGLWidget

OSG和OSGEarth嵌入到qt窗口的几种方式 提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 OSG和OSGEarth嵌入到qt窗口的几种方式前言一、pandas是什么?二、使用步骤1.引入库2.读入数据总结 前言 提示:这里可以添加本文要记录的大概内容: 例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。 提示:以下是本篇文章正文内容,下面案例可供参考 一、pandas是什么? 示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而 阅读详情
AI摘要

博客记录了OSG使用Qt的QOpenGLWidget的解决办法。此前封装使用RTTCamera有问题,现找到解决办法,需设置默认fbo id(帧缓存)。环境要求为OSG 3.4版本以上、QT5.9,还给出了完整代码,使用中无问题且可改成线程模式。

OSG 使用Qt的QOpenGLWidget

有osg 封装的qt默认使用QGLWidget 组件,现在想使用QT的QOpenGLWidget,之前尝试封装使用RTTCamera是一直有问题,最近看到解决办法,就记录一下。

环境:OSG 3.4 版本以上,QT5.9

解决办法

就是需要设置一个默认fbo id,帧缓存。
参考bbs

if (mIsFirstRenderRun)
	{
		// set set the default FBO-id. 
		// this id will be used when the rendering-backend is finished with RTT FBOs 
		GLuint defaultFboId = this->defaultFramebufferObject();
		//mpGraphicsContext->setDefaultFboId(defaultFboId);
		graphicsWindow_->setDefaultFboId(defaultFboId);
		mIsFirstRenderRun = false;
	}
	viewer_->frame();

完整代码

  1. OSGWidget.h文件
#pragma once
#include <QPoint>
#include <QOpenGLWidget>

#include <osg/ref_ptr>

#include <osgViewer/GraphicsWindow>
#include <osgViewer/CompositeViewer>
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram>
#include <QOpenGLBuffer>
#include <QVector3D>
#include <QMatrix4x4>
#include <QThread>
#include <QMutex>
#include <QWaitCondition>
#include <QElapsedTimer>
namespace osgWidget
{
	//! The subclass of osgViewer::CompositeViewer we use
	/*!
	* This subclassing allows us to remove the annoying automatic
	* setting of the CPU affinity to core 0 by osgViewer::ViewerBase,
	* osgViewer::CompositeViewer's base class.
	*/
	class Viewer : public osgViewer::CompositeViewer
	{
	public:
		virtual void setupThreading();
	};
}
class OSGWidget;
class Renderer : public QObject, protected QOpenGLFunctions
{
	Q_OBJECT

public:
	Renderer(OSGWidget *w);
	void lockRenderer() { m_renderMutex.lock(); }
	void unlockRenderer() { m_renderMutex.unlock(); }
	QMutex *grabMutex() { return &m_grabMutex; }
	QWaitCondition *grabCond() { return &m_grabCond; }
	void prepareExit() { m_exiting = true; m_grabCond.wakeAll(); }

signals:
	void contextWanted();
public :
	void render();

private:

	bool m_inited;
	qreal m_fAngle;
	qreal m_fScale;
	QVector<QVector3D> vertices;
	QVector<QVector3D> normals;
	int vertexAttr;
	int normalAttr;
	int matrixUniform;
	OSGWidget *m_glwidget;
	QMutex m_renderMutex;
	QElapsedTimer m_elapsed;
	QMutex m_grabMutex;
	QWaitCondition m_grabCond;
	bool m_exiting;
};
// openg 组件信息过程
class OSGWidget : public QOpenGLWidget
{
	Q_OBJECT

public:
	OSGWidget(osgViewer::GraphicsWindowEmbedded* graphic,osgViewer::View* view,QWidget* parent = 0,
		Qt::WindowFlags f = 0);

	virtual ~OSGWidget();

protected:

	virtual void paintEvent(QPaintEvent* paintEvent);
	virtual void paintGL();
	virtual void resizeGL(int width, int height);

	virtual void keyPressEvent(QKeyEvent* event);
	virtual void keyReleaseEvent(QKeyEvent* event);

	virtual void mouseMoveEvent(QMouseEvent* event);
	virtual void mousePressEvent(QMouseEvent* event);
	virtual void mouseReleaseEvent(QMouseEvent* event);
	virtual void mouseDoubleClickEvent(QMouseEvent * event);
	virtual void wheelEvent(QWheelEvent* event);

	virtual bool event(QEvent* event);

public:

	virtual void onHome();
	virtual void onResize(int width, int height);

	osgGA::EventQueue* getEventQueue() const;

	osg::ref_ptr<osgViewer::GraphicsWindowEmbedded> graphicsWindow_;
	osg::ref_ptr<osgWidget::Viewer> viewer_;


	void processSelection();
	//
	//
signals:
	void renderRequested();

	public slots:
	void grabContext();

	private slots:
	void onAboutToCompose();
	void onFrameSwapped();
	void onAboutToResize();
	void onResized();
private:
	QThread *m_thread;
	Renderer *m_renderer;
	bool mIsFirstRenderRun;
	int64_t m_lastTime;
};

  1. OSGWidget.cpp 文件
#include "OSGWidget.h"
//#include "PickHandler.h"
#include <QGuiApplication>
#include <osg/Camera>

#include <osg/DisplaySettings>
#include <osg/Geode>
#include <osg/Material>
#include <osg/Shape>
#include <osg/ShapeDrawable>
#include <osg/StateSet>

#include <osgDB/WriteFile>
#include <QDateTime>
#include <osgGA/EventQueue>
#include <osgGA/TrackballManipulator>

#include <osgUtil/IntersectionVisitor>
#include <osgUtil/PolytopeIntersector>

#include <osgViewer/View>
#include <osgViewer/ViewerEventHandlers>

#include <cassert>

#include <stdexcept>
#include <vector>

#include <QDebug>
#include <QKeyEvent>
#include <QPainter>
#include <QWheelEvent>

namespace
{



}

namespace osgWidget
{
	void Viewer::setupThreading()
	{
		if (_threadingModel == SingleThreaded)
		{
			if (_threadsRunning)
				stopThreading();
		}
		else
		{
			if (!_threadsRunning)
				startThreading();
		}
	}
}

OSGWidget::OSGWidget(osgViewer::GraphicsWindowEmbedded* graphic, osgViewer::View* view, QWidget* parent,
	Qt::WindowFlags f)
	: QOpenGLWidget(parent,
		f)
	, graphicsWindow_(graphic)
	, viewer_(new osgWidget::Viewer)
	,mIsFirstRenderRun(true),
	m_lastTime(0)
{
	QSurfaceFormat format;
	format.setRenderableType(QSurfaceFormat::OpenGL);
	format.setProfile(QSurfaceFormat::CoreProfile);
	//format.setVersion(4, 1);
	format.setSamples(16);
	setFormat(format);
	viewer_->addView(view);
	viewer_->setThreadingModel(osgViewer::CompositeViewer::SingleThreaded);
	viewer_->realize();

	// This ensures that the widget will receive keyboard events. This focus
	// policy is not set by default. The default, Qt::NoFocus, will result in
	// keyboard events that are ignored.
	this->setFocusPolicy(Qt::StrongFocus);
	this->setMinimumSize(100, 100);

	// Ensures that the widget receives mouse move events even though no
	// mouse button has been pressed. We require this in order to let the
	// graphics window switch viewports properly.
	this->setMouseTracking(true);
	//后台线程模式
	//connect(this, &QOpenGLWidget::aboutToCompose, this, &OSGWidget::onAboutToCompose);
	//connect(this, &QOpenGLWidget::frameSwapped, this, &OSGWidget::onFrameSwapped);
	//connect(this, &QOpenGLWidget::aboutToResize, this, &OSGWidget::onAboutToResize);
	//connect(this, &QOpenGLWidget::resized, this, &OSGWidget::onResized);

	//m_thread = new QThread;
	//m_renderer = new Renderer(this);
	//m_renderer->moveToThread(m_thread);
	//connect(m_thread, &QThread::finished, m_renderer, &QObject::deleteLater);

	//connect(this, &OSGWidget::renderRequested, m_renderer, &Renderer::render);
	//connect(m_renderer, &Renderer::contextWanted, this, &OSGWidget::grabContext);

	//m_thread->start();
}

OSGWidget::~OSGWidget()
{
	//m_renderer->prepareExit();
	//m_thread->quit();
	//m_thread->wait();
	//delete m_thread;
}

void OSGWidget::paintEvent(QPaintEvent* /* paintEvent */)
{
	this->makeCurrent();

	QPainter painter(this);

	this->paintGL();

#ifdef WITH_SELECTION_PROCESSING
	if (selectionActive_ && !selectionFinished_)
	{
		painter.setPen(Qt::black);
		painter.setBrush(Qt::transparent);
		painter.drawRect(makeRectangle(selectionStart_, selectionEnd_));
	}
#endif

	painter.end();

	this->doneCurrent();
}

void OSGWidget::paintGL()
{
	int64_t curTime = QDateTime::currentMSecsSinceEpoch();
	if(curTime-m_lastTime<5)
		QMetaObject::invokeMethod(this, "update", Qt::QueuedConnection);
	m_lastTime = curTime;
	if (mIsFirstRenderRun)
	{
		// set set the default FBO-id. 
		// this id will be used when the rendering-backend is finished with RTT FBOs 
		GLuint defaultFboId = this->defaultFramebufferObject();
		//mpGraphicsContext->setDefaultFboId(defaultFboId);
		graphicsWindow_->setDefaultFboId(defaultFboId);
		mIsFirstRenderRun = false;
	}
	viewer_->frame();
	QMetaObject::invokeMethod(this, "update", Qt::QueuedConnection);
}

void OSGWidget::resizeGL(int width, int height)
{
	this->getEventQueue()->windowResize(this->x(), this->y(), width, height);
	graphicsWindow_->resized(this->x(), this->y(), width, height);

	this->onResize(width, height);
}

void OSGWidget::keyPressEvent(QKeyEvent* event)
{
	QString keyString = event->text();
	const char* keyData = keyString.toLocal8Bit().data();

	if (event->key() == Qt::Key_S)
	{
#ifdef WITH_SELECTION_PROCESSING
		selectionActive_ = !selectionActive_;
#endif

		// Further processing is required for the statistics handler here, so we do
		// not return right away.
	}
	else if (event->key() == Qt::Key_D)
	{
		return;
	}
	else if (event->key() == Qt::Key_H)
	{
		this->onHome();
		return;
	}

	this->getEventQueue()->keyPress(osgGA::GUIEventAdapter::KeySymbol(*keyData));
}

void OSGWidget::keyReleaseEvent(QKeyEvent* event)
{
	QString keyString = event->text();
	const char* keyData = keyString.toLocal8Bit().data();

	this->getEventQueue()->keyRelease(osgGA::GUIEventAdapter::KeySymbol(*keyData));
}

void OSGWidget::mouseMoveEvent(QMouseEvent* event)
{
	// Note that we have to check the buttons mask in order to see whether the
	// left button has been pressed. A call to `button()` will only result in
	// `Qt::NoButton` for mouse move events.
	{
		auto pixelRatio = this->devicePixelRatio();

		this->getEventQueue()->mouseMotion(static_cast<float>(event->x() * pixelRatio),
			static_cast<float>(event->y() * pixelRatio));
	}
}

void OSGWidget::mousePressEvent(QMouseEvent* event)
{

	{
		// 1 = left mouse button
		// 2 = middle mouse button
		// 3 = right mouse button

		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;
		}

		auto pixelRatio = this->devicePixelRatio();

		this->getEventQueue()->mouseButtonPress(static_cast<float>(event->x() * pixelRatio),
			static_cast<float>(event->y() * pixelRatio),
			button);
	}
}

void OSGWidget::mouseReleaseEvent(QMouseEvent* event)
{

	{
		// 1 = left mouse button
		// 2 = middle mouse button
		// 3 = right mouse button

		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;
		}

		auto pixelRatio = this->devicePixelRatio();

		this->getEventQueue()->mouseButtonRelease(static_cast<float>(pixelRatio * event->x()),
			static_cast<float>(pixelRatio * event->y()),
			button);
	}
}
void OSGWidget::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;
	}
	int pixelRatio = this->devicePixelRatio();
	this->getEventQueue()->mouseDoubleButtonPress(event->x()*pixelRatio, event->y()*pixelRatio, button);
}
void OSGWidget::wheelEvent(QWheelEvent* event)
{
	// Ignore wheel events as long as the selection is active.

	event->accept();
	int delta = event->delta();

	osgGA::GUIEventAdapter::ScrollingMotion motion = delta > 0 ? osgGA::GUIEventAdapter::SCROLL_UP
		: osgGA::GUIEventAdapter::SCROLL_DOWN;

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

bool OSGWidget::event(QEvent* event)
{
	bool handled = QOpenGLWidget::event(event);

	// This ensures that the OSG widget is always going to be repainted after the
	// user performed some interaction. Doing this in the event handler ensures
	// that we don't forget about some event and prevents duplicate code.
	switch (event->type())
	{
	case QEvent::KeyPress:
	case QEvent::KeyRelease:
	case QEvent::MouseButtonDblClick:
	case QEvent::MouseButtonPress:
	case QEvent::MouseButtonRelease:
	case QEvent::MouseMove:
	case QEvent::Wheel:
		this->update();
		break;

	default:
		break;
	}

	return handled;
}

void OSGWidget::onHome()
{
	osgViewer::ViewerBase::Views views;
	viewer_->getViews(views);

	for (std::size_t i = 0; i < views.size(); i++)
	{
		osgViewer::View* view = views.at(i);
		view->home();
	}
}

void OSGWidget::onResize(int width, int height)
{
	std::vector<osg::Camera*> cameras;
	viewer_->getCameras(cameras);

	assert(cameras.size() >= 1);

	auto pixelRatio = this->devicePixelRatio();

	cameras[0]->setViewport(0, 0, width  * pixelRatio, height * pixelRatio);
	//cameras[1]->setViewport(width / 2 * pixelRatio, 0, width / 2 * pixelRatio, height * pixelRatio);
}

osgGA::EventQueue* OSGWidget::getEventQueue() const
{
	osgGA::EventQueue* eventQueue = graphicsWindow_->getEventQueue();

	if (eventQueue)
		return eventQueue;
	else
		throw std::runtime_error("Unable to obtain valid event queue");
}

void OSGWidget::processSelection()
{

}

void OSGWidget::grabContext()
{
	m_renderer->lockRenderer();
	QMutexLocker lock(m_renderer->grabMutex());
	context()->moveToThread(m_thread);
	m_renderer->grabCond()->wakeAll();
	m_renderer->unlockRenderer();
}

void OSGWidget::onAboutToCompose()
{
	m_renderer->lockRenderer();
}

void OSGWidget::onFrameSwapped()
{
	m_renderer->unlockRenderer();
	// Assuming a blocking swap, our animation is driven purely by the
	// vsync in this example.
	emit renderRequested();
}

void OSGWidget::onAboutToResize()
{
	m_renderer->lockRenderer();
}

void OSGWidget::onResized()
{
	m_renderer->unlockRenderer();
}


Q_GLOBAL_STATIC(QMutex, initMutex)
Renderer::Renderer(OSGWidget *w) : m_inited(false),
m_glwidget(w),
m_exiting(false) {

}
void Renderer::render()
{
	if (m_exiting)
		return;

	QOpenGLContext *ctx = m_glwidget->context();

	if (!ctx) // QOpenGLWidget not yet initialized
		return;
	QSurfaceFormat format;
	format.setVersion(2, 1);
	format.setOption(QSurfaceFormat::DeprecatedFunctions, true);
	format.setProfile(QSurfaceFormat::CoreProfile);
	format.setSamples(8);
	ctx->setFormat(format);
	// Grab the context.
	m_grabMutex.lock();
	emit contextWanted();
	m_grabCond.wait(&m_grabMutex);
	QMutexLocker lock(&m_renderMutex);
	m_grabMutex.unlock();

	if (m_exiting)
		return;

	Q_ASSERT(ctx->thread() == QThread::currentThread());

	// Make the context (and an offscreen surface) current for this thread. The
	// QOpenGLWidget's fbo is bound in the context.
	m_glwidget->makeCurrent();

	if (!m_inited) {
		m_inited = true;
		initializeOpenGLFunctions();

		QMutexLocker initLock(initMutex());
	

		m_elapsed.start();
		// set set the default FBO-id. 
		// this id will be used when the rendering-backend is finished with RTT FBOs 
		GLuint defaultFboId = m_glwidget->defaultFramebufferObject();
		//mpGraphicsContext->setDefaultFboId(defaultFboId);
		m_glwidget->graphicsWindow_->setDefaultFboId(defaultFboId);
	}
	m_glwidget->viewer_->frame();
	// Make no context current on this thread and move the QOpenGLWidget's
	// context back to the gui thread.
	m_glwidget->doneCurrent();
	ctx->moveToThread(qGuiApp->thread());

	// Schedule composition. Note that this will use QueuedConnection, meaning
	// that update() will be invoked on the gui thread.
	QMetaObject::invokeMethod(m_glwidget, "update");
}

在使用过程中没有发现问题,并且可以改成线程模式,osg 的渲染在线程中渲染。

OSG嵌入Qt的第二种方式:使用QOpenGLWidget/QGLWidget 几天前有朋友问OSG嵌入Qt的思路。我说整体思路就是用OpenGL的方式来进行OSG的绘制,而正好Qt已经整合了OpenGL的功能,我们可以以此为依托来进行OSG的渲染绘制工作。而在Qt中却有QWidget和QGraphicsView两种不同的体系框架,于是我们也就有了两种不同的嵌入方式,关于QGraphicsView的嵌入方式我前面的博客OSGEarth嵌入Qt的QGraphicsView框架已经 阅读详情

相关推荐

osgQOpenGL的简单使用——在一个窗口中显示三维模型

本文目录1 简介2 环境准备2.1 OSG2.2 osgQOpenGL2.2.1 osgQOpenGL下载2.2.2 osgQOpenGL编译2.3 Qt3 osgQOpenGL的简单使用3.1 osgQOpenGL源码3.2 osgQOpenGLWidget的使用。3.2.1 MyWidget.h头文件3.2.2 MyWidget.cpp源文件3.2.3 程序效果 1 简介 osgQOpenGL是OSG嵌入到QT的一种新的实现方法。OSG使用OpenGL进行三维模型的渲染,恰好Qt5也提供了对OpenGL

GeomasterYi的博客 8878

QOpenGLWidget

QOpenGLWidget 类是一个用于渲染 OpenGL 图形的小部件。QOpenGLWidget 提供了显示集成到 Qt 应用程序中的 OpenGL 图形的功能。它使用起来非常简单:自定义类继承它并像其他 QWidget 子类一样使用,还可以选择使用 QPainter 和标准 OpenGL 渲染命令。QOpenGLWidget 提供了三个方便的虚函数,可以在子类中重新实现这些虚函数来执行典型的 OpenGL 任务:paintGL():渲染 OpenGL 场景,每当需要更新小部件时调用。

hw5230的博客 3206

Qt与OSG深度整合:基于QOpenGLWidget的3D渲染实践

本文详细介绍了如何在Qt应用中深度整合OSG三维图形引擎,实现高效稳定的3D渲染。通过使用QOpenGLWidget作为渲染容器,重点解决了事件处理、渲染循环与线程同步等核心问题,并提供了从环境搭建到实战开发的完整代码示例与避坑指南,帮助开发者构建兼具强大GUI与专业3D渲染能力的应用。

pytorch8learner的博客 731

Qt 集成OSG

Qt 集成OSG

qthello 1418

OSG基础教程(二)osg嵌入Qt窗口(兼容Qt5)

将osg嵌入Qt。

hongfei_163的博客 4428

OSG开发笔记(二十三):Qt使用QOpenGLWidget渲染OSG和地球仪

若该文为原创文章,未经允许不得转载 原博主博客地址:https://blog.youkuaiyun.com/qq21497936 本文章博客地址:https://blog.youkuaiyun.com/qq21497936/article/details/98730328 目录 前言 地球控件 运行效果 运行Demo下载地址 QGLWidget与QOpenGLWidget详解 QOpenGLWidget放置...

长沙红胖子 Qt・西安|省级科研团队从业背景,深耕双一流体系高精尖技术配套研发|剥离高精尖机理,沉淀高端特种行业领域 Qt 工程化落地经验|博文仅分享通用技术总结,输出公开普适工程思路。 5万+

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

文章目录说明Demo 说明 网上大部分操作介绍都讲得很繁琐,并且编译未必能过 在网上找到这么一个讲解,感觉很好 链接:Step-by-step on how to set up your CMake, Qt and OSG in draw-on-demand mode(分为1和2)两个部分 Demo /* * =======================================...

Neverland_LY‘s Domain 1万+

VS2017下Qt与OSG集成实战:QOpenGLWidget无缝渲染三维场景

在桌面级三维应用开发中,将高性能场景图库与成熟的GUI框架融合是常见刚需。OSG(OpenSceneGraph)负责三维场景的组织与渲染,Qt提供交互界面与业务组件,两者通过QOpenGLWidget实现渲染上下文的统一嵌入,使三维视图与控件共享同一窗口和事件循环。这种架构避免了独立窗口嵌套带来的通信复杂度,尤其适合场景点击联动面板刷新、实时参数调整等跨模块交互的仿真工具与数据可视化系统。结合Visual Studio 2017的64位编译环境,可稳定发挥OSG对大内存点云与模型加载的优势。本文基于该思路,

weixin_28829903的博客 265

vs2017 实现 Qt + OSG 并在osg上用qpainter画图

vs2017 实现 Qt + OSG 并在osg上用qpainter画图

weixin_38123874的博客 1087

MSVC2017+OSG3.63+OSGEarth2.10+Qt5.14 Windows构建避坑指南

OpenSceneGraph(OSG)与OSGEarth是工业级三维地理可视化的核心渲染引擎,其与Qt的深度集成依赖严格的ABI兼容性与OpenGL上下文生命周期管理。本文聚焦Windows平台下C++三维GIS开发中高频出现的‘CMake找不到osgDB’‘Qt平台插件加载失败’‘EarthTileSource初始化崩溃’等典型问题,解析MSVC2017工具链不可替代的原因——它在Qt5.14生态中唯一支持稳定CRT内存池与OpenGL Core Profile协同;同时阐明OSG3.63与OSGEart

weixin_33859135的博客 214

osgQt(包含osgQOpenGLWidget)

包含osgQOpenGLWidget

OSG嵌入到Qt5

OSG版本:3.6.5 32位 Qt版本:5.12.4 32位 VS版本:VS2017 找了一天,发现了这样一段代码,实现了OSG嵌入到Qt5中。 代码如下: #include <QApplication> #include <QMainWindow> #include <QOpenGLWidget> #include <QMouseEvent> #include <QWheelEvent> #include <Q...

dreamcs的专栏 707

Qt加载Osg的新方式osgQOpenGL简介(文件中有错误,能够删除吗?)

Qt加载Osg的老方式是使用osg3.4以及以前的某些版本中提供的osgQt项目加载osg,不过这种方式,在3.6等新版本中不再支持,更改起来比较麻烦,osg::GraphicsContext类不再提供osg::GraphicsContext::setWindowingSystemInterface接口函数,无法编译成功。不过目前有个替代方案,使用osgQOpenGL的osgQOpenGLWidget类进行三维模型的加载。

osg嵌入Qt窗体的方式

在新的版本中,已经移除了osgQt,需要下载osgQt单独编译,编译及配置参考此博客。

枫影竹韵的博客 647

EtherCAT应用层协议选型指南:CoE、SoE、EoE、FoE、AoE到底怎么选?看完这篇就懂了

本文深入解析EtherCAT应用层协议(CoE、SoE、EoE、FoE、AoE)的选型策略,从实时性、数据吞吐量和功能完整性三大核心指标出发,提供工业场景下的实战决策框架。通过技术特性对比、混合协议架构设计和常见故障规避指南,帮助工程师优化自动化设备通信性能。

weixin_28718793的博客 493

光纤布拉格光栅(FBG)笔记【1】:波导结构和布拉格波长推导

引言 本文是光纤布拉格光栅(FBG)的笔记【1】,主要介绍了光纤布拉格光栅的波导结构,并且利用动量和能量守恒推导了光纤布拉格波长的表达式 普通光纤中让折射率发生周期性变化就是结构最简单的均匀光纤布拉格光栅(FBG),其波导结构如下图所示。 其传感原理描述可以分为以下的三点: ①光纤纤芯传播的光会在每个光栅面进行反射和透射; ②如果不满足布拉格条件,依次排列的光栅平面反射的光会逐渐变得不同直到最后相互抵消;同时由于系数不匹配,与布拉格波长不相符的光在每个光栅平面的反射也很微弱,这些光大部分在光纤中发生透.

subtitle_的博客 2万+

Osg3.6集成到Qt5.13

本文采用OsgQt将Osg显示到Qt界面,继承osgQOpenGLWidget(使用QOpenGLWidget,非QGLWidget),可按QWidget进行处理,代码如下: class ViewerWidget : public osgQOpenGLWidget { Q_OBJECT public: ViewerWidget(QWidget* parent, osg:...

小杨的专栏 1889

CMU的local_planner学习笔记

ros::Subscriber subOdometry = nh.subscribe//当接收到/state_estimation话题消息更新时启动odometryHandler回调函数 (消息格式:nav_msgs::Odometry消息内容:关于机器人或车辆的位置和方向(姿态)信息)pcl::PointCloud::Ptr freePaths(new pcl::PointCloud());

qq_35971623的博客 3878

osg嵌入Qt后,键盘响应以及程序退出崩溃问题解决

osg3.6.5 Qt5.9.9 使用osgQOpenGLWidget将osg嵌入Qt后, 出现osg窗口无法响应s键统计信息,查了半天资料后发现是widget默认焦点属性是noFocus,设置后可以响应了。(setFocusPolicy(Qt::StrongFocus)) 但是同时出现另外一个问题,程序退出崩溃 原来是delete 本身就是用来删除动态分配的内存, 如果不是delete掉动态分配的, 会有报错该问题。 ...

智能指针C++的专栏 1036

Android HTTPS抓包证书配置全解:Proxyman实战避坑指南

HTTPS抓包本质是中间人(MITM)通信的可信建立过程,其核心在于客户端对代理根证书的信任链配置。在Android平台,自7.0起系统默认不信任用户安装的CA证书,必须通过Network Security Config显式声明trust-anchors,将Proxyman导出的PEM格式根证书纳入App级信任锚点。这一机制区别于iOS和桌面浏览器,导致大量开发者卡在‘证书已安装却无法解密’的误区。技术价值在于打通开发调试闭环:精准定位SSLHandshakeException、绕过证书固定、支持React

weixin_32175665的博客 650

遥感图像小白--2--图像分割

遥感图像分割基础入门

Mary的博客 4235

Windows下VS2019+Qt5.14.2+OSG3.6.5+OSGEarth3.2环境搭建与Qt集成实战

三维地理信息可视化中,OSGEarth作为基于OpenSceneGraph的地理引擎层,封装了坐标转换、瓦片调度与地形渲染等核心能力,广泛应用于军工仿真与指挥调度。其技术价值在于将复杂的地理空间计算抽象为可复用的渲染管线,但Windows下的编译链依赖版本匹配极为严格。典型应用场景包括三维地球、态势标绘与飞行仿真。本文聚焦VS2019、Qt5.14.2、OSG3.6.5与OSGEarth3.2的完整环境搭建,详解第三方依赖、CMake配置及Qt集成中的高频报错与解决路径。

weixin_31822733的博客 95

机器人中的数值优化(十三)——QP二次规划

本系列文章主要是我在学习《数值优化》过程中的一些笔记和相关思考,主要的学习资料是深蓝学院的课程《机器人中的数值优化》和高立编著的《数值最优化方法》等,本系列文章篇数较多,不定期更新,上半部分介绍无约束优化,下半部分介绍带约束的优化,中间会穿插一些路径规划方面的应用实例

慕羽★的博客 2793
上一篇: 3dTile 数据文件格式说明
下一篇: OSG 绘制Geometry使用
jdq0603
博客等级 码龄17年 19粉丝 11原创
评论 8
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值