Newer
Older
Import / research / 3d-z-maps / viewer / viewer.cpp
/*
 * =====================================================================================
 *
 *       Filename:  viewer.cpp
 *
 *    Description:  View multi-z-buffer views
 *
 *        Version:  1.0
 *        Created:  23/02/2011 08:31:52
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  John Ryland (jryland), jryland@xiaofrog.com
 *        Company:  InvertedLogic
 *
 * =====================================================================================
 */

#include <viewer.h>
#include <QMatrix4x4>


Viewer::Viewer(QWidget *parent) : QWidget(parent)
{
    for (int f = 0; f < 6; f++)
    {
        QImage img(QString("side_%1_.png").arg(f));
        unsigned int *data = (unsigned int *)img.bits();
        for (int j = 0; j < 256; j++)
        {
            for (int i = 0; i < 256; i++)
            {
                //if ( data[j*256+i] & 0x00ffffff )
                {
                    switch ( f )
                    {
                    case 0:
                        face[f][(255-j)*256+(255-i)] = data[j*256+i] & 0xff;
                        break;
                    case 1:
                        face[f][(255-j)*256+i] = 255 - data[j*256+i] & 0xff;
                        break;
                    case 2:
                        face[f][(255-j)*256+i] = data[j*256+i] & 0xff;
                        break;
                    case 3:
                        face[f][j*256+i] = data[j*256+i] & 0xff;
                        break;
                    case 4:
                        face[f][(255-j)*256+i] = 255 - data[j*256+i] & 0xff;
                        break;
                    case 5:
                        face[f][(255-j)*256+(255-i)] = 255 - data[j*256+i] & 0xff;
                        break;
                    /*
                    case 1:
                        face[f][j*256+i] = 255 - (data[j*256+i] & 0xff);
                        break;
                    case 4:
                        face[f][j*256+i] = 255 - (data[j*256+i] & 0xff);
                        break;
                    case 5:
                        face[f][j*256+i] = 255 - (data[j*256+i] & 0xff);
                        break;
                        */
                    default:
                        face[f][j*256+i] = data[j*256+i] & 0xff;
                        break;
                    }

                }
                //else
                {
                    //face[f][j*256+i] = 0xff;
                }
            }
        }
        for (int i = 0; i < 256*256; i++)
        {
            face2[0][i] = (face[3][i] << 16) | face[1][i];
            face2[1][i] = (face[0][i] << 24) | (face[4][i] << 16) |
                            (face[2][i] << 8) | face[5][i];
            face2[2][i] = (face[2][i] << 8) | face[5][i];


            // Should generate some mip levels
        }
    }
    angle = 0;

    startTimer(1);
}


Viewer::~Viewer()
{
}


void Viewer::timerEvent(QTimerEvent *event)
{
    repaint();
}


#include <time.h>


float calcFPS()
{
    static unsigned lastTick = clock();
    unsigned currTick = clock();
    unsigned tickDiff=currTick-lastTick;
    lastTick = currTick;
    return (float)(CLOCKS_PER_SEC) / (float)(tickDiff);   // Inverse
}


void Viewer::paintEvent(QPaintEvent *pe)
{
    QPainter p(this);

    angle += 15;

    QImage output( 256, 256, QImage::Format_ARGB32 );
    unsigned int *data = (unsigned int *)output.bits();
/*
    int sideX[6];
    int sideY[6];
    int sideZ[6];
    int sideDX[6];
    int sideDY[6];
    int sideDZ[6];
    int sideIncX[6];
    int sideIncY[6];
    int sideIncZ[6];
    
    sideX[0] = 128;
    sideY[0] = 0;
    sideZ[0] = -128;
    sideDX[0] = -1;
    sideDY[0] = 0;
    sideDZ[0] = 1;
    sideIncX[0] = 1;
    sideIncY[0] = 0;
    sideIncZ[0] = 1;
    // y = y
    
    sideX[1] = 128;
    sideZ[1] = -128;
    sideDX[1] = -1;
    sideDZ[1] = 1;
    sideIncX[1] = 1;
    sideIncZ[1] = 1;
    
    sideX[2] = 128;
    sideZ[2] = -128;
    sideDX[2] = -1;
    sideDZ[2] = 1;
    sideIncX[2] = 1;
    sideIncZ[2] = 1;
    
    sideX[3] = 128;
    sideZ[3] = -128;
    sideDX[3] = -1;
    sideDZ[3] = 1;
    sideIncX[3] = 1;
    sideIncZ[3] = 1;
    
    sideX[4] = 128;
    sideZ[4] = -128;
    sideDX[4] = -1;
    sideDZ[4] = 1;
    sideIncX[4] = 1;
    sideIncZ[4] = 1;
    
    sideX[5] = 128;
    sideZ[5] = -128;
    sideDX[5] = -1;
    sideDZ[5] = 1;
    sideIncX[5] = 1;
    sideIncZ[5] = 1;
*/

    // At the moment this is orthographic, but shouldn't be hard to modify that
    QMatrix4x4 invViewSpace;
    invViewSpace.translate( 128, 128, 128 );
    invViewSpace.rotate( angle, 0, 1, 0 );
    invViewSpace.rotate( angle + 30, 1, 0, 0 );
    invViewSpace.rotate( angle - 30, 0, 0, 1 );
    invViewSpace.translate( -128, -128, -128 );

    for (int y = 0; y < 256; y++)
    {
        QVector3D pntA(0, y, -10);
        pntA = invViewSpace.map(pntA);
        QVector3D pntB(256, y, -10);
        pntB = invViewSpace.map(pntB);
        QVector3D dxpnt1 = (pntB - pntA) / 256.0f;

        QVector3D pntC(0, y, 256);
        pntC = invViewSpace.map(pntC);
        QVector3D pntD(256, y, 256);
        pntD = invViewSpace.map(pntD);
        QVector3D dxpnt2 = (pntD - pntC) / 256.0f;

        int ipntA[3];
        int ipntC[3];
        short int idPntA[3];
        short int idPntC[3];

        const float scaleUp = 256.0f;//65536.0f;
        const int iScaleUp = 256;//65536;
//        const int shiftDown = 8;//16;
#define shiftDown 8

        ipntA[0] = pntA.x() * scaleUp;
        ipntA[1] = pntA.y() * scaleUp;
        ipntA[2] = pntA.z() * scaleUp;
        ipntC[0] = pntC.x() * scaleUp;
        ipntC[1] = pntC.y() * scaleUp;
        ipntC[2] = pntC.z() * scaleUp;
        idPntA[0] = dxpnt1.x() * scaleUp;
        idPntA[1] = dxpnt1.y() * scaleUp;
        idPntA[2] = dxpnt1.z() * scaleUp;
        idPntC[0] = dxpnt2.x() * scaleUp;
        idPntC[1] = dxpnt2.y() * scaleUp;
        idPntC[2] = dxpnt2.z() * scaleUp;

        for (int x = 0; x < 256; x++)
        {
            data[y*256+x] = 0xff000000;
            bool inside = false;
            int ipnt[3];
            int ipnt2[3];
            short int idpnt[3];
            for (int i = 0; i < 3; i++)
            {
                ipnt[i] = ipntA[i];
                ipnt2[i] = ipntC[i];
                ipntA[i] += idPntA[i];
                ipntC[i] += idPntC[i];
                idpnt[i] = (ipnt2[i] - ipnt[i]) / 256;
            }

            int px, py, pz;

            int c = -10;

            for (int j = 0; j < 3; j++)
            {
                int cnt = 1;
                if ( ipnt[j] < 0 )
                {
                    if ( idpnt[j] > 0 ) {
                        cnt = -ipnt[j] / idpnt[j];

                    }
                }
                else if ( ipnt[j] > 256*iScaleUp )
                {
                    if ( idpnt[j] < 0 ) {
                        cnt = (ipnt[j] - 256*iScaleUp) / -idpnt[j];
                    }
                }
                for (int i = 0; i < 3; i++)
                    ipnt[i] += (cnt - 1) * idpnt[i];
                c += cnt - 1;
            }

            int iterations = 512;

            for (int j = 0; j < 3; j++)
            {
                if ( idpnt[j] > 0 )
                {
                    int its = (256*iScaleUp - ipnt[j]) / idpnt[j];
                    if ( its < 512 )
                    {
                        iterations = its;
                    }
                }
                else if ( idpnt[j] < 0 )
                {
                    int its = ipnt[j] / -idpnt[j];
                    if ( its < 512 )
                    {
                        iterations = its;
                    }
                }
           }

           int z = 0;
           
           px = ipnt[0] >> shiftDown;// / 65536;
           py = ipnt[1] >> shiftDown;// / 65536;
           pz = ipnt[2] >> shiftDown;/// 65536;
/*
            face2[0][i] = (face[3][i] << 16) | face[1][i];
            face2[1][i] = (face[0][i] << 16) | face[4][i];
            face2[2][i] = (face[2][i] << 16) | face[5][i];
*/
/*
            face2[1][i] = (face[0][i] << 24) | (face[4][i] << 16) |
                            (face[2][i] << 8) | face[5][i];
           while ( z <= iterations
                   && 
                   (    (ipnt[1] & 0xFF00) <= ( (face2[0][(ipnt[2] & 0xFF00) | (ipnt[0] >> 8)] >>  8) & 0xFF00 )
                     || (ipnt[1] & 0xFF00)  > ( (face2[0][(ipnt[2] & 0xFF00) | (ipnt[0] >> 8)] <<  8) & 0xFF00 )
                     || (ipnt[0] & 0xFF00) <= ( (face2[1][(ipnt[1] & 0xFF00) | (ipnt[2] >> 8)] >> 16) & 0xFF00 ) 
                     || (ipnt[0] & 0xFF00)  > ( (face2[1][(ipnt[1] & 0xFF00) | (ipnt[2] >> 8)] >>  8) & 0xFF00 )
                     || (ipnt[2] & 0xFF00) <= ( (face2[1][(ipnt[1] & 0xFF00) | (ipnt[0] >> 8)] >>  0) & 0xFF00 )
                     || (ipnt[2] & 0xFF00)  > ( (face2[1][(ipnt[1] & 0xFF00) | (ipnt[0] >> 8)] <<  8) & 0xFF00 ) ) )
*/

           while ( z <= iterations
                   && 
                   (    py <= face[3][(pz << 8) | px] 
                     || py  > face[1][(pz << 8) | px]
                     || px <= face[0][(py << 8) | pz] 
                     || px  > face[4][(py << 8) | pz]
                     || pz <= face[2][(py << 8) | px] 
                     || pz  > face[5][(py << 8) | px] ) )
           {
               for (int i = 0; i < 3; i++)
                   ipnt[i] += idpnt[i];
               px = ipnt[0] >> shiftDown;// / 65536;
               py = ipnt[1] >> shiftDown;// / 65536;
               pz = ipnt[2] >> shiftDown;/// 65536;
               z++;
           }

           if ( z <= iterations )
           {
               int col = z + c;//128;
               data[(y<<8)+x] = 0xff000000 | (col << 16) | (col << 8) | col;
           }
        }
    }

/*
    for (int i = 0; i < 256*256; i++)
    {
        unsigned char z = face[0][i];
        data[i] = 0xff000000 | (z << 16) | (z << 8) | z;
    }
*/

    p.drawImage(0, 0, output);
    
    p.setPen( Qt::green );
    p.drawText( 10, 30, QString("fps: %1").arg(calcFPS()) );
}


void Viewer::mouseMoveEvent(QMouseEvent *me)
{
}


void Viewer::mouseClickEvent(QMouseEvent *me)
{
}