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