[SOLVED]Problem with OpenGL method.

Jan 22, 2013 at 3:17pm
Hello, guys.
I'm trying to make a program using C++ and OpenGL, but i'm facing some difficulties. I created a class that i called "Keyboard", in this class i've tryied to implement a callback called "keyPressed". When i try call "glutKeyboardFunc" of the GLUT in main method, i have this error message:
error: argument of type ‘void (Keyboard::)(unsigned char, int, int)’ does not match ‘void (*)(unsigned char, int, int)’

Below, you can see my code.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//keyboard.h
#ifndef __keyboard_h__
#define __keyboard_h__

#include<iostream>
#include<GL/gl.h>
#include<GL/glut.h>
#include<GL/glx.h>

using namespace std;

class Keyboard
{
	public:
		Keyboard(void);
		~Keyboard(void);
		void keyPressed (unsigned char key, int x, int y);
};
#endif 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//keyboard.cpp
#include"keyboard.h"

Keyboard :: Keyboard(void)
{
	cout<<"Object created."<<endl;
}

Keyboard :: ~Keyboard(void)
{
	cout<<"Object killed with success."<<endl;
}

void Keyboard :: keyPressed(unsigned char key, int x, int y)
{
	// Not yet implemented.
}

1
2
3
4
5
6
7
8
9
//main.cpp
#include"keyboard.h"

int main()
{
	Keyboard key;
	glutKeyboardFunc(key.keyPressed);
	return 0;
}


I'm using Linux Debian and G++ compiler. What i'm doing wrong?
Last edited on Jan 23, 2013 at 10:23pm
Jan 22, 2013 at 4:46pm
I've had this problem too, the thing is that OpenGL expects a C-style function callback, and you can make callbacks to member-functions. It sucks... If I remember exactly what I did I'll get back to you :P

EDIT:

Ok, so what I did was keeping a global instance of the class I wanted to register the callback with (in this case it would be an instance of your Keyboard-class), and then create a "normal" keyboard function that just called the keyboard-function in that global instance.
Last edited on Jan 22, 2013 at 4:58pm
Jan 22, 2013 at 7:38pm
and then create a "normal" keyboard function that just called the keyboard-function in that global instance.


Dude, i really didn't understand. If is not ask too much, could you please make a example in my code?
Jan 22, 2013 at 7:58pm
1
2
3
4
5
6
7
8
9
10
Keyboard global_keyboard;

void keypress_wrapper(unsigned char key, int x, int y){
   global_keyboard.keyPressed(key, x, y);
}

int main(){
   //...
   glutKeyboardFunc(keypress_wrapper);
}


Your member functions should not be a member function, since it does not use/modify the state of the object.
Last edited on Jan 22, 2013 at 7:59pm
Jan 22, 2013 at 9:53pm
Thank you ne555. But i'm having a new error message.
/tmp/ccf8PTZj.o: In function `main':
main.cpp:(.text+0x48): undefined reference to `glutKeyboardFunc'
collect2: ld returned 1 exit status


What now?
Jan 22, 2013 at 10:04pm
I'm using to compile this command:
g++ -o test main.cpp keyboard.cpp
Last edited on Jan 22, 2013 at 10:04pm
Jan 22, 2013 at 10:34pm
Problem solved:
g++ -o test main.cpp keyboard.cpp -lglut
Last edited on Jan 22, 2013 at 10:34pm
Jan 22, 2013 at 11:16pm
ne555, that was exactly what I meant :) Sorry if I confused you, I realize I didn't explain it very well :P
Jan 23, 2013 at 12:01am
Ok man, but i have a new problem.
When i run y program, what i see is
Object created.
Object killed with success.

I thought the "main" method would be waiting i push a button on the keyboard. I'm saying this because of "glutMainLoop();".
Why it doesn't happen, and the "glutMainLoop();" method does not enter in loop?
I've changed the "keyPressed" method to do a simple test.
1
2
3
4
5
6
7
8
void Keyboard :: keyPressed(unsigned char key, int x, int y)
{
	switch(key)
	{
		case 'j': cout<<"Nothing, just testing."<<endl;
			break;
	}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//Archive main.cpp
#include"keyboard.h"

Keyboard global_keyboard;

void keypress_wrapper(unsigned char key, int x, int y)
{
   	global_keyboard.keyPressed(key, x, y);
}

int main(int argc, char **argv)
{
	glutInit(&argc, argv);
	glutKeyboardFunc(keypress_wrapper); 
	glutMainLoop();
}
Last edited on Jan 23, 2013 at 12:01am
Jan 23, 2013 at 1:13am
Have you registered a callback for glutIdleFunc? I think the glutMainLoop will exit immediately if you haven't, because there isn't really anything for it to run.
Jan 23, 2013 at 1:37am
Have you registered a callback for glutIdleFunc


Probably no. How do i do that?
Jan 23, 2013 at 1:40am
In main:

glutIdleFunc(renderScene);

where renderScene is where you do all the drawing. This is strictly not recommended, because it will cause the program to redraw as fast as possible, but it will work fine to begin with.
Jan 23, 2013 at 1:47am
But i'm not trying to draw nothing, yet. You said that i have to register a callback for glutIdleFunc. In my case is "keyPressed(unsigned char key, int x, int y)" as you can see, the arguments are different that glutIdleFunc accepct.
void glutIdleFunc(void (*func)(void));


I've tried:
glutIdleFunc(keypress_wrapper);

And i have this error message:
invalid conversion from ‘void (*)(unsigned char, int, int)’ to ‘void (*)()’

Last edited on Jan 23, 2013 at 1:49am
Jan 23, 2013 at 1:52am
Well, you don't need to draw anything yet, but you need to have an idlefunc, which is the function glut calls everytime it redraws. You can probably leave the function empty, but you need to have it. You can't register the keyboard function as the idle function, the way you were doing it before was correct. Putting this into your code from before we get:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include"keyboard.h"

Keyboard global_keyboard;

void keypress_wrapper(unsigned char key, int x, int y)
{
   	global_keyboard.keyPressed(key, x, y);
}

void render_scene(void) {
	//this is where you'll be drawing later
}

int main(int argc, char **argv)
{
	glutInit(&argc, argv);
	glutKeyboardFunc(keypress_wrapper); 
	glutIdleFunc(render_scene);
	glutMainLoop();
}
Jan 23, 2013 at 2:03am
Still doesn't work :(
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//keyboard.h
#ifndef __keyboard_h__
#define __keyboard_h__

#include<iostream>
#include<GL/gl.h>
#include<GL/glut.h>
#include<GL/glx.h>

using namespace std;

class Keyboard
{
	public:
		Keyboard(void);
		~Keyboard(void);
		void keyPressed (unsigned char key, int x, int y);
};
#endif 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//keyboard.cpp
#include"keyboard.h"

Keyboard :: Keyboard(void)
{
	cout<<"Object created."<<endl;
}

Keyboard :: ~Keyboard(void)
{
	cout<<"Object killed with success."<<endl;
}

void Keyboard :: keyPressed(unsigned char key, int x, int y)
{
	switch(key)
	{
		case 'j': cout<<"Nothing, just testing."<<endl;
			break;
	}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//main.cpp
#include"keyboard.h"

Keyboard global_keyboard;

void keypress_wrapper(unsigned char key, int x, int y)
{
   	global_keyboard.keyPressed(key, x, y);
}

void render_scene(void) {
	//this is where you'll be drawing later
}

int main(int argc, char **argv)
{
	glutInit(&argc, argv);
	glutKeyboardFunc(keypress_wrapper); 
	glutIdleFunc(render_scene);
	glutMainLoop();
}


To compile:
g++ -o test main.cpp keyboard.cpp -lglut


Same thing happens.

I'll try to ask this question in OpenGL forum too.
Last edited on Jan 23, 2013 at 2:07am
Jan 23, 2013 at 2:18am
Hmm, maybe you also need to do glutDisplayFunc(renderScene);. If not, here's an excellent tutorial on glut: http://www.lighthouse3d.com/opengl/glut/
Jan 23, 2013 at 10:22pm
So, i've asked this question in opengl forum,and a guy answered me.
Take a look in his answer:
You have to create a window.Until you have a window, you don't have a window message processing loop. And without that, you can't have idle time (ie: when you're not processing messages). You can't process keyboard messages because you can't process messages.

GUI programming is generally built around a window of some sort. In Win32 especially, the Window is what gets keyboard messages, not the application. That's why different windows of the same application can process keyboard messages differently.


Then i created a window and now everything is working fine.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include"keyboard.h"

Keyboard global_keyboard;

void keypress_wrapper(unsigned char key, int x, int y)
{
   	global_keyboard.keyPressed(key, x, y);
}

int main(int argc, char **argv)
{
	glutInit(&argc, argv);

	glutInitWindowSize (500, 500);
	glutCreateWindow ("My first OpenGL Window");

	glutKeyboardFunc(keypress_wrapper); 

	glutMainLoop();
}


Thank you very much.
Topic archived. No new replies allowed.