Einführung OpenGL und GLUT WPF Spiele, Simulation und dynamische Systeme



Ähnliche Dokumente
Spiele, Simulation, dynamische Systeme

Grafikprogrammierung (Echtzeitrendering)

Kapitel 21: OpenGl 1

Computergrafik SS 2008 Oliver Vornberger. Kapitel 21: OpenGl

Programmierpraktikum 3D Computer Grafik

Lineargleichungssysteme: Additions-/ Subtraktionsverfahren

Erstellen von x-y-diagrammen in OpenOffice.calc

Erstellen einer Collage. Zuerst ein leeres Dokument erzeugen, auf dem alle anderen Bilder zusammengefügt werden sollen (über [Datei] > [Neu])

Datenbanken Kapitel 2

Matrix42. Use Case - Sicherung und Rücksicherung persönlicher Einstellungen über Personal Backup. Version September

Hinweise zum Übungsblatt Formatierung von Text:

Übungsstunde 5 zu Computergrafik 1

Handbuch. NAFI Online-Spezial. Kunden- / Datenverwaltung. 1. Auflage. (Stand: )

Grundlegende Darstellungsfunktionen

1 topologisches Sortieren

Zwischenablage (Bilder, Texte,...)

Windows. Workshop Internet-Explorer: Arbeiten mit Favoriten, Teil 1

Binäre Bäume. 1. Allgemeines. 2. Funktionsweise. 2.1 Eintragen

Mediator 9 - Lernprogramm

Vektoren mit GeoGebra

Ein Bild in den Text einfügen

FuxMedia Programm im Netzwerk einrichten am Beispiel von Windows 7

Anleitung über den Umgang mit Schildern

2. Im Admin Bereich drücken Sie bitte auf den Button Mediathek unter der Rubrik Erweiterungen.

Adobe Flash CS4»3D-Tool«

Digitalisieren im GeoBrowser und Exportieren als GPX-Datei

Punkt 1 bis 11: -Anmeldung bei Schlecker und 1-8 -Herunterladen der Software

Informatik Kurs Simulation. Hilfe für den Consideo Modeler

Einführung in die Programmierung

Verfasser: M. Krokowski, R. Dietrich Einzelteilzeichnung CATIA-Praktikum. Ableitung einer. Einzelteilzeichnung. mit CATIA P2 V5 R11

1 Vom Problem zum Programm

Zahlen auf einen Blick

1. Allgemein Speichern und Zwischenspeichern des Designs Auswahl der zu bearbeitenden Seite Text ergänzen Textgrösse ändern 3

Übung Bilder verschmelzen

Grafischer Tischeplan

Symbolbearbeitung mit EPLAN 5.60/5.70 DIC_***D.SYM

Zählen von Objekten einer bestimmten Klasse

QTTabBar Einrichtung, ein Tutorial

Erstellen einer GoTalk-Auflage

Lehrer: Einschreibemethoden

Produktschulung WinDachJournal

Filialpreisverwaltung

Funktionsbeschreibung Website-Generator

Satzhilfen Publisher Seite Einrichten

CAD-Gruppen. 1. Inhaltsverzeichnis. 1. Inhaltsverzeichnis 1 2. Was ist eine CAD-Gruppe? Erstellen von CAD-Gruppen 5

V o r w o r t. A n l e i t u n g

Animationen erstellen

Anwendungshinweise zur Anwendung der Soziometrie

1) Farbsteuergerät in der Nikobus-Software unter Modul zufügen hinzufügen.

Einführung in OpenGL. Einführung in OpenGL

teamsync Kurzanleitung

Bereich METIS (Texte im Internet) Zählmarkenrecherche

Handbuch ECDL 2003 Basic Modul 6: Präsentation Diagramm auf einer Folie erstellen

Professionelle Seminare im Bereich MS-Office

Aufgabe. - Beispiel "Fahrt durch Blutgefäße":

1 Mathematische Grundlagen

Tutorial Speichern. Jacqueline Roos - Riedstrasse 14, 8908 Hedingen, jroos@hispeed.ch -

inviu routes Installation und Erstellung einer ENAiKOON id

Informationsblatt Induktionsbeweis

Konzepte der Informatik

PhotoFiltre: Fotokorrektur schnell und einfach

Text Formatierung in Excel

Fallbeispiel: Eintragen einer Behandlung

6.2 Scan-Konvertierung (Scan Conversion)

1. Aktionen-Palette durch "Fenster /Aktionen ALT+F9" öffnen. 2. Anlegen eines neuen Set über "Neues Set..." (über das kleine Dreieck zu erreichen)

Globale Tastenkombinationen für Windows

Programme im Griff Was bringt Ihnen dieses Kapitel?

icartoon HANDBUCH COMPOSING

Novell Client. Anleitung. zur Verfügung gestellt durch: ZID Dezentrale Systeme. Februar ZID Dezentrale Systeme

OpenGL. (Open Graphic Library)

Handbuch Fischertechnik-Einzelteiltabelle V3.7.3

Leitfaden zur ersten Nutzung der R FOM Portable-Version für Windows (Version 1.0)

Schrittweise Anleitung zur Erstellung einer Angebotseite 1. In Ihrem Dashboard klicken Sie auf Neu anlegen, um eine neue Seite zu erstellen.

Primzahlen und RSA-Verschlüsselung

OECD Programme for International Student Assessment PISA Lösungen der Beispielaufgaben aus dem Mathematiktest. Deutschland

Domino Feldplaner 3.3

Die wichtigsten Funktionen im Umgang mit Windows. Achim Ermert Diese Unterlagen sind nur für den internen Gebrauch zu nutzen Seite 1

Arbeiten mit UMLed und Delphi

Dokumentation IBIS Monitor

Erwin Grüner

Gruppenrichtlinien und Softwareverteilung

Modellbildungssysteme: Pädagogische und didaktische Ziele

Papierverbrauch im Jahr 2000

4. BEZIEHUNGEN ZWISCHEN TABELLEN

Erweiterung der Aufgabe. Die Notenberechnung soll nicht nur für einen Schüler, sondern für bis zu 35 Schüler gehen:

Anwendertreffen 20./21. Juni

Handbuch ECDL 2003 Modul 2: Computermanagement und Dateiverwaltung Der Task-Manager

Windows 8.1. Grundkurs kompakt. Markus Krimm, Peter Wies 1. Ausgabe, Januar inkl. zusätzlichem Übungsanhang K-W81-G-UA

Alle Schlüssel-Karten (blaue Rückseite) werden den Schlüssel-Farben nach sortiert und in vier getrennte Stapel mit der Bildseite nach oben gelegt.

Hilfe Bearbeitung von Rahmenleistungsverzeichnissen

MORE Profile. Pass- und Lizenzverwaltungssystem. Stand: MORE Projects GmbH

Der Frosch als Vektorgrafik

Microsoft Access 2010 Navigationsformular (Musterlösung)

PowerPoint: Text. Text

Quadratische Gleichungen

Advanced Rendering Interior Szene

Die Statistiken von SiMedia

Modellierung und Programmierung 1

Schnelleinstieg in die (cs) AuftragPro

Transkript:

Einführung OpenGL und GLUT WPF Spiele, Simulation und dynamische Systeme bei Prof. Dr. Wolfgang Konen erstellt von: Sebastian Skalec, 11038991 Christian Fehmer, 11042419 Fachhochschule Köln Campus Gummersbach Allgemeine Informatik

Inhaltsverzeichnis 1 Einführung und Zielsetzung... 4 1.1 Einführung / Schematischer Aufbau...4 1.2 OpenGL... 4 1.3 GLUT...5 1.4 GLU... 5 1.5 GLX, WGL und Co... 5 1.6 Syntax... 6 2 Initialisierung von GLUT... 8 2.1 Einleitung...8 2.2 Initialisierung der GLUT-Basis... 8 2.3 Setzen des Displaymodes...8 2.4 Erstellen und Parametrisieren eines Fensters...10 2.5 Start der glutmainloop...10 2.6 Zusammenfassung... 10 3 Interaktion mit GLUT...11 3.1 Einführung... 11 3.2 Interaktion mit der Tastatur... 13 3.3 Interaktion mit der Maus...15 3.4 Spezielle Callback-Funktionen...16 3.5 Zusammenfassung... 17 4 Einführung in 3D...18 5 Zeichnen einfacher grafischer Primitive...19 5.1 Einführung und Definition...19 5.2 Zeichnen von Primitiven...19 5.3 Zusammenfassung... 25 6 Darstellung: Koordinaten und Matrizen...26 6.1 Einführung... 26 6.2 Koordinatensysteme...26 6.3 Arbeiten mit Matrizen...27 6.4 Befehle rund um Matrizenfunktionen...27 6.5 Zusammenfassung... 28 7 Modellierung, Manipulation des Modells... 29 7.1 Einführung... 29 7.2 Rotation...29 7.3 Translation... 30 7.4 Skalierung... 30 7.5 Freie Manipulation...31 7.6 Zusammenfassung... 31 8 Perspektive und Projektion (Kamera)...32 8.1 Einführung... 32 8.2 Orthographische Projektion... 32 8.3 Perspektivische Projektion...34 8.4 Hilfsfunktion GluLookAt... 35 8.5 Zusammenfassung... 35 9 Listing 2: Beispielprogramm...36

Abbildungsverzeichnis Abbildung 1: Schematische Darstellung von Hardware bis zur Anwendung [GCB06]... 4 Abbildung 2: Das Konzept des Double-Buffers [GCB06]...9 Abbildung 3: Funktionsweise glutmainloop [GCB06]...11 Abbildung 4: Achsenbereiche in OpenGL [DGLWIKI]... 18 Abbildung 5: Primitiven GL_POINTS...20 Abbildung 6: Primitiven GL_LINES... 21 Abbildung 7: Primitiven GL_LINE_STRIP...21 Abbildung 8: Primitiven GL_LINE_LOOP... 22 Abbildung 9: Primitiven GL_TRIANGLES... 22 Abbildung 10: Primitiven GL_TRIANGLE_STRIP...23 Abbildung 11: Primitiven GL_TRIANGLE_FAN...24 Abbildung 12: Primitiven GL_QUADS...24 Abbildung 13: Primitiven GL_QUAD_STRIP... 25 Abbildung 14: Primitiven GL_POLYGON...25 Abbildung 15: Koordinatenumwandlung von Model nach Screen [rbapg93]... 26 Abbildung 16: Rotation des Modells [rbapg93]...29 Abbildung 17: Translation des Modells [rbapg93]... 30 Abbildung 18: Skalierung des Modells [rbapg93]... 31 Abbildung 19: Orthografische Projektion [rbapg93]... 33 Abbildung 20: Orthographische Darstellung von Quadraten [DGLWIKI]...33 Abbildung 21: Perspektivische Projektion [rbapg93]... 34 Abbildung 22: Perspektivische Darstellung von Quadraten [DGLWIKI]... 35 Tabellenverzeichnis Tabelle 1: Übersicht betriebsystemspezifischer Bibliotheken... 6 Tabelle 2: Präfixe der verwendeten Bibliotheken... 6 Tabelle 3: Anzahl der Parameter und Beispiele der Aufrufe... 6 Tabelle 4: Zuordnung der Kürzel für Datentypen... 7 Tabelle 5: Bedeutung einiger DisplayMode Konstanten...8 Tabelle 6: Übersicht der GLUT Events und Callback-Funktionen... 12 Tabelle 7: GLUT Keycodes für spezielle Tastatureingaben... 14 Tabelle 8: OpenGL-Befehle in einem Primitiven-Block...19

1 Einführung und Zielsetzung OpenGL/GLUT 1 Einführung und Zielsetzung 1.1 Einführung / Schematischer Aufbau Abbildung 1: Schematische Darstellung von Hardware bis zur Anwendung [GCB06] 1.2 OpenGL OpenGL(Open Graphics Library) ist eine plattformunabhängige API zur Entwicklung von 3D- Computergrafik.es enthält über 250 Befehle die eine Darstellung von komplexer 3D -Szenarien in Echtzeit ermöglicht. OpenGL hat allerdings kein Bezug zum der eigentlichen grafischen Oberfläche des Systems. So können mit OpenGL weder Fenster gezeichnet noch Benutzereingaben verarbeitet werden. Geschichte OpenGL basiert auf dem von Silicon Graphics (SGI) entwickelten IRIS GL. Der OpenGL-Standard wird vom OpenGL ARB (Architecture Review Board) festgelegt. Das ARB existiert seit 1992 und besteht aus einer Reihe von Firmen. Stimmberechtigte Mitglieder sind die Firmen 3DLabs, Apple, ATI, Dell, Intel, IBM, Nvidia, SGI und SUN. Microsoft hat als eines der Gründungsmitglieder das ARB im März 2003 verlassen. Architektur OpenGL wurde als Zustandsautomat entworfen, der nicht bei jedem Funktionsaufruf alle benötigten Parameter erhält, sondern so lange die gesetzten Werte verwendet, bis die entsprechenden Zustände Sebastian Skalec, Christian Fehmer Seite 4 / 45

1.2 OpenGL OpenGL/GLUT geändert werden. Auf diese Weise muss man zum Beispiel nicht für jeden Vertex die gewünschte Farbe mitteilen, sondern setzt einmalig eine Farbe, woraufhin alle folgenden Vertices in dieser Farbe dargestellt werden. Auf dieselbe Weise kann man global Lichtquellen an- oder ausschalten und viele weitere Zustände setzen. Der Grund für dieses Design ist, dass fast jede Änderung des Zeichenmodus aufwändige Reorganisationen der Rendering-Pipeline nach sich zieht, daher vermeidet man diese lieber, so lange es sinnvoll möglich ist. Auch wäre es für den Programmierer ermüdend, dutzende Parameter immer wieder neu anzugeben. Oft können viele tausend Vertices bearbeitet werden, bevor wieder ein Zustand geändert werden muss, während manche Zustände sogar nie geändert werden. Beispielsweise bleiben die Lichtquellen meistens für alle Objekte einer Szene die gleichen. Viele Zustände werden zumindest für die Dauer des Renderns eines kompletten Objekts beibehalten, zum Beispiel wird ein Auto komplett um einen bestimmten Vektor verschoben und nicht in seine Einzelteile zerlegt und diese einzeln verschoben. 1.3 GLUT Das OpenGL Utility Toolkit oder auch kurz (GLUT) genannt ermöglicht es Aufgaben plattformunabhängig zu erledigen, wie die Erstellung von Fenstern oder Tastaturein- und -ausgaben. Daneben sind einige Funktionen zum Zeichnen einfacher geometrischer Objekte wie Würfel,Zylinder,Kugel vorhanden. GLUT wird seit geraumer Zeit nicht mehr weiterentwickelt, was dazu führte, dass viele Programmierer auf Alternativen wie das kompatible FreeGLUT wechselten. 1.4 GLU Die OpenGL Utility Libtary (GLU) ist eine Grafikbibliothek, welche auf OpenGL aufsetzt und höhere Grafikfunktionen bietet. Zum Beispiel eine Hilfsfunktion für Perspektive. 1.5 GLX, WGL und Co Hierbei handelt es sich um betriebssystemspezifische Anbindungen, die die Verbindung zwischen dem zu Grunde liegenden Betriebssystem und den OpenGL Funktionen liefert. Eine Übersicht zeigt Tabelle 1. Sebastian Skalec, Christian Fehmer Seite 5 / 45

1.5 GLX, WGL und Co OpenGL/GLUT Bibliothek GLX OpenGL Extension for X Window System WGL Windows Graphics Library AGL PGL Betriebsystem X Window System (Linux/Unix) Microsoft Windows MacOS OS/2 Warp Tabelle 1: Übersicht betriebsystemspezifischer Bibliotheken 1.6 Syntax [Präfix]Funktionsname[Anzahl][Datentyp]{Vektor (...) Präfixe Alle Befehle lassen sich anhand ihres Präfixes ihrer Bibliothek zuordnen. gl glu glut Präfix Bibliothek Open Graphics Library (OpenGL) OpenGL Utilities OpenGL Utility Toolkit Tabelle 2: Präfixe der verwendeten Bibliotheken Anzahl die Anzahl gibt die Anzahl der Parameter an. Beispiele: Anzahl 2 fnkt2(x, y) 3 fnkt3(x, y, z) 4 fnkt4(x, y, z, w) Beispiel Tabelle 3: Anzahl der Parameter und Beispiele der Aufrufe Sebastian Skalec, Christian Fehmer Seite 6 / 45

1.6 Syntax OpenGL/GLUT Datentyp b ub s us i ui f d Datentyp Beschreibung byte unsigned byte short unsigned shorh integer unsigned integer float double Tabelle 4: Zuordnung der Kürzel für Datentypen Vektor Vektor gibt an, ob die zu übergebenden Parameter in skalarer oder vektorieller Form geschiet. In der skalaren Form würden zum Beispiel 3 Floatwerte übergeben: glcolor3f(0.3,0.4,0.8); Dies entspricht folgender vektorieller Form: float arg= {0.3,0.4,0.8; glcolor3fv(arg); Sebastian Skalec, Christian Fehmer Seite 7 / 45

2 Initialisierung von GLUT OpenGL/GLUT 2 Initialisierung von GLUT 2.1 Einleitung Im diesem Kapitel erstellen wir ein Grundgerüst für ein OpenGL-Programm. 2.2 Initialisierung der GLUT-Basis Die Initialisierung der GLUT-Basis wird mit dem Befehl glutinit() aufgerufen. void glutinit(int* argcp, char** argv) Der Funktion wird ein Zeiger auf die Anzahl der Übergabeparameter (&argc) sowie das Array mit den Übergabeparameter selbst. Die Funktion glutinit filtert alle GLUT-relevanten Parameter raus und ändert somit argc und argv. 2.3 Setzen des Displaymodes Mit dem Befehl glutinitdisplaymode() werden Optionen des Fensters gesetzt. void glutinitdisplaymode(unsigned int mode) Die nachfolgende Tabelle zeigt mögliche Werte für mode und deren Bedeutung. Grundsätzlich können mehrere Werte in einer Oder-Verknüpfung angegeben werden. Beispiel: glutinitdisplaymode(glut_rgba GLUT_DOUBLE GLUT_DEPTH ); GLUT_RGBA GLUT_SINGLE GLUT_DOUBLE GLUT_DEPTH Mode Bedeutung Farbdarstellung als Quartett aus Rot, Grün, Blau und dem Alpha-Wert, welcher für die Deckkraft/Transparenz steht. Nutzung eines single buffered Fensters (s.u.) Nutzung eines double buffered Fensters (s.u.) Nutzung des Tiefenpuffers Tabelle 5: Bedeutung einiger DisplayMode Konstanten Sebastian Skalec, Christian Fehmer Seite 8 / 45

2.3 Setzen des Displaymodes OpenGL/GLUT Single- und Double-Buffer Beim Single-Buffer zeichnen die OpenGL-Befehle direkt in den Teil des Grafikkartenspeichers, der zyklisch an den Monitor zur Ausgabe gesendet wird. Hierbei kann es dazu kommen, dass die Zeichenoperation noch nicht fertig ist und das halb fertige Ergebnis auf dem Monitor zu erkennen ist. Der Anwender nimmt dieses als Flackern wahr. Abhilfe schafft hier das Prinzip des Double-Buffers. Hierzu wird im Grafikkartenspeicher ein zweiter Buffer mit der gleichen Größe angelegt. Alle Grafikfunktionen arbeiten solange auf dem einem Buffer und der Monitor bekommt den Inhalt des nicht aktiven Buffers bis die Zuordnung aktiv vom Programm getauscht wird. Der Buffer auf dem geschrieben wird, wird auch Back-Buffer und der Buffer der auf den Monitor angezeigt wird Front-Buffer genannt. Ein Tauschen der Buffer kann man explizit mit dem Befehl glutswapbuffers() auslösen. void glutswapbuffers() Abbildung 2: Das Konzept des Double-Buffers [GCB06] Sebastian Skalec, Christian Fehmer Seite 9 / 45

2.4 Erstellen und Parametrisieren eines Fensters OpenGL/GLUT 2.4 Erstellen und Parametrisieren eines Fensters Zunächst müssen Größe und Position des Fensters festgelegt werden: void glutinitwindowsize(int width, int height) void glutinitwindowposition(int x, int y) Mit glutinitwindowsize wird die Höhe und Breite des Fensters angegeben. GlutInitWindowPosition hingegen legt die Startposition auf dem Bildschirm fest. Nachdem diese Informationen gesetzt sind, kann das Fenster erstellt werden: int glutcreatewindow(char* title) Dieser Befehl veranlasst die betriebssystemspezifische Bibliothek dazu mit dem Windowsystem eine Session für ein Fenster auszuhandeln und dieses zu zeichnen. Die Rückgabe der Funktion ist ein Integerwert, welches die FensterID innerhalb des Programms entspricht. Mit dem Parameter Title kann der Fenstertitel angegeben werden. 2.5 Start der glutmainloop Nach allen Initialisierungen von GLUT und dem eigenen Programm wird am Ende der Main der Befehl glutmainloop() aufgerufen. Die genaue Arbeitsweise erläutert das nächste Kapitel. 2.6 Zusammenfassung Bevor man mit OpenGL zeichnen oder visualisieren kann, muss zunächst eine Zeichenfläche geschaffen werden. Dieses übernimmt GLUT im Zusammenspiel mit der betriebssystemspezifischen Erweiterung wie zum Beispiel WGL. Ganz am Ende der Main muss dabei der Aufruf glutmainloop() erfolgen, welches eine Art Endlosschleife ist welche ermöglicht, dass Fenster und Zeichenfläche weiterhin zu sehen sind. Listing 1 zeigt das Grundgerüst eines OpenGL-Programmes: int main(int argc, char **argv){ glutinit(&argc, argv); glutinitdisplaymode(glut_depth GLUT_DOUBLE GLUT_RGBA); glutinitwindowposition(100,100); glutinitwindowsize(640,360); glutcreatewindow("titel"); glutmainloop(); return(0); Sebastian Skalec, Christian Fehmer Seite 10 / 45

3 Interaktion mit GLUT OpenGL/GLUT 3 Interaktion mit GLUT 3.1 Einführung Kennzeichnend für ein GLUT-Programm ist der Aufruf glutmainloop() am Ende der Main- Funktion. Dieser Aufruf startet die interne MainLoop des GLUT. Zentrale Aufgabe dieser Funktion ist die so genannte Event-Verarbeitung. Ein Event kann zum Beispiel das Drücken einer Taste ober das Bewegen der Maus sein. Die eigentliche Verarbeitung dieses Events wird nicht von GLUT übernommen, sondern mit dem Mechanismus des Callbacks wieder in der eigenen Programm geleitet. Daher nennt man die eigenen Funktionen, die durch die Event-Verarbeitung von Glut aufgerufen werden Callback-Funktionen oder auch Event-Handler. Die Signatur der Funktion ist je nach zu verarbeitenden Element anders. Tabelle 6 zeigt die GLUT-Events, die Funktionen zum registrieren und die Signatur der Callback-Funktion. Abbildung 3: Funktionsweise glutmainloop [GCB06] Sebastian Skalec, Christian Fehmer Seite 11 / 45

3.1Einführung Einführung OpenGL/GLUT Event Beschreibung Registrierung Signatur Parameter Keybord Drücken einer Taste glutkeyboardfunc KeyboadUp Loslassen einer Taste glutkeybordupfunc Special Drücken einer Spezialtaste glutspecialfunc SpecialUp Loslassen einer Spezialtaste glutspecialupfunx Void fnkt(unsigned char key, int x, int y) Void fnkt(int key, int x, int y) Key: Tastencode x,y: Position der Maus Key: Tastencode x,y: Position der Maus Mouse Drücken der Maustasten glutmousefunc Void fnkt(int button, int state, int x, int y) Button: Maustaste State: Gedrückt ja/nein x,y: Position der Maus Motion Bewegen der Maus bei gedrückter Taste PassiveMotion Bewegen der Maus ohne gedrückter Taste glutmotionfunc glutpassivemotionfunc Display Szene muss neu gezeichnet werden GlutDisplayFunc Idle Nichts ist passiert GlutIdleFunc Reshape Fenstergröße wurde geändert GlutReshapeFunc Void fnkt(int x, int y) Void fnkt() x,y: Position der Maus Tabelle 6: Übersicht der GLUT Events und Callback-Funktionen Sebastian Skalec, Christian Fehmer Seite 12 / 45

3.2 Interaktion mit der Tastatur OpenGL/GLUT 3.2 Interaktion mit der Tastatur Bei Tastatureingaben unterscheidet man 2 Arten von Tasten, die Normalen Tasten, also Ziffern und Buchstaben und die Speziellen Tasten, wie zum Beispiel die Pfeil- oder Funktionstasten. Normale Tastatureingaben Callback-Funktionen für normale Tastatureingaben registriert man mit glutkeyboardfunc(mykeyboard); glutkeyboardupfunc(mykeyboardup); wobei Keyboard beim Drücken der Taste und KeyboardUp beim Loslassen der Taste aufgerufen wird. Die Signatur der Callback-Funktion ist bei beiden Events gleich: void mykeyboard(unsigned char key, int x, int y){.. Key beinhaltet den Tastatur-Code der Taste die das Event ausgelößt hat. X und Y geben die Position der Maus im Fenster an, als die Taste gedrückt wurde. Die Tastatur-Codes entsprechen den normalen ASCII-Zahlen. Die Implementierung einer Callback-Funktion könnte so aussehen: void mykeyboard(unsigned char key, int x, int y){ switch(key){ case 'q': exit(0); break; case 'x': dosth(); break; ; Spezielle Tastatureingaben Spezielle Tastatureingaben betreffen spezielle Tasten wie zum Beispiel Pfeil- und Funktionstasten. Eine Callback-Funktion für dieses Event wird registriert mit glutspecialfunc(myspecial); glutspecialfunc(myspecialup); Sebastian Skalec, Christian Fehmer Seite 13 / 45

3.2 Interaktion mit der Tastatur OpenGL/GLUT wobei Special wieder beim Drücken der Taste und SpecialUp beim Loslassen der Taste aufgerufen wird. Die Signatur der Callback-Funktion ist bei beiden Events gleich: void myspecial(int key, int x, int y){.. Der Parameter key ist diesmal ein int-wert. Mit Hilfe der Tastenzuordnung in Tabelle 7 kann die Callbackfunktion je nach Taste anders reagieren. Es folgt wieder eine kleine Beispielimplementierung: void myspecial(in key, int x, int y){ switch(key){ case GLUT_KEY_UO: moveup(); break; case GLUT_KEY_F1: printhelp(); break; ; GLUT_KEY_F1 GLUT_KEY_F3 GLUT_KEY_F5 GLUT_KEY_F7 GLUT_KEY_F9 GLUT_KEY_F11 GLUT_KEY_LEFT GLUT_KEY_UP GLUT_KEY_PAGE_UP GLUT_KEY_END GLUT_KEY_INSERT GLUT_KEY_F2 GLUT_KEY_F4 GLUT_KEY_F6 GLUT_KEY_F8 GLUT_KEY_F10 GLUT_KEY_F12 GLUT_KEY_RIGHT GLUT_KEY_DOWN GLUT_KEY_PAGE_DOWN GLUT_KEY_HOME Tabelle 7: GLUT Keycodes für spezielle Tastatureingaben Sebastian Skalec, Christian Fehmer Seite 14 / 45

3.3 Interaktion mit der Maus OpenGL/GLUT 3.3 Interaktion mit der Maus Bei der Interaktion mit der Maus unterscheidet GLUT zunächst 2 Events, auf der einen Seite das Drücken von Maustasten und auf der anderen die Bewegung der Maus. Drücken der Maustasten Die Registrierung der Callback-Funktion für die Maustasten geschieht mit dem Befehl glutmousefunc(mymouse); Die zugehörige Callback-Funktion mymouse hat folgende Signatur: void mymouse(int button, int state, int x, int y){.. Button gibt an, welcher Mausbutton gedrückt wurde. Hierfür verwendet man die GLUT-Konstanten GLUT_LEFT_BUTTON für den linken, GLUT_MIDDLE_BUTTON für den mittleren und GLUT_RIGHT_BUTTON für den rechten Mausknopf. State steht für den Zustand des Knopfes, er ist entweder GLUT_UP für nicht gedrückt oder GLUT_DOWN für gedrückt. X und Y sind wieder die Position der Maus innerhalb des Fensters. Beispiel für eine Callback-Funktion für das Event Mouse: void mymouse(int button, int state, int x, int y){ if(button==glut_right_button && state== GLUT_UP){ printhelppopupat(x,y); Bewegung der Maus Bei dem Event Mausbewegung wird wieder in 2 verschiedene Events unterteilt. Das Bewegen der Maus mit und das bewegen der Maus ohne das eine der Maustasten gedrückt ist. Die Registrerungs- Funktionen dafür sind glutmotionfunc(mymotion); glutpassivemotionfunc(mypassivemotion); Sebastian Skalec, Christian Fehmer Seite 15 / 45

3.3 Interaktion mit der Maus OpenGL/GLUT Die Signatur der entsprechenden Callback-Funktionen sind wieder identisch: void mymotion(int x, int y){.. Bei Motion und PassiveMotion wird nur die Position der Maus übergeben. Es folgt wieder eine kleine Beispielimplementierung der Callback-Funktion: void mymotion(int x, int y){ setfocus(x,y); 3.4 Spezielle Callback-Funktionen Wenn die GlutMainLoop() am ende der Main gestartet wird, läuft diese bis zum Programmabbruch weiter. Deshalb brauchen wir spezielle Callback-Funktionen, in denen wir Teile unseres Programms, wie zum Beispiel das Zeichnen von Objekten aufrufen können. Hierzu bietet GLUT spezielle Callback-Funktionen wie Idle, Display und Reshape. Idle-Event Das Idle-Event wird immer dann aufgerufen, wenn in einem Durchgang der GlutMainLoop kein anderes Event aufgetreten ist. Diese Event eignet sich sehr gut um eigene Programmteile anzusprechen, die periodisch wiederholt werden sollen. Die Registrierung der Funktion geschieht über glutidlefunc(myidle); und die Signatur der Callback-Funktion ist void myidle(){.. Display-Event Das Display-Event wird immer dann aufgerufen, wenn ein Neuzeichnen der Szene nötig ist. Dies kann zum Beispiel explizit mit dem Aufruf glutpostredisplay(); erzwungen werden. Hier registriert Sebastian Skalec, Christian Fehmer Seite 16 / 45

3.4 Spezielle Callback-Funktionen OpenGL/GLUT man typischerweise die Zeichenfunktion. Die Registrierung der Funktion geschieht über glutdisplayfunc(mydisplay); und die Signatur der Callback-Funktion ist void mydisplay(){.. Reshape-Event Das Reshape-Event wird aufgerufen, wenn der Benutzer die Größe des Fensters geändert hat. Bei diesem Event müssen typischerweise die internen Variablen für die Größe der Zeichenfläche sowie des Größenverhältnisses geändert werden und i.d.r. wird das Bild neu gezeichnet. Die Registrierung der Funktion geschieht über glutreshapefunc(myreshape); und die Signatur der Callback-Funktion ist void myreshape(){.. 3.5 Zusammenfassung Für die Interaktion mit dem Programm werden eigene Funktiononen, die das Event behandeln sollen und daher Event-Handler oder Callback-Funktionen heißen, durch Registrierung-Funktionen bei GLUT angemeldet. GLUT selbst ruft diese Funktionen beim Eintritt des Events in der GlutMainLoop mit den passenden Parametern auf. Nach der Abarbeitung der Callback-Funktion wird wieder zurück in die GlutMainLoop gesprungen. Die eigenen Programmteile zum Beispiel zur Steuerung der Simulation werden über das gleiche Prinzip aufgerufen. Hier bedient man sich spezieller Callback-Funktionen wie Idle, Display oder Reshape. Diese Funktionen führen nach Abarbeitung auch wieder in die GlutMainLoop zurück. Dieses kann durch den Aufruf exit(0) verhindert werden, zum Beispiel wenn das Programm beendet werden soll. Sebastian Skalec, Christian Fehmer Seite 17 / 45

4 Einführung in 3D OpenGL/GLUT 4 Einführung in 3D Abbildung 4: Achsenbereiche in OpenGL [DGLWIKI] In OpenGL verteilen sich die Achsen wie in Abbildung 4. Zu beachten ist die Besonderheit, das die Z-Achse im nach hinten kleiner wird. Sebastian Skalec, Christian Fehmer Seite 18 / 45

5 Zeichnen einfacher grafischer Primitive OpenGL/GLUT 5 Zeichnen einfacher grafischer Primitive 5.1 Einführung und Definition Modelle, die in einem grafischen System dargestellt werden sollen, bestehen aus komplexen Objekten. Diese komplexen Objekte bestehen wiederum aus einfachen Bestandteilen, diese nennt man Primitive. In OpenGL unterscheidet man Punkte, Strecken und Polygone, wobei Polygone aus mehreren Strecken bestehen, die wiederum die Verbindung zweier Punkte durch eine Gerade sind. Mit Hilfe von Polygonen ist es zunächst möglich, Oberflächen von Körpern zu beschreiben. 5.2 Zeichnen von Primitiven In OpenGL werden grafische Primitiven durch Angeben von (Eck-)Punkten definiert. Dieses geschieht in einem so genannten Block. Die Syntax hierfür ist: void glbegin(glenum mode):... void glend(); Ausprägungen von Mode und deren Bedeutung werden in Tabelle beschrieben. Innerhalb eines solchen Blockes sind nur wenige OpenGL-Befehle zulässig: glvertex glcolor glindex glnormal glmaterial gledgeflag glcalllist Befehl Beschreibung Koordinaten eines Eckpunktes Farbe setzen Farbindex setzen Normalvektor setzen Materialeigenschaften bestimmen Gehört die Kante zur Kontur des Objektes Aufruf von Darstellungslisten Tabelle 8: OpenGL-Befehle in einem Primitiven-Block Sebastian Skalec, Christian Fehmer Seite 19 / 45

5.2 Zeichnen von Primitiven OpenGL/GLUT Wir betrachten nun die Verschiedenen Modi für Primitiven anhand folgenden Beispieles im 2D: glbegin(mode); glvertex2i(2,2); glvertex2i(4,2); glvertex2i(6,2); glvertex2i(8,2); glvertex2i(2,4); glvertex2i(4,4); glvertex2i(6,4); glvertex2i(8,4); glend(); Es werden 8 Eckpunkte angegeben. Es folgt die Ausgabe der verschiedenen Modi (Quelle: [DGLWIKI] GL_Points Behandelt jeden Eckpunkt als einzelnen Punkt. Eckpunkt n definiert Punkt n, und N Punkte werden gerendert. Abbildung 5: Primitiven GL_POINTS Sebastian Skalec, Christian Fehmer Seite 20 / 45

5.2 Zeichnen von Primitiven OpenGL/GLUT GL_LINES Abbildung 6: Primitiven GL_LINES Behandelt jedes Eckpunkt-Paar als unabhängigen Linienabschnitt. Eckpunkte 2*n-1 und 2*n beschreiben Linie n. N/2 Linien werden gerendert. GL_LINE_STRIP Rendert eine Gruppe von miteinander verbundenen Liniensegmenten, beginnend beim ersten Eckpunkt bis zum letzten. Eckpunkte n und n+1 beschreiben dabei Linie n. N-1 Linien werden gerendert. Abbildung 7: Primitiven GL_LINE_STRIP GL_LINE_LOOP Rendert eine miteinander verbundene Gruppe von Linienabschnitten, beginnend beim ersten Eckpunkt und endend beim letzten, und dann wieder abschliessend zurück zum ersten. Eckpunkte n Sebastian Skalec, Christian Fehmer Seite 21 / 45

5.2 Zeichnen von Primitiven OpenGL/GLUT und n+1 definieren Linie n. Die letzte Linie wird jedoch durch die Eckpunkte N und 1 definiert. N Linien werden gerendert. Abbildung 8: Primitiven GL_LINE_LOOP GL_TRIANGLES Behandelt jedes Eckpunkt-Trio als unabhängiges Dreieck. Eckpunkte 3*n-2, 3*n-1 und 3*n beschreiben Dreieck n. N/3 Dreiecke werden gerendert. Eigenschaften: Alle Dreiecke bestehen aus jeweils 3 Vertices, die ausschließlich nur zu diesem Dreieck gehören. Abbildung 9: Primitiven GL_TRIANGLES Sebastian Skalec, Christian Fehmer Seite 22 / 45

5.2 Zeichnen von Primitiven OpenGL/GLUT GL_TRIANGLE_STRIP Rendert eine verbundene Gruppe von Dreiecken. Ein Dreieck wird für jeden Eckpunkt der nach den beiden ersten Eckpunkten definiert wird gerendert. Für ein ungerades n definieren die Eckpunkte n, n+1 und n+2 Dreieck n, für gerade ns definieren die Eckpunkte n+1, n und n+2 ein Dreieck. N-2 Dreiecke werden gerendert. Eigenschaften: Nacheinander erstellte Dreiecke haben eine gemeinsame Kante. Nacheinander erstellte Dreiecke benutzen 2 gemeinsame Vertices. Abbildung 10: Primitiven GL_TRIANGLE_STRIP GL_TRIANGLE_FAN Rendert eine verbundene Gruppe von Dreiecken. Ein Dreieck wird für jeden Eckpunkt gerendert der nach den ersten beiden definiert wird. Eckpunkte 1, n+1 und n+2 definieren Dreieck n. N-2 Dreiecke werden gerendert. Eigenschaften: Alle Dreiecke haben mindestens einen gemeinsamen Punkt (Vertex1). Nacheinander erstellte Dreiecke haben eine gemeinsame Kante. Nacheinander erstellte Dreiecke benutzen 2 gemeinsame Vertices. Sebastian Skalec, Christian Fehmer Seite 23 / 45

5.2 Zeichnen von Primitiven OpenGL/GLUT Abbildung 11: Primitiven GL_TRIANGLE_FAN GL_QUADS Behandelt jeweils vier Eckpunkte als unabhängiges Viereck. Eckpunkte 4*n-3, 4*n-2, 4*n-1 und 4*n beschreiben Viereck n. N/4 Vierecke werden gerendert. Eigenschaften: Alle Vierecke bestehen aus jeweils 4 Vertices, die ausschließlich nur zu diesem Viereck gehören. Abbildung 12: Primitiven GL_QUADS GL_QUAD_STRIP Rendert eine verbundene Gruppe von Vierecken. Ein Viereck wird wird für jedes nach den ersten beiden Eckpunkten übergebene Eckpunktepaar gerendert. Eckpunkte 2*n-1, 2*n, 2*n+2 und 2*n+1 beschreiben Viereck n. N/2-1 Vierecke werden gerendert. Es gilt allerdings zu beachten, das die Reihenfolge der Eckpunkte die genutzt werden um Vierecke aus einem Streifen zu generieren Sebastian Skalec, Christian Fehmer Seite 24 / 45

5.2 Zeichnen von Primitiven OpenGL/GLUT unterschiedlich ggü. der unabhängigen Konstruktion sind. Eigenschaften: Nacheinander erstellte Vierecke haben eine gemeinsame Kante. Nacheinander erstellte Vierecke benutzen 2 gemeinsame Vertices. Abbildung 13: Primitiven GL_QUAD_STRIP GL_POLYGON Rendert eine einzelnes, Polygon (=Vieleck). Eckpunkte 1 bis N definieren dieses Polygon. Abbildung 14: Primitiven GL_POLYGON 5.3 Zusammenfassung OpenGL bietet die Möglichkeit unterschiedliche Primitiven nur mit Hilfe der Eckpunkte zu zeichnen. Es ist nicht nötig, sich mit dem Verlauf der einzelnen Linien zu beschäftigen. Sebastian Skalec, Christian Fehmer Seite 25 / 45

6 Darstellung: Koordinaten und Matrizen OpenGL/GLUT 6 Darstellung: Koordinaten und Matrizen 6.1 Einführung OpenGL unterscheidet zwischen dem sogenannten Modelview und der Projektion. Im Modelview wird die Szene beschrieben und verändert (Translation, Rotation). Unabhängig davon ist die Projektion, welche die Art der Abbildung (orthographische-, perspektivische Projektion) beinhaltet. 6.2 Koordinatensysteme OpenGL unterscheidet bis zu fünf verschiedene Koordinatensysteme: Objektkoordinaten Weltkoordinaten oder Blickpunkkoordinaten Clippingkoordinaten normierte Projektionskoordinaten Bildschirmkoordinaten Das Zeichnen der Primitiven findet im Objektkoordinatensystem statt. Danach werden die Koordinaten stufenweise bis hin zu den Bildschirmkoordinaten umgewandelt. Siehe Abbildung YY Abbildung 15: Koordinatenumwandlung von Model nach Screen [rbapg93] Sebastian Skalec, Christian Fehmer Seite 26 / 45

6.3 Arbeiten mit Matrizen OpenGL/GLUT 6.3 Arbeiten mit Matrizen Die Parametrisierung der Umwandlung durch die oben genannten Koordinatensysteme wird über 3 Matrizen gesteuert. GL_MODELVIEW Matrix für Modellierungstransformationen wie Rotation, Skalierung oder Translation. Damit kann die Ausrichtung und die Position der Primitiven festgelegt werden. GL_PROJECTION In der Projektionsmatrix setzt man die Sicht auf die Szene. Hier legt man zum Beispiel die Art der Perspektive fest. Mehr dazu im nächsten Kapitel. GL_TEXTURE Parametrisierung von Texturen, wird in dieser Arbeit nicht weiter betrachtet. 6.4 Befehle rund um Matrizenfunktionen glmatrixmode(glenum mode) Auswahl einer der oben genannten Matrizen. Es kann immer nur eine Matrix aktiv sein. Nach dem Auswählen werden alle weiteren Befehle auf die aktuelle Matrix angewendet. Mode ist entweder GL_MODELVIEW, GL_PROJECTION oder GL_TEXTURE. glloadidentity() Laden der Einheitsmatrix, sie stellt sozusagen den Urzustand der Matrix da und hat die Form 0 0 0 0 0 0 0 E= 1 1 0 0 1 0 0 0 0 glpushmatrix() und glpopmatrix() Anstatt nur einer Matrix können für die 3 oben genannten Bereiche auch Matrizenstapel verwendet werden. Diese sind praktisch, wenn man nur ein Objekt manipulieren möchte ohne jedes Mal zur Grundmatrix zurückzukehren. glpushmatrix() legt die aktuelle Matrix auf den Stack und Sebastian Skalec, Christian Fehmer Seite 27 / 45

6.4 Befehle rund um Matrizenfunktionen OpenGL/GLUT glpopmatrix() ersetzt die aktuelle Matrix mit der obersten auf dem Stapel. Ein Beispiel für die Verwendung: Zeichnen von einem Würfel auf Position (3,4,5) und eines um 30 um Y rotierten Würfels auf Position (1,2,3). void zeichnewuerfel(){ glbegin(gl_quads); glvertex3f(-0.5, 0.5, 0.5); glvertex3f(-0.5,-0.5, 0.5); glvertex3f( 0.5,-0.5, 0.5); glvertex3f( 0.5, 0.5, 0.5); glend; glpushmatrix; gltranslatef(3,4,5); zeichnewuerfel(); glpopmatrix(); glpushmatrix(); gltranslatef(1,2,3); glrotatef(30,0,1,0); glscalef(2,2,2); zeichnewuerfel(); glpopmatrix(); 6.5 Zusammenfassung OpenGL nimmt uns die Umrechnung des Modells zur Perspektive und schließlich zu den Bildschirmkoordinaten ab. Wir müssen lediglich das Modell definieren und die Perspektive angeben. Dazu benutzt man die beiden Matrizen Modelview und Perspektive. Sebastian Skalec, Christian Fehmer Seite 28 / 45

7 Modellierung, Manipulation des Modells OpenGL/GLUT 7 Modellierung, Manipulation des Modells 7.1 Einführung In diesem Kapitel wird auf die Möglichkeiten der Manipulation der Modelview-Matrix eingegangen. Dazu muss vor dem Aufruf der unten vorgestellten Befehle die Modelview-Matrix geladen werden: glmatrixmode(gl_modelview); 7.2 Rotation Um das Modell (bzw. die aktuelle Modelview-Matrix) zu drehen nutzt man den Befehl void glrotate{f d (TYPE angle, TYPE x, TYPE y, TYPE z); Angle gibt an, um wieviel Grad rotiert werden soll. Es wird immer im mathematisch positiven Drehsinn gedreht, also gegen den Uhrzeigersinn. Die Parameter x,y und z geben die Rotationsachse in Form eines Vektors(x,y,z) vom derzeitigen Ursprung (0,0,0) an. Mathematisch wird eine Rotationsmatrix R gebildet, die mit der aktuellen Matrix M zu M ' =M R multipliziert wird. M' ersetzt dann die oberste Matrix auf dem Matrizenstapel. Abbildung 16: Rotation des Modells [rbapg93] Sebastian Skalec, Christian Fehmer Seite 29 / 45

7.3 Translation OpenGL/GLUT 7.3 Translation Der Befehl gltranslate verschiebt das Modell bzw. die aktuelle Modellmatrix. Die Syntax ist: void gltranslate{f d( TYPE x, TYPE y, TYPE z); x,y,z geben hierbei die Verschiebung auf den entsprechenden Achsen an. Mathematisch wird aus dem Verschiebungsvektor (x,y,z) eine Translationsmatrix T gebildet, die mit der aktuellen Matrix M zu M ' =M T multipliziert wird. M' ersetzt dann die oberste Matrix auf dem Matrizenstapel. 7.4 Skalierung Abbildung 17: Translation des Modells [rbapg93] Um das Modell zu skalieren nutzt man den Befehl void glscale{f d (TYPE x, TYPE y, TYPE z); x,y,z geben die Skalierung in die entsprechende Richtung an. Mathehatisch wird eine Skalierungsmatrix S bestimmt, die mit der aktuellen Matrix M zu M ' =M S multipliziert wird. M' ersetzt dann die oberste Matrix auf dem Matrizenstapel. Sebastian Skalec, Christian Fehmer Seite 30 / 45

7.5 Freie Manipulation OpenGL/GLUT Abbildung 18: Skalierung des Modells [rbapg93] 7.5 Freie Manipulation Um mehrere Schritte, Translation, Skalierung und Rotation auf einmal auszuführen oder eine ganz eigene Manipulationsmatrix anzuwenden wird der Befehl glmultmatrix benutzt void glmultmatrix{f d(const TYPE* m); Wobei TYPE* m eine spaltenweise von oben nach unten und von links nach rechts serialisierte Matrix ist. Diese Matrix wird mathematisch analog zu den obigen Funktionen mit M multipliziert und wieder auf den Stack gelegt. 7.6 Zusammenfassung Mit Hilfe der Funktionen zur Manipulierung der Modelview-Matrix lassen sich Objekte rotieren, verschieben und skalieren. Die Matrizen dazu müssen nicht selbst ausgerechnet werden. So müssen zum Beispiel die Eckpunkte eines um 30 rotierten Würfels der um 4 Einheiten nach links oben verschoben ist nicht aufwendig berechnet werden. glviewmode(gl_modelview); glloadidentity(); glpushmatrix(); gltranslatef(4,4,0); glrotatef(30,0,1,0); zeichnewürfel(); glpopmatrix; Sebastian Skalec, Christian Fehmer Seite 31 / 45

8 Perspektive und Projektion (Kamera) OpenGL/GLUT 8 Perspektive und Projektion (Kamera) 8.1 Einführung Wie bereits besprochen wird die Sicht auf ein Modell mit Hilfe der Projektionsmatrix beschrieben. Das Modell ändert sich bei einer anderen Sicht nicht. Um die Projektionsmatrix zu bearbeiten muss sie vorher aktiviert werden: glmatrixmode(gl_projection); In OpenGL gibt es keine Kamera, wir können den Betrachtungspunkt nicht ändern. Deshalb bewegt man zum Beispiel die komplette Welt nach rechts um dem Betrachter die Illusion zu geben sich nach links zu bewegen. 8.2 Orthographische Projektion In der orthographische Projektion (auch Parallelprojektion genannt) haben weit entfernte Objekte (kleines Z) die gleiche Größe wie nahe (großes Z) Objekte. Dieser Modus wird in der Regel für 2D- Anwendungen benutzt oder für 2D-Bereiche in 3D-Anwendungen (wie zum Beispiel Menüs). Die Projektionsmatrix für die orthographische Projektion wird mit dem Befehl glortho() gesetzt. void glortho(gldouble left, Gldouble right, Gldouble bottom, Gldouble top, Gldouble near, Gldouble far); Mathematisch entspricht die neue Projektionsmatrix P nun 2 right left 0 0 right left right left 2 top bottom 0 0 left bottom top bottom 2 0 0 P= far near far near far near 0 0 0 1 Sebastian Skalec, Christian Fehmer Seite 32 / 45

8.2 Orthographische Projektion OpenGL/GLUT Abbildung 19: Orthografische Projektion [rbapg93] Der Sichtbereich wird durch die 4 Eckpunkt definiert. Man kann sich diese Projektion wie ein Blick in eine Milchtüte vorstellen. Die z-werte near und far geben an, ab wo Objekte gezeichnet werden und ab wann sie nicht mehr zu sehen sind. Nun noch ein Beispiel der Perspektive. Wir zeichnen 3 Quadrate einmal mit gleichen und einmal mit unterschiedlichen Z-Werten: Abbildung 20: Orthographische Darstellung von Quadraten [DGLWIKI] Gleiche Z-Werte (oben) und unterschiedliche Z-Werte (unten) Sebastian Skalec, Christian Fehmer Seite 33 / 45

8.3 Perspektivische Projektion OpenGL/GLUT 8.3 Perspektivische Projektion Mit Hilfe der perspektivischen Projektion werden Objekte, die weiter entfernt sind oder die wir nicht frontal ansehen richtig gezeichnet. Dieses Verhalten wird durch den Hilfsbefehl gluperspective erreicht. void gluperspective(gldouble fovy, Gldouble aspect, Gldouble znear, Gldouble zfar); Abbildung 21: Perspektivische Projektion [rbapg93] Dabei gibt fovy den so genannten Field of View in Grad an, aspect das Größenverhältnis des Fensters und znear und zfar begrenzen das Sichtfeld vorn und nach hinten. Mathematisch entspricht die neue Projektionsmatrix nun: 0 0 0 aspect 0 fovy 0 0 P= fovy zfar znear 2 zfar znear 0 0 znear zfar znear zfar 0 0 1 0 Nun noch einmal das Beispiel von oben in der perspektivischen Darstellung. Wir zeichnen 3 Quadrate einmal mit gleichen und einmal mit unterschiedlichen Z-Werten: Sebastian Skalec, Christian Fehmer Seite 34 / 45

8.3 Perspektivische Projektion OpenGL/GLUT Abbildung 22: Perspektivische Darstellung von Quadraten [DGLWIKI] Gleiche Z-Werte (oben) und unterschiedliche Z-Werte (unten) 8.4 Hilfsfunktion GluLookAt Mit der Hilfsfunktion GluLookAt lässt sich die Projektionsmatrix verändern: void glulookat(glfloat eyex, GLfloat eyey, GLfloat eyez, GLfloat scenex, GLfloat sceney, GLfloat scenez, GLfloat upx, GLfloat upy, GLfloat upz); Der Vekor eye(x,y,z) legt dabei die Position des Betrachters fest und der Vektor scene(x,y,z) den Punkt, auf den die Kamera blicken soll. Der sogenannte Up-Vektor bestimmt die Drehung der Kamera um die Sichtachse. 8.5 Zusammenfassung OpenGL bietet mit der Projektionsmatrix die Möglichkeit, das Modell ohne Berücksichtigung der Sicht zu erstellen. Die Projektion und damit die Darstellung auf dem Bildschirm übernimmt OpenGL. Man muss nur in der Projektionsmatrix die gewünschte Sicht parametrisieren. Sebastian Skalec, Christian Fehmer Seite 35 / 45

9 Listing 2: Beispielprogramm OpenGL/GLUT 9 Listing 2: Beispielprogramm #include <math.h> #include <GL/glut.h> #include <stdlib.h> /**** T O C ******************************* * Variablen * - Kamera * - Objekte * - Beleuchtung * Callback * - Reshape * - Keyboard * - Mouse * Kamerasteuerung * Render * - Schneemann * - DrawFloor * - renderscrene * CreateDL (Schneemann laden) * initscene * main * * */ int light=1; int reflection=1; int anz=6; /**** Kamera ********************************/ /* angle/angle2 drehung der Kamera */ float angle=0.0, angle2=0.0; /* bildverhã ltnis */ float ratio; /* richtung und startkoordinaten der kamera-bewegung (x,y,z) */ int moving, startx, starty; /* initialer Blickpunkt */ float x=0.0f,y=-1.75f,z=0.0f; float xp=0.0f,yp=1.75f,zp=-8.0f; /* Veränderung der Kamera pro frame */ float lx=1.0f,ly=1.0f,lz=1.0f; /* verã nderung der Kamera * Flat=z-Achse * Side=x-Achse * Move=y-Achse */ Sebastian Skalec, Christian Fehmer Seite 36 / 45

9 Listing 2: Beispielprogramm OpenGL/GLUT int deltamoveflat = 0,deltaMoveSide = 0,deltaMoveUp = 0; int deltapointflat = 0,deltaPointSide = 0,deltaPointUp = 0; /**** Objekte *******************************/ /* Teile des Schneemanns */ GLint snowman_display_list; /* Farben des Schneemanns */ GLfloat bodycolor[] = {0.8, 0.8, 0.8, 1.0, eyecolor[] = {0.2, 0.2, 0.2, 1.0,hatColor[] = {0.2, 0.2, 0.2, 1.0, nosecolor[] = {0.8, 0.2, 0.2, 1.0; /**** Beleuchtung ***************************/ GLfloat lightzeroposition[] = {10.0, 14.0, 10.0, 1.0; GLfloat lightzerocolor[] = {0.8, 0.8, 1.0, 1.0; GLfloat lightoneposition[] = {-1.0, 1.0, 1.0, 0.0; GLfloat lightonecolor[] = {0.9, 0.9, 1.0, 1.0; /**** Callback ******************************/ /* callback funktion für reshape */ void changesize(int width, int height) { /* Fenster darf nie eine Höhe von 0 haben */ if(height == 0) height = 1; ratio = 1.0f * width / height; /* Alle Projektionen zurücksetzen */ glmatrixmode(gl_projection); glloadidentity(); /* Perspektive auf 45. Near=1, Far=1000 */ gluperspective(45,ratio,1,1000); glmatrixmode(gl_modelview); glloadidentity(); /* auf Startposition gehen */ gltranslatef(x,y,z); /* Callback für Special */ void presskey(int key, int x, int y) { switch (key) { /* je nach Richtung */ case GLUT_KEY_UP : deltamoveup = -1;break; case GLUT_KEY_DOWN : deltamoveup = 1;break; case GLUT_KEY_LEFT : deltamoveside = 1;break; case GLUT_KEY_RIGHT : deltamoveside = -1;break; Sebastian Skalec, Christian Fehmer Seite 37 / 45

9 Listing 2: Beispielprogramm OpenGL/GLUT /* Callback für SpecialUp */ void releasekey(int key, int x, int y) { /* wenn Taste losgelassen, Bewegung stoppen */ switch (key) { case GLUT_KEY_UP : case GLUT_KEY_DOWN : deltamoveup = 0;break; case GLUT_KEY_LEFT : case GLUT_KEY_RIGHT : deltamoveside = 0;break; /* Callback für KeyboardUp */ void releasenormalkeys(unsigned char key, int x, int y) { /* wieder stoppen der Bewegung */ switch (key) { case 'w' : case 's' : deltamoveflat = 0;break; case 'a' : case 'd' : deltamoveside = 0;break; case 'i': case 'k': deltapointflat = 0;break; case 'j': case 'l': deltapointside = 0;break; ; /* Callback für Keyboard */ void processnormalkeys(unsigned char key, int x, int y) { switch (key){ case 27 : case 'q': exit(0); break; case 'n': z=y=x=0; break; case 'w': deltamoveflat = 1;break; case 's': deltamoveflat = -1;break; case 'a': deltamoveside = 1;break; case 'd': deltamoveside = -1;break; ; case 'i': deltapointflat = 1;break; case 'k': deltapointflat = -1;break; case 'j': deltapointside = 1;break; case 'l': deltapointside = -1;break; glutpostredisplay(); /* Callback für mouse */ void mouse(int button, int state, int x, int y){ /* bei gedrückter linker taste drehung starten */ if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) { moving = 1; startx = x; starty = y; Sebastian Skalec, Christian Fehmer Seite 38 / 45

9 Listing 2: Beispielprogramm OpenGL/GLUT /* wenn taste wieder losgelassen wird, stoppen */ if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) { moving = 0; /* callback für Motion (mausbewegung) */ void motion(int x, int y){ /* moving wurde von mouse gesetzt */ if (moving) { angle = angle + (x - startx); angle2 = angle2 + (y - starty); startx = x; starty = y; glutpostredisplay(); /**** Kamerasteuerung ***********************/ void movemeflat(int i) { z = z + i*(lz)*0.1; glloadidentity(); gltranslatef(x,y,z); void movemeside(int i) { x = x + i*(lx)*0.1; glloadidentity(); gltranslatef(x,y,z); void movemeup(int i) { y = y + i*(ly)*0.1; glloadidentity(); gltranslatef(x,y,z); void movepointflat(int i) { zp = zp + i*(lz)*0.1; glloadidentity(); glulookat(xp,yp,zp,0,0,0,0,1,0); void movepointside(int i) { xp = xp + i*(lx)*0.1; glloadidentity(); glulookat(xp,yp,zp,0,0,0,0,1,0); void movepointup(int i) { Sebastian Skalec, Christian Fehmer Seite 39 / 45

9 Listing 2: Beispielprogramm OpenGL/GLUT yp = yp + i*(ly)*0.1; glloadidentity(); glulookat(xp,yp,zp,0,0,0,0,1,0); /**** Render ********************************/ /* zeichnen von einem Schneemann */ void drawsnowman() { glcolor3d(1,1,1); // Körper if(light)glmaterialfv(gl_front, GL_DIFFUSE, bodycolor); gltranslatef(0.0f,0.75f, 0.0f); glutsolidsphere(0.75f,20,20); // Kopf gltranslatef(0.0f, 1.0f, 0.0f); glutsolidsphere(0.25f,20,20); // Augen if(light)glmaterialfv(gl_front, GL_DIFFUSE, eyecolor); glpushmatrix(); glcolor3f(0.0f,0.0f,0.0f); gltranslatef(0.05f, 0.10f, 0.18f); glutsolidsphere(0.05f,10,10); gltranslatef(-0.1f, 0.0f, 0.0f); glutsolidsphere(0.05f,10,10); glpopmatrix(); // Nase if(light)glmaterialfv(gl_front, GL_DIFFUSE, nosecolor); glcolor3f(1.0f, 0.5f, 0.5f); glrotatef(0.0f,1.0f, 0.0f, 0.0f); glutsolidcone(0.08f,0.5f,10,2); /* Untergrund rendern */ drawfloor(void) { if(light)gldisable(gl_lighting); glbegin(gl_quads); glvertex3f(-anz*10.0, 0.0, anz*10.0); glvertex3f(anz*10.0, 0.0, anz*10.0); glvertex3f(anz*10.0, 0.0, -anz*10.0); glvertex3f(-anz*10.0, 0.0, -anz*10.0); glend(); if(light)glenable(gl_lighting); Sebastian Skalec, Christian Fehmer Seite 40 / 45

9 Listing 2: Beispielprogramm OpenGL/GLUT /* Rendern der Szene */ void renderscene(void) { int i,j; /* zeichenflã che LÃ schen */ glclear(gl_color_buffer_bit GL_DEPTH_BUFFER_BIT); /* Abfrage auf Kamerabewegung */ if (deltamoveflat) movemeflat(deltamoveflat); if (deltamoveside) movemeside(deltamoveside); if (deltamoveup) movemeup(deltamoveup); if (deltapointflat) movepointflat(deltapointflat); if (deltapointside) movepointside(deltapointside); if (deltapointup) movepointup(deltapointup); /* */ glpushmatrix(); /* Kamera drehen */ glrotatef(angle2, 1.0, 0.0, 0.0); glrotatef(angle, 0.0, 1.0, 0.0); if(light){ /* Beleuchtung setzen */ gllightfv(gl_light0, GL_POSITION, lightzeroposition); gllightfv(gl_light1, GL_POSITION, lightoneposition); /* */ glpushmatrix(); if(reflection){ /* fã¼r die Reflektion */ /* Y-Achse invertieren, wir zeichnen "unter dem Tisch" */ glscalef(1.0, -1.0, 1.0); /* Die Lichter mit unter den Tisch nehmen */ Sebastian Skalec, Christian Fehmer Seite 41 / 45

9 Listing 2: Beispielprogramm OpenGL/GLUT gllightfv(gl_light0, GL_POSITION, lightzeroposition); gllightfv(gl_light1, GL_POSITION, lightoneposition); /* Back face culling bei den Reflektionen aus */ glenable(gl_normalize); glcullface(gl_front); // Reflektion der 36 Schneemà nner unter dem Tisch bauen for(i = -anz/2; i < anz/2; i++) for(j=-anz/2; j < anz/2; j++) { glpushmatrix(); gltranslatef(i*10.0,0,j * 10.0); glcalllist(snowman_display_list);; glpopmatrix(); /* Backface culling wieder aktivieren */ gldisable(gl_normalize); glcullface(gl_back); glpopmatrix(); /* Lichter wieder mitnehmen */ gllightfv(gl_light0, GL_POSITION, lightzeroposition); gllightfv(gl_light1, GL_POSITION, lightoneposition); /* Untergrund ("Tischplatte") rendern */ glenable(gl_blend); glblendfunc(gl_src_alpha, GL_ONE_MINUS_SRC_ALPHA); if(reflection!=1)glpopmatrix(); glcolor4f(0.0, 0.0, 0.9, 0.6); drawfloor(); if(reflection)gldisable(gl_blend); /* jetzt rendern der Schneemà nner auf der Oberflà che */ for(i = -anz/2; i < anz/2; i++) for(j=-anz/2; j < anz/2; j++) { glpushmatrix(); gltranslatef(i*10.0,0,j * 10.0); glcalllist(snowman_display_list);; glpopmatrix(); glpopmatrix(); /* bisher haben wir alles in den (offline) Zwischenbuffer geschrieben. * deswegen tauschen wir die Buffer jetzt */ glutswapbuffers(); Sebastian Skalec, Christian Fehmer Seite 42 / 45

9 Listing 2: Beispielprogramm OpenGL/GLUT /* DrawingList erstellen, gibt die ID zurück */ GLuint createdl() { GLuint snowmandl; // ID der Liste erstellen snowmandl = glgenlists(1); // starte liste glnewlist(snowmandl,gl_compile); // funktion aufrufen, die das Objekt rendert drawsnowman(); // ende des listen blockes glendlist(); return(snowmandl); /* Initialisiren der Scene */ void initscene() { /* deeptest und backface culling*/ glenable(gl_depth_test); glenable(gl_cull_face); if(light){ /* lichter definieren und aktivieren */ glenable(gl_lighting); gllightmodeli(gl_light_model_local_viewer, 1); gllightfv(gl_light0, GL_DIFFUSE, lightzerocolor); gllightf(gl_light0, GL_CONSTANT_ATTENUATION, 0.1); gllightf(gl_light0, GL_LINEAR_ATTENUATION, 0.05); gllightfv(gl_light1, GL_DIFFUSE, lightonecolor); glenable(gl_light1); glenable(gl_light0); gllightfv(gl_light0, GL_POSITION, lightzeroposition); gllightfv(gl_light1, GL_POSITION, lightoneposition); /* Object in den speicher laden */ snowman_display_list = createdl(); /**** Main **********************************/ int main(int argc, char **argv) { /* Fenster initialisieren */ glutinit(&argc, argv); glutinitdisplaymode(glut_depth GLUT_DOUBLE GLUT_RGBA); glutinitwindowposition(100,100); Sebastian Skalec, Christian Fehmer Seite 43 / 45

9 Listing 2: Beispielprogramm OpenGL/GLUT glutinitwindowsize(640,360); glutcreatewindow("freie Kamera"); initscene(); /* optimierung, wir merken und beim drücken einmal welche bewegung * ausgelößt wurde. Deswegen wird beim zweiten durchlauf der main * loop bereits gedrückte Tasten ignoriert */ glutignorekeyrepeat(1); /* registrierung callback funktionen */ /* Tastatur */ glutkeyboardfunc(processnormalkeys); glutkeyboardupfunc(releasenormalkeys); glutspecialfunc(presskey); glutspecialupfunc(releasekey); /* maus */ glutmousefunc(mouse); glutmotionfunc(motion); /* andere */ glutdisplayfunc(renderscene); glutidlefunc(renderscene); glutreshapefunc(changesize); glutmainloop(); return(0); Sebastian Skalec, Christian Fehmer Seite 44 / 45

Literaturverzeichnis / Quellen [claussen97] Programmieren in OpenGL, Ute Claussen, Springer Verlag, 97 [rbapg93] OpenGL Programming Guide,Architecture Review Board, Addison-Wesley 93 [rbarm93] OpenGL Reference Manual,Architecture Review Board, Addison-Wesley 93 OpenGL-Tutorial,António Ramires Fernandes, http://www.lighthouse3d.com/opengl/glut/ Glut Programmierung, Miguel Angel Sepulveda, 1998 http://ldp.mirroring.de/linuxfocus/deutsch/january1998/article16.html Wikipedia, http://de.wikipedia.org/wiki/ Thema OpenGL, GLU, GLUT usw. Stand 05/07 OpenGL Spezifikation, Architecture Review Board, http://www.opengl.org/documentation/specs/glut/spec3/spec3.html OpenGL Tutorial, Christian Marten, Heise Verlag 1992 http://www.heise.de/ix/artikel/1999/12/160/ [DGLWIKI] OpenGL Wikipedia für Delphi-Programmierer, 2007, http://wiki.delphigl.com [GCB06] Generative Computergrafik, Vorlesungsfolien v. Dr. Hanno Bgeck, FH Wiesbaden 2006, http://www.mi.fhwiesbaden.de/~schwan/vorlesungen/gencg/skripte/gencgus5.pdf