MatrixGLWidget.cpp 6.8 KB
Newer Older
1 2
#include "MatrixGLWidget.hpp"

3 4
#include "MatrixWindow.hpp"

5 6 7
#define BACKGROUND_COLOR_R      0.9f
#define BACKGROUND_COLOR_G      0.9f
#define BACKGROUND_COLOR_B      0.9f
8

9
/* Helpers */
10 11 12
static void drawSquare(GLfloat x, GLfloat y, GLfloat dx, GLfloat dy, GLfloat r, GLfloat g, GLfloat b)
{
    glBegin(GL_QUADS);
Mathieu Faverge's avatar
Mathieu Faverge committed
13 14 15 16 17 18 19 20 21 22

    // Setup color
    glColor3f(r, g, b);

    // Setup square corners
    glVertex2f(x,      y);
    glVertex2f(x + dx, y);
    glVertex2f(x + dx, y + dy);
    glVertex2f(x,      y + dy);

23 24 25
    glEnd();
}

26
static void drawTemporarySelection(int x, int y, int dx, int dy)
27
{
Mathieu Faverge's avatar
Mathieu Faverge committed
28 29 30
    glBegin(GL_QUADS);

    // Setup color
31
    glColor4f(1.f, 1.f, 1.f, .5f);
Mathieu Faverge's avatar
Mathieu Faverge committed
32 33 34 35 36 37 38 39

    // Setup vertex
    glVertex2f(x,      y);
    glVertex2f(x + dx, y);
    glVertex2f(x + dx, y + dy);
    glVertex2f(x,      y + dy);

    glEnd();
40 41
}

42
MatrixGLWidget::MatrixGLWidget(QWidget* parent, symbol_matrix_t* matrix, QLabel* label)
43
    :
44
#ifdef USE_QT5
45
    QOpenGLWidget(parent)
46
#else
47
    QGLWidget(parent)
48
#endif
Mathieu Faverge's avatar
Mathieu Faverge committed
49 50
    , m_label(label)
    , m_frameCount(0)
51
{
52 53
    this->setFixedSize(MATRIX_WINDOW_LENGTH, MATRIX_WINDOW_HEIGHT);

54
    m_zooming = new Zooming( matrix );
55

Mathieu Faverge's avatar
Mathieu Faverge committed
56 57
    m_qtToGLWidthCoeff  = 1.f;
    m_qtToGLHeightCoeff = 1.f;
58

Mathieu Faverge's avatar
Mathieu Faverge committed
59 60 61 62
    m_camera.m_cameraX  = 0.f;
    m_camera.m_cameraY  = 0.f;
    m_camera.m_cameraDx = 1.f;
    m_camera.m_cameraDy = 1.f;
63

Mathieu Faverge's avatar
Mathieu Faverge committed
64 65
    m_mouseXClicked = -1;
    m_mouseYClicked = -1;
66 67 68 69
}

MatrixGLWidget::~MatrixGLWidget()
{
70
    delete m_zooming;
71 72 73 74
}

void MatrixGLWidget::initializeGL()
{
75
#ifdef USE_QT5
76
    initializeOpenGLFunctions();
77
#endif
Mathieu Faverge's avatar
Mathieu Faverge committed
78 79
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND);
80

Mathieu Faverge's avatar
Mathieu Faverge committed
81
    glClearColor(BACKGROUND_COLOR_R, BACKGROUND_COLOR_G, BACKGROUND_COLOR_B, 1.f);
82 83 84

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
85
    glOrtho(0, Zooming::DEFAULT_LEVEL_POWER_2, Zooming::DEFAULT_LEVEL_POWER_2, 0, -1, 1);
86 87 88 89

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslatef(0, 2, 0);
90 91 92 93
}

void MatrixGLWidget::resizeGL(int w, int h)
{
94 95
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
96
    glOrtho(0, Zooming::DEFAULT_LEVEL_POWER_2, Zooming::DEFAULT_LEVEL_POWER_2, 0, -1, 1);
97 98 99

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
Mathieu Faverge's avatar
Mathieu Faverge committed
100
    glTranslatef(0, 2, 0);
101

Mathieu Faverge's avatar
Mathieu Faverge committed
102 103
    m_qtToGLWidthCoeff  = (double)Zooming::DEFAULT_LEVEL_POWER_2 / (double)w;
    m_qtToGLHeightCoeff = (double)Zooming::DEFAULT_LEVEL_POWER_2 / (double)h;
104 105 106 107
}

void MatrixGLWidget::paintGL()
{
108 109
    int i, j;

110
#ifdef USE_QT5
111
    initializeOpenGLFunctions();
112
#endif
113

114
    if (m_frameCount == 0) {
Mathieu Faverge's avatar
Mathieu Faverge committed
115
        m_time.start();
116
    }
Mathieu Faverge's avatar
Mathieu Faverge committed
117 118 119 120 121
    else
    {
        sprintf(m_fpsString, "FPS: %f ms", m_time.elapsed() / float(m_frameCount));
        m_label->setText(m_fpsString);
    }
122

Mathieu Faverge's avatar
Mathieu Faverge committed
123
    glClear(GL_COLOR_BUFFER_BIT);
124 125 126 127
    glClearColor( BACKGROUND_COLOR_R,
                  BACKGROUND_COLOR_G,
                  BACKGROUND_COLOR_B,
                  0.f );
128

129
    for (i = 0; i < Zooming::DEFAULT_LEVEL_POWER_2; ++i)
130
    {
131
        for (j = 0; j < Zooming::DEFAULT_LEVEL_POWER_2; ++j)
132
        {
Mathieu Faverge's avatar
Mathieu Faverge committed
133
            GLfloat grey = m_zooming->getColor(i, j);
134

135 136 137 138 139 140 141
            if (grey != 1.f) {
                if (grey != 0.f) {
                    drawSquare(i, j, 1, 1, 0., 0., grey);
                }
                else {
                    drawSquare(i, j, 1, 1, grey, grey, grey);
                }
142
            }
143 144 145
        }
    }

146
    if (m_drawTempSelection == 1) {
Mathieu Faverge's avatar
Mathieu Faverge committed
147
        drawTemporarySelection(m_tempSelectionX, m_tempSelectionY, m_tempSelectionDx, m_tempSelectionDy);
148
    }
149

Mathieu Faverge's avatar
Mathieu Faverge committed
150
    m_frameCount++;
151 152
}

153 154 155 156
void MatrixGLWidget::keyPressEvent(QKeyEvent *keyEvent)
{
    switch (keyEvent->key())
    {
Mathieu Faverge's avatar
Mathieu Faverge committed
157 158 159
    default:
        break;
    }
160
}
161 162 163

void MatrixGLWidget::mousePressEvent(QMouseEvent* mouseEvent)
{
Mathieu Faverge's avatar
Mathieu Faverge committed
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
    if (mouseEvent->button() == Qt::RightButton)
    {
        if (m_savedPositions.size() > 0)
        {
            CameraPosition newCamera = m_savedPositions.top();
            m_savedPositions.pop();

            m_camera = newCamera;

            refreshCamera();
        }
    }
    else if (mouseEvent->button() == Qt::LeftButton)
    {
        m_mouseXClicked = mouseEvent->x() * m_qtToGLWidthCoeff;
        m_mouseYClicked = mouseEvent->y() * m_qtToGLHeightCoeff;
    }
181 182 183 184
}

void MatrixGLWidget::mouseMoveEvent(QMouseEvent* mouseEvent)
{
185 186
    if ( (m_mouseXClicked != -1) &&
         (m_mouseYClicked != -1) )
Mathieu Faverge's avatar
Mathieu Faverge committed
187 188 189 190 191 192
    {
        int glPosX = mouseEvent->x() * m_qtToGLWidthCoeff;
        int glPosY = mouseEvent->y() * m_qtToGLHeightCoeff;

        m_drawTempSelection = 1;

193 194 195 196
        m_tempSelectionX  = m_mouseXClicked;
        m_tempSelectionY  = m_mouseYClicked;
        m_tempSelectionDx = glPosX - m_mouseXClicked;
        m_tempSelectionDy = glPosY - m_mouseYClicked;
197 198

        update();
Mathieu Faverge's avatar
Mathieu Faverge committed
199
    }
200 201 202 203
}

void MatrixGLWidget::mouseReleaseEvent(QMouseEvent* mouseEvent)
{
204 205
    if ( (m_mouseXClicked != -1) &&
         (m_mouseYClicked != -1) )
Mathieu Faverge's avatar
Mathieu Faverge committed
206
    {
207
        int xmin, xmax, ymin, ymax;
Mathieu Faverge's avatar
Mathieu Faverge committed
208 209 210
        int glPosX = mouseEvent->x() * m_qtToGLWidthCoeff;
        int glPosY = mouseEvent->y() * m_qtToGLHeightCoeff;

211 212 213 214 215 216 217 218 219 220
        if ( glPosX > m_mouseXClicked )
        {
            xmin = m_mouseXClicked;
            xmax = glPosX;
        }
        else
        {
            xmin = glPosX;
            xmax = m_mouseXClicked;
        }
Mathieu Faverge's avatar
Mathieu Faverge committed
221

222
        if ( glPosY > m_mouseYClicked )
Mathieu Faverge's avatar
Mathieu Faverge committed
223
        {
224 225
            ymin = m_mouseYClicked;
            ymax = glPosY;
Mathieu Faverge's avatar
Mathieu Faverge committed
226
        }
227
        else
Mathieu Faverge's avatar
Mathieu Faverge committed
228
        {
229 230
            ymin = glPosY;
            ymax = m_mouseYClicked;
Mathieu Faverge's avatar
Mathieu Faverge committed
231 232
        }

233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
        // Compute positions/dimensions in ratio of the current window
        double X  = (double)(xmin) / (double)Zooming::DEFAULT_LEVEL_POWER_2;
        double Y  = (double)(ymin) / (double)Zooming::DEFAULT_LEVEL_POWER_2;
        double dX = (double)(xmax - xmin) / (double)Zooming::DEFAULT_LEVEL_POWER_2;
        double dY = (double)(ymax - ymin) / (double)Zooming::DEFAULT_LEVEL_POWER_2;

        // Check for out of bounds
        X  = ( X  < 0. ) ? 0. : X;
        Y  = ( Y  < 0. ) ? 0. : Y;
        dX = ( (X+dX) > 1. ) ? 1. - X : dX;
        dY = ( (Y+dY) > 1. ) ? 1. - Y : dY;

        // Translate to the full display
        X  = X  * m_camera.m_cameraDx + m_camera.m_cameraX;
        Y  = Y  * m_camera.m_cameraDy + m_camera.m_cameraY;
        dX = dX * m_camera.m_cameraDx;
        dY = dY * m_camera.m_cameraDy;

251 252
        m_drawTempSelection = 0;

253 254 255
        // Return if in the upper triangular part
        if ( (Y + dY) < X )
        {
256
            update();
257 258
            return;
        }
Mathieu Faverge's avatar
Mathieu Faverge committed
259

260 261
        // Position is valid, we save it
        m_savedPositions.push(m_camera);
Mathieu Faverge's avatar
Mathieu Faverge committed
262

263 264 265 266
        m_camera.m_cameraX  = X;
        m_camera.m_cameraY  = Y;
        m_camera.m_cameraDx = dX;
        m_camera.m_cameraDy = dY;
Mathieu Faverge's avatar
Mathieu Faverge committed
267 268 269 270 271 272

        refreshCamera();

        m_mouseXClicked = -1;
        m_mouseYClicked = -1;
    }
273 274 275 276
}

void MatrixGLWidget::refreshCamera()
{
277 278 279
    m_zooming->move( m_camera.m_cameraX, m_camera.m_cameraX + m_camera.m_cameraDx,
                     m_camera.m_cameraY, m_camera.m_cameraY + m_camera.m_cameraDy );
    update();
Mathieu Faverge's avatar
Mathieu Faverge committed
280
}