VOICE-Homepage: http://de.os2voice.org |
Januar 2005
Inhaltsverzeichnis
|
Von Per Johansson © Januar 2005, Übersetzung: Jürgen Gaida |
OpenGL ist eine grafische Entwicklungsumgebung für nette Bildschirmschoner bis hin zu Maschinensimulationen. Mit OpenGL kann man bestehende Programme ausführen als auch eigene Programme erstellen. Dieser Artikel beschreibt, wie man OpenGL-Programme mit dem neuesten C++-Complier, Innotek GCC-3.2.2, erstellt. Es ist keine Einführung in OpenGL als solches, sondern beschreibt vielmehr, wie man vorhandenen Beispielcode und verfügbare Werkzeuge einsetzen kann um OpenGL-Programme zu erzeugen.
OS/2 Warp4 enthält einiges an Unterstützung für OpenGL, allerdings in der Version 1.0. Wenn ich mich recht erinnere, wurde dies nicht mehr in die eComStation übernommen. Für diesen Artikel verwende ich OpenGL 1.1. Dies ist die letzte (allerletzte?) Version für OS/2, für diesen Zweck aber ausreichend. Wenn Sie sich für neuere Entwicklungen interessieren, schauen Sie sich die MesaGL an (siehe unten). Ich werde zunächst folgende Werkzeuge einsetzen:
Unter eComStation 1.1 können sie die OpenGL 1.1-Laufzeitkomponenten (letztes Dateidatum ist 1997-10-06) von der Applikationen-CD installieren. Die Installation umfaßt einige DLL-Dateien, die in Ihr X:\OS2\DLL Verzeichnis kopiert werden müssen.
Das OS/2-Developer-Toolkit Version 4.52, Dateidatum 2001-10-04, wird mit der eComStation 1.1 ausgeliefert. Man installiert es von CD 2, "Developer Software". Es enthält die Bibliotheken glut.lib, libaux.lib und opengl.lib. Es enthält auch Quellcode und compilierte Programme. Unglücklicherweise basiert dies alles auf OpenGL 1.0 und läuft nicht unter OpenGL 1.1. Sie können aber den Quellcode verwenden und mit den OpenGL 1.1-Bibliotheken neu kompilieren. Darüber hinaus wurde das Toolkit mit IBM Visual Age C++ Version 3 erstellt, weshalb Sie manchmal den Code modifizieren müssen, um es mit GCC zu kompilieren.
Die Version 1.1 der OpenGL API (letztes Dateidatum 1997-10-06) finden Sie auf Hobbes. Entweder nehmen Sie das opengl.zip, das ist das Original von IBM, oder das opengl_gold_110.wpi, welches einige Modifikationen enthält, um es zum Beispiel mit dem Watcom-Kompiler zu verwenden. In jedem Fall müssen Sie eine Header-Datei, glut.h, ändern, damit Sie sie mit dem GCC kompilieren können. Tatsächlich habe ich eine etwas neuere, offizielle glut.h gesehen, welche die gleichen Änderungen enthielt wie ich sie vorgenommen habe, also scheint es richtig zu sein, diese Änderungen zu machen. Der Zweck der glut.h ist zum Beispiel Funktionen zur Fensterbehandlung bereitzustellen, weshalb Sie keine PM-Programmierung vornehmen müssen.
Um das Verzeichnis F:\oglgold\include statt F:\oglgold\include\gl einzubinden, änderte ich folgende Zeilen:
#include <gl.h> #include <glu.h>
zu:
#include <GL/gl.h> #include <GL/glu.h>
Ich habe ebenfalls 20 Funktionsparameter abgeändert, entfernte einen APIENTRY
(definiert als _System
, vollständig erweitert zu __attribute__((__system__)))
),
um folgenden Kompiler-Fehler zu vermeiden: "invalid type
modifier within pointer declarator". Ich weiß nicht worin das Problem besteht, aber meine Programme funktionieren ohne diese Modifikation tadellos.
extern void APIENTRY glutDisplayFunc (void (* APIENTRY)(void));
zu:
extern void APIENTRY glutDisplayFunc (void (*)(void));
Die überarbeitete glut.h erhalten Sie hier.
Sie erhalten den GCC von Innotek. Ich habe die beta 4 CSD 1 eingesetzt. Sie enthält eine Installationsroutine.
Dieser Linker ist wird standardmäßig für GCC 3.2.2 eingesetzt. Ich habe erfolglos ältere Alternativen versucht, IBM Linker 4.0 (oder LINK386), der mit OS/2, eComStation und dem Toolkit ausgeliefert wird, einzusetzen. Auch den IBM C/C++ 3.6.5-Linker habe ich getestet. Keiner hat funktioniert, jedenfalls nicht im C++-Modus. Den IBM Linker 5.0 (Dateidatum 2003-10-07) findet man nicht so leicht; Ich habe ihn auf der Warpzilla build Seite gefunden. Die Installation ist simpel. Entpacken Sie das Archiv und ergänzen sie den PATH- und LIBPATH-Eintrag um das BIN-Verzeichnis.
Während des Studiums der OpenGL-Programmierung haben wir das Buch
Hill: Computer Programming using Open GL, 2nd edition. ISBN 0-02-254856-8genutzt. Dieses Buch enthält viele Programmbeispiele, die auch auf der Webseite hinterlegt sind. Hier ist das erste Programm, FIG2_10.CPP mit meinen Änderungen:
/* #include <windows.h> entfernt #include <GL/Gl.h> entfernt, da es schon in der glut.h eingebunden ist #include <gl/glut.h> in #include <GL/glut.h> geändert, wegen UNIX Kompatibilität Der Rücksprung im Hauptprogramm von der Fehlerstelle auf int geändert, in Übereinstimmung mit ISO C/C++ (ein ausdrücklicher Rücksprungbefehl ist im Hauptprogramm nicht nötig) */ #define OS2 #define __IBMC__ /* #include <windows.h> // Wenn Ihr System dies benötigt #include <gl/Gl.h> #include <gl/glut.h> */ #include <GL/glut.h> //<<<<<<<<<<<<<<<<<<<<<<< myInit >>>>>>>>>>>>>>>>>>>> void myInit(void) { glClearColor(1.0,1.0,1.0,0.0); // setze weißen Hintergrund glColor3f(0.0f, 0.0f, 0.0f); // setze die Zeichnungsfarbe glPointSize(4.0); // ein Rasterpunkt sind 4 mal 4 Punkte glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0.0, 640.0, 0.0, 480.0); } //<<<<<<<<<<<<<<<<<<<<<<<< myDisplay >>>>>>>>>>>>>>>>> void myDisplay(void) { glClear(GL_COLOR_BUFFER_BIT); // den Fensterinhalt löschen glBegin(GL_POINTS); glVertex2i(100, 50); // zeichne 3 Punkte glVertex2i(100, 130); glVertex2i(150, 130); glEnd(); glFlush(); // erzeuge Ausgabe auf dem Bildschirm } //<<<<<<<<<<<<<<<<<<<<<<<< main >>>>>>>>>>>>>>>>>>>>>> int main(int argc, char** argv) { glutInit(&argc, argv); // das Toolkit initialisieren glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); // den Anzeigemodus setzen glutInitWindowSize(640,480); // Fenstergröße setzen glutInitWindowPosition(100, 150); // Fensterposition auf dem Bildschirm setzen glutCreateWindow("my first attempt"); // öffnen des Ausgabefensters glutDisplayFunc(myDisplay); // Register Neuzeichnungsfunktion myInit(); glutMainLoop(); // starte Endlosschleife }
Zum Kompilieren:
set path=F:\ILINK50\bin;%path% set beginlibpath=F:\ILINK50\bin g++ -Wall -ansi -pedantic -DOS2=1 -D__IBMC__=1 fig2_10.cpp -I\oglgold\INCLUDE -lglut -lopengl -L/oglgold/lib -Zomf -Zlinker /PM:PM
Starten Sie das Programm mit dem Befehl fig2_10. Sie werden ein Fenster mit drei Rasterpunkten sehen.
Dies ist schon etwas aufwendiger. Es zeigt ein (unrealistisches) Sonnensystem mit einer Sonne und drei sich mit verschiedenen Geschwindigkeiten umkreisenden Planeten. Der Beobachtungspunkt liegt in einem Winkel zur Rotationsebene, weshalb die Umlaufbahnen elliptisch erscheinen. Durch die eingesetzte perspektivische Betrachtung ändern sich die Größen der Planeten mit ihren Entfernungen. Die Planeten werden durch das Sonnenlicht beleuchtet, das Umgebungslicht läßt auch die dunklen Seiten sichtbar werden.
#include <GL/glut.h> #include <cstdlib> const GLfloat light_pos[] = {0, 0, 0, 1} , light_ambient[] = {0.1, 0.1, 0.1, 1} , light_diffuse[] = {1, 1, 1, 1} , light_specular[] = {1, 1, 1, 1} ; static int iteration = 0; static GLint slices = 30 , stacks = 30 ; void myCreateObjects(int iteration) { GLfloat white[] = {1, 1, 1, 1}, red[] = {1, 0, 0, 1}, green[] = {0, 1, 0, 1}, blue[] = {0, 1, 1, 1}, spec_exp = 100; glPushAttrib(GL_LIGHTING_BIT); glDisable(GL_LIGHTING); glColor3ub(255, 255, 0); glutSolidSphere(5, slices, stacks); glPopAttrib(); glMaterialfv(GL_FRONT, GL_AMBIENT, white); glMaterialfv(GL_FRONT, GL_SPECULAR, white); glMaterialf(GL_FRONT, GL_SHININESS, spec_exp); for (int i(1); i <=3; ++i) { glPushMatrix(); glRotatef((iteration) * 3/i, 0, 1, 0); glTranslatef(i * 10, 0, 0); switch (i) { case 1: glMaterialfv(GL_FRONT, GL_DIFFUSE, red) ; break ; case 2: glMaterialfv(GL_FRONT, GL_DIFFUSE, green) ; break ; case 3: glMaterialfv(GL_FRONT, GL_DIFFUSE, blue) ; break ; default: glMaterialfv(GL_FRONT, GL_DIFFUSE, white) ; } glutSolidSphere(2, slices, stacks); glPopMatrix(); } } void myKeyHandler(unsigned char key, int x, int y) { //während der Mauszeiger auf dem Fenster liegt if (key == 'q') { exit(0); } } void myDisplay() { } void myReshape(int w, int h) { GLint border = 10 ; GLint size_of_curve ; GLint low_left_x, low_left_y ; if (w > h) { if (h < 2 * border) { border = 0 ; } /* endif */ size_of_curve = h - 2 * border ; low_left_x = static_cast<GLint>(0.5 * (w - size_of_curve)) ; low_left_y = border ; } else { if (w < 2 * border) { border = 0 ; } /* endif */ size_of_curve = w - 2 * border ; low_left_x = border ; low_left_y = static_cast<GLint>(0.5 * (h - size_of_curve)) ; } /* endif */ glViewport(low_left_x, low_left_y, size_of_curve, size_of_curve) ; } void myMenuHandler(int id) { if (id == 1) { slices = 4 ; stacks = 4 ; } else { if (id == 2) { slices = 30 ; stacks = 30 ; } else { if (id == 3) { exit(0); } else { } /* endif */ } /* endif */ } /* endif */ } void myIdle() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); myCreateObjects(++iteration); glFlush(); glutSwapBuffers(); glutPostRedisplay(); } void myInit() { GLdouble aspect = 1; glClearColor(0.0, 0.0, 0.2, 0.0); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45, aspect, 50, -50); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0, 20, 80, 0, 0, 0, 0, 1, 0); glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glLightfv(GL_LIGHT0, GL_POSITION, light_pos); glShadeModel(GL_SMOOTH); glEnable(GL_DEPTH_TEST); } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE); glutInitWindowSize(640, 480); glutInitWindowPosition(100, 150); glutCreateWindow("Solar System"); glutKeyboardFunc(myKeyHandler); glutDisplayFunc(myDisplay); glutReshapeFunc(myReshape); glutCreateMenu(myMenuHandler); glutAddMenuEntry("Fast", 1); glutAddMenuEntry("Slow", 2); glutAddMenuEntry("Quit", 3); glutAttachMenu(GLUT_RIGHT_BUTTON); glutIdleFunc(myIdle); myInit(); glutMainLoop(); }
Zum Kompilieren:
g++ -ansi -pedantic -DOS2=1 -D__IBMC__=1 solar.cpp -I\oglgold\INCLUDE -lglut -lopengl -L/oglgold/lib -Zomf -Zlinker /PM:PM
Im Verzeichnis \OS2TK45\samples\opengl liegen einige Beispiele. Die meisten davon verwenden die abgelehnte
libaux Bibliothek, aber es gibt zwei GLUT-Programme, atlantis und test7 im
glutdemo Verzeichnis. Ich konnte sie kompilieren und ausführen lassen, nachdem ich die OpenGL #include
wie oben gezeigt abgeändert hatte,
obwohl test7 nicht ganz korrekt läuft - ich weiß bis heute nicht warum.
Ich hatte Schwierigkeiten mit dem Einstieg in OpenGL, weil ich es mit dem GCC machen wollte. Vielleicht hilft dieser Artikel anderen aufstrebenden Programmierern. Er zeigt, was man benötigt, um einfachen Beispielcode mit dem Innotek GCC Compiler zu kompilieren und auszuführen.
Daten und Quellen:
|
Artikelverzeichnis
editor@os2voice.org
< Vorherige Seite | Inhaltsverzeichnis | Nächste Seite >
VOICE-Homepage: http://de.os2voice.org