功能模块 |
简介 |
osg |
场景图核心类 |
osgDB |
读写模型/图像文件 |
osgViewer |
创建窗口/渲染主循环 |
osgGA |
相机操作与输入事件处理 |
osgUtil |
几何处理(求交、LOD、裁剪等) |
osgText |
文本绘制支持 |
示例1:渲染一个正方体


cpp
复制代码
#ifndef OSGWIDGET_H
#define OSGWIDGET_H
#include <QOpenGLWidget>
#include <osgViewer/Viewer>
#include <QMouseEvent>
class OSGWidget : public QOpenGLWidget {
Q_OBJECT
public:
explicit OSGWidget(QWidget* parent = nullptr);
virtual ~OSGWidget() override;
protected:
void initializeGL() override;
void paintGL() override;
void resizeGL(int w, int h) override;
void mousePressEvent(QMouseEvent* event) override;
void mouseReleaseEvent(QMouseEvent* event) override;
void mouseMoveEvent(QMouseEvent* event) override;
void wheelEvent(QWheelEvent* event) override;
private:
osg::ref_ptr<osgViewer::Viewer> viewer;
osg::ref_ptr<osgViewer::GraphicsWindowEmbedded> graphicsWindow;
};
#endif // OSGWIDGET_H
cpp
复制代码
#include "osgwidget.h"
#include <osg/Geode>
#include <osg/ShapeDrawable>
#include <osg/Material>
#include <osg/Light>
#include <osg/LightSource>
#include <osg/MatrixTransform>
#include <osgGA/TrackballManipulator>
#include <QDebug>
#include<QTimer>
OSGWidget::OSGWidget(QWidget* parent) : QOpenGLWidget(parent)
{
// 1. 创建Viewer和图形窗口
viewer = new osgViewer::Viewer;
viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
graphicsWindow = new osgViewer::GraphicsWindowEmbedded(
this->x(), this->y(), width(),height());
graphicsWindow->getEventQueue()->getCurrentEventState()->setWindowRectangle(
0, 0, width(), height());
// 2. 配置相机(关键修改)
osg::Camera* camera = viewer->getCamera();
camera->setGraphicsContext(graphicsWindow);
camera->setViewport(0, 0, width(), height());
camera->setClearColor(osg::Vec4(0.2f, 0.2f, 0.4f, 1.0f)); // 蓝色背景
// 设置合理的投影矩阵
camera->setProjectionMatrixAsPerspective(
30.0f, // 视野角度
float(width())/float(height()), // 宽高比
0.1f, // 近平面
100.0f // 远平面
);
// 3. 添加跟踪球控制器(支持鼠标交互)
viewer->setCameraManipulator(new osgGA::TrackballManipulator);
viewer->getCamera()->setGraphicsContext(graphicsWindow);
viewer->getCameraManipulator()->setHomePosition(
osg::Vec3(0, -5, 3), // 眼睛位置
osg::Vec3(0, 0, 0), // 中心点
osg::Vec3(0, 0, 1) // 上方向
);
viewer->home();
// 4. 创建带光照的红色立方体(关键修改)
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
geode->addDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(), 1.0f)));
// 设置红色材质
osg::ref_ptr<osg::Material> material = new osg::Material;
material->setDiffuse(osg::Material::FRONT, osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
geode->getOrCreateStateSet()->setAttribute(material);
// 5. 添加光源(关键修改)
osg::ref_ptr<osg::LightSource> lightSource = new osg::LightSource;
osg::ref_ptr<osg::Light> light = new osg::Light;
light->setLightNum(0);
light->setPosition(osg::Vec4(1.0f, 1.0f, 1.0f, 0.0f)); // 方向光
light->setDiffuse(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
light->setAmbient(osg::Vec4(0.2f, 0.2f, 0.2f, 1.0f));
lightSource->setLight(light);
// 6. 构建场景图
osg::ref_ptr<osg::Group> root = new osg::Group;
root->addChild(lightSource);
root->addChild(geode);
viewer->setSceneData(root);
// 在构造函数最后添加
qDebug() << "Viewer scene valid:" << (viewer->getSceneData() != nullptr);
// 定时器保证最小刷新率(可选)
QTimer* timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, [this](){
if(!this->isVisible()) return;
update();
});
timer->start(16); // ~60fps
}
void OSGWidget::initializeGL()
{
viewer->realize();
viewer->home(); // 重置视角到初始位置
}
void OSGWidget::paintGL()
{
viewer->frame();
update(); // 新增:强制持续刷新
}
void OSGWidget::resizeGL(int w, int h)
{
graphicsWindow->resized(this->x(), this->y(), w, h);
viewer->getCamera()->setViewport(0, 0, w, h);
viewer->getCamera()->setProjectionMatrixAsPerspective(
30.0f, float(w)/float(h), 0.1f, 100.0f);
}
OSGWidget::~OSGWidget()
{
// 清理OSG资源
if(viewer) {
viewer->setSceneData(nullptr);
viewer = nullptr;
}
graphicsWindow = nullptr;
}
// 新增事件处理函数实现
void OSGWidget::mousePressEvent(QMouseEvent* event) {
graphicsWindow->getEventQueue()->mouseButtonPress(
event->x(), event->y(),
(event->button() == Qt::LeftButton) ? 1 :
(event->button() == Qt::MiddleButton) ? 2 : 3);
update(); // 新增:事件处理后立即请求重绘
}
void OSGWidget::mouseReleaseEvent(QMouseEvent* event) {
graphicsWindow->getEventQueue()->mouseButtonRelease(
event->x(), event->y(),
(event->button() == Qt::LeftButton) ? 1 :
(event->button() == Qt::MiddleButton) ? 2 : 3);
update(); // 新增:事件处理后立即请求重绘
}
void OSGWidget::mouseMoveEvent(QMouseEvent* event) {
graphicsWindow->getEventQueue()->mouseMotion(event->x(), event->y());
update(); // 新增:事件处理后立即请求重绘
}
void OSGWidget::wheelEvent(QWheelEvent* event) {
graphicsWindow->getEventQueue()->mouseScroll(
event->angleDelta().y() > 0 ?
osgGA::GUIEventAdapter::SCROLL_UP :
osgGA::GUIEventAdapter::SCROLL_DOWN);
update(); // 新增:事件处理后立即请求重绘
}
cpp
复制代码
#include <QApplication>
#include "osgwidget.h"
int main(int argc, char** argv) {
QApplication app(argc, argv);
// 强制使用软件渲染(解决虚拟机/驱动兼容性问题)
qputenv("LIBGL_ALWAYS_SOFTWARE", "1");
qputenv("QT_XCB_FORCE_SOFTWARE_OPENGL", "1");
OSGWidget widget;
widget.resize(800, 600);
widget.setWindowTitle("OSG");
widget.show();
return app.exec();
}
示例2:渲染一个飞行器
cpp
复制代码
QT += core gui opengl
greaterThan(QT_MAJOR_VERSION, 5)
TARGET = osgdemo2
TEMPLATE = app
CONFIG += c++17
DEFINES += QT_DEPRECATED_WARNINGS
LIBS += -L/usr/local/lib \
-losg\
-losgViewer\
-losgGA\
-losgDB\
-lOpenThreads\
-losgUtil
INCLUDEPATH += /usr/local/include
SOURCES += \
main.cpp \
graphicswindowqt.cpp
HEADERS += \
graphicswindowqt.h
FORMS += \
mainwindow.ui
cpp
复制代码
#ifndef GRAPHICSWINDOWQT_H
#define GRAPHICSWINDOWQT_H
#include <QOpenGLWidget>
#include <osgViewer/Viewer>
#include <osgViewer/GraphicsWindow>
class QInputEvent;
class GraphicsWindowQt : public QOpenGLWidget, public osgViewer::Viewer
{
Q_OBJECT
public:
GraphicsWindowQt(QWidget *parent = 0);
~GraphicsWindowQt();
bool event(QEvent *e);
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:
osg::ref_ptr<osg::Group> root;
osgViewer::GraphicsWindow *window;
};
#endif // GRAPHICSWINDOWQT_H
cpp
复制代码
#include "graphicswindowqt.h"
#include <QInputEvent>
#include <QApplication>
#include <osgDB/ReadFile>
#include <osgGA/TrackballManipulator>
#include <osgGA/GUIEventAdapter>
#include <osgViewer/ViewerEventHandlers>
#include <osgGA/StateSetManipulator>
#include <osg/ShapeDrawable>
#include <osg/Light>
#include <osg/LightSource>
#include <QDebug>
GraphicsWindowQt::GraphicsWindowQt(QWidget *parent)
: QOpenGLWidget(parent)
{
init3D();
setMouseTracking(true);
setFocusPolicy(Qt::StrongFocus);
}
GraphicsWindowQt::~GraphicsWindowQt()
{
}
bool GraphicsWindowQt::event(QEvent *e)
{
switch (e->type()) {
case QEvent::TouchBegin:
case QEvent::TouchEnd:
case QEvent::TouchUpdate: {
QList<QTouchEvent::TouchPoint> touchPoints = static_cast<QTouchEvent *>(e)->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 (e->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 (e->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 (e->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(e);
}
void GraphicsWindowQt::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 GraphicsWindowQt::keyPressEvent(QKeyEvent *event)
{
setKeyboardModifiers(event);
window->getEventQueue()->keyPress(event->key());
qDebug() << "key pressed.";
QOpenGLWidget::keyPressEvent(event);
update();
}
void GraphicsWindowQt::keyReleaseEvent(QKeyEvent *event)
{
setKeyboardModifiers(event);
window->getEventQueue()->keyRelease(event->key());
QOpenGLWidget::keyReleaseEvent(event);
update();
}
void GraphicsWindowQt::mousePressEvent(QMouseEvent *event)
{
int button = 0;
switch (event->button()) {
case Qt::LeftButton: button = 1; break;
case Qt::MiddleButton: 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 GraphicsWindowQt::mouseReleaseEvent(QMouseEvent *event)
{
int button = 0;
switch (event->button()) {
case Qt::LeftButton: button = 1; break;
case Qt::MiddleButton: 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 GraphicsWindowQt::mouseDoubleClickEvent(QMouseEvent *event)
{
int button = 0;
switch (event->button()) {
case Qt::LeftButton: button = 1; break;
case Qt::MiddleButton: 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 GraphicsWindowQt::mouseMoveEvent(QMouseEvent *event)
{
setKeyboardModifiers(event);
window->getEventQueue()->mouseMotion(event->x(), event->y());
QOpenGLWidget::mouseMoveEvent(event);
update();
}
void GraphicsWindowQt::wheelEvent(QWheelEvent *event)
{
setKeyboardModifiers(event);
#if(QT_VERSION < QT_VERSION_CHECK(6,0,0))
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));
#else
window->getEventQueue()->mouseScroll(
event->angleDelta().y() != 0 ?
(event->angleDelta().y() > 0 ? osgGA::GUIEventAdapter::SCROLL_UP : osgGA::GUIEventAdapter::SCROLL_DOWN) :
(event->angleDelta().x() > 0 ? osgGA::GUIEventAdapter::SCROLL_LEFT : osgGA::GUIEventAdapter::SCROLL_RIGHT));
#endif
QOpenGLWidget::wheelEvent(event);
update();
}
void GraphicsWindowQt::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();
QOpenGLWidget::resizeEvent(event);
}
void GraphicsWindowQt::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 GraphicsWindowQt::timerEvent(QTimerEvent *)
{
update();
}
void GraphicsWindowQt::paintGL()
{
if (isVisibleTo(QApplication::activeWindow())) {
frame();
}
}
void GraphicsWindowQt::init3D()
{
osg::ref_ptr<osg::Node> nd = osgDB::readNodeFile("/mnt/hgfs/gongxiang/OpenSceneGraph-Data-3.4.0/OpenSceneGraph-Data/glider.osg");
root = new osg::Group();
root->addChild(nd);
setCamera(createCamera(0, 0, width(), height()));
setCameraManipulator(new osgGA::TrackballManipulator);
addEventHandler(new osgViewer::StatsHandler);
addEventHandler(new osgViewer::ThreadingHandler());
addEventHandler(new osgViewer::HelpHandler);
addEventHandler(new osgGA::StateSetManipulator(this->getCamera()->getOrCreateStateSet()));
setThreadingModel(osgViewer::Viewer::SingleThreaded);
setSceneData(root);
realize();
getCamera()->setComputeNearFarMode(osg::CullSettings::COMPUTE_NEAR_FAR_USING_PRIMITIVES);
getCamera()->setNearFarRatio(0.000003f);
// setRunFrameScheme(ON_DEMAND);
startTimer(10);
}
osg::ref_ptr<osg::Camera> GraphicsWindowQt::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 = false;
traits->x = x;
traits->y = y;
traits->width = w;
traits->height = h;
traits->doubleBuffer = true;
traits->sharedContext = 0;
traits->windowDecoration = false;
traits->setInheritedWindowPixelFormat = true;
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::Vec4f(0.1,0.3, 0.5,0.4)); //改背景色
return camera.release();
}
cpp
复制代码
#include "mainwindow.h"
#include <QApplication>
#include "graphicswindowqt.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
GraphicsWindowQt w;
w.show();
w.resize(1200,800);
return a.exec();
}
示例3:渲染一头牛
cpp
复制代码
#include "mainwindow.h"
#include <QApplication>
#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
osgViewer::Viewer viewer;
viewer.setSceneData(osgDB::readNodeFile("/mnt/hgfs/gongxiang/cow.osg"));
viewer.run();
return a.exec();
}