[SOLVED]Problem with OpenGL method.

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
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
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?
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
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?
I'm using to compile this command:
g++ -o test main.cpp keyboard.cpp
Last edited on
Problem solved:
g++ -o test main.cpp keyboard.cpp -lglut
Last edited on
ne555, that was exactly what I meant :) Sorry if I confused you, I realize I didn't explain it very well :P
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
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.
Have you registered a callback for glutIdleFunc


Probably no. How do i do that?
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.
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
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();
}
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
Hmm, maybe you also need to do glutDisplayFunc(renderScene);. If not, here's an excellent tutorial on glut: http://www.lighthouse3d.com/opengl/glut/
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.