Horde3D http://horde3d.org/forums/ |
|
Integrating Horde3D with QtQuick 1.0 http://horde3d.org/forums/viewtopic.php?f=2&t=1645 |
Page 1 of 1 |
Author: | Christoph [ 25.02.2012, 16:48 ] |
Post subject: | Integrating Horde3D with QtQuick 1.0 |
Hi, I have a working implementation of Horde3D along with QtQuick 1.0 (see stripped code snipped below). There is a very fundamental problem with this implementation: The Horde3DViewport won't render correctly if flipped or rotated by QML (think of taking the result image and putting it inside a Flippable). To make this work properly I think Horde3D should be rendering to an FBO. This FBO should then be rendered to a quad - with proper rotation and projection matrices. I have thought about using h3dGetRenderTargetData(...), but I think that won't perform well, because it will copy every frame from VRAM to RAM and back again. Any hints how to get this working? Code: class Horde3DViewport : public QDeclarativeItem
{ Q_OBJECT public: Horde3DViewport(QDeclarativeItem *parent) : QDeclarativeItem(parent), m_initialized(false), m_animation(this) { setFlag(QGraphicsItem::ItemHasNoContents, false); // XXX: start redraw animation (a timer, that calls QDeclarativeItem::update()). } ~Horde3DViewport() { // XXX: destroy scene and release Horde3D. } protected: void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { Q_UNUSED(option); QPaintEngine::Type engineType = painter->paintEngine()->type(); if (engineType == QPaintEngine::OpenGL || engineType == QPaintEngine::OpenGL2) { painter->beginNativePainting(); // Initialize. if (!m_initialized) { // XXX: initialize Horde3D and create a scene m_initialized = true; } // Render. h3dRender(m_camera); h3dFinalizeFrame(); // Restore render state. glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindRenderbuffer(GL_RENDERBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); painter->endNativePainting(); } } private: // XXX: Pipeline, etc. H3DNode m_camera; }; |
Author: | Volker [ 25.02.2012, 19:54 ] |
Post subject: | Re: Integrating Horde3D with QtQuick 1.0 |
One of the last changes to the SVN trunk was that Horde does not bind 0 as the main render target anymore but does retain the currently bound FBO and use that to render the main output into. So if you create an bind an FBO outside of Horde and then call it's render function you should get what you want. |
Author: | Christoph [ 26.02.2012, 02:18 ] |
Post subject: | Re: Integrating Horde3D with QtQuick 1.0 |
Thanks alot. I had to work around one thing: GL_CULL_FACE, GL_DEPTH_TEST and GL_MULTISAMPLE dont get restored (had to brute-force-check the OpenGL state using glIsEnabled ). A simplified (untested) version of my code is below (Header+Source+QDeclarativeView usage). Steal it if you want to Cheers, Christoph Code: #ifndef HORDEVIEWPORT_H #define HORDEVIEWPORT_H #include <QtDeclarative/QDeclarativeItem> #include <QtCore/QBasicTimer> #include <Horde3D.h> class QGLFramebufferObject; class HordeViewport; class HordeViewportAnimation : public QAbstractAnimation { Q_OBJECT public: HordeViewportAnimation(HordeViewport *parent = 0); ~HordeViewportAnimation(); int duration() const; protected: void updateCurrentTime(int currentTime); private: HordeViewport* m_viewport; }; class HordeViewport : public QDeclarativeItem { Q_OBJECT public: HordeViewport(QDeclarativeItem *parent = 0); ~HordeViewport(); protected: void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry); void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); private: void validateGL(int deviceWidth, int deviceHeight); void paintGL(); bool m_firstRun; bool m_valid; QGLFramebufferObject *m_fbo; HordeViewportAnimation m_animation; H3DNode m_camera; }; QML_DECLARE_TYPE(HordeViewport) #endif Code: #include "hordeviewport.h" #include <QGLFramebufferObject> HordeViewportAnimation::HordeViewportAnimation(HordeViewport *parent) : QAbstractAnimation(parent), m_viewport(parent) { // Do nothing. } HordeViewportAnimation::~HordeViewportAnimation() { // Do nothing. } int HordeViewportAnimation::duration() const { // Duration is undefined (infinite). return -1; } void HordeViewportAnimation::updateCurrentTime(int currentTime) { // Schedule redraw. m_viewport->update(); } HordeViewport::HordeViewport(QDeclarativeItem *parent) : QDeclarativeItem(parent), m_firstRun(true), m_valid(false), m_fbo(0), m_animation(this), m_camera(0) { setFlag(QGraphicsItem::ItemHasNoContents, false); m_animation.start(); } HordeViewport::~HordeViewport() { h3dRelease(); m_animation.stop(); if (m_fbo) { delete m_fbo; } } void HordeViewport::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { Q_UNUSED(option); QPaintEngine::Type engineType = painter->paintEngine()->type(); if (engineType == QPaintEngine::OpenGL || engineType == QPaintEngine::OpenGL2) { painter->beginNativePainting(); // Validate if required. if (!m_valid) { validateGL(painter->device()->width(), painter->device()->height()); m_valid = true; } // Render to FBO. m_fbo->bind(); paintGL(); m_fbo->release(); // Render FBO to quad. glEnable(GL_TEXTURE_2D); m_fbo->drawTexture(QPointF(0, 0), m_fbo->texture()); painter->endNativePainting(); } } void HordeViewport::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) { QDeclarativeItem::geometryChanged(newGeometry, oldGeometry); m_valid = false; } void HordeViewport::validateGL(int deviceWidth, int deviceHeight) { if (m_firstRun) { if (!h3dInit()) { qCritical() << "h3dInit failed"; } // XXX: other init code m_firstRun = false; } if (m_fbo) { delete m_fbo; } m_fbo = new QGLFramebufferObject(deviceWidth, deviceHeight); if (m_camera) { // Resize viewport h3dSetNodeParamI(m_camera, H3DCamera::ViewportXI, 0); h3dSetNodeParamI(m_camera, H3DCamera::ViewportYI, 0); h3dSetNodeParamI(m_camera, H3DCamera::ViewportWidthI, deviceWidth); h3dSetNodeParamI(m_camera, H3DCamera::ViewportHeightI, deviceHeight); // Set virtual camera parameters float aspectRatio = static_cast<float>(deviceWidth) / deviceHeight; h3dSetupCameraView(m_camera, 45.0f, aspectRatio, 0.1f, 1000.0f); H3DRes cameraPipeRes = h3dGetNodeParamI(m_camera, H3DCamera::PipeResI); h3dResizePipelineBuffers(cameraPipeRes, deviceWidth, deviceHeight); } } void HordeViewport::paintGL() { if (...camera changed...) { m_camera = // XXX: get camera. m_valid = false; } // XXX: Update scene. // Render scene. if (m_camera) { // Render. h3dRender(m_camera); h3dFinalizeFrame(); // Restore render state. glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); } } Code: QDeclarativeView *m_view
qmlRegisterType<HordeViewport>("HordeComponents", 1, 0, "HordeViewport"); // Setup view. m_view->setViewport(new QGLWidget(QGLFormat::defaultFormat())); m_view->setRenderHint(QPainter::SmoothPixmapTransform); m_view->setRenderHint(QPainter::Antialiasing); m_view->setResizeMode(QDeclarativeView::SizeRootObjectToView); |
Page 1 of 1 | All times are UTC + 1 hour |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |