OSG:(1)渲染正方体

#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();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值