Постоянно обновляемый OpenTK GLControl в WindowsFormsHost в WPF - Как? - PullRequest
1 голос
/ 06 июля 2011

У меня есть OpenTK GLControl, встроенный в WindowsFormsHost в моем приложении WPF. Я хочу постоянно обновлять и визуализировать его. В Winforms решением было бы присоединить метод UpdateAndRender к событию Application.Idle, но в WPF такого нет.

Итак, как лучше всего (60FPS) обновить мою сцену и GLControl?

Ответы [ 2 ]

2 голосов
/ 01 октября 2014

Вы можете использовать Invalidate() для этого.Это заставляет GLControl перерисовывать его содержимое.

Если вы вызываете его в конце Paint(), вы можете заблокировать некоторую визуализацию пользовательского интерфейса других элементов управления WPF.

WPF предоставляетсобытие рендеринга кадра: CompositionTarget.Rendering.Это событие вызывается до того, как WPF хочет отобразить содержимое.Подпишитесь на него и позвоните Invalidate:

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

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

Вам необходимо отписаться, если вы больше не используете его (чтобы избежать утечек памяти).

Вот это Как:Рендеринг с интервалом за кадр с использованием CompositionTarget из MSDN.

Я использую GLControl с этим методом, и он работает нормально.Я не проверял, сколько у меня FPS, но он выглядит плавно.

Вы также можете посмотреть на это: Почему частота кадров в WPF нерегулярна и не ограничивается обновлением монитора?

1 голос
/ 26 июля 2012

Вы можете использовать System.Timers.Timer, чтобы контролировать, как часто вызывается ваш код рендеринга. В вашем окне, содержащем GLControl-in-WindowsFormsHost, объявите private System.Timers.Timer _timer;, затем, когда вы будете готовы запустить цикл рендеринга, установите интервал таймера и его обработчик событий, а затем запустите его, как в следующем примере:

    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
    }

Вам явно нужно добавить using System.Timers к вашему использованию.

...