Reputation: 11
Thank you for your reading this question!
A program I used before has main window form. when I click a button , another thread creates Gamewindow
form which displays frame data from a Camera. OnUpdateFrame()
, OnRenderFrame()
are automatically called, and process data and render in the created window.
I am working on the update vision of this software which has a glControl
in the Main window form.
Yes, I am using glControl
instead of Gamewindow
. but problem is..
Because Main Window form need to handle user input, I have to control glControl
in another thread which continually update and render Frame data. But glControl
in created and displayed main window form. the glControl
manipulated in the other thread is not applied to main window form. (I only can use glControl.Swapbuffers()
or .invalidate()
in other thread code)
I found a info which says glControl
is controlled in only one thread. So how can I render frame data on the glControl
automatically while using Mainwindow
Form.
I have tried GL. functions to update an render frame data using timer , but the timer is also another thread, so changes are not applied to the glControl
in the Main form.
And I have tried to new and create the glControl
in the other thread but, it shows a exception when using GL. functions (: No GraphicsContext available in the calling thread)
How can I solve this problem?
==========
this is a way i tried, and found it doesn't work.. RenderFrame() called by a timer thread can not do anything for displaying on glControl1, even thought glcontrol1.Invalidate() is called periodically.
actually when using gamewindow before, OnRenderFrame() is periodically and displays objects in the window. but how can i do this on glControl in main window form. can Main thread periodically call RenderFrame()?? it seems a timer is also a thread, so RenderFrame() called by a timer thread do not work properly.
public partial class MainWindowForm : Form
{
System.Timers.Timer glControlTimer;
...
private void InitializeComponent()
{
glcontrol1 = new OpenTK.GLControl();
...
}
private void btShowLive2_Click(object sender, EventArgs e)
{
...
oHandleGLControl = new HandleGLControl(glcontrol1);
glControlTimer = new System.Timers.Timer(300);
glControlTimer.Elapsed += TimerElapsed;
glControlTimer.Start();
}
private void TimerElapsed(object sender, ElapsedEventArgs e)
{
oHandleGLControl.UpdateFrame(); //processing frame data
oHandleGLControl.RenderFrame(); //rendering
glcontrol1.Invalidate();
...
}
}
public class HandleGLControl
{
public void UpdateFrame()
{...
}
public void RenderFrame()
{
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.PushMatrix();
GL.MatrixMode(MatrixMode.Modelview);
GL.Translate(-cameraPosition[0], -cameraPosition[1], -cameraPosition[2]);
GL.Rotate(g_pitch, 1.0f, 0.0f, 0.0f);
GL.Rotate(g_heading, 0.0f, 0.0f, 1.0f);
....
}
...
}
Upvotes: 1
Views: 1656
Reputation: 143
I had the same exact issue a while ago, and the problem you are facing regards OpenGL contexts, specifically the fact that OpenGL contexts can only be bound to one thread.
However, despite popular belief, this thread doesn't have to be the main window thread, it can be any thread you want.
The process is simple but delicate:
In OpenTK this is how I do it:
private void glcontrol1_Load(object sender, EventArgs e){
glcontrol1.Context.MakeCurrent(null); //Unbinds the context from the current thread.
Thread renderThread = new Thread(() => {
glcontrol1.Context.MakeCurrent(glcontrol1.WindowInfo); //Bimds the OpenGL context to this new thread
while(DoRender) { RenderFrame(); }
}
renderThread.Start();
}
You can put the glcontrol1.SwapBuffers()
call in the RenderFrame() method too, it hasn't given me any problems so far.
As a suggestion, I'd run the UpdateFrame() and RenderFrame() methods on different threads, so not to limit the update logic to the frame rate of the program.
Upvotes: 2