0

For a class we got code that visualizes smoke using GLUT and OpenGL. I am trying to convert this to QT following https://stackoverflow.com/a/17794523/651779 and the examples from here: http://www.bogotobogo.com/Qt/Qt5_OpenGL_QGLWidget.php. It now draws the widget but the OpenGL part does not work as intended (see image below, should be a black screen which changes when mouse moves over it). Compiling the code does not give me any warnings or errors.

With breakpoints I can see that it never goes to do_one_simulation_step(), so is it possible that the event queue is never empty and therefore the slot from QObject::connect(timer,SIGNAL(timeout()),this,SLOT(do_one_simulation_step())); does not get called? My code I put below. enter image description here

myglwidget.h

#ifndef MYGLWIDGET_H
#define MYGLWIDGET_H

#include <QGLWidget>
#include <QTimer>
#include <rfftw.h>            

class MyGLWidget : public QGLWidget
{
    Q_OBJECT
public:
    explicit MyGLWidget(QWidget *parent = 0);
    ~MyGLWidget();
signals:

public slots:
    void do_one_simulation_step();

protected:
    void initializeGL();
    void paintGL();
    void resizeGL(int width, int height);
    QSize minimumSizeHint() const;
    QSize sizeHint() const;
    void mousePressEvent(QMouseEvent *event);
    void mouseMoveEvent(QMouseEvent *event);

public slots:

signals:

private:
    void visualize();
    QBasicTimer timer;
    int   winWidth, winHeight;      
    int   color_dir;           
    float vec_scale;            
    int   draw_smoke;          
    int   draw_vecs;            
    static const int COLOR_BLACKWHITE=0;   
    mapping: black-and-white, rainbow, banded
    static const int COLOR_RAINBOW=1;
    static const int COLOR_BANDS=2;
    int   scalar_col;           
    QPoint lastPos;
};

#endif // MYGLWIDGET_H

myglwidget.cpp

// myglwidget.cpp

#include <QtWidgets>
#include <QtOpenGL>
#include <GLUT/glut.h>         
#include "myglwidget.h"
#include "visualization.cpp"
#include <simulation.cpp>              

MyGLWidget::MyGLWidget(QWidget *parent)
    : QGLWidget(QGLFormat(QGL::SampleBuffers), parent)
{
    int   winWidth, winHeight;      
    int   color_dir = 0;            
    float vec_scale = 1000;         
    int   draw_smoke = 0;         
    int   draw_vecs = 1;           
    int   scalar_col = 0;          
    simulation.init_simulation(simulation.DIM);
    QTimer *timer = new QTimer;
    QObject::connect(timer,SIGNAL(timeout()),this,SLOT(do_one_simulation_step()));
}

MyGLWidget::~MyGLWidget()
{
}

QSize MyGLWidget::minimumSizeHint() const
{
    return QSize(50, 50);
}

QSize MyGLWidget::sizeHint() const
{
    return QSize(400, 400);
}

void MyGLWidget::initializeGL()
{
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
f->glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
}

void MyGLWidget::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    visualize();
    glFlush();
    swapBuffers();
}

//display: Handle window redrawing events. Simply delegates to draw().
void MyGLWidget::resizeGL(int width, int height)
{
    glViewport(0.0f, 0.0f, (GLfloat)width, (GLfloat)height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0.0, (GLdouble)width, 0.0, (GLdouble)height);
    winWidth = width; winHeight = height;
}

void MyGLWidget::mousePressEvent(QMouseEvent *event)
{
    lastPos = event->pos();
}

void MyGLWidget::mouseMoveEvent(QMouseEvent *event)
{
    int mx = event->x() - lastPos.x();
    int my = event->y() - lastPos.y();

    int xi,yi,X,Y; double  dx, dy, len;
    static int lmx=0,lmy=0; 

    xi = (int)simulation.clamp((double)(simulation.DIM + 1) * ((double)mx / (double)winWidth));
    yi = (int)simulation.clamp((double)(simulation.DIM + 1) * ((double)(winHeight - my) / (double)winHeight));

    X = xi; Y = yi;

    if (X > (simulation.DIM - 1))  X = simulation.DIM - 1; if (Y > (simulation.DIM - 1))  Y = simulation.DIM - 1;
    if (X < 0) X = 0; if (Y < 0) Y = 0;

    // Add force at the cursor location
    my = winHeight - my;
    dx = mx - lmx; dy = my - lmy;
    len = sqrt(dx * dx + dy * dy);
    if (len != 0.0) {  dx *= 0.1 / len; dy *= 0.1 / len; }
    simulation.get_fx()[Y * simulation.DIM + X] += dx;
    simulation.get_fy()[Y * simulation.DIM + X] += dy;
    simulation.get_rho()[Y * simulation.DIM + X] = 10.0f;
    lmx = mx; lmy = my;
    lastPos = event->pos();
}

void MyGLWidget::visualize()
{

    int        i, j, idx, idx0, idx1, idx2, idx3; double px0,py0,px1,py1,px2,py2,px3,py3;
    fftw_real  wn = (fftw_real)winWidth / (fftw_real)(simulation.DIM + 1);   // Grid cell width
    fftw_real  hn = (fftw_real)winHeight / (fftw_real)(simulation.DIM + 1);  // Grid cell heigh

    if (draw_smoke)
    {
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    glBegin(GL_TRIANGLES);
    for (j = 0; j < simulation.DIM - 1; j++)            //draw smoke
    {
        for (i = 0; i < simulation.DIM - 1; i++)
        {
            px0  = wn + (fftw_real)i * wn;
            py0  = hn + (fftw_real)j * hn;
            idx0 = (j * simulation.DIM) + i;

            px1  = wn + (fftw_real)i * wn;
            py1  = hn + (fftw_real)(j + 1) * hn;
            idx1 = ((j + 1) * simulation.DIM) + i;

            px2  = wn + (fftw_real)(i + 1) * wn;
            py2  = hn + (fftw_real)(j + 1) * hn;
            idx2 = ((j + 1) * simulation.DIM) + (i + 1);

            px3  = wn + (fftw_real)(i + 1) * wn;
            py3  = hn + (fftw_real)j * hn;
            idx3 = (j * simulation.DIM) + (i + 1);

            set_colormap(simulation.get_rho()[idx0]);   glVertex2f(px0, py0);
            set_colormap(simulation.get_rho()[idx1]);   glVertex2f(px1, py1);
            set_colormap(simulation.get_rho()[idx2]);   glVertex2f(px2, py2);

            set_colormap(simulation.get_rho()[idx0]);   glVertex2f(px0, py0);
            set_colormap(simulation.get_rho()[idx2]);   glVertex2f(px2, py2);
            set_colormap(simulation.get_rho()[idx3]);   glVertex2f(px3, py3);
        }
    }
    glEnd();
    }

    if (draw_vecs)
    {
      glBegin(GL_LINES);
      for (i = 0; i < simulation.DIM; i++)
        for (j = 0; j < simulation.DIM; j++)
        {
          idx = (j * simulation.DIM) + i;
          direction_to_color(simulation.get_vx()[idx],simulation.get_vy()[idx],color_dir);
          glVertex2f(wn + (fftw_real)i * wn, hn + (fftw_real)j * hn);
          glVertex2f((wn + (fftw_real)i * wn) + vec_scale * simulation.get_vx()[idx], (hn + (fftw_real)j * hn) + vec_scale * simulation.get_vy()[idx]);
        }
      glEnd();
    }

}

void MyGLWidget::do_one_simulation_step()
{
    if (!simulation.get_frozen())
    {
        simulation.set_forces();
        simulation.solve(simulation.DIM, simulation.get_vx(), simulation.get_vy(), simulation.get_vx0(),
                         simulation.get_vy0(), simulation.get_visc(), simulation.get_dt());
        simulation.diffuse_matter(simulation.DIM, simulation.get_vx(), simulation.get_vy(),
                                 simulation.get_rho(), simulation.get_rho0(), simulation.get_dt());
        updateGL();
    }
}

window.h

// window.h

#ifndef WINDOW_H
#define WINDOW_H

#include <QWidget>
#include <QSlider>

namespace Ui {
class Window;
}

class Window : public QWidget
{
    Q_OBJECT

public:
    explicit Window(QWidget *parent = 0);
    ~Window();

protected:
    void keyPressEvent(QKeyEvent *event);

private:
    Ui::Window *ui;
};

#endif // WINDOW_H

window.cpp

// window.cpp

#include <QtWidgets>
#include "window.h"
#include "ui_window.h"
#include "myglwidget.h"

Window::Window(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Window)
{
    ui->setupUi(this);
}

Window::~Window()
{
    delete ui;
}

void Window::keyPressEvent(QKeyEvent *e)
{
    if (e->key() == Qt::Key_Escape)
        close();
    else
        QWidget::keyPressEvent(e);
}

window.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
  <class>Window</class>
  <widget class="QWidget" name="Window">
    <property name="geometry">
      <rect>
      <x>0</x>
      <y>0</y>
      <width>600</width>
      <height>638</height>
      </rect>
      </property>
      <property name="windowTitle">
        <string>Window</string>
        </property>
        <layout class="QVBoxLayout" name="verticalLayout">
          <item>
          <widget class="MyGLWidget" name="myGLWidget" native="true">
            <property name="minimumSize">
              <size>
              <width>500</width>
              <height>500</height>
              </size>
              </property>
              </widget>
              </item>
              </layout>
              </widget>
              <layoutdefault spacing="6" margin="11"/>
                <customwidgets>
                <customwidget>
                <class>MyGLWidget</class>
                <extends>QWidget</extends>
                <header>myglwidget.h</header>
                <container>1</container>
                <slots>
                <slot>setXRotation(int)</slot>
                <slot>setYRotation(int)</slot>
                <slot>setZRotation(int)</slot>
                </slots>
                </customwidget>
                </customwidgets>
                <resources/>
                <connections/>
                </ui>

1 Answer 1

1
  1. You create QTimer and store it in local variable (not class member).
  2. You cannot start the timer which you create.
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.