0

私は現在、小さな粒子システムをセットアップしようとして Qt で遊んでいます。そこで、GLWidget をサブクラス化し、ハッキングしました。不明な変更を加えるまではすべてうまくいっていましたが、マウスを動かしたときにのみウィジェットが再描画されるようになりました (QTimer が起動しているため、常に再描画されているはずです)。関連コード:

OpenGLWidget.h

class OpenGLWidget :  public QGLWidget  {

   Q_OBJECT

public:
   OpenGLWidget(QWidget * parent = 0);
   ~OpenGLWidget();

public slots:
   void toggleEmitter();

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);

protected slots:
   void timeOut();

private:

   void testFunc(Particle & p, unsigned int t);

   QTime time;
   QTimer timer;

   Emitter emitter;

.cpp からの関連コード

// in the constructor
time.start();
connect(&timer, SIGNAL(timeout()), this, SLOT(timeOut()));
timer.start(0);

void OpenGLWidget::initializeGL()  {
   GLuint tex = 0;

   qglClearColor(bgColor);
   glEnable(GL_DEPTH_TEST);   
   glClearDepth(1.0f);
    glDepthFunc(GL_LEQUAL);
   glShadeModel(GL_SMOOTH); 

   glDisable(GL_CULL_FACE);
   glEnable(GL_TEXTURE_2D); 
   glEnable( GL_BLEND );
   glBlendFunc( GL_SRC_ALPHA, GL_ONE); // _MINUS_SRC_ALPHA );

   glPointSize(3.0f);

   tex = bindTexture(QPixmap(QString("testparticle2.png")), GL_TEXTURE_2D);
   emitter = Emitter(Vector(0, 0, 0.0f), tex, 50, fastdelegate::FastDelegate2<Particle &, unsigned int>(this, &OpenGLWidget::testFunc));
}

void OpenGLWidget::paintGL()  {
   makeCurrent();
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

   mainCam.SetView();

   glRotatef(xRot, 1, 0, 0);
   glRotatef(yRot, 0, 1, 0);

   emitter.Process(time.elapsed());

   totalTime += time.elapsed();
   time.restart();

}

void OpenGLWidget::resizeGL(int width, int height)  {
   contextWidth = width;
   contextHeight = height;

   glViewport(0, 0, width, height);

   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   gluPerspective(55.0f, width / (float) height, 0.01f, 100.0f);

   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();

}

void OpenGLWidget::timeOut()  {
   updateGL();
}

void OpenGLWidget::mousePressEvent(QMouseEvent *event)  {
    lastX = event->pos().x();
    lastY = event->pos().y();
}

void OpenGLWidget::mouseMoveEvent(QMouseEvent *event)  {
    int dx = event->x() - lastX;
    int dy = event->y() - lastY;

    if (event->buttons() & Qt::LeftButton) {
        xRot += 3 * dy;
        yRot += 3 * dx;
    } else if (event->buttons() & Qt::RightButton) {
        xRot += 3 * dy;
        yRot += 3 * dx;
    }

    lastX = event->pos().x();
    lastY = event->pos().y();

}
4

3 に答える 3

1

updateGL()がpaintGL()を呼び出すglDraw()を呼び出すことを考えると、タイマーは、mousemoveイベントと同じ機能を呼び出す必要があると思います。

タイマーが実際に刻々と過ぎているのは確かですか?

ところで、paintGL()でmakeCurrent()を呼び出す必要はありません。

編集:追加情報が追加された後:

QTimerは言う

「特別な場合として、タイムアウト0のQTimerは、ウィンドウシステムのイベントキュー内のすべてのイベントが処理されるとすぐにタイムアウトになります。」

したがって、できるだけ速く実行したい場合(ただし、Windowsおよびほとんどのx386ベースのシステムでは10msがおそらく最小です)、0ではなく1の値でタイマーを開始します。これが問題だと思います。キューからのメッセージの読み取りが終了したときにのみカチカチ音をたてます。

于 2009-01-15T19:03:11.430 に答える
1

タイマーは 20ms 未満では機能しません。それは0に等しいです。ある反復から別の反復までの時間を測定する単純なループを使用できます。測定方法はお使いのOSのAPIを利用したほうがよいでしょう。

于 2012-03-22T10:02:07.093 に答える
1

タイムアウトが 0 秒の QTimer は、イベント ループが制御を取得したときにのみ起動します。そうではないと思います。ただし、マウスを動かすと、イベント ループがいくつかのイベントを (再び) 処理し、保留中のタイマー イベントを配信します。QTimer からの保留中のタイマー イベントが確実に処理されるように、更新ループでprocessEvents()を呼び出す必要があるかもしれません。

于 2009-05-28T20:22:38.197 に答える