steelscout's picture

Using OpenTK to draw a given mesh during a simulation at pre-defined intervals

Hi there,

I've written a small simulation code, which calculates new positions of the nodes of a triangulated mesh at every step.
I want to use OpenTK to draw this mesh in a new window and keep that image static until it should be re-rendered with a new configuration.
I don't have much experience with 3D drawing and was trying to achieve this by using the GameWindow class according to some examples I found, but I assume this is the wrong choice,
since it basically stops the simulation as long as the game window is displayed.

How can I simply render a static scene, keep it open, return to the simulation loop and just redraw it from time to time?
(I currently don't need any user interaction capabilites)

I'm sorry, this is probably a very simple issue, but I haven't found a good explanation in the examples I was looking at.
Thanks a lot!
steelscout


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
the Fiddler's picture

GameWindow.Run will block the calling thread until the window is closed. You have three options:

  1. Hook your simulation loop to the GameWindow.UpdateFrame event, like this:

    using (var gw = new GameWindow())
    {
        gw.UpdateFrame += (sender, e) =>
        {
            // e.Time gives you the time delta, if you need that in your simulation
            RunSimulationStep();
        };
     
        gw.RenderFrame += (sender, e) =>
        {
            RenderSimulationResults();
            gw.SwapBuffers();
        };
     
        // Run 30 simulation steps per second. Pass 0 to run as fast as your computer can handle.
        gw.Run(30);
    }
  2. Create the GameWindow on a separate thread:
    var thread = new Thread(() =>
    {
        using (var gw = new GameWindow())
        {
            gw.RenderFrame += (sender, e) =>
            {
                RenderSimulationResults();
                gw.SwapBuffers();
            };
     
            gw.Run();
        }
    });
    thread.IsBackground = true;
    thread.Start();

    You must take care to synchronize your simulation with the rendering in this case, as they are both running at the same time.

  3. Replace GameWindow.Run() with your custom implementation. (Refer to the source code, possible but not recommended.)
steelscout's picture

Thank you very much for your answer.
I only have a few more questions on that:

- What exactly is the difference between UpdateFrame and RenderFrame? Is UpdateFrame called at every frame and might (or might not) then call RenderFrame, if the next image should be rendered?

- Is there a recommended efficient way to draw a mesh of many triangular faces using opengl? (e.g. "store all triangles in a structure and then draw everything at once" vs. "draw one triangle at a time".) Does it even make a difference?

Thank you very much!
steelscout

the Fiddler's picture

Conceptually, UpdateFrame is meant for logic and RenderFrame is meant for displaying results. In games, logic must typically run in the same rate regardless of the underlying hardware (e.g. 60 logic updates per second), whereas rendering can run in different rates depending on the hardware (e.g. 20 fps on a low-end netbook, but 120 fps on a high-end gaming system.)

OpenTK will try to maintain the UpdateFrame rate you specify in GameWindow.Run(), by skipping RenderFrame events if there is not enough time to display them. This means that an UpdateFrame handler can assume it is running at a fixed rate. You can disable this behavior by passing 0 to GameWindow.Run().

Regarding rendering, there is a big performance difference between rendering all triangles in a batch compared to rendering each triangle on its own. The easiest approach is to upload all triangles in a Vertex Buffer Object (VBO) and draw them in one call. Check out the "Static VBO" example in OpenTK.Examples.