ganeswidgets/src/hgvgquadrenderer.cpp
changeset 2 49c70dcc3f17
parent 1 e48454f237ca
child 5 4fa04caf0f43
--- a/ganeswidgets/src/hgvgquadrenderer.cpp	Mon May 03 13:32:54 2010 +0300
+++ b/ganeswidgets/src/hgvgquadrenderer.cpp	Fri May 14 16:57:01 2010 +0300
@@ -16,6 +16,7 @@
 */
 
 #include "hgvgquadrenderer.h"
+#include "hgtransformedquad.h"
 #include "hgquad.h"
 #include "hgvgimage.h"
 #include "trace.h"
@@ -29,231 +30,46 @@
 #include <qpainter>
 
 
-class HgVgQuad
-{
-public:
-    HgVgQuad(HgVgQuadRenderer* renderer);
-    ~HgVgQuad();
-    
-    int index() const;
-    bool isPointInside(const QPointF& point) const;
-    void transformQuad(int index, const QMatrix4x4& matrix, HgQuad* quad, 
-        const QRectF& rect, qreal mirroringPlaneY, const QVector2D& translate);
-    void draw();
-
-    void getTransformedPoints(QPolygonF& polygon) const;
-        
-    void computeMirrorMatrix(const QMatrix4x4& tm, const QMatrix4x4& projView, 
-        const QRectF& rect, qreal mirroringPlaneY, 
-        const QVector2D& translate);
-    
-    bool perspectiveTransformPoints(QVector2D* points, const QMatrix4x4& matrix, 
-        const QRectF& rect);
-    
-    void computeWarpMatrix(VGfloat* matrix, int pxWidth, int pxHeight, const QVector2D* points, 
-        const QVector2D& translate);
-    
-    void drawImage(HgVgImage* image, qreal alpha);
-    
-    int mIndex;
-    HgQuad* mQuad;
-    QVector2D mTransformedPoints[4];
-    VGfloat mMatrix[9];
-    VGfloat mMirrorMatrix[9];
-    HgVgQuadRenderer* mRenderer;
-    bool mDegenerate;
-private:
-    HgVgQuad(const HgVgQuad&);
-    HgVgQuad& operator=(const HgVgQuad&);
-};
-
-static bool quadSorter(HgVgQuad* a, HgVgQuad* b)
-{
-    return a->mQuad->position().z() < b->mQuad->position().z();
-}
-
-HgVgQuad::HgVgQuad(HgVgQuadRenderer* renderer) : mRenderer(renderer)
-{
-    
-}
-
-HgVgQuad::~HgVgQuad()
+static void matrixFromTransform(VGfloat* matrix, const QTransform& tm)
 {
-    
-}
-
-int HgVgQuad::index() const
-    {
-    return mIndex;
-    }
-
-bool HgVgQuad::isPointInside(const QPointF& point) const
-{    
-    QPolygonF poly;
-    getTransformedPoints(poly);
-    QRectF rect = poly.boundingRect();
-    if (rect.contains(point))
-    {
-        return true;
-    }
-    return false;
-}
-
-
-void HgVgQuad::computeMirrorMatrix(const QMatrix4x4& trans, const QMatrix4x4& projView, 
-    const QRectF& rect, qreal mirroringPlaneY, const QVector2D& translate)
-{
-    HgQuad* quad = mQuad;
+    matrix[0] = tm.m11();
+    matrix[1] = tm.m12();
+    matrix[2] = tm.m13();
 
-    QMatrix4x4 mirror = trans;
+    matrix[3] = tm.m21();
+    matrix[4] = tm.m22();
+    matrix[5] = tm.m23();
 
-    qreal distToPlane = qAbs(quad->position().y() - mirroringPlaneY);
-    
-    mirror.translate(quad->position().x(), mirroringPlaneY - distToPlane/2, quad->position().z());
-    mirror.scale(quad->scale().x(), -quad->scale().y()/2);
-    mirror.rotate(quad->rotation());
-        
-    QMatrix4x4 modelViewProjMatrix = projView * mirror;
-    
-    QVector2D temp[4];
-    
-    perspectiveTransformPoints(temp, modelViewProjMatrix, rect);
-    
-    HgVgImage* image = (HgVgImage*)mQuad->image();
-    
-    if (image == NULL)
-    {
-        image = mRenderer->defaultImage();
-        if (!image) {
-            return;
-        }
-    }
-    
-    int pxWidth = image->mirrorImageWidth();
-    int pxHeight = image->mirrorImageHeight();
-
-    computeWarpMatrix(mMirrorMatrix, pxWidth, pxHeight, temp, translate);
+    matrix[6] = tm.m31();
+    matrix[7] = tm.m32();
+    matrix[8] = tm.m33();
 }
 
-void HgVgQuad::transformQuad(int index, const QMatrix4x4& projView, HgQuad* quad, 
-    const QRectF& rect, qreal mirroringPlaneY, const QVector2D& translate)
+class HgVgQuad : public HgTransformedQuad
 {
-    mIndex = index;
-    mQuad = quad;
-        
-    QMatrix4x4 tm;
-    tm.setToIdentity();
-    tm.rotate(quad->outerRotation());
-
-    if (mQuad->mirrorImageEnabled())
+public:
+    
+    HgVgQuad(HgVgQuadRenderer* renderer) : HgTransformedQuad(-1), mRenderer(renderer)
     {
-        computeMirrorMatrix(tm, projView, rect, mirroringPlaneY, translate);
-    }
-    
-    tm.translate(quad->position());    
-    tm.rotate(quad->rotation());    
-    tm.scale(quad->scale().x(), quad->scale().y());
-
-    tm = projView * tm;         
-    //QMatrix4x4 tmt = tm.transposed();
-    
-    mDegenerate = false;
-    if (!perspectiveTransformPoints(mTransformedPoints, tm, rect))
-    {
-        mDegenerate = true;
+        
     }
 
-    HgVgImage* image = (HgVgImage*)mQuad->image();
-    
-    if (image == NULL)
+    ~HgVgQuad()
     {
-        image = mRenderer->defaultImage();
-        if (!image)
-            return;
-    }
-    
-    int pxWidth = image->width();
-    int pxHeight = image->height();
-    
-    
-    computeWarpMatrix(mMatrix, pxWidth, pxHeight, mTransformedPoints, translate);
-    
-    for (int i = 0; i < 4; i++)
-        mTransformedPoints[i] += translate;
-    
-}
-
-bool HgVgQuad::perspectiveTransformPoints(QVector2D* outPoints, const QMatrix4x4& matrix, 
-    const QRectF& rect)
-{
-    const QVector4D points[] = 
-    {
-        QVector4D(-0.5f, -0.5f, 0.0f, 1.0f),
-        QVector4D( 0.5f, -0.5f, 0.0f, 1.0f),
-        QVector4D( 0.5f,  0.5f, 0.0f, 1.0f),
-        QVector4D(-0.5f,  0.5f, 0.0f, 1.0f)
-    };
-
-    qreal hw = rect.width() * 0.5f;
-    qreal hh = rect.height() * 0.5f;
-
-    for (int i = 0; i < 4; i++)
-    {
-        QVector4D temp = matrix * points[i];
-                            
-        outPoints[i] = QVector2D(
-            hw + temp.x() / temp.w() * hw, 
-            hh + temp.y() / temp.w() * hh);
-
+        
     }
-    
-    return true;
-}
 
-void HgVgQuad::computeWarpMatrix(VGfloat* matrix, int pxWidth, int pxHeight, const QVector2D* points, 
-    const QVector2D& translate)
-{        
-
-    vguComputeWarpQuadToQuad(
-        points[0].x() + translate.x(), points[0].y() + translate.y(), 
-        points[1].x() + translate.x(), points[1].y() + translate.y(),
-        points[2].x() + translate.x(), points[2].y() + translate.y(),
-        points[3].x() + translate.x(), points[3].y() + translate.y(),
-        0, pxHeight,
-        pxWidth, pxHeight,
-        pxWidth, 0,
-        0, 0,
-        matrix);
-/*    
-    INFO("P0 x:" << points[0].x() << " y:" << points[0].y());
-    INFO("P1 x:" << points[1].x() << " y:" << points[1].y());
-    INFO("P2 x:" << points[2].x() << " y:" << points[2].y());
-    INFO("P3 x:" << points[3].x() << " y:" << points[3].y());*/
-}
-
-
-void HgVgQuad::draw()
-{
-    if (!mQuad->visible())
-        return;
-    
-    if (mDegenerate)
-        return;
-    
-    HgVgImage* image = (HgVgImage*)mQuad->image();
-    
-    
-    if (image == NULL  || image->alpha() == 0)
+    void draw(QPainter* painter, const QRectF& rect)    
     {
-        if (mRenderer->defaultImage()) {
-            drawImage(mRenderer->defaultImage(), 1.0f);
-        }
-    }
-    else
-    {
-        image->upload(mQuad->mirrorImageEnabled());
+        Q_UNUSED(painter)
+        Q_UNUSED(rect)
         
-        if (image->image() == VG_INVALID_HANDLE)
+        if (!mQuad->visible())
+            return;
+                
+        HgVgImage* image = (HgVgImage*)mQuad->image();
+                
+        if (image == NULL  || image->alpha() == 0)
         {
             if (mRenderer->defaultImage()) {
                 drawImage(mRenderer->defaultImage(), 1.0f);
@@ -261,75 +77,94 @@
         }
         else
         {
-
-            if ( mQuad->alpha() < 1.0f )
+            image->upload(mQuad->mirrorImageEnabled());
+            
+            if (image->image() == VG_INVALID_HANDLE)
             {
                 if (mRenderer->defaultImage()) {
-                    drawImage(mRenderer->defaultImage(), 1.0f - mQuad->alpha());            
+                    drawImage(mRenderer->defaultImage(), 1.0f);
                 }
             }
+            else
+            {
+
+                if ( mQuad->alpha() < 1.0f )
+                {
+                    if (mRenderer->defaultImage()) {
+                        drawImage(mRenderer->defaultImage(), 1.0f - mQuad->alpha());            
+                    }
+                }
+                
+                drawImage(image, mQuad->alpha());
+            }
+        }
+        
+        
+    }
+
+    void drawImage(HgVgImage* image, qreal alpha)
+    {
+        Q_UNUSED(alpha)
             
-            drawImage(image, mQuad->alpha());
+        VGImage vgImage = image->image();
+        
+        vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
+
+        VGfloat m[9];
+        vgGetMatrix(m);
+        
+        computeWarpMatrix(mMatrix, image->width(), image->height(), mTransformedPoints, QVector2D());
+
+        vgMultMatrix(mMatrix);
+        vgDrawImage(vgImage);    
+        
+        vgLoadMatrix(m);
+
+        if (mQuad->mirrorImageEnabled())
+        {
+            VGImage mirrorImage = image->mirrorImage();
+            if (mirrorImage == VG_INVALID_HANDLE)
+                return;
+            
+            computeWarpMatrix(mMirrorMatrix, image->mirrorImageWidth(), image->mirrorImageHeight(), mMirroredPoints, QVector2D());
+            vgMultMatrix(mMirrorMatrix);
+                
+            vgDrawImage(mirrorImage);    
+            vgLoadMatrix(m);    
         }
+        
     }
     
-    
-}
+private:
 
-void HgVgQuad::drawImage(HgVgImage* image, qreal alpha)
-{
-    Q_UNUSED(alpha)
+    void computeWarpMatrix(VGfloat* matrix, int pxWidth, int pxHeight, const QVector2D* points, 
+        const QVector2D& translate)
+    {        
 
-    //VGfloat values[] = { 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0 };
-    //values[3] = alpha;
-    
-    //vgSetfv(VG_COLOR_TRANSFORM_VALUES, 8, values);
-        
-    VGImage vgImage = image->image();
-    
-    vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
-
-    VGfloat m[9];
-    vgGetMatrix(m);
-    
-    vgMultMatrix(mMatrix);
-    vgDrawImage(vgImage);    
+        vguComputeWarpQuadToQuad(
+            points[0].x(), points[0].y(), 
+            points[1].x(), points[1].y(),
+            points[2].x(), points[2].y(),
+            points[3].x(), points[3].y(),
+            0, pxHeight,
+            pxWidth, pxHeight,
+            pxWidth, 0,
+            0, 0,
+            matrix);
     
-    vgLoadMatrix(m);
+    }
 
-    if (mQuad->mirrorImageEnabled())
-    {
-        VGImage mirrorImage = image->mirrorImage();
-        if (mirrorImage == VG_INVALID_HANDLE)
-            return;
-        
-        vgMultMatrix(mMirrorMatrix);
-            
-        vgDrawImage(mirrorImage);    
-        vgLoadMatrix(m);    
-    }
-    
-}
-
-
-void HgVgQuad::getTransformedPoints(QPolygonF& poly) const
-{
-    poly.append(mTransformedPoints[0].toPointF());
-    poly.append(mTransformedPoints[1].toPointF());
-    poly.append(mTransformedPoints[2].toPointF());
-    poly.append(mTransformedPoints[3].toPointF());    
-}
+    HgVgQuadRenderer* mRenderer;
+    VGfloat mMatrix[9];
+    VGfloat mMirrorMatrix[9];
+};
 
 
 HgVgQuadRenderer::HgVgQuadRenderer(int maxQuads) : 
-    HgQuadRenderer(maxQuads),
+    HgTransformedQuadRenderer(maxQuads),
     mDefaultVgImage(NULL)
 {
-    for (int i = 0; i < maxQuads; i++)
-    {
-        mTransformedQuads.append(new HgVgQuad(this));
-    }
-    mImageFader = new HgImageFader();
+    init(maxQuads);
 }
 
 HgVgQuadRenderer::~HgVgQuadRenderer()
@@ -337,133 +172,52 @@
     delete mDefaultVgImage;
 }
 
-HgQuad* HgVgQuadRenderer::getQuadAt(const QPointF& point) const
-{
-    FUNC_LOG
-        
-    // TODO: need to use sorted quads here, in reversed order.
-    QList<HgVgQuad*>::const_iterator i = mSortedQuads.begin();
-    while(i != mSortedQuads.end())
-    {
-        HgVgQuad* q = (*i);
-        if (q->isPointInside(point))
-        {
-            return q->mQuad;
-        }
-        i++;
-    }
-    
-    return NULL;
-}
-
-
-void HgVgQuadRenderer::transformQuads(const QMatrix4x4& view, const QMatrix4x4& proj, 
-    const QRectF& rect)
+void HgVgQuadRenderer::drawQuads(QPainter* painter, const QRectF& rect, 
+    const QMatrix4x4& viewMatrix, const QMatrix4x4& projectionMatrix,
+    Qt::Orientation orientation, 
+    const QTransform& sceneTransform)
 {
-    QMatrix4x4 pv = proj * view;
-    
-    mSortedQuads.clear();
-    
-    for (int i = 0; i < mQuads.size(); i++)
-    {
-        HgQuad* q = mQuads[i];
-            
-        HgVgQuad* tq = mTransformedQuads[i];
-        
-        if (q->visible())
-        {
-            tq->transformQuad(i, pv, q, rect, mMirroringPlaneY, mTranslation);   
-            mSortedQuads.append(tq);
-        }
-    }
-        
-    qSort(mSortedQuads.begin(), mSortedQuads.end(), quadSorter);
-}
-
-void HgVgQuadRenderer::drawQuads(const QRectF& rect, QPainter* painter)
-{
-    Q_UNUSED(rect)
-            
-    
+    // start direct vg
     painter->beginNativePainting();
 
-    // need to save old scissoring rects, otherwise hb
-    // screws up with rendering
-/*    VGint oldScissoring = vgGeti(VG_SCISSORING);
-    VGint numRects = 32;//vgGeti(VG_MAX_SCISSOR_RECTS);
-    VGint oldRects[32*4];
-    vgGetiv(VG_SCISSOR_RECTS, numRects, oldRects);
-
-    // setup our new scissoring rects
-    VGint sRect[4];
-    sRect[0] = rect.left();
-    sRect[1] = rect.top();
-    sRect[2] = rect.width();
-    sRect[3] = rect.height();
-    vgSeti(VG_SCISSORING, VG_TRUE);
-    vgSetiv(VG_SCISSOR_RECTS, 4, sRect);
- */
-    // setup root transform
-    vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
-    vgLoadIdentity();    
-    vgTranslate(rect.left(), rect.top());
-    
+    // setup default vg states
     vgSeti(VG_COLOR_TRANSFORM, VG_FALSE);
     vgSeti(VG_BLEND_MODE, VG_BLEND_SRC_OVER);
     vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_NORMAL);
-    
-    // draw quads
-    for (int i = 0; i < mSortedQuads.size(); i++)
-    {
-        mSortedQuads[i]->draw();
-    }
-    
-    // set back old scissor rects
-  //  vgSeti(VG_SCISSORING, oldScissoring);
-  //  vgSetiv(VG_SCISSOR_RECTS, numRects, oldRects);
+
+    // setup root transform
+    vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
+    VGfloat toVgMatrix[9];
+    matrixFromTransform(toVgMatrix, qtToVgTransform(painter, sceneTransform, rect, orientation));
+    vgLoadMatrix(toVgMatrix);   
 
+    // transform quads to screen
+    transformQuads(viewMatrix, projectionMatrix, QPointF(rect.width()/2, rect.height()/2), 
+        QSizeF(rect.width(), rect.height()));
+
+    drawTransformedQuads(painter, rect);
+
+    // end directt vg
     painter->endNativePainting();
     
 }
 
-bool HgVgQuadRenderer::getQuadTranformedPoints(QPolygonF& points, int index) const
-{
-    for (int i = 0; i < mSortedQuads.count(); i++)
-    {
-        HgVgQuad* quad = mSortedQuads[i];
-        if (quad->mQuad)
-        {
-            bool bOk;
-            if (quad->mQuad->userData().toInt(&bOk) == index)
-            {
-                quad->getTransformedPoints(points);
-                return true;
-            }
-        }
-    }
-    
-    return false;
-}
-
 HgImage* HgVgQuadRenderer::createNativeImage()
 {    
     return new HgVgImage(this);   
 }
 
+HgTransformedQuad* HgVgQuadRenderer::createNativeQuad()
+{
+    return new HgVgQuad(this);
+}
+
 HgVgImage* HgVgQuadRenderer::defaultImage()
 {
     if (mDefaultVgImage && mDefaultVgImage->image() == VG_INVALID_HANDLE) {
         mDefaultVgImage->upload(true);
     }
-/*    if (mDefaultVgImage == NULL)
-    {
-        QImage defaultImage(64,64,QImage::Format_RGB16);
-        defaultImage.fill(qRgb(255,0,0));
-        mDefaultVgImage = static_cast<HgVgImage*>(createNativeImage());
-        mDefaultVgImage->setImage(defaultImage);
-        mDefaultVgImage->upload(true);        
-    }
-    */
+
     return mDefaultVgImage;
 }
 
@@ -477,27 +231,23 @@
     mDefaultVgImage->upload(true);    
 }
 
-HgImageFader* HgVgQuadRenderer::imageFader()
-{
-    return mImageFader;
-}
-
-QList<HgQuad*> HgVgQuadRenderer::getVisibleQuads(const QRectF& rect) const
+QTransform HgVgQuadRenderer::qtToVgTransform(QPainter* painter, const QTransform& sceneTransform, 
+    const QRectF& rect, Qt::Orientation orientation) const
 {
-    FUNC_LOG;
-    
-    // this implementation isn't 100% precise
-    QList<HgQuad*> result;
-    for (int i = 0; i < mSortedQuads.count(); i++) {
-       QPolygonF poly;
-       mSortedQuads[i]->getTransformedPoints(poly);
-       QRectF bounds = poly.boundingRect();       
-       if (bounds.intersects(rect) || rect.contains(bounds)) {
-           result.append(mSortedQuads[i]->mQuad);
-       }           
+    QTransform t;
+    if (orientation == Qt::Vertical)
+    {
+        t.translate(sceneTransform.dx(), painter->viewport().height() - sceneTransform.dy());
+        t.scale(1, -1);    
     }
-    
-    return result;    
+    else
+    {
+        // TODO: this will need reviewing later :)
+        t.translate(rect.bottom(), 0);
+        t.scale(-1, 1);
+        t.translate(0, rect.right());
+        t.rotate(-90, Qt::ZAxis);        
+    }
+
+    return t;
 }
-
-