15

我喜欢使用 Qt3D,但我看到的所有示例都是全窗口应用程序。从示例中我无法理解的是如何将 qt3d 渲染窗口添加到常规 qt gui 应用程序。

基本上我想要的是我的 Qt5 Gui 应用程序的一个小渲染小部件。

我查看了 Qtgl 小部件,但我真的很想使用 Qt3D 的场景管理功能。

如何在 qt Gui 窗口内渲染为子窗口?

这可能吗?

更新

所以我将此添加到我的 MainWindow.cpp 它松散地基于此https://www.qt.io/blog/2013/02/19/introducing-qwidgetcreatewindowcontainer

LoadModelView *view = new LoadModelView(); //Crashes on this. Will not compile with
                                           // LoadModelView(this) 

    QWidget *container = QWidget::createWindowContainer(view);
    container->setFocusPolicy(Qt::TabFocus);

    ui->gridLayout->addWidget(container);

这似乎是对的。

我的 load_model.cpp 是这样开始的:

#include "qglmaterialcollection.h"
#include "qglmaterial.h"
#include "qglscenenode.h"
#include "qgllightmodel.h"
#include "qglabstractscene.h"
#include <QtGui/qmatrix4x4.h>

#include <QPropertyAnimation>
#include <QtCore/qmath.h>

#define DEGREE_TO_RAD (3.1415926/180.0)

LoadModelView::LoadModelView(QWindow *parent)
    : QGLView(parent)
    , m_pSTLScene(0)
{
    loadModels();

    camera()->setCenter(QVector3D(0, 0, 0));
    camera()->setEye(QVector3D(0, 4, 10));
}
LoadModelView::~LoadModelView()
{
    delete m_pSTLScene;
}

void LoadModelView::paintGL(QGLPainter *painter)
{
    QMatrix4x4 stlWorld;
    stlWorld.setToIdentity();
    stlWorld.scale(0.1);
    stlWorld.translate(QVector3D(2.0,0.0,0.0));

    painter->setStandardEffect(QGL::LitMaterial);
    painter->setFaceColor(QGL::AllFaces,QColor(170,202,0));

    painter->modelViewMatrix() = camera()->modelViewMatrix() * stlWorld;

    m_pSTLScene->mainNode()->draw(painter);
}

void FixNodesRecursive(int matIndex, QGLSceneNode* pNode)
{
    if (pNode) {
        pNode->setMaterialIndex(matIndex);
       // pNode->setEffect(QGL::FlatReplaceTexture2D);
        foreach (QGLSceneNode* pCh, pNode->children()) {
            FixNodesRecursive(matIndex, pCh);
        }
    }
}

void LoadModelView::loadModels()
{
    {
        m_pSTLScene = QGLAbstractScene::loadScene(QLatin1String(":/models/Sheep.stl"), QString(),"CorrectNormals CorrectAcute");
        Q_ASSERT(m_pSTLScene!=0);
        QGLMaterial *mat = new QGLMaterial;
        mat->setAmbientColor(QColor(170,202,0));
        mat->setDiffuseColor(QColor(170,202,0));
        mat->setShininess(128);

        QGLSceneNode* pSTLSceneRoot = m_pSTLScene->mainNode();
        int matIndex = pSTLSceneRoot->palette()->addMaterial(mat);
        pSTLSceneRoot->setMaterialIndex(matIndex);
        pSTLSceneRoot->setEffect(QGL::FlatReplaceTexture2D);
        FixNodesRecursive(matIndex,pSTLSceneRoot);
    }
}

它崩溃了:

此应用程序已请求运行时以不寻常的方式终止它。

在 qt 应用程序输出中:

传递给 C 运行时函数的参数无效。

编辑添加了相关课程的其余部分

我注意到在示例中我正在调整https://github.com/Distrotech/qt3d/blob/master/tutorials/qt3d/penguin/main.cpp窗口初始化时说:

LoadModelView view;

然而,说

LoadModelView *view = new LoadModelView(this)

崩溃

4

2 回答 2

8

您可以继承 QGLView 类,该类扩展了 QGLWidget 并支持 3D 查看:

class GLView : public QGLView
{
    Q_OBJECT

public:
    GLView(QWidget *parent = 0);
    ~GLView();

protected:
    void initializeGL(QGLPainter *painter);
    void paintGL(QGLPainter *painter);

private:
    QGLAbstractScene *m_scene;
    QGLSceneNode *m_rootNode;
};

GLView::GLView(QWidget *parent)
    : QGLView(parent)
    , m_scene(0)
    , m_rootNode(0)
{
    // Viewing Volume
    camera()->setFieldOfView(25);
    camera()->setNearPlane(1);
    camera()->setFarPlane(1000);

    // Position of the camera
    camera()->setEye(QVector3D(0, 3, 4));

    // Direction that the camera is pointing
    camera()->setCenter(QVector3D(0, 3, 0));
}

GLView::~GLView()
{
    delete m_scene;
}

void GLView::initializeGL(QGLPainter *painter)
{
    // Background color
    painter->setClearColor(QColor(70, 70, 70));

    // Load the 3d model from the file
    m_scene = QGLAbstractScene::loadScene("models/model1/simplemodel.obj");

    m_rootNode = m_scene->mainNode();
}

void GLView::paintGL(QGLPainter *painter)
{
    m_rootNode->draw(painter);
}

Qt 5.1 引入了函数 QWidget::createWindowContainer()。一个为现有 QWindow 创建 QWidget 包装器的函数,允许它存在于基于 QWidget 的应用程序中。您可以使用 QWidget::createWindowContainer 在 QWidget 中创建 QWindow。这允许在 Widget-Layouts 中放置 QWindow 子类。通过这种方式,您可以将 QGLView 嵌入到小部件中。

于 2014-04-23T09:14:25.383 回答
4

这就是我在 Qt5.10 上的做法。此示例显示了一个带有长方体的场景。Scene你可以比使用一个按钮左右...使用这个添加QT += 3dextras到你的项目文件中。

szene.h

#ifndef SCENE_H
#define SCENE_H

#include <QObject>
#include <QWidget>

class Scene
      : public QWidget
{
    Q_OBJECT

private:
    QWidget *container;

public:
    explicit Scene(QWidget *parent = nullptr);

protected:
    // reimplementation needed to handle resize events
    // http://doc.qt.io/qt-5/qwidget.html#resizeEvent
    void
    resizeEvent ( QResizeEvent * event );

public slots:
    void
    resizeView(QSize size);
};

#endif // SCENE_H

场景.cpp

#include "scene.h"

#include <Qt3DExtras/Qt3DWindow>
#include <Qt3DExtras/QForwardRenderer>
#include <QQuaternion>
#include <Qt3DCore/QEntity>
#include <Qt3DCore/QTransform>
#include <Qt3DRender/QCamera>
#include <Qt3DExtras/QCuboidMesh>
#include <Qt3DExtras/QPhongMaterial>

Scene::Scene(QWidget *parent)
   : QWidget(parent)
{
    auto view = new Qt3DExtras::Qt3DWindow();

    // create a container for Qt3DWindow
    container = createWindowContainer(view,this);

    // background color
    view->defaultFrameGraph()->setClearColor(QColor(QRgb(0x575757)));

    // Root entity
    auto rootEntity = new Qt3DCore::QEntity();

    // Camera
    auto camera = new Camera(rootEntity,view);
    auto cameraEntity = view->camera();

    cameraEntity->setPosition(QVector3D(0, 0, 50.0f));
    cameraEntity->setUpVector(QVector3D(0, 1, 0));
    cameraEntity->setViewCenter(QVector3D(0, 0, 0));

    // Cuboid
    auto cuboidMesh = new Qt3DExtras::QCuboidMesh();

    // CuboidMesh Transform
    auto cuboidTransform = new Qt3DCore::QTransform();
    cuboidTransform->setScale(10.0f);
    cuboidTransform->setTranslation(QVector3D(0.0f, 0.0f, 0.0f));
    cuboidTransform->setRotation(QQuaternion(1,1.5,1,0).normalized());

    auto cuboidMaterial = new Qt3DExtras::QPhongMaterial();
    cuboidMaterial->setDiffuse(QColor(QRgb(0x005FFF)));

    // assamble entity
    auto cuboidEntity = new Qt3DCore::QEntity(rootEntity);
    cuboidEntity->addComponent(cuboidMesh);
    cuboidEntity->addComponent(cuboidMaterial);
    cuboidEntity->addComponent(cuboidTransform);

    // Set root object of the scene
    view->setRootEntity(rootEntity);
}

void
Scene::resizeView(QSize size)
{
    container->resize(size);
}

void
Scene::resizeEvent ( QResizeEvent * /*event*/ )
{
  resizeView(this->size());
}
于 2018-03-03T23:54:19.993 回答