srodrb
srodrb

Reputation: 1344

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

I'm writing some OpenGL/Glut functions for visualize the results of my fluid dynamics code (all in C++). My data is stored in a matrix declared as global.

Here is the pseudo-code:

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

On the solve() function I have a Loop.

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

I'm quite new to OpenGL, but as far as I understand using glutPostRedisplay() inside IterateLoop() function will not perform a new image until the loop finish (because glutPostRedisplay() only set a flag and wait to an idle state), so...Any ideas? (1)

It's possible to employ glutIdleFunc? or glutTimerFunc pointing to IterateLoop splitting the Loop in small ones? (in that case, how it's supposed to pass a void pointer to a class member from inside the class? :S)

NOTE; I could re-write code so I accept every suggestion, but I think it's important to have all my fluid dynamics operations inside a class.

Upvotes: 1

Views: 492

Answers (3)

Andreas Haferburg
Andreas Haferburg

Reputation: 5510

Conceptually, the rendering and the solving are two different things, and you should not do rendering directly in the solver. Think of it this way: Your solver could do its thing without any GUI, so the GUI is just something that sits on top of it. So put it in a different class.

There's two basic approaches: Threaded and non-threaded. Your solver consists of the current state at the current time, and should be able to advance its state to the next time frame. So you can either do the solving (one iteration) in a glutIdleFunc, which is a bit ugly:

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

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

Or do the solving in a separate thread, store the state, and have the OpenGL thread fetch it for rendering.

One aspect of that is that you don't necessarily know if the time it takes to compute the next state has anything to do with the time from one frame to the next, but your question doesn't say if that is a problem.

Upvotes: 1

srodrb
srodrb

Reputation: 1344

I left here a tricky solution that works for me, since I don't recommend taking this approach; probably you will have to solve many issues related to "non-static member function..." error.

There are two classes, fluid_dynamics and visualize.

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

Every IterateStep updates a global array with new results.

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.

Here the display member:

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

Cons;

  1. Almost every function -or class members- should be static because glutDisplayFunct requires a static function.
  2. You lose some control of the solver because it relies on glutMainLoop Loop.
  3. You should initialize some class parameters statically outside main(), less control for you.

Upvotes: 0

ypnos
ypnos

Reputation: 52337

Seriously I would not go with GLUT but instead use Qt which provides excellent cross-platform GL wrapping.

You can just use a QGLWidget and embed your GL code into drawing the widget. There are tons of examples on the web. Then you can also use Qt's event system and QTimers etc. to trigger updates and redrawing of the scene.

Or you could use QGraphicsView rendering to a QGLWidget. Then again while rendering the QGraphicsScene you can embed GL code. This allows even more freedom and you get a lot of stuff for free, e.g. better mouse input handling or widgets on top of your view.

The possibities are endless and you will not write much more code then with GLUT. As a nice, relatively small example with QGraphicsView see: http://qt.gitorious.org/qt-labs/modelviewer

It is very powerful concept (just using QGLWidget however is easier).

Upvotes: -1

Related Questions