


#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
#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(); // 新增:事件处理后立即请求重绘
}
#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();
}