如何在迭代(for循环)求解器中更新粒子位置

How to update particles position inside an iterative (for-loop) solver

本文关键字:更新 位置 粒子 迭代 循环 for      更新时间:2023-10-16

我正在编写一些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?或glutTimerFunc指向iteratelloop分裂小的循环?(在这种情况下,它应该如何从类内部传递一个void指针到类成员?: S)

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

从概念上讲,渲染和求解是两件不同的事情,您不应该直接在求解器中进行渲染。可以这样想:你的解算器可以在没有任何GUI的情况下完成它的工作,所以GUI只是位于它之上的东西。所以把它放到不同的类中。

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

solver* g_solver;
void step()
{
  g_solver->step();
}
int main()
{
  ...
  g_solver = &solver;
  glutIdleFunc(&step);
}

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

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

我在这里留下了一个适合我的棘手的解决方案,因为我不建议采用这种方法;可能你将不得不解决许多与"非静态成员函数…"错误相关的问题。

有两个类,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.

这里是display成员:

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

缺点;

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

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

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

或者您可以使用QGraphicsView渲染到QGLWidget。然后,在渲染QGraphicsScene时,您可以嵌入GL代码。这允许更多的自由,你可以免费获得很多东西,例如更好的鼠标输入处理或视图顶部的小部件。

的可能性是无止境的,你不会写更多的代码比与GLUT。作为一个不错的,相对较小的例子与QGraphicsView见:http://qt.gitorious.org/qt-labs/modelviewer

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