How to render in Qt3D in standard GUI application?

匿名 (未验证) 提交于 2019-12-03 02:48:02

问题:

I enjoy using Qt3D, but all of the examples I see for it are full window applications. What I can't understand from the examples is how to add a qt3d rendering window to a regular qt gui application.

Basically what I want is a little rendering widget for my Qt5 Gui application.

I've looked into Qtgl widget, but I really want to use the scene management abilities of Qt3D.

How can I render as a sub window inside of a qt Gui window?

Is this possible?

Update

So I added this to my MainWindow.cpp It is loosely based off of this http://blog.qt.digia.com/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);

which seems right.

my load_model.cpp begins like this:

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

It crashes with: This application has requested the runtime to terminate it in an unusual way.

and in the qt application output: Invalid parameter passed to C runtime function.

EDIT Added the rest of the class in question

I notice that in the example I am adapting http://doc.qt.digia.com/qt-quick3d-snapshot/qt3d-penguin-main-cpp.html the window is initialized by saying:

LoadModelView view;

However, saying

LoadModelView *view = new LoadModelView(this)

crashes

回答1:

You can subclass QGLView class which extends QGLWidget with support for 3D viewing:

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 introduces the function QWidget::createWindowContainer(). A function that creates a QWidget wrapper for an existing QWindow, allowing it to live inside a QWidget-based application. You can use QWidget::createWindowContainer which creates a QWindow in a QWidget. This allows placing QWindow-subclasses in Widget-Layouts. This way you can embed your QGLView inside a widget.



回答2:

This is how I did it on Qt5.10. This example shows a scene with a cuboid. Scene you can than use like a button or so... To use this add QT += 3dextras to your project file.

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

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


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!