How to zoom toward a 3D mesh with qt? - c++

I'm using a Wheelevent to Zoom in/out in a QWidget view,in use the event to translate the QCamera, is there a solution from the qt api to move toward a point or zoom with the camera to a specific point? I searched in many sections but did'nt find something useful unfortunately.

Edit: Stefan Reinhardt suggested to use QAbstractCameraController to achieve what you want to do. The example I provided is a quick-and-dirty solution. I agree that using the camera controller is the way intended in Qt3D.
The Qt3D API doesn't support this directly, but you can implement it easily yourself.
Here is a minimally working example, that should get you started (note, that you have to adjust the upvector, when scrolling past the view center I guess):
main.cpp:
#include <QApplication>
#include "graphicswindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
GraphicsWindow graphicsWindow;
graphicsWindow.show();
return a.exec();
}
graphicswindow.h:
#include <Qt3DExtras/Qt3DWindow>
#include <Qt3DCore/QEntity>
class GraphicsWindow : public Qt3DExtras::Qt3DWindow {
public:
GraphicsWindow();
void wheelEvent ( QWheelEvent * event ) override;
private:
Qt3DCore::QEntity *createScene();
};
graphicswindow.cpp:
#include "graphicswindow.h"
#include <QMouseEvent>
#include <QVector3D>
#include <Qt3DRender/QCamera>
#include <Qt3DRender/QMaterial>
#include <Qt3DExtras/QGoochMaterial>
#include <Qt3DExtras/QCuboidMesh>
GraphicsWindow::GraphicsWindow() : Qt3DExtras::Qt3DWindow() {
// You could also create a dedicated setup method
Qt3DCore::QEntity *root = createScene();
setRootEntity(root);
Qt3DRender::QCamera *camera = this->camera();
camera->lens()->setPerspectiveProjection(45.0f, 16.0f/9.0f, 0.1f, 1000.0f);
camera->setPosition(QVector3D(20.0, 20.0, 20.0f));
camera->setViewCenter(QVector3D(0, 0, 0));
}
void GraphicsWindow::wheelEvent(QWheelEvent *event) {
QVector3D camPos = this->camera()->position();
camPos.normalize();
camPos = this->camera()->position() - QVector3D(event->delta() / 300.f,
event->delta() / 300.f,
event->delta() / 300.f);
this->camera()->setPosition(camPos);
}
Qt3DCore::QEntity* GraphicsWindow::createScene() {
Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity;
Qt3DRender::QMaterial *material = new Qt3DExtras::QGoochMaterial(rootEntity);
//Cube
Qt3DCore::QEntity *cubeEntity = new Qt3DCore::QEntity(rootEntity);
Qt3DExtras::QCuboidMesh *cubeMesh = new Qt3DExtras::QCuboidMesh;
cubeEntity->addComponent(cubeMesh);
cubeEntity->addComponent(material);
return rootEntity;
}

Related

Using several transforms in one Entity

Tried to create simple program showing torus with lighting. Everything works, but have this problem with light position.
When trying to create new transform for light after creating torus light's transform is being used for new torus position, instead of light.
Tried to change values and move addComponent, but no result.
Here's photo of result
Here's my entire code.
#include <QGuiApplication>
#include <Qt3DExtras/Qt3DWindow>
#include <Qt3DExtras/QTorusMesh>
#include <Qt3DExtras/QPhongMaterial>
#include <Qt3DCore/QEntity>
#include <Qt3DCore/QTransform>
#include <Qt3DRender/QCamera>
#include <Qt3DRender/QPointLight>
Qt3DCore::QEntity *createScene();
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
Qt3DExtras::Qt3DWindow view;
Qt3DCore::QEntity *rootEntity = createScene();
Qt3DRender::QCamera *camera =view.camera();
camera->lens()->setPerspectiveProjection(60,(float)view.width()/view.height(),0.1f,1000.0f);
camera->setPosition(QVector3D(0.0f,0.0f,40.0f));
camera->setViewCenter(QVector3D(0.0f,0.0f,0.0f));
view.setRootEntity(rootEntity);
view.show();
return app.exec();
}
Qt3DCore::QEntity *createScene()
{
Qt3DCore::QEntity *resultEntity = new Qt3DCore::QEntity;
Qt3DExtras::QTorusMesh *torusMesh = new Qt3DExtras::QTorusMesh(resultEntity);
torusMesh->setRadius(15.0f);
torusMesh->setMinorRadius(6.0f);
torusMesh->setSlices(16);
torusMesh->setRings(32);
Qt3DExtras::QPhongMaterial *torusMaterial = new Qt3DExtras::QPhongMaterial(resultEntity);
Qt3DCore::QTransform *torusTransform = new Qt3DCore::QTransform(resultEntity);
resultEntity->addComponent(torusMesh);
resultEntity->addComponent(torusMaterial);
resultEntity->addComponent(torusTransform);
Qt3DCore::QEntity *lightEntity = new Qt3DCore::QEntity(resultEntity);
Qt3DRender::QPointLight *pointLight = new Qt3DRender::QPointLight(lightEntity);
Qt3DCore::QTransform *lightTransform = new Qt3DCore::QTransform(resultEntity);
lightTransform->setTranslation(QVector3D(0.0f,0.0f,30.0f));
resultEntity->addComponent(pointLight);
resultEntity->addComponent(lightTransform);
return resultEntity;
}

Can't see/load a .obj file with Qt3D, written in cpp

I'm having a lot of issues to have a simple working app that load a light mesh in Qt3D, nothing shows up on screen.
Here's some code I put together to have a have striped down to show.
You'll notice that it's a shorter version of this Qt example
You won't see it in this example but in my actual project I already
tried loading it with
qrc and
localfile QUrl
Qt3DExtras::QTorusMesh work without an issue.
I tried to watch the loading status of the mesh, on my actual project it does go from None though Loading to Loaded
Also, I have no trouble loading the file su.obj using a Qt QML example, so it's
not the file that is corrupted. The file being a simple Suzanne from Blender, exported.
I used Qt5 and 6.
Finally, I know the question has been asked a few times, but nothing helped.
#include <QGuiApplication>
#include <Qt3DCore/QEntity>
#include <Qt3DRender/QCamera>
#include <Qt3DRender/QCameraLens>
#include <Qt3DCore/QTransform>
#include <Qt3DCore/QAspectEngine>
#include <Qt3DInput/QInputAspect>
#include <Qt3DRender/QRenderAspect>
#include <Qt3DRender/QGeometryRenderer>
#include <Qt3DExtras/QForwardRenderer>
#include <Qt3DExtras/QPhongMaterial>
#include <Qt3DExtras/QSphereMesh>
#include <Qt3DExtras/QTorusMesh>
#include <QMesh>
#include <QPropertyAnimation>
#include "orbittransformcontroller.h"
#include "qorbitcameracontroller.h"
#include "qt3dwindow.h"
#include <qdebug.h>
Qt3DCore::QEntity *createScene()
{
// Root entity
Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity;
// Material
Qt3DRender::QMaterial *material = new Qt3DExtras::QPhongMaterial(rootEntity);
// Sphere
Qt3DCore::QEntity *sphereEntity = new Qt3DCore::QEntity(rootEntity);
auto *sphereMesh = new Qt3DRender::QMesh();
sphereMesh->setSource(QUrl::fromLocalFile("su.obj"));
Qt3DCore::QTransform *sphereTransform = new Qt3DCore::QTransform;
OrbitTransformController *controller = new OrbitTransformController(sphereTransform);
controller->setTarget(sphereTransform);
controller->setRadius(20.0f);
QPropertyAnimation *sphereRotateTransformAnimation = new QPropertyAnimation(sphereTransform);
sphereRotateTransformAnimation->setTargetObject(controller);
sphereRotateTransformAnimation->setPropertyName("angle");
sphereRotateTransformAnimation->setStartValue(QVariant::fromValue(0));
sphereRotateTransformAnimation->setEndValue(QVariant::fromValue(360));
sphereRotateTransformAnimation->setDuration(10000);
sphereRotateTransformAnimation->setLoopCount(-1);
sphereRotateTransformAnimation->start();
sphereEntity->addComponent(sphereMesh);
sphereEntity->addComponent(sphereTransform);
sphereEntity->addComponent(material);
return rootEntity;
}
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
Qt3DExtras::Qt3DWindow view;
Qt3DCore::QEntity *scene = createScene();
// Camera
Qt3DRender::QCamera *camera = view.camera();
camera->lens()->setPerspectiveProjection(45.0f, 16.0f/9.0f, 0.1f, 1000.0f);
camera->setPosition(QVector3D(0, 0, 40.0f));
camera->setViewCenter(QVector3D(0, 0, 0));
// For camera controls
Qt3DExtras::QOrbitCameraController *camController = new Qt3DExtras::QOrbitCameraController(scene);
camController->setLinearSpeed( 50.0f );
camController->setLookSpeed( 180.0f );
camController->setCamera(camera);
view.setRootEntity(scene);
view.show();
return app.exec();
}
With the help from #eyllanesc and qDebug, I found how to write it in three ways:
const QUrl url = QUrl( "qrc:/path/copied/from/qtcreator/su.obj");
const QUrl url = QUrl::fromLocalFile( "C:/path/to/folder/su.obj");
const QUrl url = QUrl::fromLocalFile( "su.obj");
qDebug() << QDir::currentPath(); // I used this to make sure I was at the right place
and
sphereMesh->setSource(url);

How to load and display a blender .obj source file scene using Qt 3D libraries

I'm trying to load a .obj source file from blender, and display it, LibertStatue.obj is the .obj file which is located in the same folder as the main.cpp file below. When I run this code, I get blank window which I think is supposed to show a statue of liberty, and a command prompt that says QObject::connect(opneglcontext, unknown) Invalid nullptr parameter.
I'm using Qt Creator on linux Xubuntu.
I downloaded the .obj file of statue of liberty from here : https://free3d.com/3d-model/statue-of-liberty-73656.html.
#include <QGuiApplication>
#include <Qt3DExtras/QPhongMaterial>
#include <Qt3DExtras/Qt3DWindow>
#include <Qt3DExtras/QOrbitCameraController>
#include <Qt3DRender>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QUrl data = QUrl::fromLocalFile("LibertStatue.obj");
Qt3DExtras::Qt3DWindow view;
Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity;
Qt3DCore::QEntity *flyingwedge = new Qt3DCore::QEntity(rootEntity);
Qt3DExtras::QPhongMaterial *material = new Qt3DExtras::QPhongMaterial();
material->setDiffuse(QColor(254, 254, 254));
Qt3DRender::QMesh *flyingwedgeMesh = new Qt3DRender::QMesh;
flyingwedgeMesh->setMeshName("FlyingWedge");
flyingwedgeMesh->setSource(data);
flyingwedge->addComponent(flyingwedgeMesh);
flyingwedge->addComponent(material);
Qt3DRender::QCamera *camera = view.camera();
camera->lens()->setPerspectiveProjection(40.0f, 16.0f/9.0f, 0.1f, 1000.0f);
camera->setPosition(QVector3D(0, 0, 40.0f));
camera->setViewCenter(QVector3D(0, 0, 0));
Qt3DCore::QEntity *lightEntity = new Qt3DCore::QEntity(rootEntity);
Qt3DRender::QPointLight *light = new Qt3DRender::QPointLight(lightEntity);
light->setColor("white");
light->setIntensity(0.8f);
lightEntity->addComponent(light);
Qt3DCore::QTransform *lightTransform = new Qt3DCore::QTransform(lightEntity);
lightTransform->setTranslation(QVector3D(60, 0, 40.0f));
lightEntity->addComponent(lightTransform);
Qt3DExtras::QOrbitCameraController *camController = new Qt3DExtras::QOrbitCameraController(rootEntity);
camController->setCamera(camera);
view.setRootEntity(rootEntity);
view.show();
return app.exec();
}
The problem is the setMeshName call. The documentation for the QMesh C++ class is misleading: setMeshName is not for setting a name to the QMesh object, but for selecting which geometry from the OBJ file you want to load. Its actual behavior is explained in the documentation of the corresponding QML type.
So you have two options: just remove the setMeshName call, or pass the actual name of the geometry, which you can find out by opening the OBJ file with a text editor.
Inspecting your code it looks to me that the Qt3Dwindow cannot be displayed standalone and the creation of a window container is needed to display the Qt3DWindow inside of a Widget (QFrame).
A typical Qt3D application I use for testing looks as follows:
#include <QApplication>
#include <QDebug>
#include <QFrame>
#include <QVBoxLayout>
#include <QWidget>
#include <QTimer>
#include <Qt3DRender/QCamera>
#include <Qt3DRender/QCameraLens>
#include <Qt3DExtras/Qt3DWindow>
#include <Qt3DExtras/QOrbitCameraController>
#include <Qt3DExtras/QDiffuseSpecularMaterial>
#include <Qt3DExtras/QSphereMesh>
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
auto view = new Qt3DExtras::Qt3DWindow();
auto rootEntity = new Qt3DCore::QEntity();
view->setRootEntity(rootEntity);
auto camera = view->camera();
camera->lens()->setPerspectiveProjection(45.0f, 1., 0.1f, 10000.0f);
camera->setPosition(QVector3D(0, 0, 5));
camera->setUpVector(QVector3D(0, 1, 0));
camera->setViewCenter(QVector3D(0, 0, 0));
auto camController = new Qt3DExtras::QOrbitCameraController(rootEntity);
camController->setCamera(camera);
auto sphereMat = new Qt3DExtras::QDiffuseSpecularMaterial;
sphereMat->setDiffuse(QColor(Qt::blue));
auto mesh = new Qt3DExtras::QSphereMesh();
mesh->setRadius(1);
auto sphereEntity = new Qt3DCore::QEntity(rootEntity);
sphereEntity->addComponent(mesh);
sphereEntity->addComponent(sphereMat);
auto container = QWidget::createWindowContainer(view);
QFrame frame;
frame.setLayout(new QVBoxLayout);
frame.layout()->addWidget(container);
frame.resize(QSize(400, 300));
QTimer::singleShot(100, [&]() {
camera->viewAll();
});
frame.show();
return a.exec();
}

2D meshes in QT3D

It seems to me that Qt3D cannot render 2D meshes well. To see what I mean open the shadow map QML example and change the camera controller from FirstPersonCameraController to OrbitCameraController. Run the program and attempt to view the ground plane from below, you will see it disappear. So QT3D just renders 2D meshes from one side and makes them transparent from the other side.
How can I fix this? i.e. render 2D meshes from both sides?
EDIT: Now I know that I have to disable culling for the rendering to work. I came up to this point:
//'this' refers to Qt3DWindow
rootEntity->addComponent(this->renderSettings());
QCullFace *face = new QCullFace();
QRenderStateSet *stateSet = new QRenderStateSet(this->renderSettings()->activeFrameGraph());
QRenderSurfaceSelector *selector = new QRenderSurfaceSelector(this->renderSettings());
face->setMode(QCullFace::NoCulling);
stateSet->addRenderState(face);
selector->setSurface(this);
but this still doesn't seem to change anything. Am I missing something?
Here is a minimally working example:
main.cpp:
#include <QApplication>
#include "clickwindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
GraphicsWindow graphicsWindow;
graphicsWindow.show();
return a.exec();
}
graphicswindow.h:
#include <Qt3DExtras/Qt3DWindow>
#include <Qt3DCore/QEntity>
#include <Qt3DCore/QTransform>
class GraphicsWindow : public Qt3DExtras::Qt3DWindow {
public:
GraphicsWindow();
void wheelEvent ( QWheelEvent * event ) override;
private:
Qt3DCore::QEntity *createScene();
Qt3DCore::QTransform *planeTransform;
};
graphicswindow.cpp:
#include "graphicswindow.h"
#include <QMouseEvent>
#include <Qt3DRender/QViewport>
#include <Qt3DRender/QClearBuffers>
#include <Qt3DRender/QRenderSurfaceSelector>
#include <Qt3DRender/QRenderStateSet>
#include <Qt3DRender/QCullFace>
#include <Qt3DRender/QCameraSelector>
#include <Qt3DRender/QCamera>
#include <Qt3DRender/QMaterial>
#include <Qt3DExtras/QGoochMaterial>
#include <Qt3DExtras/QPlaneMesh>
#include <Qt3DRender/QDepthTest>
GraphicsWindow::GraphicsWindow() : Qt3DExtras::Qt3DWindow() {
Qt3DRender::QCamera *camera = this->camera();
camera->lens()->setPerspectiveProjection(45.0f, 16.0f/9.0f, 0.1f, 1000.0f);
camera->setPosition(QVector3D(20.0, 20.0, 20.0f));
camera->setViewCenter(QVector3D(0, 0, 0));
Qt3DRender::QRenderSurfaceSelector *surfaceSelector = new Qt3DRender::QRenderSurfaceSelector;
surfaceSelector->setSurface(this);
Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport(surfaceSelector);
viewport->setNormalizedRect(QRectF(0, 0, 1.0, 1.0));
Qt3DRender::QCameraSelector *cameraSelector = new Qt3DRender::QCameraSelector(viewport);
cameraSelector->setCamera(camera);
Qt3DRender::QClearBuffers *clearBuffers = new Qt3DRender::QClearBuffers(cameraSelector);
clearBuffers->setBuffers(Qt3DRender::QClearBuffers::ColorDepthBuffer);
clearBuffers->setClearColor(Qt::white);
Qt3DRender::QRenderStateSet *renderStateSet = new Qt3DRender::QRenderStateSet(clearBuffers);
Qt3DRender::QCullFace *cullFace = new Qt3DRender::QCullFace(renderStateSet);
cullFace->setMode(Qt3DRender::QCullFace::NoCulling);
renderStateSet->addRenderState(cullFace);
Qt3DRender::QDepthTest *depthTest = new Qt3DRender::QDepthTest;
depthTest->setDepthFunction(Qt3DRender::QDepthTest::Less);
renderStateSet->addRenderState(depthTest);
setActiveFrameGraph(surfaceSelector);
Qt3DCore::QEntity *root = createScene();
setRootEntity(root);
}
void GraphicsWindow::wheelEvent(QWheelEvent *event) {
planeTransform->setRotationZ(planeTransform->rotationZ() + event->delta() / 40.f);
}
Qt3DCore::QEntity* GraphicsWindow::createScene() { // Root entity
Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity;
Qt3DCore::QEntity *planeEntity = new Qt3DCore::QEntity(rootEntity);
Qt3DRender::QMaterial *meshMaterial = new Qt3DExtras::QGoochMaterial;
Qt3DExtras::QPlaneMesh *planeMesh = new Qt3DExtras::QPlaneMesh;
planeMesh->setHeight(10);
planeMesh->setWidth(10);
planeTransform = new Qt3DCore::QTransform;
planeEntity->addComponent(planeTransform);
planeEntity->addComponent(planeMesh);
planeEntity->addComponent(meshMaterial);
return rootEntity;
}
Keep in mind that the setActiveFramegraph function of the Qt3DWindow automatically adds the QRenderSettings returned by the renderSettings() function of the window on the frame graph node that you set as the active frame graph. If you are implementing your own 3D window or create and offscreen renderer you have to use QRenderSettings as the root node of your framegraph (the window sets its render settings as the parent of the root frame graph node that you set) and add the render settings to the actual root node, i.e. the node that is the parent of the frame graph and the scene graph.

How to render in Qt3D in standard GUI application?

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 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);
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 https://github.com/Distrotech/qt3d/blob/master/tutorials/qt3d/penguin/main.cpp the window is initialized by saying:
LoadModelView view;
However, saying
LoadModelView *view = new LoadModelView(this)
crashes
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.
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());
}