PDA

View Full Version : how to run a OpenGL thread in a c++ console app?



RafalTypiak
05-26-2009, 01:02 AM
Hello,
I wasn't sure where to go with my problem as I'm not sure if it's a strictly OpenGL or C++ problem. Here's my story.

I made a console application that controls some servomotors via a rs232 port. All in all the program gets a joystick status from a controller device, opens a RS port, sends a command to the servocontroler and closes the port /and does other maintenance stuff, but that's not important/.
The thing is, that the joystick needs to be set up right to work correctly and this is where I decided to create a 'setup' image which would show the user how to set up the controller correctly. That is why I decided to create a OpenGl window, put in the image and at the start of the program display it to the user so that he can configure everything correctly before going any further. So I though to myself 'no biggy' I'll copy-paste a simple tutorial program which opens a OpenGL window /at first just opens it. nothing more/.
Imagine my surprise when the window opened, but the console app froze, and after closing the window, the app closed as well /yeah. now it's clear to me why it happened, back then I though the OpenGL window was a different process/. So now I'm left with a problem and no real idea how to handle it. I'm not keen on creating threads, but I did manage to create them using CreateThread () but here's the thing, I can pass only one parameter to the thread, and I saw glutInit uses 2:


glutInit(&argc, argv);

plus I can't seem to run functions inside a thread as I get an error:

error C2601: 'init' : local function definitions are illegal

and putting those functions outside the thread gives an:

error C3861: 'glutInit': identifier not found
error

I'm in a jam and if someone could help me I would be really grateful. Here's how the code looks like is someone would like to get a better perspective:




//glowne
#include <stdio.h>
#include <cstdlib>
#include <iostream>

//joystick i port szeregowy = sterowanie pojazdem
#include "../joystick.h"
#include "../Serial.h"
#include <conio.h>
#include <tchar.h>

Joystick* joysticks[4];
unsigned int i;
unsigned int j;
int ch;

CSerial serial;
LONG lLastError = ERROR_SUCCESS;

//zmienne dla serwomechanizmow
int serwa[3];
unsigned char str[4];
unsigned char wychyl_poziom = str[2], wychyl_pion = str [2];

//GLUT

#include "stdafx.h"
#include "windows.h"
#include <gl/gl.h>

//funkcje OpenGL
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
void EnableOpenGL(HWND hWnd, HDC * hDC, HGLRC * hRC);
void DisableOpenGL(HWND hWnd, HDC hDC, HGLRC hRC);

// funkcja pobodu liczby joystickow
unsigned int numJoysticks = Joystick::deviceCount();

****** CODE STARTS HERE **********

DWORD WINAPI FunkcjaWatku(PVOID pvParam)
{
int g=(int)pvParam;
int argc;
char** argv;
glutInit(&amp;argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(250,250);
glutInitWindowPosition(100,100);
glutCreateWindow("Hello World");
init();
glutDisplayFunc(display);
glutMainLoop();

return 0;

}

// ***MAIN THREAD***

int main()
{

....some code......

// new thread

DWORD IdWatku;
int x = 6;

if(CreateThread(NULL, 0, FunkcjaWatku, (PVOID)x, 0, &amp;IdWatku)==NULL)
{
printf("Problem z inicjacja watku");
}

else
{
printf("Help uruchomiony.");
}

...additional code.....

}


is there a scheme for creating OpenGL threads? Say something like:



1. include glut

2. OpenGL functions

3. thread declaration

4. main
{
5. new thread
}



?

And so my question is this:
How can I create a new thread which opens a OpenGL window in a console app? It's kind of important for me in the future as I would like to use a similar window for visualization of data later on.

Thank you for any help you can give.

Rafal Typiak

vivek vyas
05-26-2009, 01:18 AM
apologies me if wrong info cause i am a beginner

you need to put
#include <GL/glut.h> or #include <gl/glut.h>
below the
#include <windows.h>
and put glutXXX calls in main function
and us glutJoysticFunc(unsigned int,int,int,int);
function
i think you need to find out glut joystic demos on net or in Mesa Demos(www.Mesa3d.org)

tionxtion
05-26-2009, 01:21 AM
hi, i dunno if i completely understand your question.. So for me, in my case, i have 3 threads, and only the 3rd threads contain openGL.

To solve the "single parameter" issue for the thread, i just simply make a struct type, so I can pass all variable i need inside a single struct variable.

And, since only the 3rd thread contains openGL, and the main module is fully console window (not OpenGL) i don't really need the argc and argv variable in the OpenGL.

However, it seems OpenGL won't run without those.
So in the OpenGL method, i just make a dummy argc and argv like this:


//this argc and argv value doesn't change, this is fake argc and argv value, since freeglut wont run without this
int argc = 1;
char* argv[1] = {{""}};

EDIT:
For your errors, I have no idea, my best guess would be that you make mistake in the includes, perhaps..

One more thing, I use Freeglut instead of Glut, because Freeglut
has glutMainLoopEvent(). In my understanding:
- glutMainLoop = you call it once, and it keep on looping itself regardless you call it or not, until you kill it.
- glutMainLoopEvent = you call it once, and it will do the OpenGL stuff loop only once (in my case, render once), then returns.

So in my OpenGL thread is more or less like this:


DWORD WINAPI myOpenGLThread(void *param)
{
//this struct contains all the variables i need in this my OpenGLThread method
myStructType *myStruct = param;
....

//call the render initialization method
render_init(...);

while (somecondition)
{
.....
main_render_call(...);
.....
}
}

So, the idea is :
- render_init function will call the initialization stuffs of the OpenGL (in my case glutCreateWindow, glInit, etc).
- main_render_call function call the glutMainLoopEvent, aka the "render" call.

So, the rendering will happen only if I call it, in this case it happen in "somecondition" while loop.

I'm also a beginner as well, I might made mistake and this might not be the best solution, but this is how i do it xD

RafalTypiak
05-26-2009, 03:09 AM
Thank you for a fast reply,
first things first.
@vivek vyas:
I'm already putting all the necessary includes which you said.
And I don't have any problems with the joystick. I don't need to use it in the OpenGL. My console app handles the joystick functions.

@tionxtion

I'm gonna’ stick to the normal GLUT as making Freeglut work looks like a lot of work for me. A lot more that it's needed. /I can't for example use 'make' in the cmd, and so on..../

I'm probably making a syntax error here somewhere. Here's the whole program with only the glut code inside. Could you try and correct me in what I'm doing wrong here?

/stdafx.h and stdafx.cpp are included in the VS2008 solution/



//GLUT

#include "stdafx.h"
#include "windows.h"
#include <gl/gl.h>

DWORD WINAPI Thread(void *param)
{

int argc = 1;
char* argv[1] = {{""}};

glutInit(&amp;argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(250,250);
glutInitWindowPosition(100,100);
glutCreateWindow("Hello World");
init();
glutDisplayFunc(display);
glutMainLoop();


}

int main()
{
...other stuff...

CreateThread(NULL, 0, Thread, (PVOID)parameters, 0, &amp;IdWatku);

...other stuff...

return 0;
}



should this run? Or am I missing something? And if, than what?

tionxtion
05-26-2009, 03:33 AM
I am really sorry, as i'm also new to openGL, im not capable to sense mistake just by seeing :)
Also my project is quite different from you, so i use more includes

#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include <GL/glut.h>
#include <GL/freeglut_ext.h>
#include <GL/wglew.h>
#include <wglext.h>

But i think its ok, can you run it? If not what error complain you get?

One thing that bothers me, if im not mistaken, glutMainLoop never returns (unless you assign some keyboard control to shutdown with glutKeyboardFunc (glutKeyboard)).
So, how did you exit, by killing the threads perhaps?

RafalTypiak
05-26-2009, 03:42 AM
again thank you. I'm ...a ctually I don't know how to describe the mistake I made so it won't look completly and utterly 'ultra-stupid'. I found what I was doing wrong, and it's thanks to you :)
I did inclue all the neccesary header files but.... i misspelled the 'glut.h'. I put in 'gl.h' instead. I had to relook at the gl folder in VS include root to see what I did wrong :p I feel like crap about it.
So it's working! yey! :) /I'm actually happy about it/
But here's another thing. After I close the GL window, the program closes again. It may be due to the fact that it returns 0 to the main program /could it be the case?/. But than how to overcome this? The compiler sais that my thread has to return a value. Do you know how to 'fix' this?

Thank you for your help
Rafal

tionxtion
05-26-2009, 04:03 AM
haha no worry, did lots of stupid mistakes here too..

Could it be that after your OpenGL thread finish its task, it returns 0 to the main, and your main thread has nothing to do anymore, so it exits?

I think if you have multiple threads, the main will not exit until all of the threads finish its tasks.
Do you only have OpenGL thread, or is there any other thread?

Its not a smart trick, but just for testing, try put "getchar();" in the end of your main thread, just before "return 0;". In hope to prevent the console window from closing, until you press Enter.

RafalTypiak
05-26-2009, 04:23 AM
actually the programm was running in an infinite loop fine without the OpenGL thread. I tried putting in the getchar(); but it's the same as it was wiuthout it. The whole programm closes when I close the OpenGL window :(

And another thing is that I'm trying to load an image from the hard drive to the window. I saw the glDrawPixelsfunction, but it requires "const GLvoid *pixels"



void glDrawPixels( GLsizei width,
GLsizei height,
GLenum format,
GLenum type,
const GLvoid *pixels )




but it's only giving me a black screen. This is what I have:




void display(void)
{
//Clear all pixels
glClear(GL_COLOR_BUFFER_BIT);

//draw white polygon (rectangle) with corners at
// (0.25, 0.25, 0.0) and (0.75, 0.75, 0.0)
glDrawPixels( 800, 560, GL_RGB, GL_BITMAP,"C:\Sterowanie Q0.jpg" );
glEnd();

// Don't wait start processing buffered OpenGL routines)
glFlush();
}

void init(void)
{
//select clearing (background) color
glClearColor(0.0, 0.0, 0.0, 0.0);

//initialize viewing values
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);

}



If I understand correctly, the glutInit(); function is used only once at the start, and than when the thread goes into the "glutMainLoop();" it simply loops /hmmm. a question. what does it loop? every glut function? glutDisplayFunc()? what?/.

What do I need to chane in the:


glDrawPixels( 800, 560, GL_RGB, GL_BITMAP,"C:\Sterowanie Q0.jpg" );

to get the image correctly?

regards,
Rafal