1

I have an OpenTK GLControl embedden in a WindowsFormsHost in my WPF application. I want to continuously update and render it. In Winforms a solution would be to attach the UpdateAndRender method to the Application.Idle event, but there is no such thing in WPF.

So what would be the best way to do (60FPS) updating of my scene and GLControl ?

Pygmy
  • 1,268
  • 17
  • 33
  • Not related to the question but based on my experience using this path(GLControl and WPF), I would recommend NOT using WPF. I have problems wiring the UI and GLControl. – Syaiful Nizam Yahya Apr 23 '15 at 08:34

2 Answers2

2

You can use a System.Timers.Timer to control how often your render code is called. In your window containing the GLControl-in-WindowsFormsHost, declare a private System.Timers.Timer _timer;, then when you're ready to start the rendering loop, set the timer interval and it's event handler, then start it up, as in the following example:

    private void btnLoadModel_Click(object sender, RoutedEventArgs e)
    {
        LoadModel(); // do whatever you need to do to prepare your scene for rendering
        _timer = new System.Timers.Timer(10.0); // in milliseconds - you might have to play with this value to throttle your framerate depending on how involved your update and render code is
        _timer.Elapsed += TimerElapsed;
        _timer.Start();
    }

    private void TimerElapsed(object sender, ElapsedEventArgs e)
    {
        UpdateModel(); // this is where you'd do whatever you need to do to update your model per frame
        // Invalidate will cause the Paint event on your GLControl to fire
        _glControl.Invalidate(); // _glControl is obviously a private reference to the GLControl
    }

You'll clearly need to add using System.Timers to your usings.

seveland
  • 181
  • 12
  • To do 60 frames per second, of course, you'd pass 1000.0/60.0 into the Timer's constructor. – seveland Jul 26 '12 at 19:44
  • Why was this answer down-voted? It is the most sensible thing to do for a Forms-based application. Although it might be improved with some sort of frame-dropping in case the renderer can't keep up. – M.Stramm Sep 22 '14 at 00:35
  • @M.Stramm Possibly because, it is more practical to update the windows when there is visual change(next frame animation etc). The biggest problem with common graphic rendering system is that it will update the screen whether there is a visual change or not. – Syaiful Nizam Yahya Feb 06 '15 at 02:29
  • @publicENEMY The question was how to _continuously_ update the scene and control at 60fps, this is a very concise and practical answer to that question: Use a timer. Of course decoupling the UpdateModel() and Render() would be a good idea, but that's not within the scope of the question – M.Stramm Apr 17 '15 at 09:25
2

You can use Invalidate() for it. This causes the GLControl to redraw it's content.

If you call it at the end of Paint() you may blocking some UI rendering of the other WPF controls.

WPF provides a per frame render event: CompositionTarget.Rendering. This event is called before WPF wants to render the content. Subscribe from it and call Invalidate:

public YourConstructor()
{
  //...
  CompositionTarget.Rendering += CompositionTarget_Rendering;
}

void CompositionTarget_Rendering(object sender, EventArgs e)
{
  _yourControl.Invalidate();
}

You need to unsubscribe if you don't use it anymore (to avoid memory leaks).

Here is a How to: Render on a Per Frame Interval Using CompositionTarget from MSDN.

I use GLControl with that method and it works fine. I did not checked how much FPS I have but it feels smooth.

You may also have a look on this: Why is Frame Rate in WPF Irregular and Not Limited To Monitor Refresh?

Community
  • 1
  • 1
fedab
  • 978
  • 11
  • 38