summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYoann Lopes <yoann.lopes@nokia.com>2010-07-14 21:06:27 +0200
committerYoann Lopes <yoann.lopes@nokia.com>2010-07-14 21:06:27 +0200
commitab3edf1da3d76caaa189a04afed34b9eeeeb0739 (patch)
treeeaf5129028a6f3e6d29c32d826349b63490b068f
parent295bd2bf44858df39557b0ed63e729d7d88763be (diff)
Draw the graphicsView in a texture.
-rw-r--r--declarativeviewtexture.cpp93
-rw-r--r--declarativeviewtexture.h28
-rw-r--r--ogrewidget.cpp133
-rw-r--r--ogrewidget.h13
-rw-r--r--qmlogre.pro8
5 files changed, 231 insertions, 44 deletions
diff --git a/declarativeviewtexture.cpp b/declarativeviewtexture.cpp
new file mode 100644
index 0000000..2af4879
--- /dev/null
+++ b/declarativeviewtexture.cpp
@@ -0,0 +1,93 @@
+#include "declarativeviewtexture.h"
+
+#include <QtGui/QPainter>
+#include <QtGui/QImage>
+#include <QtGui/QPaintEvent>
+#include <QtCore/QDebug>
+
+static inline void qgl_byteSwapImage(QImage &img, GLenum pixel_type)
+{
+ const int width = img.width();
+ const int height = img.height();
+
+ if (pixel_type == GL_UNSIGNED_BYTE && QSysInfo::ByteOrder == QSysInfo::LittleEndian)
+ {
+ for (int i = 0; i < height; ++i) {
+ uint *p = (uint *) img.scanLine(i);
+ for (int x = 0; x < width; ++x)
+ p[x] = ((p[x] << 16) & 0xff0000) | ((p[x] >> 16) & 0xff) | (p[x] & 0xff00ff00);
+ }
+ } else {
+ for (int i = 0; i < height; ++i) {
+ uint *p = (uint *) img.scanLine(i);
+ for (int x = 0; x < width; ++x)
+ p[x] = (p[x] << 8) | ((p[x] >> 24) & 0xff);
+ }
+ }
+}
+
+DeclarativeViewTexture::DeclarativeViewTexture(QWidget *parent) :
+ QDeclarativeView(parent),
+ m_bufferPainter(0)
+{
+ setAttribute(Qt::WA_DontShowOnScreen);
+ setOptimizationFlag(QGraphicsView::IndirectPainting);
+
+ glGenTextures(1, &m_textureId);
+}
+
+DeclarativeViewTexture::~DeclarativeViewTexture()
+{
+
+}
+
+void DeclarativeViewTexture::paintEvent(QPaintEvent *event)
+{
+ // Render the view in an offscreen image
+ if (m_bufferPainter)
+ delete m_bufferPainter;
+ m_bufferPainter = new QPainter;
+
+ QRegion exposedRegion = event->region();
+ QImage im(exposedRegion.boundingRect().size(), QImage::Format_ARGB32_Premultiplied);
+ im.fill(Qt::transparent);
+ m_bufferPainter->begin(&im);
+ m_bufferPainter->translate(-exposedRegion.boundingRect().topLeft());
+ m_bufferPainter->setClipRegion(exposedRegion);
+
+ QDeclarativeView::paintEvent(event);
+
+ m_bufferPainter->end();
+
+ // Upload the image in graphics memory
+ glBindTexture(GL_TEXTURE_2D, m_textureId);
+ qgl_byteSwapImage(im, GL_UNSIGNED_BYTE);
+ foreach (const QRect &rect, exposedRegion.rects()) {
+ if (rect.size() == size()) {
+ glTexImage2D(GL_TEXTURE_2D, 0, 4, rect.width(), rect.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, im.bits());
+ glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
+ break;
+ } else {
+ QRect adjustedRect = rect.translated(-exposedRegion.boundingRect().topLeft());
+ QImage subIm = im.copy(adjustedRect);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, rect.left(), rect.top(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE, subIm.bits());
+ }
+ }
+ glBindTexture(GL_TEXTURE_2D, 0);
+}
+
+void DeclarativeViewTexture::drawItems(QPainter *painter, int numItems, QGraphicsItem *items[], const QStyleOptionGraphicsItem options[])
+{
+ QDeclarativeView::drawItems(m_bufferPainter, numItems, items, options);
+}
+
+void DeclarativeViewTexture::drawBackground(QPainter *painter, const QRectF &rect)
+{
+ QDeclarativeView::drawBackground(m_bufferPainter, rect);
+}
+
+void DeclarativeViewTexture::drawForeground(QPainter *painter, const QRectF &rect)
+{
+ QDeclarativeView::drawForeground(m_bufferPainter, rect);
+}
diff --git a/declarativeviewtexture.h b/declarativeviewtexture.h
new file mode 100644
index 0000000..edf93e3
--- /dev/null
+++ b/declarativeviewtexture.h
@@ -0,0 +1,28 @@
+#ifndef DECLARATIVEVIEWTEXTURE_H
+#define DECLARATIVEVIEWTEXTURE_H
+
+#include <QtDeclarative/QDeclarativeView>
+#include <QtOpenGL/qgl.h>
+
+class DeclarativeViewTexture : public QDeclarativeView
+{
+ Q_OBJECT
+public:
+ explicit DeclarativeViewTexture(QWidget *parent = 0);
+ ~DeclarativeViewTexture();
+
+ GLuint textureId() const
+ { return m_textureId; }
+
+protected:
+ void paintEvent(QPaintEvent *event);
+ void drawItems(QPainter *painter, int numItems, QGraphicsItem *items[], const QStyleOptionGraphicsItem options[]);
+ void drawBackground(QPainter *painter, const QRectF &rect);
+ void drawForeground(QPainter *painter, const QRectF &rect);
+
+private:
+ QPainter *m_bufferPainter;
+ GLuint m_textureId;
+};
+
+#endif // DECLARATIVEVIEWTEXTURE_H
diff --git a/ogrewidget.cpp b/ogrewidget.cpp
index 7b5d0e5..991bf2a 100644
--- a/ogrewidget.cpp
+++ b/ogrewidget.cpp
@@ -1,5 +1,7 @@
#include "ogrewidget.h"
+#include "declarativeviewtexture.h"
+
#include <OgreRoot.h>
#include <OgreRenderWindow.h>
#include <OgreColourValue.h>
@@ -7,7 +9,7 @@
#include <OgreSceneNode.h>
#include <OgreEntity.h>
#include <OgreResourceGroupManager.h>
-#include <QtGui/QResizeEvent>
+#include <OgreMaterialManager.h>
#include <QtCore/QDebug>
#if defined(Q_WS_X11)
@@ -15,19 +17,19 @@
#endif
OgreWidget::OgreWidget(QWidget *parent) :
- QWidget(parent),
+ QGLWidget(parent),
m_root(0),
m_camera(0),
m_sceneManager(0),
m_renderWindow(0),
- m_viewport(0)
+ m_viewport(0),
+ m_QmlUI(0)
{
- setAttribute(Qt::WA_PaintOnScreen);
- setAttribute(Qt::WA_NoSystemBackground);
+ setAutoBufferSwap(false);
+ setFormat(QGLFormat(QGL::DoubleBuffer | QGL::SampleBuffers));
+ setAttribute(Qt::WA_OpaquePaintEvent);
resize(1024, 768);
- initOgre();
-
startTimer(16);
}
@@ -48,6 +50,90 @@ OgreWidget::~OgreWidget()
delete m_root;
}
+void OgreWidget::paintGL()
+{
+ // Render Ogre
+ Ogre::WindowEventUtilities::messagePump();
+ m_root->renderOneFrame();
+
+ // Set a clear pass to give the renderer a clear renderstate
+ static Ogre::Pass* clearPass = 0;
+ if (!clearPass)
+ {
+ Ogre::MaterialPtr clearMat = Ogre::MaterialManager::getSingleton().getByName("BaseWhite");
+ clearPass = clearMat->getTechnique(0)->getPass(0);
+ }
+ m_sceneManager->_setPass(clearPass, true, false);
+
+ // Render the QDeclarativeView texture on top
+ glBindTexture(GL_TEXTURE_2D, m_QmlUI->textureId());
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glEnable(GL_TEXTURE_2D);
+ glDisable(GL_LIGHTING);
+ glEnable(GL_BLEND);
+ glEnable(GL_DEPTH_TEST);
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ /*float top = qMax(-1.f, qMin(1.f, (rect().center().y() - m_QmlUI->pos().y()) / float(rect().center().y())));
+ float left = qMax(-1.f, qMin(1.f, (rect().center().x() - m_QmlUI->pos().x()) / float(-rect().center().x())));
+ float bottom = qMax(-1.f, qMin(1.f, (rect().center().y() - m_QmlUI->pos().y() - m_QmlUI->height()) / float(rect().center().y())));
+ float right = qMax(-1.f, qMin(1.f, (rect().center().x() - m_QmlUI->pos().x() - m_QmlUI->width()) / float(-rect().center().x())));
+ float texTop = qMin(1.f, qMax(-m_QmlUI->pos().y() / float(m_QmlUI->height()), 0.f));
+ float texLeft = qMin(1.f, qMax(-m_QmlUI->pos().x() / float(m_QmlUI->width()), 0.f));
+ float texBottom = qMax(0.f, qMin(height() - m_QmlUI->pos().y() / float(m_QmlUI->height()), 1.f));
+ float texRight = qMax(0.f, qMin(width() - m_QmlUI->pos().x() / float(m_QmlUI->width()), 1.f));*/
+
+ float top = (rect().center().y() - m_QmlUI->pos().y()) / float(rect().center().y());
+ float left = (rect().center().x() - m_QmlUI->pos().x()) / float(-rect().center().x());
+ float bottom = (rect().center().y() - m_QmlUI->pos().y() - m_QmlUI->height()) / float(rect().center().y());
+ float right = (rect().center().x() - m_QmlUI->pos().x() - m_QmlUI->width()) / float(-rect().center().x());
+
+ glBegin(GL_QUADS);
+ /*glTexCoord2f(texLeft, texTop); glVertex3f(left, top, -1.0f); // Top Left
+ glTexCoord2f(texLeft, texBottom); glVertex3f(left, bottom, -1.0f); // Bottom Left
+ glTexCoord2f(texRight, texBottom); glVertex3f(right, bottom, -1.0f); // Bottom Right
+ glTexCoord2f(texRight, texTop); glVertex3f(right, top, -1.0f); // Top Right*/
+ glTexCoord2f(0, 0); glVertex3f(left, top, -1.0f); // Top Left
+ glTexCoord2f(0, 1); glVertex3f(left, bottom, -1.0f); // Bottom Left
+ glTexCoord2f(1, 1); glVertex3f(right, bottom, -1.0f); // Bottom Right
+ glTexCoord2f(1, 0); glVertex3f(right, top, -1.0f); // Top Right
+ glEnd();
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+}
+
+void OgreWidget::timerEvent(QTimerEvent *e)
+{
+ Q_UNUSED(e)
+ paintGL();
+ swapBuffers();
+}
+
+void OgreWidget::initializeGL()
+{
+ initOgre();
+
+ m_QmlUI = new DeclarativeViewTexture(this);
+}
+
+void OgreWidget::resizeGL(int w, int h)
+{
+ if (m_renderWindow) {
+ m_renderWindow->resize(w, h);
+ m_renderWindow->windowMovedOrResized();
+ }
+ if (m_camera) {
+ Ogre::Real aspectRatio = Ogre::Real(w) / Ogre::Real(h);
+ m_camera->setAspectRatio(aspectRatio);
+ }
+}
+
+
void OgreWidget::initOgre()
{
m_root = new Ogre::Root;
@@ -60,9 +146,6 @@ void OgreWidget::initOgre()
Ogre::NameValuePairList params;
Ogre::String externalWindowHandleParams;
- //Accept input focus
- //setFocusPolicy(Qt::StrongFocus);
-
#if defined(Q_WS_WIN)
//positive integer for W32 (HWND handle) - According to Ogre Docs
externalWindowHandleParams = Ogre::StringConverter::toString((unsigned int)(winId()));
@@ -86,6 +169,9 @@ void OgreWidget::initOgre()
params["parentWindowHandle"] = externalWindowHandleParams;
#endif
+ params["externalGLControl"] = "true";
+ params["currentGLContext"] = "true";
+
//Finally create our window.
m_renderWindow = m_root->createRenderWindow("OgreWindow", width(), height(), false, &params);
m_renderWindow->setVisible(true);
@@ -119,30 +205,3 @@ void OgreWidget::initOgre()
m_camera->move(Ogre::Vector3(0, 0, 300));
m_camera->lookAt(0, 0, 0);
}
-
-void OgreWidget::render()
-{
- Ogre::WindowEventUtilities::messagePump();
- m_root->renderOneFrame();
-}
-
-void OgreWidget::timerEvent(QTimerEvent *e)
-{
- Q_UNUSED(e)
- render();
-}
-
-void OgreWidget::resizeEvent(QResizeEvent *e)
-{
- const QSize &newSize = e->size();
- if (m_renderWindow) {
- m_renderWindow->resize(newSize.width(), newSize.height());
- m_renderWindow->windowMovedOrResized();
- }
- if (m_camera) {
- Ogre::Real aspectRatio = Ogre::Real(newSize.width()) / Ogre::Real(newSize.height());
- m_camera->setAspectRatio(aspectRatio);
- }
-
- QWidget::resizeEvent(e);
-}
diff --git a/ogrewidget.h b/ogrewidget.h
index 6b940a3..d1a2ec4 100644
--- a/ogrewidget.h
+++ b/ogrewidget.h
@@ -1,7 +1,7 @@
#ifndef OGREWIDGET_H
#define OGREWIDGET_H
-#include <QWidget>
+#include <QGLWidget>
#define STRINGIFY_(x) #x
#define STRINGIFY(x) STRINGIFY_(x)
@@ -15,8 +15,9 @@ class RenderWindow;
class Viewport;
class RenderTarget;
}
+class DeclarativeViewTexture;
-class OgreWidget : public QWidget
+class OgreWidget : public QGLWidget
{
Q_OBJECT
public:
@@ -36,9 +37,11 @@ public:
protected:
void initOgre();
- void render();
void timerEvent(QTimerEvent *);
- void resizeEvent(QResizeEvent *);
+
+ void initializeGL();
+ void resizeGL(int w, int h);
+ void paintGL();
private:
Ogre::Root *m_root;
@@ -46,6 +49,8 @@ private:
Ogre::SceneManager *m_sceneManager;
Ogre::RenderWindow *m_renderWindow;
Ogre::Viewport *m_viewport;
+
+ DeclarativeViewTexture *m_QmlUI;
};
#endif // OGREWIDGET_H
diff --git a/qmlogre.pro b/qmlogre.pro
index ac72c56..e0308a0 100644
--- a/qmlogre.pro
+++ b/qmlogre.pro
@@ -1,5 +1,5 @@
CONFIG += qt
-QT += opengl
+QT += opengl declarative
TEMPLATE = app
TARGET = qmlogre
@@ -40,7 +40,9 @@ MOC_DIR = ./.moc
SOURCES += main.cpp \
- ogrewidget.cpp
+ ogrewidget.cpp \
+ declarativeviewtexture.cpp
HEADERS += \
- ogrewidget.h
+ ogrewidget.h \
+ declarativeviewtexture.h