如何更新迭代(for-loop)求解器内的粒子位置

时间:2013-05-24 19:40:58

标签: c++ opengl

我正在编写一些OpenGL / Glut函数来可视化我的流体动力学代码的结果(全部用C ++编写)。 我的数据存储在一个声明为全局的矩阵中。

这是伪代码:

class fluid_dynamics{
    //...
    void set_conditions();    // Here is my opengl init function
    void solve();             // This is an iterative loop with stop criteria
    void IterateLoop();
}

在solve()函数中,我有一个循环。

void fluid_dynamics::solve(){
    glutDisplayFunc(DisplayMatrix);

    IterateLoop(  // here I update my data each n-steps
                  // and I want to update my "scene" every time I do that.
               );
    glutMainLoop();          

我对OpenGL很新,但据我所知,在IterateLoop()函数中使用glutPostRedisplay()将不会执行新的图像,直到循环结束(因为glutPostRedisplay()只设置一个标志并等待空闲国家),所以...任何想法? (1)

可以使用glutIdleFunc吗? 或者指向IterateLoop的glutTimerFunc将Loop分成小的? (在这种情况下,它应该如何从类内传递一个void指针到一个类成员?:S)

请注意;我可以重新编写代码,所以我接受每一个建议,但我认为将所有流体动力学操作都放在一个类中是很重要的。

3 个答案:

答案 0 :(得分:1)

从概念上讲,渲染和求解是两回事,你不应该直接在求解器中渲染。可以这样想:你的求解器可以在没有任何GUI的情况下完成它的工作,因此GUI就是它的基础。所以把它放在另一个班级。

有两种基本方法:螺纹和非螺纹。您的求解器包含当前时间的当前状态,并且应该能够将其状态提前到下一个时间帧。所以你可以在glutIdleFunc中进行求解(一次迭代),这有点难看:

solver* g_solver;
void step()
{
  g_solver->step();
}

int main()
{
  ...
  g_solver = &solver;
  glutIdleFunc(&step);
}

或者在单独的线程中进行求解,存储状态,并让OpenGL线程获取它以进行渲染。

这方面的一个方面是你不一定知道计算下一个状态所花费的时间是否与从一帧到下一帧的时间有关,但你的问题并不是说它是否是一个问题

答案 1 :(得分:0)

我离开这里是一个对我有用的棘手解决方案,因为我不建议采用这种方法;可能你必须解决许多与“非静态成员函数...”错误相关的问题。

有两个类,fluid_dynamics和visualize。

class fluid_dynamics{
    //...
    void set_conditions();    // Here is my opengl init function
    void IterateStep();
}

每个IterateStep都会使用新结果更新全局数组。

class visualize{
    visualize()              // main constructor, set the opengl environment; buffer mode, 
                             // window size, etc, and call glutDisplayFunc() and glutMainLoop()
    static void display();   
    static fluid_dynamics *copy; //statically initialized copy of a fluid_dynamics obj.

这里显示成员:

visualize::display(){
    ... //draw scene
    if-condition{            //control iteration < max. iterations condition
    fluid_dynamics::IterateStep(*copy)
    }
    glutPostRedisplay();
}

缺点;

  1. 几乎每个函数 - 或类成员 - 都应该是静态的,因为glutDisplayFunct需要一个静态函数。
  2. 你失去了对解算器的一些控制权,因为它依赖于glutMainLoop Loop。
  3. 你应该在main()之外静态初始化一些类参数,减少对你的控制。

答案 2 :(得分:-1)

说真的,我不会选择GLUT,而是使用Qt,它提供了出色的跨平台GL包装。

您可以使用QGLWidget并将GL代码嵌入到绘制窗口小部件中。网上有很多例子。然后你也可以使用Qt的事件系统和QTimers等来触发更新和重绘场景。

或者您可以将QGraphicsView渲染用于QGLWidget。然后在渲染QGraphicsScene时再次嵌入GL代码。这样可以获得更大的自由度,并且您可以免费获得大量内容,例如在视图之上更好的鼠标输入处理或小部件。

可能性是无穷无尽的,你不会用GLUT写更多的代码。作为QGraphicsView的一个不错的,相对较小的例子,请参阅: http://qt.gitorious.org/qt-labs/modelviewer

这是非常强大的概念(仅使用QGLWidget更容易)。