Shawn A
Shawn A

Reputation: 107

OpenGL pointing glutSpecialFunc to member function

My OpenGL function glutSpecialFunc requires a void function pointer with 3 int parameters. This is easy to do with global functions by simply

glutSpecialFunc(processArrowKeys);

But i want to make it point to a member-function in a struct in another file like so:

inputs.h

struct Keyboard {
bool leftMouseDown;
bool keyRight, keyLeft, keyUp, keyDown;

Keyboard() : leftMouseDown(false), keyRight(false), keyLeft(false), keyUp(false), keyDown(false) {

}

void Keyboard::processArrowKeys(int key, int x, int y) {

    // process key strokes
    if (key == GLUT_KEY_RIGHT) {
        keyRight = true;
        keyLeft = false;
        keyUp = false;
        keyDown = false;
    }
    else if (key == GLUT_KEY_LEFT) {
        keyRight = false;
        keyLeft = true;
        keyUp = false;
        keyDown = false;
    }
    else if (key == GLUT_KEY_UP) {
        keyRight = false;
        keyLeft = false;
        keyUp = true;
        keyDown = false;
    }
    else if (key == GLUT_KEY_DOWN) {
        keyRight = false;
        keyLeft = false;
        keyUp = false;
        keyDown = true;
    }

}

}; 

main.cpp

#include "inputs.h"

Keyboard keyboard;

...

int main(int argc, char **argv) {

...

// callbacks
glutDisplayFunc(displayWindow);
glutReshapeFunc(reshapeWindow);
glutIdleFunc(updateScene);
glutSpecialFunc(&keyboard.processArrowKeys); // compiler error: '&': illegal operation on bound member function expression
glutMouseFunc(mouseButton);
glutMotionFunc(mouseMove);

glutMainLoop();

return 0;
}

Any idea how to solve this compiler error?

Upvotes: 1

Views: 662

Answers (1)

Yakov Galka
Yakov Galka

Reputation: 72469

You can't do that directly because member functions have an implicit this pointer which has to be passed somehow through the call-chain. Instead you create an intermediary function that will forward the call to the right place:

void processArrowKeys(int key, int x, int y) {
    keyboard.processArrowKeys(key, x, y);
}

int main() {
    // ...
    glutSpecialFunc(processArrowKeys);
    // ...
}

keyboard in your code appears to be global so it is going to work. If you ever want to have a non-global state, then you will have to use a user-data pointer that some GLUT implementations support as an extension (including FreeGLUT and OpenGLUT):

void processArrowKeys(int key, int x, int y) {
    Keyboard *k = (Keyboard*)glutGetWindowData();
    k->processArrowKeys(key, x, y);
}

int main() {
    // ...
    glutSpecialFunc(processArrowKeys);
    glutSetWindowData(&keyboard);
    // ...
}

Upvotes: 2

Related Questions