Trouble to save a QT3D rendered scene to a image file?
I am trying to save an QT3D rendered view into a image file, the scene is rendered and displayed fine but somehow the saved file only show a blank image. I tried different way and format (bmp and png) but no success. I am new to QT, what am I doing wrong? Any suggestion is appreciated.
so here is rough illustration of my code :
Qt3DExtras::Qt3DWindow *m_view = new Qt3DExtras::Qt3DWindow();
and its container:
QWidget *m_viewContainer = QWidget::createWindowContainer(m_view, parent, Qt::Window|Qt::MSWindowsOwnDC);
// save to an image
// QMessageBox::warning(this, "File could not be saved", "ok", QMessageBox::Ok);
BTW, I am using QT5.8 for windows.
by the way, QPixmap::grabWidget is an obsolete member function
@Flotisable , Thank you for the suggestion. Just tried the following code, it still just save a blank image.
QScreen *screen = m_view->screen();
However the debug print the following message, I am still trying to figure out what it means maybe I am missing something in my code above?
Qt3D.Renderer.Backend: bool Qt3DRender::Render::GraphicsContext::makeCurrent(QSurface*) makeCurrent failed
@guy-incognito , thanks for providing the info. I will give it a try.
@Flotisable , @guy-incognito , I kinds of get it working (partly) with the grabWindow approach. however the new issue is that even the onscreen view is changed, somehow the captured image is always stay the same (for example I changed the viewpoint) . Any clue why ? .
maybe the time you capturing the image is not correct.
could you provide some code on how and when you capture the image?
@Flotisable , First please allow me to explain what I am trying to do : my ultimate goal is to take controllable multiple camera view of the 3D scene with objects in motion, to be clear, say we create a 3D scene with moving objects, I want to capture the rendered image from multiple viewpoint at any frame. The number and location of camera viewpoints, and scene creation etc are programmable. And what I have done so far include: created a qt widget application which include a main GUI window with controls (on scene creation, camera pose / location parameters), and a second window which serve as the container of the camera view of 3D scene ( The second window is a member object of main window) .
As the number of the viewpoint can be quite big (also it seems QT has a limitation on number of virtual cameras can be setup ?), I am trying to use the one camera and move it around, i.e. by pausing the scene object at every frame, move the camera and capture the scene at each viewpoint, then resume the scene to next frame,.. and continue the process. – This part are still need to be done, by reading QT docs/examples, I think I probably can get the control of scene object and pause /resume with QTimeline + QPropertyAnimation. ( The scene object property can be animated, but can the camera position also be animated property?)
I am all new to QT, and I am all ears here for any suggestion/advice. There are not many examples, especially on QT3D with widget GUI application, my google search also show some message saying this is a limitation ( I think it may be outdated info, and only apply to older QT version? as I get my main GUI + 3D view working with QT5.8)
With regarding to the capture problem I initially posted, after studying the link @guy-incognito posted, and I think it should serve my purpose better.
But I would like to know how grabWindow behave and why it fails to update view. For test purpose, I used a test button to save view: so the app starts, a 3D scene with default setting is shown in 2nd window. By change the camera positon/pose, I can see the 2nd window view is updated (almost real-time) to the latest setting, however if I press the test save button, the saved image is still the original view, and not updated. below are the related code:
// test save
QString saveFilename = m_ctrl.viewcapture.saveFilename;
QScreen *screen = view->screen();
QMessageBox::warning(this, "File could not be saved", "ok", QMessageBox::Ok);
I write a simple Qt 3D program to test it, and it works.
maybe it's a silly question, but have you checked that the slot is triggered?
and what does
getViewdo, does it return the correct window?
by the way, I do not set
Qt3DExtras::Qt3DWindowas the child of
QMainWindow, I'm not sure if it is the reason that you can't save correct image.
@Flotisable , thanks for the info. In my code, there is a GUI window containing controls and the 3D rendered view is shown in a separate window (not child) . getview basically pass the Qt3DExtras::Qt3DWindow pointer back to the main window, and the slot function does get triggered. But as you pointed out, I have the similar concern that maybe QT3D does not work with widget window? it seems all the qt3d examples I saw so far always have 3D rendered view contained in the main window, not sure if there is any QT limitation? (I googled a bit, haven't found a sure answer for this).
Anyone had the experience of rendering QT3D rendered view in a separate child window, in a widget-based application? Is there any QT limitation of doing this? Thanks.
Some interesting finding from this link (http://development.qt-project.narkive.com/PnbzvDC3/add-widgets-into-qt3d-window) , at the very end, Sean comments "We do not yet have any widget/Qt3D integrations." not sure if it is still apply for QT5.8?
@shangariLa , I was able to embed a Qt3DWindow object into a QWidget using QWidget::createWindowContainter. The rendering works fine on Desktop (only tested on Linux) using Qt 5.8, but I'm having issues doing this for Android (which does not render anything). Look at the basicshape c++ example on how to do this. Currently, I don't think there's a direct QWidget-Qt3d integration in 5.8.
@HoTiX , in your case, do you embed QT3D view in main GUI window (so there is only one window), or do you have it in separate window? In my case, I have it in separate window, the rendering part is mostly working (occasional crash) but having trouble to save the rendered image.
At the moment, I can save the single capture with qrendercapture approach, but not continuous capture,
@shangariLa , in my case I embed the Qt3DWindow in a QMainWindow using the createWindowContainer and it does render fine on Desktop, but not on Android.
I tried to detach the Qt3DWindow into a separate window (QMainWindow and Qt3DWindow) and nothing is render to the Qt3DWindow. I can see that defaultFrameGraph()->setClearColor() works fines but nothing more is showed.
I post my code, maybe you can find the difference between our method.
and I tried separate and embedded the window, all work fine, except that embed the window sometimes cause the app to crash when exit.
It was my mistake... I show() the window before even creating the scene. Anyway, I just wanted to replicate your issue, but I created my own in the process.
I found a bug which cause the multi-capture failure. Now the original capture issue I posted are mostly solved. Thanks everyone for providing the info.
However, it still crashes or capture sometimes behave unexpectedly. By debugging, it seems some of the signal / slot connection do not always behave as expected. how do you guys debug the Qt signal connection issues? other tools? I havn't figure out how to use debugger for this purpose.
An additional tool that might be of interest is KDAB's GammaRay.