2010-08-28 8 views
25

Ich habe eine C++ - Klasse (myPixmap) erstellt, um die Arbeit von OpenGL GLUT-Toolkit kapseln. Die display() Mitgliedsfunktion der Klasse enthält den größten Teil des Codes, der zum Einrichten von GLUT erforderlich ist.Mit OpenGL GlutDisplayFunc innerhalb der Klasse


void myPixmap::display() 
{ 
    // open an OpenGL window if it hasn't already been opened 
    if (!openedWindow) 
    { 
     // command-line arguments to appease glut 
     char *argv[] = {"myPixmap"}; 
     int argc = 1; 
     glutInit(&argc, argv); 
     glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); 
     glutInitWindowSize(640, 480); 
     glutInitWindowPosition(30, 30); 
     glutCreateWindow("Experiment"); 
     glutDisplayFunc(draw); 
     glClearColor(0.9f, 0.9f, 0.9f, 0.0); 
     glClear(GL_COLOR_BUFFER_BIT); 
     glutMainLoop(); 

     openedWindow = true; 
    } 
} 

Die Funktionsanzeige zu glutDisplayFunc() geben wird, ist ein weiteres Mitglied Funktion der Klasse:


void myPixmap::draw(void) 
{ 
    glDrawPixels(m,n,GL_RGB,GL_UNSIGNED_BYTE, pixel); 
} 

jedoch gcc 4.2.1 auf Mac OS X 10.6.4 verweigert diesen Code zu kompilieren und behauptete, dass:

argument of type 'void (myPixmap::)()' does not match 'void (*)()'

gibt es eine Möglichkeit, die GLUT-Toolkit innerhalb einer Elementfunktion einer Klasse zu verwenden, oder muss ich rufe alle GLUT functio ns innerhalb der main Funktion des Programms?

Antwort

30

Das Problem besteht darin, dass ein Zeiger auf eine instanzgebundene Elementfunktion den Zeiger this enthalten muss. OpenGL ist eine C-API und weiß nichts über this Zeiger. Sie müssen eine statische Elementfunktion verwenden (die keine Instanz erfordert und daher keine this) und einige statische Datenelemente festlegen (um auf die Instanz zuzugreifen), um glutDisplayFunc zu verwenden.

class myPixmap 
{ 
private: 
    static myPixmap* currentInstance; 

    static void drawCallback() 
    { 
    currentInstance->draw(); 
    } 

    void setupDrawCallback() 
    { 
    currentInstance = this; 
    ::glutDisplayFunc(myPixmap::drawCallback); 
    } 
}; 

Sie können auch Probleme mit C-Bindung vs C++ Bindung haben, wobei in diesem Fall werden Sie mit extern "C" rumspielen müssen. Wenn dies der Fall ist, müssen Sie möglicherweise eine globale Funktion anstelle einer statischen Elementfunktion als Callback verwenden und haben , dass Anruf myPixmap::draw. Etwas wie:

class myPixmap 
{ 
public: 
    void draw(); 

private: 
    void setupDrawCallback(); 
}; 

myPixmap* g_CurrentInstance; 

extern "C" 
void drawCallback() 
{ 
    g_CurrentInstance->draw(); 
} 

void myPixmap::setupDrawCallback(); 
{ 
    ::g_CurrentInstance = this; 
    ::glutDisplayFunc(::drawCallback); 
} 

Mit allen diesen, versuchen, so wenig Änderungen wie möglich zu machen, da dies wirklich ein bisschen eine Flickschusterei ist w/OpenGL ist ein C-API zu beschäftigen.

Wenn Sie mehrere Instanzen möchten (ich glaube nicht, dass die meisten Leute mit GLUT mehrere Instanzen erstellen, aber vielleicht sind Sie das), müssen Sie eine Lösung mit std :: map finden, um die Instanz abzurufen:

static std::map<int, myPixmap> instanceMap; 

Wo Sie die intdie Instanz zu lösen bekommen würde, ich :)

FYI bin nicht sicher, Sie Funktionen, die auf diese Weise keine Parameter nehmen definieren sollten:

void some_function() { } 

nicht

void some_function(void) { } 
+0

Dank Merlyn; Das ist eine ausgezeichnete Lösung. Ich fand, dass ich in meinem Fall Probleme mit C-Verknüpfung vs C++ - Verknüpfung hatte, also musste ich eine globale Funktion verwenden, wie in Ihrem zweiten Beispielcode-Block gezeigt. Endlich konnte ich das Programm kompilieren. Ich benötige nicht mehrere Instanzen, daher ist dies für mich noch kein Problem. –

2

Merlyn Lösung funktioniert nicht für mich, also habe ich eine kleine Änderung von currentInstance bringen außerhalb Klasse und es hat funktioniert:

Class myPixmap; 
static myPixmap* currentInstance; 
Class myPixmap { 
... 
} 
+0

Alle anderen Optionen funktionierten nicht für mich, aber das lief perfekt. –

1

Ich hatte Schwierigkeiten, die richtige Antwort von Merlyn zu verstehen, also hier ist es die vereinfachte Version :

In myPixmap.h, ändert Anzeigefunktion statische Elementfunktion. Sollte arbeiten.

class myPixmap 
{ 
    //... 
    static void display(); 
    //... 
}; 
Verwandte Themen