OpenGL-Programmierung in C++ -> OO

Davicito

Erfahrenes Mitglied
Hallo, ich hab schon mal ein Game in C mit OpenGl (Glut) programmiert und würde das gleiche Game nun einmal Objektorientiert, in C++, programmieren.

Codeausschnitte von C:
Java:
//Die Fenster-Dimension (Sichtweite etc.)
void reshape (int w, int h){
   glViewport(0, 0, (GLsizei) w, (GLsizei) h); 
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 80.0);
   glMatrixMode(GL_MODELVIEW);
}

//Zeichnet die Objekte
void display()
{
	glClearColor(0.0,0.0,0.0,0.0);
	glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // setzt Bildschirmspeicher zurück um neues Bild zu zeichnen.
	
	glMatrixMode(GL_MODELVIEW); 
	glLoadIdentity();  
	gluLookAt(ex+bx, ey+by, ez+bz, center_x + bx, center_y + by, center_z + bz, 0.0, 1.0, -0.1);
...

}

//Tastatur-Event
void keyboard(unsigned char key, int x, int y)
{
     switch(key)
     {
         ..... 
     }
}

//Wiederhold die Endlosschleife (Game loop) für die game animation.
void Timer(int wert)
{
    glutPostRedisplay();
    glutTimerFunc(25, Timer, 0);
}

//Öffnet ein OpenGL-Fenster und Triggert das Spiel durch eine Endlosschleife an
int main(int argc, char** argv){
	glutInitWindowSize(1024,768);  // legt die Fenstergröße fest  (muss vor glutInit(&argc, argv); stehen)
	glutInitWindowPosition(200,100);   // legt die Fensterposition fest  (muss vor glutInit(&argc, argv); stehen)	
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); 	
	glutInit(&argc, argv);        //Bestandteil jedes GLUT-OP-GL-Progr. - initialisiert den Zustandsautomaten von GLUT

	glutCreateWindow("Cubo - Nivel 1");  // Öffnet ein Animationsfenster und setzt eine Fensterüberschrift in das Animationsfenster
    init();
    
	/* CallBack-Funktionen, die wärend der gesamten Animation durch Evebts (Mausklick, nichts passieren, Fensterumgestaltung, etc.) mit hilfe der glutmainLoop()
	am leben gehalten werden. CallBack-Funktionen stehen immer vor der glutMainLoop(); */
	glutDisplayFunc(display);      // Bildschirmaufruf, zum Darstellen von Bildern/Animationen durch Bildschirm-Funktion Display vor dem Hauptprogrammm.	
    glutReshapeFunc(reshape);
    glutKeyboardFunc(keyboard);
	glutTimerFunc(25, Timer, 0);   // Sogt dafür, das die Timerfunktion den Quader zum kippen bringt, falls Richtungstaste gedrückt wurde. 
    glutMainLoop();                // Endlosschleife und muss bei jedem OpenGL-Programm am Ende der Main-Funktion/Hauptprogramm stehen.

	return 0;    
}

...so als Spagetti-Code, ist das machbar. Möchte das jetzt aber ein bisschen in Klassen aufteilen, um das Ganze übersichtlicher zu gestalten.
Folgendes Problem habe ich. Ich möchte die Game-Schleife in der globalen Funktion "main()" so bei belassen und die Unterfunktionen in einer Klasse Darstellung unterbringen. Also die Funktionen display(), reshape(), timer() und keyboard(). Muss ich in main() einfach nur ne Instanz zur Klasse "Darstellung" erstellen, damit meine game loop die Aufrufparapmeter glutDisplayFunc(display), glutKeyboardFunc(keyboard) etc. akzeptieren?

Oder wie würdet Ihr vorgehen?
Ich freue mich über Anregungen, und danke Euch schon mal in Voraus.
Gruß, Davicito.
 
Nach langem hin und her habe ich natürlich auf Directx gesetzt. Mit Directx ist man nicht nur in der Lage OOP zu programmieren, man hat auch mehr Möglichkeiten, als in OpenGL ;-)

Beste Grüße!
 
Hallo Davicito,
dein ursprünglicher Post ist ja schon etwas älter, aber ich möchte trotzdem kurz darauf eingehen. Zuvor hätte ich aber noch 2 Fragen zum neuen Post:
Nach langem hin und her habe ich natürlich auf Directx gesetzt.
Wieso ist das natürlich?
Mit Directx ist man nicht nur in der Lage OOP zu programmieren, man hat auch mehr Möglichkeiten, als in OpenGL ;)
Wie kommst du darauf?

Nun aber zu deiner Originalfrage bezüglich der Klasse. Ein Blick in die Dokumentation von GLUT (http://users.informatik.uni-halle.de/~schenzel/ws02/opengl/spec3.pdf) zeigt, dass die Callback-Setter wie glutDisplayFunc(...) einen C-Funktionspointer als Argument erwarten. Die Dokumentation gibt folgende Signaturen an:
C++:
void glutDisplayFunc(void (*func)(void));
void glutReshapeFunc(void (*func)(int width, int height));
void glutKeyboardFunc(void (*func)(unsigned char key,
                                   int x, int y));

Du kannst jetzt prinzipiell beliebige Funktionen (bzw. Pointer auf beliebige Funktionen) die in ihrer Signatur passen überreichen. Eine Möglichkeit wäre, wie du ja schon angesprochen hast, eine Klasse "Darstellung" zu schreiben und darin deine Szene und die Render-Funktionen zu kapseln.
Muss ich in main() einfach nur ne Instanz zur Klasse "Darstellung" erstellen, damit meine game loop die Aufrufparapmeter glutDisplayFunc(display), glutKeyboardFunc(keyboard) etc. akzeptieren?
In dem Fall schon. Du musst dann eben statt der Pointer auf die "freien" Funktionen Pointer auf die Funktionen deiner Klasse übergeben.
Oder wie würdet Ihr vorgehen?
Wie du bei DirectX sicherlich schon gemerkt hast, geht in der Praxis die Kapselung in Klassen noch deutlich weiter. Ich würde sämtliche Zeichenroutinen in einer Render-Klasse kapseln. Diese bräuchte dann wiederum Pointer zu den aktiven Teilen des Spiels (z.B. Scene-Klasse, Service-Klasse, diverse Manager-Klassen, diverse Automaten, etc.). Die Frage ist im Umfang eines Forumposts leider nicht zu beantworten, die Engine-Architektur ist ein ganzer Wissenschaftszweig. :D
Ich persönlich habe in die Richtung bereits Game Programming Patterns von R. Nystrom und Game Engine Architecture von J. Gregory gelesen, und kann mit Sicherheit sagen dass da kein Unfug drinsteht. Das ist natürlich keine Kaufempfehlung, sondern nur eine Anregung falls dich das Thema interessiert. Es müssten auch nicht diese Bücher sein, es gibt wirklich viel Literatur dazu. ;)

Falls du die GLUT-Geschichte nochmal versuchen willst sind wir da.
Gruß Technipion
 
Zurück