对于一个类,我们获得了使用GLUT和OpenGL可视化烟雾的代码。我想在https://stackoverflow.com/a/17794523/651779之后将此转换为QT以及此处的示例:http://www.bogotobogo.com/Qt/Qt5_OpenGL_QGLWidget.php。它现在绘制小部件,但OpenGL部分不能按预期工作(见下图,应该是黑屏,当鼠标移过它时会改变)。编译代码不会给我任何警告或错误。
使用断点我可以看到它永远不会转到do_one_simulation_step(),因此事件队列可能永远不会为空,因此来自QObject::connect(timer,SIGNAL(timeout()),this,SLOT(do_one_simulation_step()));
的槽不会被调用?我的代码放在下面。
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>
答案 0 :(得分:1)
QTimer
并将其存储在本地变量(不是类成员)中。