3D-Engine für AiRmob. Bachelorarbeit

Größe: px
Ab Seite anzeigen:

Download "3D-Engine für AiRmob. Bachelorarbeit"

Transkript

1 Fachbereich 4: Informatik 3D-Engine für AiRmob Bachelorarbeit zur Erlangung des Grades eines Bachelor of Science (B.Sc.) im Studiengang Computervisualistik vorgelegt von Axel Peter Erstgutachter: Zweitgutachter: Prof. Dr.-Ing. Stefan Müller (Institut für Computervisualistik, AG Computergraphik) Dipl.-Inform. Martin Schumann (Institut für Computervisualistik, AG Computergraphik) Koblenz, im April 2012

2 Erklärung Ich versichere, dass ich die vorliegende Arbeit selbständig verfasst und keine anderen als die angegebenen Quellen und Hilfsmittel benutzt habe. Ja Nein Mit der Einstellung der Arbeit in die Bibliothek bin ich einverstanden. Der Veröffentlichung dieser Arbeit im Internet stimme ich zu (Ort, Datum) (Unterschrift) 1

3 Inhaltsverzeichnis 1 Einleitung Motivation Hintergründe des Projekts Zielsetzung Ziele des Projekts Ziele dieser Arbeit Zum Thema Android - SDK und NDK OpenGL ES OpenGL ES in Android D-Engines Scene Management Renderer Resource Management Stand der Technik für 3D-Engines Beispiel Irrlicht Beispiel jpct-ae Framework Airmob Architektur Schnittstellen der Engine Integration der Engine ins Framework Verwendung der Shader Tracker Austauschbarkeit AiRmob-Engine Ziele Bedienung Angestrebte Features Programmierung in Java Übersicht Renderer SceneManager ResourceManager Austauschbarkeit von Scene- und ResourceManager Szene und Objekte Parents Modelle Model3D und Mesh ModelCustom und Import von Modellen

4 4.3.5 Texturen und Materialien Dateiformate und Erweiterbarkeit Pfade Einschränkungen bei Import und Exporteinstellungen ModelGroup ModelAnimation Vorgegebene Modelle Lichtquellen Text Shader Funktionen onsurfacecreated onsurfacechanged ondrawframe drawallobjects drawlight drawmodel Picking Shadowmap Post-Processing Settings Techdemo 68 6 Schluss Ergebnisse Bewertung Ausblick

5 1 Einleitung 1.1 Motivation Mobiltelefone waren bis vor einigen Jahren nicht mehr als das, was ihre Bezeichnung nahe legt: eine Möglichkeit zur Telefonie auch unterwegs. Seit der Entwicklung der sogenannten Smartphones hat sich das rasant geändert. Wie der Computer Teil des alltäglichen Lebens geworden ist, haben auch Smartphones einen immer größeren Einfluss auf die Lebensqualität der Menschen. Insbesondere seit Apple sein ios sowie Google und die Open Handset Alliance ihr Android-Betriebssystem entwickelten, haben Handys und vor allem auch Applikationen für diese sich enorm verändert. So wie die Hardware und Betriebssysteme von Handys in großen Schritten gewachsen sind, sind dies auch die Möglichkeiten 3D-Inhalte auf ihnen darzustellen. Sehr beeindruckend war es, als die ersten Tech-Demos und Spiele auf Handys erschienen, die anspruchsvolle Szenen mit aufwendigeren Effekten wie Beleuchtung, Schatten und Texturierungen in Echtzeit darstellen konnten. Durch die Entwicklung von OpenGL ES 2.0 sind diese Möglichkeiten noch mehr gewachsen und es sind inzwischen schon sehr fortgeschrittene grafische Inhalte realisierbar. In meiner Arbeit möchte ich die Besonderheiten der Programmierung für mobile Geräte, also auch der Entwicklung mit OpenGL ES darstellen. Durch die Entwicklung einer eigenen 3D-Engine wollte ich mein bisheriges Wissen in diesem Bereich der Computergrafik auf die Probe stellen und herausfinden, wie es ist eine solche Engine vollständig selbst zu entwickeln und zu programmieren. Das gelernte theoretische Wissen praktisch umzusetzen war ein Ziel dieser Arbeit. 1.2 Hintergründe des Projekts Autoren: Philipp Brandt, Florian Kathe, Nils Lichtenberg und Axel Peter Diese Arbeit ist ein Teil des AiRmob-Frameworks. Dieses Framework wurde im Zuge von insgesamt vier Bachelorarbeiten parallel entwickelt. Es soll das Entwickeln für Augmented Reality Applikationen für Android ermöglichen. Das Projekt entstand aus folgenden Arbeiten: Anwendungs- und Interaktionskomponente für AiRmob - von Nils Lichtenberg Bei dieser Arbeit handelt es sich um das Grundgerüst, welches auf einfache Art und Weise mit einem Tracking- und Renderingsystem erweitert und vervollständigt werden kann. Das Verknüpfen des Frameworks mit der Standard-Android-API soll dem Benutzer möglichst einfach gemacht 4

6 werden. Trackingkomponente für AiRmob - von Florian Kathe Grundlage dieser Arbeit soll ein Tracker sein, der auf Basis von Markern oder Features ein Objekt in einem Bild tracken kann und dessen Pose berechnet. Diese soll dann wiederum an den Renderer weitergegeben werden. Dabei sollen zwei Tracker entwickelt werden, die als Standard-Tracker verwendet werden können und als Beispiel dienen, wie man Tracker für dieses Framework entwickelt. 3D-Engine für AiRmob - von Axel Peter In dieser Arbeit wird eine 3D-Engine entwickelt, welche dem Benutzer ermöglichen soll, schnell und einfach 3D-Inhalte zu produzieren. Hierzu soll der Anwender nur über grundlegende Kenntnisse von OpenGL verfügen müssen. Die anfänglichen Schwierigkeiten eines Einstiegs in OpenGL ES 2.0 sollen ihm genommen werden. Fortgeschrittene Techniken für eine möglichst hohe Effizienz und Qualität der Darstellung sollen verwendet werden. Shader und Effekte für AiRmob - von Philipp Brandt Bestandteil dieser Arbeit ist die Entwicklung verschiedener Shader, die im Renderer des Frameworks integriert und aufgerufen werden. Es wird der aktuelle Stand der Technik ermittelt und im Verlauf der Arbeit versucht, möglichst aktuelle und anspruchsvolle Shader auf den gegebenen mobilen Endgeräten echtzeitfähig zu implementieren. Texte die gemeinsam verfasst wurden, werden wie dieser entsprechend kenntlich gemacht. Auf die Zielsetzungen der einzelnen Arbeiten wird im nächsten Abschnitt noch genauer eingegangen. Architektur, Schnittstellen und Austauschbarkeit der Komponenten werden in Abschnitt 3 erläutert. 1.3 Zielsetzung Ziele des Projekts Autoren: Philipp Brandt, Florian Kathe, Nils Lichtenberg und Axel Peter Das Hauptziel der Arbeiten ist die Entwicklung des AiRmob-Frameworks. Dieses soll eine einsteigerfreundliche Entwicklungsumgebung für Augmented Reality (AR) Anwendungen auf Android-Geräten bieten. Hierzu sollen die Schritte, die zum Erstellen einer lauffähigen Applikation nötig sind, reduziert werden. Der Benutzer, im Falle dieses Frameworks ein Entwickler 5

7 von Applikationen, soll in der Lage sein, mit minimalen Vorkenntnissen von Android, OpenGL und Trackingsystemen seine Ideen schnell umzusetzen. Gleichzeitig soll es für fortgeschrittene Benutzer möglich sein, eigene Trackingsysteme und Renderer in das Framework einzubinden. Das Android-SDK soll als Basis für dieses Framework dienen. Hierdurch wird es für die Benutzer möglich sein, ihre Applikationen für alle mit Android kompatiblen Geräte zu entwickeln. Siehe hierzu auch Abschnitt 2.1 über das Android-SDK. Das Framework wird auf der SDK-Version 2.3 (Gingerbread) entwickelt und ist somit für diese und alle späteren lauffähig. Zusätzlich sollen mit Hilfe des Frameworks in gemeinsamer Arbeit zwei Applikationen entstehen. Die erste Applikation ist eine Techdemo. Mit ihr soll es möglich sein, diverse Einstellungen für die verschiedenen Komponenten auf Effizienz und Stabilität testen zu können. Diese Applikation entsteht parallel zur Entwicklung des eigentlichen Frameworks und wird nach und nach um neue Funktionalitäten erweitert. Die zweite Anwendung ist eine Beispielapplikation. Diese soll mit dem Framework selbst entwickelt worden sein und dadurch aufzeigen, in welcher Weise die Komponenten des Frameworks für eine Gesamtapplikation benutzt werden. Während die Techdemo in Abschnitt 5 beschrieben wird, ist die Beispielapplikation Teil der Arbeit von Nils Lichtenberg. Auf die genaueren Ziele dieser Arbeit wird im nächsten Abschnitt eingegangen Ziele dieser Arbeit Ziel ist es eine echtzeitfähige Engine für aktuelle Effekte zu schreiben. Hierzu sollen insbesondere die Daten des Trackers verarbeitet werden, um 3D- Inhalte korrekt in die reale Welt zu projektieren. Es sollen moderne Effekte mit objektorientierter Programmierung leicht und ohne große Einarbeitung darstellbar sein. Dazu werden die von Philipp Brandt geschriebenen Shader eingebunden. In 3D-Grafik-Programmen, wie Blender oder Cinema 4D, modellierte Objekte und Animationen sollen importiert und genutzt werden können. Dies soll für mobile Geräte mit dem Android-Betriebssystem und OpenGL ES 2.0 programmiert werden. Im Recherche-Teil sollen die Besonderheiten der Programmierung mit diesen und der Aufbau einer Engine erläutert werden. Auf die Ziele für die Implementation der AiRmob-Engine wird im Abschnitt 4.1 genauer eingegangen. 6

8 2 Zum Thema 2.1 Android - SDK und NDK Android ist ein Betriebssystem für mobile Geräte, wie Handys und PDAs. Aktuell ist es 1 in der Version 4.0 erhältlich. Es wird unter der Apache Software License 2.0 veröffentlicht und ist somit freie Software und quelloffen. [lic] Entwickelt und veröffentlicht wird Android seit 2007 von der Open Handset Alliance, einem Konsortium aus 80 Mitgliedern und insbesondere der Google Inc. Mit 52% Marktanteil läuft auf über der Hälfte aller Smartphones ein Android- Betriebssystem. Die am häufigsten benutzte Version von Android ist 2.3 (Gingerbread) mit über 43% aller Android-Geräten. Nahezu gleichauf folgt Android 2.2 (Froyo) mit über 40%. Android 2.1 (Eclair) ist noch auf 10% aller Android-Geräten vertreten. Der Rest verteilt sich auf die übrigen Versionen [ver] [hei]. Die Programmierung für Android-Handys geschieht in der Sprache Java mit Hilfe des Android Software Development Kit, kurz SDK. Das Android- SDK soll die Entwicklung für Android erleichtern. Es beinhaltet Debugger, Libraries und einen Emulator [anda]. Letzterer ist in der aktuellen Version nicht in der Lage OpenGL ES 2.0 zu emulieren, siehe hierzu auch Abschnitt 2.3. Mit dem Android-SDK wurden bislang mehr als kostenfreie und kostenpflichtige Applikationen entwickelt. Diese wurden insgesamt über 6.8 millionen Mal heruntergeladen [app]. Um Applikationen in nativem C oder C++ zu entwickeln stellt Android sein Native Development Kit, kurz NDK, zur Verfügung. 2.2 OpenGL ES 2 OpenGL ES ist wie OpenGL ein Application Programming Interface (API) für 3D-Applikationen. Im Unterschied zu OpenGL ist OpenGL ES auf eingebetteten Systeme, wie Handys oder PDAs ausgerichtet. So steht das ES für Embedded Systems, also eingebettete Systeme. Insbesondere mobile Systeme unterliegen oft speziellen Einschränkungen und Anforderungen. Sie verfügen meistens über weit weniger Speicher, eine langsamere CPU, weniger Arbeitsspeicher und ihr Stromverbrauch ist sehr wichtig. Um auf diese Umstände einzugehen weist OpenGL ES einige Unterschiede zu OpenGL auf. Sämtliche Redundanzen wurden herausgenommen und nur die effektiveren Varianten beibehalten. Wo es in OpenGL mehrere Befehle oder Möglichkeiten gab, gibt es in OpenGL ES meist nur einen. Zum Beispiel ist es in OpenGL möglich den immediate mode, display lists, 1 Stand

9 oder vertex arrays zu benutzen, während in OpenGL ES nur vertex arrays zur Verfügung stehen. Auch wurden neue Funktionen hinzugefügt, die auf diese Bedürfnisse ausgerichtet sind. In OpenGL ES lässt sich mittels Precision Qualifiers die Genauigkeit der Nachkommastellen für Shader einstellen. OpenGL ES wird von der Khronos Group entwickelt. Es ist unter einer Royalty Free Lizenz veröffentlicht und sowohl für nicht-kommerzielle als auch für kommerzielle Zwecke frei. Ähnlich dem Sprung von OpenGL 1 zu OpenGL 2 hat sich OpenGL ES stark von OpenGL ES 1 zu OpenGL ES 2 verändert. In OpenGL ES 1 wird noch eine sogenannte fixed pipeline benutzt. OpenGL ES 2 hingegen ermöglicht es dem Programmierer einige Teile der Pipeline selbst zu entwickeln. So lassen sich Vertex- und Fragmentshader mit der OpenGL ES Shading Language programmieren. Es werden die OpenGL ES Versionen 1.0, 1.1, welche beide von OpenGL 1.0 bzw. 1.3/1.5 abstammen und 2.0, dessen Pipeline wie beschrieben in Teilen programmierbar ist, unterschieden. Während 1.1 zu 1.0 abwärtskompatibel ist, gilt dies nicht für die Version 2.0 zu einer der beiden vorherigen. Durch die Möglichkeiten eines programmierbaren Vertex- und Fragmentshaders lassen sich mit OpenGL ES 2.0 bereits wesentlich fortgeschrittenere Rendering-Methoden realisieren. Jedoch sind im Vergleich zu Desktop- Rechnern noch Einschränkungen in den Möglichkeiten grafischer Darstellungen auf mobilen Geräten feststellbar. So verfügt OpenGL ES 2.0, wie OpenGL 2, nicht über einen Geometryshader, welcher in OpenGL 3.2 eingeführt wurde. Zu OpenGL ES siehe auch [MGS09, S. 1f] und [ope]. 2.3 OpenGL ES in Android Android unterstützt OpenGL ES 1.0 und 1.1 bereits seit seiner Version 1.0. Die Benutzung von OpenGL ES 2.0 wurde duch die Version 2.2 bzw. API Level 8 eingeführt. Handys mit einer älteren Androidversion können OpenGL ES 2.0 und die darauf basierenden Applikationen weiterhin nicht verwenden [andb]. Während OpenGL ES 2.0 auf Handys benutzt und getestet werden kann, wird es nicht vom Android-Emulator unterstützt. Auch ist zu erwähnen, dass Android in der Version 2.2 keine Unterstützung von Vertex Buffer Objects bietet, da die Schnittstelle hierzu in dieser Version noch nicht zur Verfügung steht. Unter anderem deshalb ist die AiRmob-Engine nur mit Android in der Version 2.3 oder neuerer kompatibel. Android bietet bereits eine Vielzahl von Funktionen, die das Arbeiten mit OpenGL ES erleichtern. Es lassen sich beispielsweise mithilfe der Matrix- Klasse schnell und unkompliziert Rechnungen mit Matrizen im Allgemeinen und auch OpenGL Matrizen, wie die View-Matrix, im Speziellen berechnen. Auch sind einige Hilfestellungen zur Beschleunigung einer 3D- 8

10 Applikation vorhanden, wie dem Komprimieren von Bilddateien, welche zur Texturierung genutzt werden sollen. Viele dieser Funktionen werde ich bei der Implementation der 3D-Engine für AiRmob verwenden. Sofern diese Einfluss auf die Entwicklung haben, werde ich an den jeweiligen Stellen in Abschnitt 4 genauer darauf eingehen D-Engines Es gibt sehr vielfältige und in ihren Aufgabenstellungen unterschiedliche 3D-Engines. So können sie für Filme oft viele Stunden an einem einzelnen Bild rendern, während 3D-Engines für Echtzeitanwendungen, wie Computerspiele, eine hohe Anzahl an Bildern pro Sekunde erzeugen müssen. Auf letztere Art von 3D-Engines wird hier eingegangen, da die Engine des AiRmob-Frameworks ebenfalls in Echtzeit rendern soll. Ziel dieser Engines ist es ein Maximum an 3D-Inhalten in Echtzeit darstellen zu können. Hierbei soll eine möglicherweise hohe Anzahl von Modellen mit zahlreichen Effekten wie Beleuchtung, Schatten und Texturierung in Echtzeit gerendert werden. Meistens werden 3D-Engines hierzu in einige Hauptkomponenten unterteilt. Typischerweise sind dies neben dem Kernsystem das Scene Management, der Renderer und das Resource Management. Im Folgenden werden diese einzelnen Komponenten und ihre Funktionen näher erläutert. An dieser Stelle soll nur ein grober Überblick über die Aufgaben der einzelnen Komponenten gegeben werden. Welche Features aktuelle 3D-Engines bieten wird im Abschnitt 4.1 anhand zweier Beispiele gezeigt. Die für die AiRmob-Engine gesetzten Ziele und die konkrete Umsetzung der einzelnen Techniken werden in Abschnitt 4 dargestellt. Die Informationen in diesem Abschnitt und den Unterabschnitten sind aus [cg] und [Kra11] zusammengetragen Scene Management Im Scenen Management werden alle 3D-Objekte erstellt und verwaltet. Hierzu werden sämtliche Modelle und ihre Transformationen in eine Hierarchie eingegliedert. Für diese wird meistens eine Baum- oder Graph-Datenstruktur verwendet, wie ein Quadtree oder ein ungerichteter Graph. Diese Hierarchie bezeichnet man meistens als Szenengraphen. Ein Scene Management kann diesen Szenengraphen nach verschiedenen Gesichtspunkten aufbauen. So kann er zunächst hierarchisch nach Objektzugehörigkeit geordnet werden. Zum Beispiel würden dem Modell eines Autos dessen Räder untergeordnet. Sobald man neben den Modellen nun noch Transformationen an 9

11 die einzelnen Blätter des Szenengraphen hängt, lassen sich durch ihn sehr leicht komplexere Bewegungen realisieren. Wenn sich das Auto in der 3D- Welt bewegt und die Räder sich dabei drehen sollen, so ist dies durch die Anwendung der Rotationsmatrix der Räder und anschließend der Bewegungsmatrix des Autos mit einem Szenengraphen leicht möglich. Eine andere Möglichkeit ist, die 3D-Objekte räumlich in den Szenengraphen einzusortieren. Hierdurch lassen sich schon vor dem eigentlichen Zeichnen viele Objekte ausschließen, die nicht zu sehen sind. Durch die Baum-/Graphen- Datenstruktur können oft ganze Gruppen von Objekten durch einen einzelnen Test ausgeschlossen werden. Nach der Sortierung kann ein View- Frustum-Culling durchgeführt werden. Bei diesem wird für jeden Knoten des Szenengraphen getestet, ob sich das Objekt bzw. dessen bounding Box komplett außerhalb des Frustums befindet. Sollte dies für einen Knoten zutreffen, können auch alle seine Kinder verworfen werden. Ein anderer Ansatz ist die Sortierung nach State-Changes. Da das Wechseln von Texturen und Shadern mit einem hohen Aufwand einhergeht, versucht man hierbei Objekte gleicher States nacheinander zu zeichnen und dadurch möglichst wenige State-Changes zu benötigen. Des Weiteren sorgt das Scene Management dafür, dass die 3D-Objekte in der richtigen Reihenfolge gezeichnet werden. Diese ist bei transparenten Objekten von Bedeutung. Zunächst müssen alle undurchsichtigen (opaque) Objekte gezeichnet werden und anschließend die transparenten Objekte aus der Sicht der Kamera von hinten nach vorn. Nachdem das Scene Management seine Aufgaben beendet hat, gibt es dem Renderer alle zu zeichnenden Objekte in der richtigen Reihenfolge an Renderer Der Renderer hat die Aufgabe das eigentliche Zeichnen einer Szene durchzuführen. Wie dies geschieht, kann je nach Umfang und Qualität der Darstellung sehr unterschiedlich ausfallen. In jedem Fall muss er alle ihm vom Scene Management gesendeten Objekte zeichnen. Bei der Benutzung einer programmierbaren Pipeline heißt das konkret, dass er die Vertices der Polygone jeden Objektes an den Vertexshader weitergibt. Für Beleuchtungseffekte müssen weiterhin pro Vertex dessen Normale und Materialeigenschaften übermittelt werden. Für weitere Effekte, wie der Texturierung, müssen zumeist zusätzliche Informationen vom Renderer an die Shader übermittelt und gegebenenfalls vorher berechnet werden. Neben den Objekten müssen ebenso sämtliche Lichtquellen mit ihren Eigenschaften an die Shader gesendet werden. Um fortgeschrittenere Effekte, wie realistische Schatten, zu erzielen muss ein Renderer zudem vor oder nach dem eigentlichen Zeichnen zusätzliche Zeichendurchläufe durchführen, um von den Shadern benötigte Werte oder Texturen zu generieren. 10

12 Weitere Shader und Effekte benötigen oftmals noch andere Daten vom Renderer, wodurch sich dieser Ablauf stark verändern kann Resource Management Das Resource Management hat, wie der Name schon sagt, die Aufgabe, die von der 3D-Engine verwendeten Ressourcen zu verwalten. Hier werden Texturen und Shader in das System geladen und auf Anfrage an die anderen Komponenten der 3D-Engine weitergegeben. Da 3D-Modelle aus vielen tausend Punkten bestehen können, muss das Importieren möglichst effizient vonstatten gehen. Hierzu sollten geeignete Datentypen gewählt bzw. vorab erzeugt werden. An dieser Stelle sollte darauf geachtet werden, dass bereits im System vorhandene Ressourcen verwendet und nicht bei jeder Anforderung neu geladen werden. 2.5 Stand der Technik für 3D-Engines In diesem Abschnitt wird auf den Stand der Technik für 3D-Engines eingegangen. Hierzu werden die Features und Techniken zweier Beispiele dargestellt. Der Fokus wird hierbei auf die out-of-the-box gegebenen Möglichkeiten für Benutzer dieser 3D-Engines gesetzt. Neben gemeinsamen Überlegungen im AiRmob-Team wurden durch diese Recherche Ideen und Anregungen gesammelt, welche Features die AiRmob-Engine haben sollte. Die endgültigen als Ziele festgelegten Features werden im Abschnitt 4.1 beschrieben Beispiel Irrlicht Die Irrlicht Engine ist eine in C++ geschriebene, plattformübergreifende 3D-Engine. Sie wurde von Nikolaus Gebhardt entwickelt und ist sowohl für nicht-kommerzielle als auch für kommerzielle Zwecke frei verfügbar. Irrlicht erlaubt dem Benutzer eine objektorientierte Programmierung. Das Scene Management von Irrlicht ermöglicht die Benutzung von Szenengraphen. Mit diesen kann Irrlicht hierarchisch Bewegungen übergeben, sowie View-Frustum-Culling und Kollisionsabfragen durchführen. Modelle können aus Polygonen, Wireframe oder Punkten bestehend dargestellt werden. Hierzu werden Daten in Form von Dreiecken, Punkten, Linien und Point Sprite Primitives verarbeitet. Für Texturen und Meshes erlaubt Irrlicht dem Benutzer das Laden einer Vielzahl von Formaten. Diese Modelle können selbst programmiert oder aus einer Vielzahl von Dateitypen, wie.obj- und.3ds-dateien (Alias Wavefront Maya und 3D Studio meshes), importiert werden. Für den Import von Texturen unterstützt Irrlicht viele gängige Bilddateitypen, wie.jpg oder.png. Animationen können in Form von Skelett- und Morphanimationen importiert werden. Bei 11

13 Skelettanimationen ist es zudem möglich dem Skelett weitere Objekte hinzuzufügen, welche anschließend von Irrlicht korrekt animiert werden. Irrlicht überprüft für die Importe, ob die zu importierenden Objekte bereits vorliegen, um gegebenenfalls Zeit und Speicher zu sparen. Out-of-the-box beinhaltet Irrlicht bereits einige Effekte, wie zum Beispiel animierte Wasseroberflächen, dynamische Lichter und Schatten, Bump- und Parallaxmapping und Skyboxes. Es können weiterhin eigene Shader hinzugefügt werden. Hierbei sind Vertex- und Fragmentshader von Version 1.1 bis 3.0 zulässig. Alle Informationen zu Irrlicht und die Engine selbst unter [irr] Beispiel jpct-ae Die jpct-engine verbindet OpenGL mit Java. Dabei stellt jpct-ae eine Portierung der Engine auf Android dar, die direkt mit Android-Geräten (ab Version 1.5) verwendet werden kann. Sie unterstützt sowohl OpenGL ES 1 als auch OpenGL ES 2. Mit ihr lassen sich externe Modelle aus 3DS, OBJ, MD2, ASC sowie serialisierten Dateien importieren. Es sind dabei auch bereits einige Modelle wie Würfel und Kugeln vorgegeben. Für Animationen unterstützt jpct- AE sowohl Key-Frame-Animationen als auch Skelett-Animationen. Objekte können mit Picking selektiert werden. Darüber hinaus bietet die Engine Collision-Detection, Lens Flares und unterstützt Transparenz und Nebeleffekte. Sie ist kompatibel mit Vertex Buffer Objects und Frame Buffer Objects. Für Modelle ohne Normalen können diese von der Engine berechnet werden. Des Weiteren wird out-of-the-box eine Beleuchtung angeboten, die die ambienten, diffusen und spekularen Therme von Materialien und Lichtquellen verwendet [jpc]. 12

14 3 Framework Airmob 3.1 Architektur Autoren: Philipp Brandt, Florian Kathe, Nils Lichtenberg und Axel Peter Framework Renderergebnis Empfängt Kamerabilder und verknüpft diese mit Engine und Tracker. Kamerabild Engine Verarbeitet Szene und Einstellungen zu gerendertem Bild. View- und Projectionmatrix Tracker Berechnet die 3D- Pose eines angegebenen Objekts im Kamerabild. Shader Rendert verschiedene Effekte auf die Szene unter Berücksichtigung übermittelter Werte. Abbildung 1: Übersicht über das Framework In Abbildung 1 wird die Systemarchitektur des Frameworks, grob in die einzelnen Teilarbeiten aufgeteilt, dargestellt. Im Grunde ergibt sich hier eine Verarbeitungsschleife, die parallel zur eigentlichen Anwendungslogik einer App auf Basis des Frameworks abläuft. Der Einstieg in die Schleife geschieht an der Komponente Framework. Hier wird nach einigen Initialisierungsschritten das Kamerabild empfangen und kontinuierlich an den Tracker weitergegeben. Der Tracker sucht in jedem Kamerabild, das er bekommt, nach einem vorher angegebenem Marker oder Textur. Wird eine Übereinstimmung gefunden, ist der nächste Schritt, die Lage des Objektes im Kamerabild zu bestimmen. Aus dieser Lage kann dann eine 3D Pose (Viewmatrix) bestimmt 13

15 werden, die im Framework dann weitergegeben wird. Zusätzlich wird bei der Initalisierung des Trackers noch eine Projectionmatrix berechnet, die dann auch in jedem Schleifendurchlauf an die Engine weitergegeben wird. Die Engine zeichnet die vom Programmierer angelegte Szene. Dazu wird die vom Tracker angereichte View- und Projectionmatrix genutzt, um die 3D-Objekte korrekt zur realen Welt zu platzieren. Mit diesen und aus der Szene, ermittelt die Engine sämtliche zu zeichnenden Werte und übergibt sie an die Shader, um sie zu zeichnen. Die Shader nehmen je nach ihrer Aufgabe alle benötigten Werte entgegen und berechnen die gewünschten Effekte. Bei mehreren Auswahlmöglichkeiten zu einem bestimmten Effekt (bspw. Beleuchtung), werden vom Benutzer festgelegte Entscheidungen mittels Variablen übermittelt. Die durch die ausgewählten Effekte berechneten Farb- oder Tiefenwerte werden wieder an den Renderer zurückgegeben. Die Ergebnisse der verschiedenen Shader werden verknüpft und das finale Renderergebnis an das Framework übermittelt. Das Renderergebnis wird anschließend in der Frameworkkomponente mit dem Livekamerabild überlagert, wodurch sich das fertige Ergebnis eines Verarbeitungsdurchgangs ergibt. 3.2 Schnittstellen der Engine Integration der Engine ins Framework Autoren: Nils Lichtenberg und Axel Peter Ein Renderer wird unter Android innerhalb einer speziellen View-Klasse, der GLSurfaceView realisiert. Diese ist zunächst mit einer normalen SurfaceView vergleichbar, bietet aber zusätzliche Funktionen, die es ermöglichen OpenGL-Inhalt darzustellen und in einem gesonderten Thread zu produzieren, um den Hauptthread der Anwendung nicht zu beeinflussen (siehe [Andc]). Außerdem wird hier festgelegt welche OpenGL-Version genutzt wird und mit welcher Farbtiefe gerendert werden soll. Die Farbtiefe ist im AiRmob-Framework aus Rücksicht auf die Performance standardgemäß auf 16 Bit eingestellt - hierbei wird ein Bit für den Alphakanal verwendet. Des Weiteren kann das Rendern auf einen kontinuierlichen oder Rendernauf-Anfrage -Modus eingestellt werden. Beim kontinuierlichen Rendern nutzt der Renderer all seine verfügbaren Ressourcen und wird nur durch die gerätespezifische vertikale Synchronisation eingeschränkt. Bei der alternativen Einstellung muss der Renderer stets zum Rendern eines neuen Bildes aufgefordert werden. Für diesen Fall bietet das Framework die Möglichkeit, für jedes getrackte Kamerabild ein Bild zu rendern. Darüber hinaus ist es dem Benutzer überlassen zusätzliche Renderanfragen zu integrieren. Das eigentliche Rendern übernimmt eine Klasse, die das GLSurfaceView.Renderer-Interface implementiert. Eine 14

16 solche Klasse kann an eine Instanz der GLSUrfaceView gekoppelt werden, um gerenderte Bilder dort anzuzeigen. Der konkrete Renderer der AiRmob-Engine implementiert die abstrakte Superklasse AiRmobRenderer. Diese Superklasse stellt grundlegende Funktionalitäten zur Kommunikation mit dem restlichen Framework zur Verfügung. Dazu gehört die Verwaltung von Modellen, bei welcher die AiRmob-Engine und die AiRmob-Activity eng zusammen arbeiten. Das ist nötig, damit auf in der Engine erstellte Objekte in der Activity zugegriffen werden kann. Hierfür legt man die Objekte erst im Renderer an und veröffentlicht sie dann mit einem Namen in einer HashMap. Auf die HashMap kann von der Activity aus zugegriffen werden. Diese Funktionalität ist typunabhängig und deckt somit alle Implementationen von Objekten ab. Im konkreten Fall der AiRmob-Engine werden Objekte vom Typ Parent registriert und die zurückgegebenen Objekte müssen in der Activity dementsprechend nach Identifier oder Group gecasted werden. Diese implementieren die grundlegenden Funktionen der Manipulation von Modellen, wie Transformationen und Sichtbarkeit. Auf die Zusammenhänge der Objekte wird in Abschnitt 4.3 genauer eingegangen. Ein weiterer wichtiger Aspekt der Kommunikation zwischen Framework und Engine stellen die Interaktionen von Benutzern mit dem von OpenGL erzeugten 3D-Raum dar. Als erstes ist hierbei das Picking zu nennen. Beim Picking tippt der Benutzer auf den Bildschirm des Gerätes, um ein Modell auszuwählen. Um dies zu ermöglichen muss die Activity eine Anfrage mit den passenden Bildschirmkoordinaten, also an der Stelle an welcher getippt wurde, an die Engine schicken. Der Renderer registriert die Anfrage und speichert sie. Im nächsten Draw-Aufruf wird dann ein Bild gerendert, in dem alle Modelle einen eigenen Farbwert haben. Aus diesem Bild wird der Farbwert der Bildschirmkoordinate ausgelesen und der zugehörige Identifier an die Activity zurückgegeben. Da hier auf den nächsten Renderframe gewartet wird, läuft die Rückgabe asynchron ab. Dies wird durch die Verwendung des Runnable-Interfaces umgesetzt. Sobald ein Identifier gefunden wurde, wird die AiRmobActivity davon in Kenntnis gesetzt und eine Referenz auf den Identifier übertragen. Die Weiterverarbeitung wird dann an die Warteschlange der AiRmobActiviy gehängt und zu einem gegebenen Zeitpunkt durchgeführt. Wie das im Detail funktioniert wird in der Arbeit von Nils Lichtenberg beschrieben. Wie das Bild für das Picking erstellt und dem Farbwert ein Identifier zugeordnet wird, wird in Abschnitt erläutert. Weitere Interaktionsmethoden werden von der AiRmob-Activity bereitgestellt. Hierzu zählen das Mappen von Bildschirmkoordinaten auf die Markerebene und das Rotieren von Modellen in Abhängigkeit von Bildschirmeingaben. Nötig sind dazu jeweils die aktuelle Projection- und Model-Matrix. Diese werden vom Renderer bereitgestellt. Die Umsetzung erfolgt in der Arbeit von Nils Lichtenberg. 15

17 3.2.2 Verwendung der Shader Autoren: Philipp Brandt und Axel Peter Zum Zeichnen der Szene müssen den verschiedenen Shadern von der Engine sämtliche dafür benötigten Werte und Texturen übermittelt werden. In der AiRmob-Engine gibt es einen festen Ablauf bestehend aus austauschbaren Shadern. Dabei benötigen die Shader teilweise die Ergebnisse anderer Shader. Die Funktionsweisen und die Theorie hinter den einzelnen Shadern wird in der Arbeit von Philipp Brandt erläutert, während der Renderablauf und die Engine in dieser Arbeit in Abschnitt 4 beschrieben werden. Es werden jeweils ein Vertex- und Fragmentshader für jede Aufgabe verwendet. Diese Aufgaben sind in der AiRmob-Engine zum einen das eigentliche Zeichnen in den Hauptshadern, das Zeichnen von Texten in den Textshadern, das Zeichnen einer Pickingtextur in den Pickingshadern, das Zeichnen der Modelle als Outlines in den Outlineshadern sowie das Erstellen der Tiefentexturen in den DepthShadern. Zusätzlich werden noch extra Shader für das Post-Processing verwendet. Im Folgenden sollen diese Shader kurz mit ihrem benötigten Input und dem was sie erzeugen vorgestellt werden. Hauptshader Im Hauptshader werden alle Berechnungen auf Vertex- und Pixelebene ausgeführt, die nicht dem Post-Processing entsprechen. Hierzu zählen Beleuchtung, Schatten und Mapping. Die Pfade der Hauptshader sind in den Variablen mainvertexshader und mainfragmentshader gespeichert. Die Funktionalität dieses Shaders ist durch den Benutzer steuerbar. Er hat die Auswahl zwischen drei verschiedenen Beleuchtungsmodellen (mit oder ohne Spotlighteinschränkung), aktiviertem oder nicht-aktiviertem Schatten, sowie Bump-, Parallax- oder keinem Mapping. Diese Effekte sind - bis auf wenige Ausnahmen - frei kombinierbar. Die Elemente sind bei Bedarf frei erweiterbar, indem den Übergabeparametern ungenutzte Werte mitgegeben werden, die man im Hauptshader mit eigenen implementierten Algorithmen abfängt. Neben den Shadern main.vert und main.frag wird ein weiteres Shaderpaar onelight_main.vert und onelight_main.frag zur Verfügung gestellt, welches alle Berechnungen für genau eine Lichtquelle durchführt. Diese Shader sind speziell für schwächere Hardware oder Szenen, die nur eine Lichtquelle verwenden, konzipiert. Wie teuer die Berechnung mehrerer Lichtquellen ist, wird in der Arbeit von Philipp Brandt gezeigt. Die Implementation zielt darauf ab, verschiedene Modelle leicht kombinierbar zu gestalten und trotzdem Erweiterbarkeit möglich zu machen. 16

18 Depthshader Der Depthshader arbeitet dem Hauptshader zu und ist deshalb von diesem abgekapselt. Er erstellt eine Textur der Tiefenwerte der Szene aus Sicht der Lichtquellen. Diese wird benötigt um Schatten zu realisieren. Da zuerst eine vollständige Textur der Szene vorliegen muss, bevor einzelne Objekte final gerendert werden können, ist es nicht möglich, diese Berechnung mit dem Hauptshader zu vereinen. Der Shader wird, falls für eine Berechnung notwendig, automatisch aktiviert und bedarf keiner weiteren Einstellung durch den Benutzer. Deaktiviert dieser in den Settings alle Modi, die die Tiefentextur nicht benötigen, so wird der Shader nicht aufgerufen, um unnötige Performanceeinbußungen zu vermeiden. Die Pfade zu diesem Shader werden in den Variablen depthvertexshader und depthfragmentshader abgelegt. Blur- und Bloomshader Beim Blurshader handelt es sich um einen IPP Shader, der die Textur der fertigen Szene benötigt, um darauf arbeiten zu können. Wie bei allen IPP Shadern ist es somit nicht möglich, ihn in den Hauptshader zu integrieren. Der Benutzer steuert über Eingaben den Blurring Effekt. Er hat die Auswahl zwischen einem einfachen Blurmodell und dem Modell nach Gauß. Beide Algorithmen benötigen die Eingabe eines Radius. Bei letzterem wird zusätzlich ein sigma-wert übergeben. Die Pfade für diesen Shader befinden sich in blurvertexshader und blurfragmentshader. Bei deaktiviertem Blurring wird dieser Shader ebenfalls, zur Schonung der Performance, nicht aufgerufen. Die Implementation von Bloom sieht vor, dass eine Textur erstellt wird, welche durch Blurring modifiziert und mit der regulären Fullscreen-Textur vereint wird. Durch aktiviertes Blooming wird der Blurshader automatisch zur Verfügung gestellt. Die Auswahl der Bloom-Textur kann durch unterschiedliche Algorithmen variieren. Das Erzeugen dieser Textur wird durch einen eigenen Shader gesteuert, der bei aktivem Bloom aufgerufen wird. Er ist, wie alle Shader, austauschbar und seine Pfade in den Variablen bloom- VertexShader und bloomfragmentshader gespeichert. Text-, Picking- und Outlineshader Die Shader, die zum Zeichnen von Texten, der Pickingtextur und von Outlines verwendet werden, sind alle sehr simpel und berechnen einfach die Position der Vertizes. Für die Farbe setzten sie konstant einen mitgegebenen Farbwert. Die AiRmob-Engine verwendet unterschiedliche Shader für diese Aufgaben, um ein Erweitern dieser zu erleichtern. Falls beispielsweise texturierter Text gewünscht ist, müssten dazu lediglich die Textshader ausgetauscht und die Textur zusammen mit den Texturkoordinaten im Renderer übergeben werden. Sie können in den Einstellungen über die Strings pickingvertexshader, textvertexshader, outlinevertexsha- 17

19 der (für die Fragmentshader dementsprechend) verändert werden. Fullscreenshader Der Fullscreenshader wird zum Zeichnen von bildschirmfüllenden Rechtecken genutzt, also beispielsweise nach Post-Processing-Effekten. Die in den Variablen fullscreenvertexshader und fullscreenfragmentshader angegebenen Pfade werden für diese Shader benutzt. Die Standardimplementierung setzt einfach den Wert der Textur als Farbe. Alle Shader können in den Einstellungen unter den jeweils genannten Variablen ausgetauscht werden. Neue Implementationen müssen dann die gleichen Bezeichnungen für Uniforms und Attributes verwenden Tracker Autoren: Florian Kathe und Axel Peter Die Schnittstelle zum Tracker besteht nur in der Übergabe der View- und Projektion-Matrix des Trackers an die Engine. Dies geschieht mittels der Funktion setcameralookat, welche sich in der abstrakten Renderer-Superklasse befindet und somit von sämtlichen Implementationen dieser verlangt wird. Der Funktion muss eine Instanz der Klasse CameraViewMatrix des Frameworks mitgegeben werden. In der genannten Klasse befinden sich dann die View- und Projectionmatrix. Durch obige Matrizen ergibt sich das Koordinatensystem in dem sich alle Objekte einer Szene befinden. Es handelt sich dabei um ein Rechtssystem bei dem die Z-Achse von der Markerebene weg nach oben zeigt (bei Blick auf den Marker gegen die Blickrichtung), wie in Abbildung 2 zu sehen. Transformationen von Modellen werden dementsprechend ausgeführt. 18

20 Abbildung 2: Koordinatensystem auf dem Marker 3.3 Austauschbarkeit Autoren: Nils Lichtenberg und Axel Peter Neben der Verwendung der AiRmob-Engine ist es auch möglich eigene Engines in das Framework zu integrieren. Diese müssen dazu gewisse Konventionen einhalten, damit die Kommunikation mit dem Rest des Frameworks funktioniert. Abbildung 3 zeigt die Klasse AiRmobRenderer im Zusammenhang mit dem für sie relevanten Ausschnitt der AiRmobActivity. 19

21 AiRmobRenderer surfacecreateddone : boolean lastsynchframerate : int lastrealfreamrate : int cameraanglehorizontal : float cameraanglevertical : float mcontext : Context availableobjects : HashMap messagehandler : Handler setmatrizes(cameraview : CameraMatrizes) : void pick(x : int,y : int) : Object setvideobackground(bmp : Bitmap) : void pickingactivated() : boolean freezecamera(freeze : boolean) : void renderercreateddone() : void rendererchangeddone() : void registerobject(obj : Object,name : String) : void getobjectbyname(name : String) : Object 1 1 enthält > 1 1 enthält > 1 1 enthält > 1 1 RendererCreatedRunnable run() : void RendererChangedRunnable run() : void id : Object run() : void PickRunnable AiRmobActivity onrenderercreated() : void onrendererchanged() : void onpick(id : Object) : void Abbildung 3: AiRmobRenderer Um Engines im AiRmob-Framework verwenden zu können, müssen diese von der abstrakten Klasse AiRmobRenderer abgeleitet werden. Diese gibt einige Felder und Funktionen zur Kommunikation mit dem Framework vor. Bei der Initialisierung einer jeden so abgeleiteten Klasse werden ihr der Android-Context und die Kameraöffnungswinkel mitgeteilt. Der Context dient zum Zugriff auf das Dateisystem, während die Öffnungswinkel der Kamera bei der Berechnung einer eigenen Projectionmatrix genutzt werden können. In der HashMap availableobjects können 3D-Objekte mit der Methode registerobject mit einem Namen registriert werden, um der AiRmobActivity Zugriff auf diese zu ermöglichen. Sie fragt Objekte anhand des bei der Registrierung gewählten Namen mit der Methode getobjectbyname ab. Um eine korrekte Anzeige von FPS zu ermöglichen, müssen die Felder lastsynchframerate und lastrealframerate von einer Implementation entsprechend gesetzt werden. Die Funktion setvideobackground wird vom Framework aufgerufen, wenn das Kamerabild als Bitmap an die Engine weitergegeben werden soll. Mit freezecamera wird ein einziges Kamerabild an die Engine geschickt. Es soll dazu genutzt werden ein Standbild anzuzeigen. Mit setmatrizes teilt das Framework der Engine die im Tracking ermittelten View- und Projectionmatrizen mit. Diese werden mit der Klasse CameraMatrizes über- 20

22 mittelt. Die Methode pick stößt wie in Abschnitt beschrieben einen asynchronen Aufruf unter Verwendung des PickRunnable an. In einer konkreten Implementation muss in dieser Methode das eigentliche Picking durchgeführt und das so gefundene Objekt durch Aufruf des Runnables in der AiRmobactivity zurückgegeben werden. Die zwei weiteren Runnables RendererCreatedRunnable und RendererChangedRunnable können dazu verwendet werden, das Framework über den Abschluss der Methoden onsurfacecreated und onsurfacechanged zu informieren. Der Handler messagehandler wird dazu benutzt, die Runnables in die Warteschlange der AiRmobActivity einzugliedern. Eine Spezialisierung des AiRmobRenderers, die die genannten Vorgaben berücksichtigt, kann die Funktionalitäten des Frameworks im vollen Umfang ausnutzen und problemlos als Renderer in die Pipeline des Frameworks integriert werden. 4 AiRmob-Engine In diesem Abschnitt wird auf die von mir im Rahmen dieser Arbeit entwickelte Engine eingegangen. Hierzu werden zunächst die für sie gesetzten Ziele für die Bedienung sowie technischen Möglichkeiten aufgezeigt und später über die allgemeine Struktur hin spezifischer werdend Klassen und Funktionen vorgestellt. 4.1 Ziele Bedienung Als ein wichtiges Ziel der AiRmob-Engine habe ich eine leichte Bedienbarkeit gesehen, sowie die Möglichkeit schnell und unkompliziert erste Ergebnisse zu erreichen. Durch die Möglichkeiten einer programmierbaren Pipeline in OpenGL ES 2.0 muss der jeweilige Entwickler zunächst selbst eine vollständige Pipeline programmieren, bevor er 3D-Inhalte visualisieren kann. Hierzu müssen ein Vertex- und Fragmentshader erstellt und an OpenGL weitergegeben werden. An diese müssen Daten übergeben werden, wie die Vertices der Modelle und die verschiedenen Matrizen. Möchte er texturierte und beleuchtete Objekte auf den Bildschirm bringen, müssen Texturen geladen und Lichtquellen angelegt werden. In den Shadern müssen die Berechnungen für Licht und Texturen programmiert werden. Das sollte natürlich möglichst effizient geschehen. So weitergehend wird es schnell ein größeres Unterfangen eine vollständige Szene echtzeitfähig zu zeichnen. Darüber hinaus fallen in OpenGL ES einige bekannte Möglichkeiten der Programmierung weg, so dass man ohne eine Vertiefung in die Sprache nur 21

23 schwer vorankommt. Diese anfängliche und oft redundante Arbeit, welche zum Darstellen von OpenGL ES 2.0 Inhalten erforderlich ist, sollte dem Benutzer erspart bleiben. Um bspw. einen Würfel korrekt in der 3D-Umgebung und auf dem Marker des Trackers anzuzeigen, sollte nur sehr wenig Code nötig sein. In Pseudocode könnte ein wünschenswerter Aufruf so aussehen: Pseudocode zum Anlegen eines Würfels in einer Szene Lege eine Szene an ; Lege einen Würfel an ; Füge den Würfel zur Szene hinzu ; Zeichne d i e Szene ; Ein solcher Ablauf setzt natürlich voraus, dass ohne weitere Angaben des Programmierers ein Set an Standardeinstellungen bereitgestellt wird. Darüber hinaus sollten fortgeschrittene Programmierer auch die Möglichkeit haben diese Einstellungen zu ändern. So sollten Shader, Einstellungen für Licht, Texturen und Weiteres leicht austauschbar sein. Auf diese Einstellungen sowie die Standardwerte für diese wird in Abschnitt 4.6 eingegangen, während die out-of-the-box vorhandenen technischen Möglichkeiten im nächsten Abschnitt genannt werden. Auch stellt bei einem AR-System die Schnittstelle zu den Kameraeingaben einen wichtigen Aspekt dar. Die View- und die Projection-Matrix müssen an die Ausgaben der Trackerkomponente und die Parameter der Kamera angepasst sein. Auf die Schnittstellen des Renderers zu dem Tracker und der Kamera wurde in Abschnitt eingegangen. Um diese Ziele zu erreichen, sollten Szenen in Java und Objektorientiert programmierbar sein, während die eigentlichen Berechnungen und die Open- GL ES 2.0 Aufrufe verborgen sind. Wenn nicht anders gewünscht soll die Engine Standardeinstellungen laden und dadurch das Sichtbarmachen eines Modells ohne viel Aufwand möglich machen. Sowohl für simple als auch für fortgeschrittene Anwendungen soll bereits ein Set an Möglichkeiten vorhanden sein Angestrebte Features Hier werden nun die Features beschrieben, welche die Engine out-of-thebox für den Programmierer bieten soll. Da im Vorfeld nicht bekannt war, welche Schwierigkeiten bei der Programmierung mit Android und OpenGL ES 2.0 auftreten würden, sind die Ziele eher allgemein formuliert. 22

24 Es sollen Modelle und Lichtquellen angelegt und transformiert werden können. Für diese soll Multiinstanziierung möglich sein. Sie sollen im Sinne eines Szenegraphen hierarchisch miteinander verbunden sein mit Gruppen als Knoten und Modellen oder Lichtquellen als Blättern. Es sollen externe Modelle, die in 3D-Grafikprogrammen erstellt wurden importiert werden können. Zusätzlich sollen bereits einige vorgegebene Modelle verfügbar sein. Neben statischen Modellen sollen auch Einzelbild-Animationen auf gleiche Weise verwendbar und importierbar sein. Es sollen Texte im 3D-Raum aus einfachen String-Eingaben erzeugt und angezeigt werden können. Externe Bilddateien sollen importiert und daraus Texturen erstellt werden können. Es sollen die von Philipp Brandt programmierten Shader ausgeführt und die dafür benötigten Daten bereitgestellt werden. Die Shader sollen austauschbar sein. Die vom Tracking ermittelten Matrizen sollen verwendet werden. Es soll ein vom Tracking losgelöster Betrieb möglich sein. In einer zentralen Klasse für Einstellungen sollen diese gesammelt sein und mit ihr alle gewünschten Einstellungsmöglichkeiten an die Engine gewählt werden können. Diese Einstellungen sollen wenn nötig an die Shader weitergegeben werden (um beispielsweise zwischen Gouraud- und Phongbeleuchtung zu wechseln). Im Vergleich zu Abschnitt 2.5 sind einige Features, die Irrlicht und jpct-ae beinhalten keine Ziele für die AiRmob-Engine. Zunächst führt die AiRmob- Engine kein View-Frustum-Culling im Scene Management durch. Es schien uns für AR-Anwendungen nicht sehr wichtig, da die Objekte einer Szene im Zusammenhang mit einem Marker gezeigt werden und dieser dazu im Bild sein muss. Auch können verschiedene Szenen je nach aktuell erkanntem Marker ausgetauscht werden, so dass nur die für diesen Marker gewünschte Szene aktiv ist. Des Weiteren sind Partikeleffekte kein Ziel dieser Arbeit, weil sie ihren Rahmen sprengen würden. 23

25 Da OpenGL ES nur Dreiecke und keine Polygone erlaubt, soll die AiRmob- Engine auch nur Modelle aus Dreiecken bestehend erwarten. Ziel dabei war nur der Import aus einem Dateiformat. Die Unterstützung weiterer Formate sollte leicht nachgerüstet werden können Programmierung in Java Wie zuvor erwähnt sollen Programmierer in Java und objektorientiert mit der AiRmob-Engine arbeiten können. Das ist insbesondere ein Ziel, da auch die Programmierung mit dem restlichen Framework in Java geschieht. Durch die Verwendung des Android NDK ist es möglich Engines in C/C++ zu programmieren. Dies kann gerade bei der Verarbeitung großer Datenmengen, wie beispielsweise beim Import von Modellen, effizienter sein. Nichtsdestotrotz wird die AiRmob-Engine komplett in Java programmiert. Ein Grund dafür ist, dass durch die nötige Kommunikation zwischen Framework und Engine bei der Verwendung des NDKs zusätzliche Kosten anfallen würden, da die Daten von der JVM übergeben werden müssten. Der Anwender müsste Szenen dann in C/C++ anlegen, während er das restliche Framework in Java bedient. Zusätzlich soll die AiRmob-Engine durch die Programmierung in Java leichter zu verstehen sein, da unnötige Kommunikationsprozesse mit dem Framework wegfallen und der Code dadurch weitaus kürzer wird und viel Boilerplate-Code wegfällt. 4.2 Übersicht In diesem Abschnitt soll der Aufbau der gesamten AiRmob-Engine erläutert werden. Hierzu wird zunächst eine Übersicht aller Komponenten gegeben. In den weiteren Abschnitten werden dann die einzelnen Komponenten dargestellt. Insbesondere auf den Ablauf eines Renderdurchlaufs und die konkrete Implementierung des Renderers wird in Abschnitt 4.5 anhand seiner Funktionen detaillierter eingegangen. Grob unterteilt sich die Engine zunächst in drei Komponenten und der zu zeichnenden Szene sowie den Einstellungen (Settings): dem Renderer, dem Resource- und dem SceneManager, (Abb. 4). ResourceManager 1 1 Renderer scene : Scene settings : Settings 1 1 SceneManager Abbildung 4: Erste Unterteilung der AiRmob-Engine Bei der Programmierung mit AiRmob wird nur ein Renderer und eine Szene angelegt. Der Renderer erzeugt für sich selbst einen SceneManager und 24

26 einen ResourceManager. Dem Renderer muss die zu zeichnende Szene mitgeteilt werden. Somit ist der Renderer die zentrale Komponente, welche das Resource- und das Scene-Management steuert. Grob lässt sich der Ablauf bis zum Zeichnen einer Szene wie folgt beschreiben: Es wird eine Szene und ein Renderer angelegt, dann wird die Szene dem Renderer zugewiesen. Der Renderer legt einen Resource- sowie einen SceneManager an. Alle in der Szene vorhandenen Objekte werden vom Programmierer erzeugt. Im ResourceManager werden die dafür benötigten Ressourcen in das System geladen. Sobald alle nötigen Ladeoperationen abgeschlossen sind, gibt der Renderer die Szene an den SceneManager, welcher den Szenengraphen aufbaut und die zu zeichnenden Objekte in einer Liste an den Renderer zurück gibt. Der Renderer führt nun für jeden Frame die nötigen Zeichenoperationen aus. In den nächsten Abschnitten werden Renderer, Scene- und ResourceManager genauer vorgestellt. Auf das Anlegen einer Szene, das Anhängen weiterer Modelle und die dabei verwendeten Klassen wird im Abschnitt 4.3 eingegangen. Die Einstellungen werden in den folgenden Abschnitten immer erwähnt, wenn sie entsprechende Auswirkungen haben. Eine komplette Übersicht über alle Einstellungen wird in Abschnitt 4.6 gegeben Renderer Der Renderer stellt die zentrale Komponente der AiRmob-Engine dar. Er wird direkt vom Programmierer angelegt und bekommt die zu zeichnende Szene zugewiesen. Neu anzulegenden Modellen muss der verwendete Renderer mitgeteilt werden, damit dessen ResourceManager die benötigten Ressourcen laden kann. Auch kommuniziert der Renderer mit den anderen Teilen des Frameworks, ihm werden also beispielsweise die im Tracking erzeugten Matrizen übermittelt und Anfragen für Picking-Tests von ihm entgegengenommen und beantwortet. Die Renderer-Klasse wird von der abstrakten AiRmobRenderer-Klasse abgeleitet, welche wiederum das Interface GLSurfaceView.Renderer implementiert. Dieses Interface ist ein von Android vorgegebenes Interface zur Kommunikation mit OpenGL [gls]. Dazu werden die Funktionen onsurfacecreated, onsurfacechanged und ondrawframe verwendet. Weitere Funktionen der AiRmobRenderer-Klasse, die zur Kommunikation mit dem Rest des Frameworks benutzt werden, wurden im Abschnitt 3.2 beschrieben, da sie die Schnittstelle zum Framework darstellen. Die drei genannten Funktionen werden zu verschiedenen Zeitpunkten von Android aufgerufen. Die Funktionen onsurfacecreated und onsurfacechanged werden beim Erstellen einer OpenGL-Oberfläche sowie dem Ändern dieser aufgerufen. Änderungen passieren hierbei insbesondere dann, wenn das Gerät gedreht wird, also von Hochkant zu Breitbild gewechselt wird und umgekehrt. Die Funktion ondrawframe wird in jedem Frame aufge- 25

27 rufen, um das Bild zu zeichnen [sur]. Anhand dieser drei Funktionen sowie der zum eigentlichen Zeichnen von Modellen und Lichtern wird in Abschnitt 4.5 der interne Ablauf beim Erstellen eines Renderers mit einer Szene sowie der eines jeden Zeichendurchlaufs erläutert SceneManager Der SceneManager bekommt vom Renderer die Szene und soll den Szenengraphen aufbauen, um anschließend eine sortierte Liste von zu zeichnenden Objekten zurückzugeben. An der Szene hängen beliebig viele Objekte. Das können entweder Knoten sein, die weitere beliebig viele Objekte beinhalten, oder ein Blatt, welches ein einzelnes zu zeichnendes Objekt beinhaltet. Welche Objekte Knoten, welche Blätter und was Modelle in der AiRmob-Engine sind, wird im Abschnitt 4.3 beschrieben. In diesem Abschnitt werden nur Knoten (mit beliebig vielen Knoten oder Blättern als Kindern) und Blätter unterschieden. Die gesamte Szene ist dabei einfach ein besonderer Knoten an den sämtliche Objekte gehängt werden müssen. Im SceneManager wird also von der Szene aus über jedes an sie gehängte Objekt traversiert und wenn dieses Objekt ein Knoten darstellt, rekursiv auch über alle ihm angehängten Objekte. Dabei wird die Transformationsmatrix jeden Objektes mit der bis zu diesem Punkt im Graphen bereits akkumulierten Transformationsmatrix multipliziert und auf einem Stack gespeichert. Sobald der SceneManager auf ein Blatt stößt wird das angehängte Modell mit der bis hierhin akkumulierten Transformationsmatrix zur Output-Liste hinzugefügt. Anschließend wird im Szenengraphen wieder eine Ebene nach oben gegangen und dementsprechend die oberste Transformationsmatrix vom Stack entfernt. In Pseudocode sieht die Funktion zum Erstellen des Szenengraphen wie folgt aus: Pseudocode zum Erstellen des Szenengraphen (mit Matrix ist hier jeweils die Transformationsmatrix gemeint) public void build ( Knoten Objekt ) { i f ( Objekt i s t Szene ) { lege einen neuen Stack an ; lege Matrix der Szene auf den Stack ; } e lse { m u l t i p l i z i e r e oberste Matrix vom Stack mit Matrix von Objekt ; lege das Ergebnis auf den Stack ; } i f ( Objekt i s t B l a t t ) { 26

28 } füge Objekt mit der obersten Matrix vom Stack zur Output L i s t e hinzu ; i f ( Objekt i s t Knoten ) { for ( j e d e s Kind des Knotens ) { build ( Kind ) ; } } } e n t f e r n e oberste Matrix vom Stack ; return ; Es werden alle Matrixmultiplikationen bei dem Erstellen des Szenengraphen berechnet. Dadurch wird vermieden, dass diese Operationen bei jedem ondrawframe-aufruf im Renderer durchgeführt werden müssen. In der Output-Liste befinden sich dann jeweils die zu zeichnenden Objekte mit ihren Transformationen, ohne dass weitere Multiplikationen nötig sind, um die Modelmatrix zu erhalten. Der SceneManager schließt dabei keinerlei Modelle aus. Es wird also insbesondere, wie in den Zielen erwähnt, kein View-Frustum-Culling durchgeführt. Da bei AR-Anwendungen Modelle in direktem Zusammenhang zu dem vom Tracking erkannten Marker/Bild stehen, muss sich dieser für sinnvolle Anzeigen auch im Bild befinden. Dadurch wird auch der OpenGL-Raum stark eingeschränkt. Zwar sind durchaus Szenarien denkbar, in denen eine große Anzahl von Modellen nichtsdestotrotz durch Culling entfernt werden könnten. Grundsätzlich jedoch, waren wir der Meinung, dass die Kosten den Nutzen überwiegen würden, weshalb die AiRmob- Engine auf Culling verzichtet. Den SceneManager um einen entsprechenden Durchlauf zu ergänzen, würde jedoch möglich sein. Nachdem die Liste aller Modelle erstellt wurde, wird sortiert. Hierbei werden zunächst alle undurchsichtigen Modelle, dann alle durchsichtigen und dann Texte einsortiert. Wenn mehrere transparente Modelle in der Szene vorhanden sind, können sie zusätzlich nach der Distanz zur Kamera von hinten nach vorn sortiert werden. Diese Sortierung wird unabhängig vom eigentlichen Erstellen der Liste durchgeführt. Es wird hierbei zunächst die Distanz für jedes transparente Modell zur Kamera berechnet. Hierzu wird einfach der erste Vertex eines Modells mit den entsprechenden Matrizen multipliziert und die Länge des Vektors gespeichert. Anschließend wird sie mit denen aller anderen Modelle verglichen. Die Sortierung ist natürlich eher grob und nicht immer korrekt. 27

29 Ob nach Distanzen sortiert werden soll, kann entweder manuell aus- oder eingeschaltet werden, oder es kann der Engine überlassen werden dies automatisch zu entscheiden. In diesem Fall wird sortiert, wenn zwei oder mehr transparente Modelle in der Szene vorhanden sind. Die in Abschnitt vorgestellten Texte werden als letztes und am Stück gezeichnet, da für sie die Shader gewechselt werden. Eine weitere Sortierung nach State-changes wird nicht durchgeführt. In Hinsicht auf Shader- Wechsel finden sie allerdings auch nicht statt, da ja nur ein Paar von Hauptshadern verwendet wird. Da das Traversieren über alle Objekte und die Multiplikation der Transformationsmatrizen teuer sind, wird der Szenengraph nur dann neu gebaut, wenn es wirklich nötig ist. Es wird dem Renderer automatisch mitgeteilt, wenn ein Objekt transformiert oder etwas Neues zur Szene hinzugefügt wurde. Da sich die Kamera bei einer AR-Anwendung quasi ständig bewegt, muss bei aktivierter Sortierung von transparenten Objekten nach Distanz diese für jeden Zeichendurchlauf durchgeführt werden ResourceManager Der ResoureceManager ist dafür zuständig, externe Dateien der Engine verfügbar zu machen. Dabei handelt es sich um die Dateien der Modelle und die Bilder zur Erstellung von Texturen und BumpMaps. Der Import wird dabei in der onsurfacecreated-funktion durchgefürt, da der OpenGL- Kontext sonst nicht bekannt ist. Das bedeutet, dass Objekte erst dann geladen werden, wenn sie zur Szene hinzugefügt wurden und diese Szene von einem Renderer verarbeitet wird. Wenn der Benutzer ein Modell anlegt, muss er dabei dem Konstruktor den verwendeten Renderer mitteilen. Der Renderer ruft dann die entsprechende Funktion des ResourceManager auf. In dieser wird der Import dann abgewickelt. Wie Modelle in das System geladen und welche Dateien dafür benötigt werden, also was aus der 3D-Grafiksoftware exportiert werden muss, wird im Abschnitt beschrieben. Für die Texturierung der Modelle müssen natürlich auch Bilder in das System importiert werden. Dieses wird in Abschnitt erläutert. Grundsätzlich ist es noch Aufgabe des ResourceManager zu überprüfen, ob sich ein Modell bzw. eine Textur bereits im System befinden. Dazu überprüft er anhand einer Liste aller bisherigen Importe, ob der Pfad der neu zu importierenden Datei bereits bekannt ist und gibt gegebenenfalls eine Referenz zurück, anstatt erneut zu importieren. Neben Modellen und Texturen werden im ResourceManager auch die Shader in das System geladen. Zusätzlich werden diese im ResourceManager zu einem Programm zusammengefügt und dem Renderer eine Referenz zu diesem zurückgegeben. 28

30 4.2.4 Austauschbarkeit von Scene- und ResourceManager Wenn der SceneManager oder die Vorgehensweisen beim Import von Modellen komplett geändert werden sollen, bietet es sich an, den Scene- oder ResourceManager zu ersetzen. Um dies zu erleichtern, besitzen die beiden Klassen die Interfaces SceneManagerInterface und ResourceManager- Interface. Sie beinhalten die Signaturen aller öffentlichen Funktionen der Klassen und Beschreibungen was diese tun. Dadurch können Klassen, die die Interfaces implementieren und die Bedingungen für Input und Output der Funktionen erfüllen, direkt den Resource- oder SceneManager im Renderer ersetzen. Um das zu ermöglichen nimmt der Renderer zu keinem Zeitpunkt direkten Zugriff auf Felder der beiden Klassen, außer über die in den Interfaces aufgeführten öffentlichen Funktionen. 4.3 Szene und Objekte Die Erstellung einer Szene mit allen Modellen, Lichtquellen und Texten stellt mit den wichtigsten Aspekt für die Programmierung mit der AiRmob- Engine dar. Hier werden nun alle Klassen vorgestellt, die dabei angelegt werden können sowie die dabei verwendeten Vorgehensweisen. Die Abbildung 5 zeigt eine Übersicht über alle Klassen, die nun genauer erläutert werden. Alle Arten von Modellen, Lichtquellen und Texten werden von der abstrakten Klasse Object abgeleitet. Diese dient hauptsächlich dazu, im SzeneManager kompositionale Programmierung zu ermöglichen. Sie besitzt eine Byte-Variable zur Angabe des Typs des Objektes sowie eine Boolean die angibt, ob das Objekt Kinder besitzt, um instanceof Tests mit anschließenden Casts im SzeneManager zu vermeiden. 29

31 Abbildung 5: Übersicht aller Objekte Parents Die vom SceneManager verwendeten Objekte sind von der abstrakten Klasse Parent abgeleitet. Abbildung 6 zeigt alle Objekte vom Typ Parent mit den wichtigsten Funktionen und Feldern. 30

32 Object Identifier child : Model3D animationchild : ModelAnimation modelgroupchild : ModelGroup lightchild : Light textchild : Text Parent colorid : int mtransformationmatrix : float parent : Parent translate(x : float,y : float,z : float) : void rotate(angle : float,x : float,y : float,z : float) : void scale(x : float,y : float,z : float) : void rotatex(angle : float) : void rotatey(angle : float) : void rotatez(angle : float) : void getscene() : Scene Group childern : LinkedList<Parent> add(parent : Parent) : void remove(parent : Parent) : void colornum : int Scene Abbildung 6: Objekte vom Typ Parents: Knoten und Blätter des Szenengraphen Parents können über ihre colorid eindeutig identifiziert werden, was vor allem für Multiinstanziierung und das Picking wichtig ist (siehe Abschnitt 3.2). Jedes Parent kennt dabei seine Herkunft, also den Parent in der Hierarchie über ihm. Auch kann mit der Funktion getscene() die Szene, in der sich das Parent befindet, ermittelt werden. Parents können konkret entweder Identifier oder Groups sein. Identifier stellen im Szenengraphen dabei Blätter dar und Groups Knoten. Ein Identifier wird bei dem Anhängen eines Modells an eine Group automatisch erzeugt und zurückgegeben. Ein Aufruf zum Erhalten eines Identifiers für die spezifische Instanz eines Modells sieht wie folgt aus: Erzeugen eines Identifiers I d e n t i f i e r id = group. add ( model ) ; Der Identifier kann dann benutzt werden um Transformationen durchzuführen. Somit wird es möglich Multiinstanziierungen von Modellen durchzuführen, da durch die Erzeugung von Java-Objekten direkt objektorientiert verschiedene Identifier benutzt werden können. Für das in Abschnitt näher beschriebene Picking wird zusätzlich beim Hinzufügen von der Szene eine colorid erfragt, um einen individuellen Farbwert für jeden Identifier generieren zu können. Ein Identifier verweist immer auf genau ein Kind, welches einer der Modell-Typen, eine Lichtquelle oder ein Text sein kann. Wenn man also beispielsweise einem Auto vier Reifen anhängen möchte, kann man das Reifenmodell viermal zu der Auto-Group hinzufügen und die dabei erzeugten Identifier entsprechend transformieren. Eine Group enthält dementsprechend eine beliebige Anzahl von Parents, welche in einer LinkedList gespeichert werden. Diese Parents können wiederum entweder Identifier oder weitere Groups sein, im Sinn des Szenen- 31

33 graphen also Blätter oder Knoten. Die Befehle um eine Group für ein Auto mit vier Instanzen eines Reifen-Modells zu erzeugen sieht beispielsweise so aus: Erstellen einer Group und Anhängen von Modelle mit Rückgabe des Identifiers Group autogruppe = new Group ( ) ; I d e n t i f i e r karosserieid = autogruppe. add ( k a r o s s e r i e ) I d e n t i f i e r reifen1id = autogruppe. add ( r e i f e n ) ;... I d e n t i f i e r reifen4id = autogruppe. add ( r e i f e n ) ; reifen1id. t r a n s l a t e ( x, y, z ) ;... reifen4id. t r a n s l a t e ( x, y, z ) ; Transformationen auf die autogruppe würden dann sämtliche mit ihr untergeordneten Parents betreffen. In diesem Beispiel würden also die Instanzen der Karosserie sowie die vier Reifen gemeinsam transformiert werden. Die gesamte Szene wird von der Klasse Scene repräsentiert und ist eine spezialisierte Group. An sie muss jedes weitere Parent gehängt werden, wenn es gezeichnet werden soll. Die zu zeichnende Scene muss dem Renderer mitgeteilt werden. Die Group des Autos aus dem vorherigen Beispiel würde zur Szene also wie zu einer Group hinzugefügt werden: scene. add ( autogruppe ) ; Hinzufügen zur Szene Damit wäre das Auto zur Szene hinzugefügt worden, der SceneManager würde die entsprechenden Matrizen berechnen und die Objekte dieser Group an den Renderer weitergeben, damit dieser sie zeichnet. Wie bereits erwähnt, sind im Szenengraphen Groups Knoten mit beliebig vielen Kindern und Identifier-Blättern, deren angehängtes Modell gezeichnet wird. Wie der SceneManager über alle in einer Szene enthaltenen Objekte wandert, wurde in Abschnitt erläutert. Natürlich müssen zunächst Modelle erzeugt werden, bevor sie an Groups angehängt werden können. Die Eigenschaften der unterschiedlichen Modelle und wie sie zu benutzen sind, wird in den nächsten Abschnitten beschrieben. 32

34 4.3.2 Modelle Die zweite wichtige Gruppe von Objekten sind die Modelle. Mit Modellen sind hier sowohl statische 3D-Modelle als auch Animationen gemeint. In der AiRmob-Engine werden vorgegebene und importierte Modelle, Modellgruppen und Animationen unterschieden, wie in Abbildung 7 zu sehen. Object Model3D 1..* 1 Mesh ModelGroup ModelAnimation Vorgegebene Modelle * 1..* ModelCustom Abbildung 7: Alle Modellklassen in der AiRmob-Engine. Im nächsten Abschnitt wird zunächst auf die grundsätzliche Vorgehensweise der AiRmob-Engine bei der Speicherung und Verarbeitung der benötigten Daten von Modellen eingegangen. In den darauffolgenden Abschnitten wird der Import von externen Dateien und dann die unterschiedlichen Modelltypen erläutert Model3D und Mesh Model3D ist die Superklasse für alle verwendeten Modelle. Zwar leiten sich ModelAnimation und ModelGroup nicht direkt von ihr ab, die von ihnen verwendeten ModelCustom-Objekte allerdings schon. Abbildung 8 zeigt die beiden Klassen Model3D und Mesh mit ihren wichtigsten Feldern. 33

35 Object Model3D 1..* 1 Mesh bindexbuffer : ShortBuffer ibuffer : int texture : Texture materialambient : float[] materialdiffuse : float[] materialspecular : float[] materialexponent : float bvertexbuffer : FloatBuffer vbuffer : int Abbildung 8: Model3D und Mesh In der AiRmob-Engine werden die Punkte der Dreiecke der 3D-Modelle in indizierten Vertexlisten gespeichert. Es werden somit Indices und Vertices unterschieden. Dabei werden die Indices als Short-Werte in den Instanzen der Klasse Model3D gespeichert, die Vertices hingegen als Float-Werte in denen der Klasse Mesh. Die Aufteilung der beiden auf zwei Klassen wurde vorgenommen, da dadurch mehrere Modelle auf dieselben Vertices zugreifen können, wenn sie sich überschneiden. Dies kann insbesondere bei ModelGroups Speicher einsparen. Zur Verbesserung der Performance verwendet die AiRmob-Engine auf Wunsch VertexBufferObjects (VBOs). Hierbei werden die Daten von Indices und Vertices bei der Erstellung eines Modells direkt in den Grafikspeicher geschrieben und müssen dadurch nicht bei jedem Draw-Aufruf von CPU zu GPU kopiert werden. Die Verwendung von VBOs kann in den Settings der AiRmob-Engine ein- und ausgeschaltet werden und ist standardmäßig aktiviert. In den Java-Buffern bindexbuffer und bvertexbuffer werden alle Daten zwischengespeichert und wenn keine VBOs verwendet werden, werden diese an die Shader übermittelt. Bei der Verwendung von VBOs hingegen werden mit Hilfe der Java-Buffer zunächst VBOs erzeugt und Referenzen auf diese als Integer-Werte in die Variablen ibuffer und vbuffer gespeichert. Die Referenzen werden dann an die Shader gegeben. In den jeweiligen Vertice-Buffern befinden sich dabei zum einen die Positionen, aber auch die Normalen und Texturkoordinaten. Die Daten werden also wie in Abbildung 9 veranschaulicht gespeichert. Dabei handelt es sich um ein sogenanntes Array of Structures. Im Gegensatz dazu steht die Structure of Arrays, in welcher für Position, Normalen und Texturkoordinaten jeweils eigene Arrays/Buffer verwendet werden. Die Verwendung eines einzelnen Buffern ermöglicht einen effizienteren Speicherzugriff für OpenGL ES [MGS09, S. 107]. 34

36 x y z x y z s t x y z x y z s t... Position Normale Textur. Position Normale Textur. Abbildung 9: Darstellung des Array of Structures (Abbildung [MGS09, S. 105] nachempfunden) ModelCustom und Import von Modellen Für die einfache Verwendung einer Engine stellt der Import externer Dateien einen der wichtigsten Aspekte dar. Entwickler müssen in die Lage versetzt werden, Modelle aus 3D-Grafiksoftware, wie Blender, Cinema4D oder 3Ds Max, importieren und verwenden zu können. Die AiRmob-Engine unterstützt den Import von Dateien im OBJ-Dateiformat (OBJ für object ). Diese können von jedem der genannten Programme exportiert werden [ble] [c4d] (von 3Ds Max nur mittels Plugins, bspw. 3D Ripper DX [3dr]). Das OBJ-Dateiformat wurde von Wavefront Technologies entwickelt und gilt als universelles Format. Der Import findet dabei im ResourceManager statt. Eine von Blender exportierte.obj-datei sieht beispielsweise wie folgt aus: Beispiel einer Datei im OBJ-Format # Kommentare m t l l i b M a t e r i a l d a t e i. mtl o Name v v vt vt vn vn usemtl Materialname1 s 1 f 645/1/1 631/2/2 629/3/3 f 645/1/1 629/3/3 643/4/4... usemtl Materialname2 f 131/379/ /380/ /381/161 f 131/379/ /381/ /382/164 35

37 Nach einigen Kommentaren gibt die erste Zeile hierbei den Namen einer.mtl-datei an (mtl für material ). Die.mtl-Dateien beinhalten Materialeigenschaften und den Pfad zu den verwendeten Bildern für Texturen. Auf den Import dieser Dateien wird im nächsten Abschnitt eingegangen. Darauf folgt der Name des Modells/Objektes (hier einfach Name ). Anschließend werden Vertices, Texturkoordinaten und Normalen angegeben. Diese sind jeweils mit den Tags v, vt oder vn gekennzeichnet. Mit usemtl Materialname1 wird kenntlich gemacht, dass das Material mit Namen Materialname1 aus der.mtl-datei für die folgenden Dreiecke verwendet werden soll. Die Indices dieser Dreiecke werden mit dem Tag f deutlich gemacht. Darauf folgen stets drei Punkte mit jeweils einem Index für Position, Texturkoordinate und Normale. Beim Import von.obj-dateien in die AiRmob-Engine wird Zeile für Zeile der Tag überprüft. Wenn es sich um eine Position, eine Texturkoordinate oder eine Normale handelt werden diese in jeweils einem Buffer gespeichert. Da in der AiRmob-Engine Arrays of structures verwendet werden, können diese Buffer jedoch nicht einfach weiterverwendet werden. Vielmehr müssen Vertices und Indices in einer neuen Reihenfolge gespeichert werden. Dazu wird in einer Schleife für jeden eingelesenen Index aus den einzelnen Buffern von Positionen, Texturkoordinaten und Normalen der passende Eintrag gesucht und an die Stelle des Indexes gesetzt. Wenn Modelle nicht über Texturen verfügen oder keine Normalen gesetzt sind, fehlen diese auch in den exportierten.obj-dateien. Um solche Dateien ebenfalls importieren zu können, müssen einige zusätzliche Abfragen durchgeführt werden. Das Ergebnis ist in jedem Fall ein einzelner Buffer von Indices und einer von Vertices im Sinne des Array of Structures. Bei aktivierten VBOs werden diese anschließend noch in den Grafikspeicher geschrieben und es wird mit Referenzen zu den VBOs gearbeitet. Um eine solche.obj-datei zu importieren, werden Instanzen der Klasse ModelCustom verwendet. Sie erweitert die Model3D-Klasse um die Funktionen die zum Import benötigt werden. Ein ModelCustom wird folgendermaßen angelegt: Importieren einer.obj-datei zum Erstellen eines ModelCustom ModelCustom eigenesmodell = new ModelCustom ( Renderer, Pfad, Dateiformat ) ; Neben dem Renderer müssen also ein Pfad als String und das Dateiformat angegeben werden. Die AiRmob-Engine unterstützt aktuell nur.obj- Dateien, weshalb auch nur der Import dieser in diesem Abschnitt erläutert wird. Auf das Dateiformat und die Erweiterbarkeit um neue Formate wird 36

38 in Abschnitt weiter eingegangen. Beim Anlegen einer Instanz von ModelCustom wird nur das erste Material verwendet. Bei mehrfachem Auftreten von usemtl Materialname wird dieses also schlichtweg ignoriert. Das bedeutet, dass ein ModelCustom für ein Modell nur eine Textur mit einem Set an Materialwerten importiert und dies auf alle in der.obj-datei beschriebenen Dreiecke anwendet. Wenn Modelle mit mehreren Materialien auch als solche importiert werden sollen, kann die Klasse ModelGroup verwendet werden. Diese wird in Abschnitt beschrieben Texturen und Materialien Wie im vorherigen Abschnitt erläutert verweisen.obj-dateien zur Angabe von Materialien auf eine.mtl-datei. Eine.mtl-Datei enthält beliebig viele Materialien. Jedes dieser Materialien kann sowohl die üblichen OpenGL- Materialwerte, wie die für den Ambienten- oder Diffusen-Anteil, als auch Pfade zu Bildern für Texturen enthalten. Eine von Blender exportierte.mtl- Datei mit einem Material sieht beispielsweise wie folgt aus: Beispiel einer Datei im OBJ-Format # Kommentare newmtl Materialname1 Ns Ka Kd Ks Ni d illum 1 map_kd Pfad map_bump Pfad Nach einigen Kommentaren folgen zunächst die Materialwerte und anschließend die Pfade zu den einzelnen Bildern. Ns gibt dabei den Exponenten für den Spekularen-Term an. Ka, Kd, Ks bezeichnen jeweils den Term für ambientes, diffuses und spekulares Licht mit den Werten für Rot-, Grün und Blauanteil. Den Wert für den Alphakanal, also für die Transparenz, findet sich hinter d. Ni gibt den Wert der optischen Dichte an. Dieser gibt an wie sehr Licht beim Durchdringen eines transparenten Objektes gebrochen wird. Welches Beleuchtungsmodell verwendet werden soll, wird mit dem Wert von illum bestimmt. Es sind noch weitere optionale Angaben möglich. Anschließend folgen die Pfade zu den zu verwendenden Bilddateien. Hier 37

39 sind beispielsweise mit map_kd und map_bump die Pfade zu Bildern für Farbtextur und Bumpmap gegeben. Diese Werte können je nach Exporteinstellungen und exportierendem Programm auch in anderer Reihenfolge, mit Leerzeilen oder Kommentarzeilen auftreten. Im ResourceManager werden diese Werte und Pfade eingelesen und verarbeitet. Die Materialwerte werden dabei im zu erzeugenden ModelCustom gespeichert, von welchen sie wiederum beim Zeichnen abgerufen werden, um sie an die Shader weiterzugeben. Mit den Pfaden zu den einzelnen Bilddateien werden Instanzen der Klasse Texture erzeugt, welche nun genauer erläutert wird. Instanzen der Klasse Texture sind in der AiRmob-Engine die objektorientierte Repräsentation der in einer Szene verwendeten Texturen. Sie werden für alle aus externen Bilddateien stammenden Texturen, wie Farbtexturen oder Normalmaps, verwendet. Der ResourceManager erzeugt beim Importieren von.obj- und.mtl-dateien für jedes zu importierende Bild eine Texture. Zusätzlich können Texturen auch vom Programmierer angelegt werden um beispielsweise zur Laufzeit die Textur eines Modells zu tauschen. Abbildung 10 zeigt die Klasse Texture. ID : int resourcepath : String Texture setfilters(minificationfilter : int,magnificationfilter : int) : void setwrapping(swrapping : int,twrapping : int) : void Abbildung 10: Die Klasse Texture Die OpenGL-Referenz unter welcher das Bild gespeichert wurde, wird in ID gespeichert. Des Weiteren weiß jede Texture den Pfad zu der ihr zugrundeliegenden Bilddatei. Dieser wird gespeichert, damit der Resource- Manager ein mehrfaches Importieren derselben Bilddatei verhindern kann und in diesem Fall stattdessen eine Referenz zu der bereits bestehenden Textur zurückgibt. Zusätzlich können die OpenGL-Einstellungen für Filter und Wrapping nachträglich geändert werden. Die Werte für setfilters müssen dabei GLES20.gl_Linear oder GLES20.gl_Nearest sein, um den Filtermodus bei Vergrößerung bzw. Verkleinerung der Textur auf Interpolation oder Auswahl des nächsten Pixels zu stellen. Die Funktion setwrapping erwartet die Werte GLES20.GL_REPEAT, GLES20.GL_CLAMP_TO _EDGE oder GLES20.GL_MIRRORED_REPEAT, um Wiederholung, Clamping oder gespiegelte Wiederholung in s- oder t-richtung zu aktivieren. Instanzen der Klasse Texture können wie folgt selbst angelegt werden: 38

40 Importieren einer Bilddatei zum Erzeugen einer Textur Texture eigenetextur = new Texture ( Renderer, Pfad, Dateitformat ) ; Es müssen also nur der verwendete Renderer und ein String, welcher den Pfad zu der Textur beschreibt, sowie das Dateiformat des zu importierenden Bildes angegeben werden. Auf das Dateiformat wird im nächsten Abschnitt eingegangen. Einem Modell kann dann mitgeteilt werden, dass es diese Textur verwenden soll. Für das Beispiel aus dem vorherigen Abschnitt ( eigenesmodell ) würde dies wie folgt aussehen: Setzten der Textur eines Modells eigenesmodell. settexture ( eigenetextur ) ; Gleichermaßen existieren Getter und Setter für sämtliche Materialwerte Dateiformate und Erweiterbarkeit In den vorherigen Abschnitten wurde erwähnt, dass zur Erstellung von Modellen und Texturen der Dateityp der zu importierenden Datei angegeben werden muss. Das geschieht in der AiRmob-Engine indem die Enumerations ModelFileType und ImageType verwendet werden. Für Modelle existiert dabei nur der Typ OBJ, also ModelFileType.OBJ. Bei Bildern werden die Dateitypen jpg, png und gif unterstützt. Entsprechend gibt es ImageType.JPG, ImageType.PNG und ImageType.GIF. Bevorzugt sollten Bilder im PNG- oder JPG-Format verwendet werden. Dies und die drei unterstützten Formate ergeben sich aus der Bitmap-Klasse von Android, siehe hierzu auch [bit]. Weitere Dateiformate können zu beiden Enumeration- Klassen hinzugefügt und dann durch zusätzliche Abfragen in den Modellund Texturklassen an neue Funktionen geleitet werden. Mit entsprechenden Funktionen ist die Engine somit leicht um weitere Dateiformate erweiterbar, während alle unterstützten Formate dem Benutzer durch die Verwendung der Enumerations klar sind Pfade Da die AiRmob-Engine externe Dateien über den AiRmobFileManager öffnet und dieser den Android-AssetManager verwendet, müssen sämtliche Dateien, die importiert werden sollen in dem Assets-Ordner gespeichert werden. In diesem gibt es jeweils einen vorgegebenen Ordner für Modelle, Texturen und Animationen. Modelle und Animationen können jedoch 39

41 in beliebigen Ordnern und Unterordnern organisiert sein. Wichtig ist dabei nur, dass die.mtl-dateien im gleichen Ordner wie ihre.obj-dateien liegen und ebenso bei Animationen die Dateien sämtlicher Frames. Die Pfade der Texturen beim Import von Modellen werden automatisch aus den.obj-dateien ermittelt. Die beim Export aus einem 3D-Grafikprogramm erstellten Pfade sind jedoch meist unbrauchbar. Es müssten lokale Pfade ausgewählt und die Bearbeitungsdateien sich im Asset-Ordner befinden, was natürlich unpraktisch wäre, da sie dann mit auf das Gerät kopiert werden würden. Aus diesen Gründen ignoriert die AiRmob-Engine die Pfade der Texturen und nimmt lediglich den Namen der Textur (also den Pfad hinter dem letzten / ). Das Bild mit dem so ermittelten Namen wird stets im Ordner textures gesucht, wo dementsprechend alle Texturen abgelegt werden müssen. Durch dieses Vorgehen kann anhand der Pfade sichergestellt werden, dass bereits im System vorhandene Bilder nicht erneut importiert werden Einschränkungen bei Import und Exporteinstellungen Beim jetzigen Stand unterliegt der Import von Modellen in der AiRmob- Engine aus dem OBJ-Dateiformat einigen Einschränkungen. So können in.obj-dateien mehrere Modelle enthalten und gruppiert sein, also der Tag o mehrfach auftreten und durch den Tag g Gruppierungen erstellt werden. Die AiRmob-Engine aber erwartet nur ein einziges Modell pro.obj- Datei. Falls also mehrere Modelle in einer Datei exportiert werden sollen, müssen diese in dem jeweiligen 3D-Grafikprogramm zusammengefügt werden (in Blender mittels join ), wobei für die einzelnen Modelle die verschiedenen Materialien erhalten bleiben können. Die.mtl-Dateien können weit mehr Werte enthalten, als die AiRmob-Engine benutzt. Dies führt zwar zu keinem Fehler, allerdings werden die Werte schlichtweg nicht verwendet. Das liegt vorrangig daran, dass nur die Werte importiert und gesetzt werden, die die Standardshader der AiRmob- Engine benötigen und benutzen. Weitere Werte könnten leicht durch zusätzliche Abfragen im ResourceManager sowie Feldern in der Model3D- Klasse hinzugefügt werden. Des Weiteren wurde der Import von Modellen nur anhand von mit Blender (in der Version 2.62) exportierten.obj-dateien getestet. Hierbei müssen die Einstellungen wie in Abbildung 11 vorgenommen werden. 40

42 Abbildung 11: Exporteinstellungen in Blender In jedem Fall müssen die Modelle aus Dreiecken bestehend exportiert werden ( Triangulate Faces ). Für eine vollständige Beleuchtung und Texturierung sollten Normalen und Texturkoordinaten (mit UV-Koordinaten) mit exportiert werden ( Include Normals und Include UVs ). Andernfalls, 41

43 also wenn Normalen oder Texturkoordinaten fehlen, gibt die AiRmob-Engine diese Werte für das entsprechende Modell auch nicht an die Shader weiter. Dies führt in der Engine also nicht zu Fehlern. Allerdings können dann gegebenenfalls gewünschte Einstellungen nicht ausgeführt werden. Wenn beispielsweise Bumpmapping aktiviert ist, aber einem Modell keine Bumpmap mitgegeben wurde, kann dieses auch nicht durchgeführt werden. Wenn keinerlei Material für ein Modell erstellt wurde und die.obj-datei dementsprechend keine.mtl-datei besitzt, werden für die Materialwerte die Standardwerte der AiRmob-Engine verwendet, die dieselben sind wie für vorgegebene Modelle. Das Koordinatensystem ergibt sich aus der Schnittstelle zum Tracking, wie in Abschnitt erläutert ModelGroup Wie bereits erwähnt können in einer.obj-datei mehrere verschiedene Materialien verwendet werden. Wenn beispielsweise das Modell eines Autos importiert werden soll, könnten in einer.obj-datei sowohl Karosserie als auch Reifen gespeichert werden. Das Material der Reifen hätte dann andere Werte und Texturen als die der Karosserie. Um solche.obj-dateien mit mehreren Materialien zu importieren, können Instanzen der Klasse ModelGroup verwendet werden. Abbildung 12 zeigt den Aufbau dieser im Zusammenhang mit Object und ModelCustom. Object Model3D ModelCustom 1..* 1 < beinhaltet ModelGroup models : LinkedList<ModelCustom> getmodel(name : String) : ModelCustom getmodel(index : int) : ModelCustom Abbildung 12: Die Klasse ModelGroup Eine ModelGroup besteht aus einer Liste von Instanzen der Klasse ModelCustom. Wichtig ist, dass eine ModelGroup im Szenengraphen keinen Knoten sondern ein Blatt darstellt (im Gegensatz zu einer Group). Wenn man eine ModelGroup an die Szene anhängt und den dabei erzeugten Identifier transformiert, werden alle Modelle der ModelGroup transformiert und können nicht einzeln transformiert werden. In diesem Fall können ModelGroups genau wie ModelCustoms erzeugt und verwendet werden. Falls man die importierten Modelle, die sich in der ModelGroup befinden 42

44 einzeln ansprechen möchte, kann man anstatt die ModelGroup an die Szene zu hängen, jedes der in ihr beinhalteten Modelle einzeln verwenden. Dazu können Modelle anhand ihrer Position oder ihres Namens in der.obj- Datei (welcher dem in der 3D-Grafiksoftware verwendeten Materialnamen des Modells entspricht) ausgewählt werden. Um Speicherplatz zu sparen verwenden alle Modelle einer ModelGroup dieselbe Instanz der Klasse Mesh, während die Indices in den jeweiligen Modellen unterschiedlich sind ModelAnimation Mit den bis hierhin beschriebenen Modell-Typen lassen sich lediglich statische Modelle erstellen. Diese können über Transformationen, welche Zeitgebundene Werte verwenden, eingeschränkt animiert werden. So können einfache Bewegungen und Drehungen mittels Translation und Rotation und Veränderungen der Größe über Skalierung realisiert werden. Selbstverständlich lassen sich jedoch in 3D-Grafikprogrammen weitaus komplexere Animationen erstellen und exportieren. Die AiRmob-Engine unterstützt hierbei wiederum den Import von.obj-dateien. Animationen werden dabei als Schlüsselbilder exportiert. Es wird also für jeden Frame eine.obj-datei (und die zugehörige.mtl-datei) erstellt. Dabei hängt den Dateinamen der.obj- und.mtl-dateien eine fortlaufende Nummer an. Die Dateien sehen also wie folgt aus: name_ obj (getestet mit Blender). Mit der Klasse ModelAnimation können diese importiert werden. Abbildung 13 gibt einen Überblick über die Klasse und einen Auszug ihrer Felder und Funktionen. 43

45 Object Model3D ModelCustom 1..* ^ beinhaltet pauseunpause() : void setstart(frame : int) : void startnow() : void ModelAnimation frames : LinkedList<ModelCustom> loop : boolean paused : boolean stopped : boolean bytime : boolean 1 Abbildung 13: Die Klasse ModelAnimation mit einem Teil ihrer Felder und Funktionen. Eine Animation besteht in der AiRmob-Engine somit aus einer Liste von Instanzen der Klasse ModelCustom. Diese Modelle enstehen jeweils aus einer importierten.obj-datei und stellen ein Schlüsselbild ( Frame ) dar. Der Renderer muss zum Zeichnen den Frame auswählen, welcher zu dem vorliegenden Zeitpunkt passend ist. Hierzu können Animationen in der AiRmob-Engine grundsätzlich entweder Draw-Aufruf- oder Zeit-basiert sein. Bei ersterem wird mit jedem Draw-Aufruf der nächste Frame aus der Liste gewählt. Zusätzlich kann hierbei noch mit setdelayperframe angegeben werden, ob ein Frame der Animation für mehrere Zeichendurchläufe des Renderers gelten soll. Wenn diese Funktion beispielsweise mit dem Wert 2 aufgerufen wurde, würde eine Animation mit 30 Frames 60 Zeichendurchläufe dauern. Bei der zeitlichen Variante muss die gewünschte Dauer angegeben werden. Anhand dieser und der Anzahl der Frames der Animation wird dann berechnet, wie viele Frames von dieser Animation pro Sekunde angezeigt werden sollen. Das genaue Vorgehen zur Bestimmung des zu zeichnenden Frames wird noch im Abschnitt anhand des Ablaufes eines Zeichendurchlaufes erläutert. Das Anlegen einer Animation sieht wie folgt aus: 44

46 Erzeugen und Importieren einer Animation ModelAnimation animation = new ModelAnimation ( Renderer, Pfad, Dateityp, Frameanzahl, Stride, z e i t l i c h, Dauer ) ; Die Angaben von Renderer, Pfad und Dateityp sind wie bei dem Anlegen eines ModelCustom, mit einer Besonderheit beim Pfad. Hierbei muss nur der Dateiname bis zu dem Unterstrich vor der fortlaufenden Zahl angegeben werden. Also anstatt name_ obj nur name. Die fortlaufenden Zahlen werden automatisch für die zu importierenden Dateien ergänzt. Welche dies sind ergibt sich zum einen aus der Frameanzahl, welche angibt bis zu welcher Dateinummer importiert werden soll. Zum anderen aber auch durch die Angabe eines Strides. Dieser ist eine einfache Integer- Zahl und eine 2 würde beispielsweise angeben, dass nur jede zweite Datei importiert werden soll. Über eine Boolean, hier zeitlich, kann noch angegeben werden, ob die Animation anhand der durchlaufenen Zeichendurchläufe oder der Zeit fortschreiten soll. Falls sie auf true steht, gibt die Float-Zahl Dauer dann zuletzt noch an, wie lange die Animation in Sekunden andauern soll. Beispiel einer Animation ModelAnimation animation = new ModelAnimation ( renderer, " animations/name", ModelFileTypes. OBJ, 60, 1, true, 6 ) ; Die in diesem Beispiel erzeugte Animation würde also alle.obj-dateien von 1-60 importieren und für die 60 Frames eine Dauer von 6 Sekunden veranschlagen. Zusätzlich verfügen Instanzen der Klasse ModelAnimation noch über Funktionen zum Pausieren und Stoppen. Des Weiteren können Animationen mit setloop(true) so eingestellt werden, dass sie sich endlos wiederholen, während sie ansonsten stoppen, sobald sie beendet sind Vorgegebene Modelle Um einen schnellen Einstieg zu ermöglichen, bietet die AiRmob-Engine einige vorgegebene Modelle. Diese können genau wie importierte Modelle verwendet werden. Das Anlegen ist dabei einfacher, da kein Pfad angegeben werden muss und keine Modelle in einer 3D-Grafiksoftware erstellt werden müssen. Ein Würfel (ModelCube) mit einer beliebigen Größe lässt sich wie folgt erzeugen (die anderen Modelle werden ohne Größenangabe erzeugt): 45

47 Erstellen eines Würfels mit beliebiger Größe unter Angabe des Renderers ModelCube cube = new ModelCube ( Renderer, Größe ) ; Alle vorgegebenen Modelle haben Normalen und Texturkoordinaten. Als Textur haben sie ein einfarbig weißes Bild mit einer Größe von 4x4 Pixeln. Die Materialfarben sind folgendermaßen eingestellt: Ambient 0.4, 0.4, 0.4, 1.0 Diffuse 0.8, 0.8, 0.8, 1.0 Specular 1.0, 1.0, 1.0, 1.0 Exponent 100. Sämtliche Werte können nach Belieben geändert werden. Abbildung 14 gibt eine Übersicht über alle vorgegebenen Modelle und ob sie aus einer.obj-datei importiert werden und wenn ja, aus welcher. Name der Klasse ModelCube ModelSphere Importiert? Nein Ja Aus folgendem Pfad importiert ModelPlane Nein - ModelTeapot Ja models/examples/teapot.obj - models/examples/sphere.obj ModelSuzanne Ja models/examples/suzanne.obj Abbildung 14: Alle vorgegebenen Modelle Der Würfel kann durch die Angabe seiner Seitenlängen im Konstruktor dazu genutzt werden, um schnell verschiedene Größen zu testen. Wenn die mitgegebenen Seitenlängen der des Markers entsprechen, verdeckt der Würfel den Marker genau. Mit ModelSphere kann eine Kugel angelegt werden, die aus einer.obj-datei importiert wird. Bei der ModelPlane handelt es sich um eine große, dünne Fläche, welche hauptsächlich zu Testzwecken für Schatten genutzt wurde. Das ModelTeapot ist eine Version des klassischen Utah-Teapots. Dieses wurde durch ein Plugin für Cinema4D erstellt und in Blender zu einer.obj-datein exportiert. Das hierbei verwendete Plugin stammt von [tea]. ModelSuzanne importiert das in einer.obj- Datei gespeicherte Blender-Standardmodell des Affenkopfes mit Namen Suzanne. Abbildung zeigt einige von ihnen gerendert. 46

48 Abbildung 15: Suzanne, der Teapot und ein Würfel im 3D-Raum (mit Phongbeleuchtung und ohne Post-Processing Effekte) Der für die in Abbildung 15 gezeigten Modelle benötigte Code sieht wie folgt aus (zusätzlich wurde lediglich eine Lichtquelle angelegt): Erstellen eines Textes im 3D-Raum f l o a t [ ] red = { 1. 0 f, 0. 0 f, 0. 0 f, 1. 0 f } ; f l o a t [ ] green = { 0. 0 f, 1. 0 f, 0. 0 f, 1. 0 f } ; f l o a t [ ] blue = { 0. 0 f, 0. 0 f, 1. 0 f, 1. 0 f } ; f l o a t [ ] black = { 0. 0 f, 0. 0 f, 0. 0 f, 1. 0 f } ; ModelSuzanne suzanne = new ModelSuzanne ( t h i s ) ; suzanne. setmaterialambient ( black ) ; suzanne. s e t M a t e r i a l D i f f u s e ( red ) ; I d e n t i f i e r suzid = samplescene. add ( suzanne ) ; suzid. t r a n s l a t e ( 1 0 0, 0, 0 ) ; ModelTeapot teapot = new ModelTeapot ( t h i s ) ; teapot. setmaterialambient ( black ) ; teapot. s e t M a t e r i a l D i f f u s e ( green ) ; I d e n t i f i e r teapotid = samplescene. add ( teapot ) ; teapotid. s c a l e ( 7, 7, 7 ) ; ModelCube cube = new ModelCube ( this, 4 0 ) ; cube. setmaterialambient ( black ) ; cube. s e t M a t e r i a l D i f f u s e ( blue ) ; I d e n t i f i e r cubeid = samplescene. add ( cube ) ; cubeid. t r a n s l a t e ( 100, 0, 0 ) ; 47

49 Lichtquellen Lichtquellen sind eine weitere wichtige Komponente einer Szene. Bei den hier verwendeten Lichtquellen handelt es sich um Spotlights oder ungerichtete Punktlichtquellen. Auch können zur selben Zeit immer nur Lichtquellen eines Typs verwendet werden. Diese Beschränkungen ergeben sich aus den Shadern, die in der AiRmob-Engine benutzt werden. Bei der Verwendung anderer Shader ließen sich diese Beschränkungen in der Engine leicht aufheben indem die Klasse Light und die Funktion drawlight im Renderer dementsprechend ergänzt werden würden. In den Settings kann mit der Boolean usespotlights entschieden werden, ob Spotlights oder Punktlichtquellen verwendet werden sollen. Ein jedes Licht verfügt über Farbwerte für die diffusen und spekularen Therme sowie dem Exponenten für letzteren. Der Konstruktor für Spotlights verlangt Werte zu Position, Blickrichtung (direction), Up-Vektor, Öffnungswinkel (angle) und Exponent (Abnahme der Lichtintensität). Aus diesen werden die View- und Projection-Matrix der Lichtquellen berechnet. Bei ungerichteten Punktlichtquellen muss nur die Position angegeben werden. Lichter können mit folgenden Konstruktoren erstellt werden: Erstellen von Lichtquellen Light l i c h t = new Light ( ) ; Light spotlight = new Light ( position, d i r e c t i o n, up, exponent, angle ) ; Light punktlq = new Light ( p o s i t i o n ) ; Im ersten Fall werden Standardwerte geladen. Es werden hierbei entweder die Werte für ein Spotlight oder für eine Punktlichtquelle angelegt, je nachdem welcher Wert in den Settings gesetzt ist. Die anderen beiden Konstruktoren sind die für Spotlights und Punktlichtquellen. Beim Erstellen und beim nachträglichen Setzen von Position, Blickrichtung oder Up- Vektor für ein Spotlight wird die View-Matrix des Lichtes (welche zur Berechnung von Schatten verwendet werden kann) direkt neu berechnet. Die Projection-Matrix wird im SceneManager beim Aufbauen des Szenegraphen berechnet, da dafür noch Höhe und Breite der Oberfläche bekannt sein müssen. An dieser Stelle wird auch, wie für Modelle, die Transformationsmatrix der Lichter berechnet. Die Werte für diffuses und spekulares Licht sowie der Exponent lassen sich einzeln setzen oder gemeinsam mit der folgenden Funktion: Setzen der Licht-Farbwerte l i c h t. s e t L i g h t C o l o r s ( diffuse, specular, 48

50 exponent ) ; Hierbei handelt es sich bei den Werten für diffuse und specular um Float- Arrays (Rot, Grün, Blau und Alpha) und bei Exponent um eine Float-Zahl. Der Wert für den ambienten Term der Lichter befindet sich in den Settings, da er global gesetzt wird. Lichter können wie Modelle an die Szene oder Gruppen angehängt werden und lassen sich danach über den zurückgegebenen Identifier individuell transformieren. Das Hinzufügen zu der Szene geschieht dabei wie für Modelle: Anhängen eines Lichts an die Szene Light l i c h t = new Light ( ) ; I d e n t i f i e r l i c h t I D = szene. add ( l i c h t ) ; In den Settings kann die maximale Anzahl der Lichtquellen pro Szene mit maxlights festgelegt werden. Dabei sind Werte von 1-8 zulässig, es können also maximal 8 Lichtquellen pro Szene verwendet werden Text Es stimmt zwar, dass ein Bild mehr als tausend Worte sagt, trotzdem ist es manchmal nicht verkehrt, sich Worten zu bedienen. Gerade in AR-Anwendungen kann es wichtig sein Text anzuzeigen, um beispielsweise ein vom Tracking erkanntes Objekt mit Informationen anzureichern. Dabei könnte es gewünscht sein, dass sich der Text nicht in der Ebene der Geräteoberfläche befindet, also nicht gerade zum Bildschirm zeigt. Vielmehr könnte es sinnvoll sein, dass sich der Text im 3D-Raum direkt bei dem Objekt befindet, auf das er sich beziehen soll. Um dies zu ermöglichen war es unerlässlich, dass die AiRmob-Engine Text erzeugen kann. In OpenGL lässt sich Text auf unterschiedliche Weise erzeugen. So können Buchstaben als 3D-Objekte aus Punkten und Dreiecken bestehen. Natürlich könnten Buchstaben auf diese Weise auch 2D gezeichnet werden. Des Weiteren wird Text oft über die Verwendung von Texturen, welche einzelne Buchstaben oder sämtliche Zeichen beinhalten, verwirklicht. Es gibt zahlreiche weitere Ansätze und Libraries, die diese implementieren. Für OpenGL ES 2.0 unter Android stehen diese Libraries nicht zur Verfügung, bzw. müssten zunächst kompatibel gemacht werden. Daher implementiert die AiRmob-Engine eine eigene Version, die im Folgenden beschrieben wird. Auf die zahlreichen anderen Möglichkeiten zur Texterstellung soll hierbei nicht weiter eingegangen werden. In der AiRmob-Engine lassen sich zwei verschiedene Arten von Text ver- 49

51 wenden. Zum einen 2D-Text im 3D-Raum, der also mittels Transformationen beliebig in den 3D-Raum platziert werden kann. Die Erstellung eines solchen Textes sieht wie folgt aus: Erstellen eines Textes im 3D-Raum Text t e x t = new Text ( Renderer, " Text ", Größe, Farbe ) ; I d e n t i f i e r textid = scene. add ( t e x t ) ; textid. t r a n s l a t e ( x, y, z ) ; Wobei Renderer der verwendete Renderer ist, Text der anzuzeigende String, Größe ein Float-Wert, der die Größe des erzeugten Texts angibt und Farbe ein Float-Array, das die Farbe bestimmt. Der erzeugte Text kann wie ein Modell verwendet werden. Dementsprechend kann er an die Szene oder andere Groups angehängt und mittels dem dabei zurückgegebenen Identifier transformiert werden. Auch lässt sich 2D-Text erzeugen, welcher in der Ebene der Geräteoberfläche liegt und zur Kamera schaut. Dies lässt sich folgendermaßen bewerkstelligen: Erstellen eines statischen Textes Text t e x t = new Text ( Renderer, " Text ", Größe, Farbe, true, xoffset, yoffset ) ; Die zusätzlichen Werte sind hierbei ein Boolean um zu bestätigen, dass dieser Text statisch zur Geräteoberfläche gezeichnet werden soll. Des Weiteren wird durch das x- und yoffset noch die Position des Textes auf dem Bildschirm bestimmt. Die AiRmob-Engine geht beim Erstellen von Texten wie folgt vor. Zunächst wird die Textur der Schrift angelegt (wenn sie bereits im System ist, wird eine Referenz dazu übergeben). In dieser Textur befinden sich alle Buchstaben, die in der AiRmob-Engine angezeigt werden können. Das hierfür verwendete Bild ist in Abbildung 16 zu sehen. Hierbei wird die Schriftart Helvetica benutzt. Dabei wird eine Instanz der Klasse Texture verwendet, deren Filter sowohl für Magnifikation als auch für Minifikation auf GL_LINEAR gestellt werden. Für jeden Buchstaben des zu erzeugenden Textes wird aus einer Lookup-Tabelle die x- und y-koordinate in dieser Schrift-Textur sowie seine Breite abgefragt und mit diesen ein Rechteck erzeugt. Anhand der zurückgegebenen Breite und der gewünschten Größe 50

52 wird die Breite des Rechteckes berechnet. Die Höhe der Rechtecke ist dabei immer identisch. Nun wird mit x-, y-koordinate und Breite der passende Buchstabe aus der Textur gelesen und auf das Rechteck gelegt. Die Breite jedes verarbeitenden Buchstabens wird auf ein Offset addiert, das die x- Position des nächsten Rechteckes bestimmt. So wird fortgefahren bis der String aus der Eingabe abgearbeitet und der Text erzeugt ist. Dann liegt für jeden Buchstaben des Strings ein Rechteck mit den passenden Texturkoordinaten und der richtigen Breite für den jeweiligen Buchstaben vor. Abbildung 17 zeigt einen statischen Text sowie einen Text im 3D-Raum unter einem Würfel im Vergleich. Der Code um diese Texte zu erzeugen ist in Listing 1 zu sehen. Abbildung 16: In der AiRmob-Engine verwendete Textur zur Texterzeugung 51

53 Abbildung 17: Zwei Beispieltexte: der erste zur Kamera gerichtet und der zweite im 3D-Raum unter einem Würfel und daher teilweise verdeckt Listing 1: Code zum Erstellen des Textes in Abbildung 17 f l o a t [ ] c o l o r = { 1. 0 f, 1. 0 f, 1. 0 f, 1. 0 f } ; Text t e x t 1 = new Text ( this, " B e i s p i e l t e x t 2 ", 20, c o l o r ) ; I d e n t i f i e r text1id = samplescene. add ( t e x t 1 ) ; text1id. r o t a t e ( 1 8 0, 0, 0, 1 ) ; Text t e x t 2 = new Text ( this, " B e i s p i e l t e x t 1 ", 10, color, true, 0.5 f, 0. 5 f ) ; I d e n t i f i e r text2id = samplescene. add ( t e x t 2 ) ; 4.4 Shader Da es sich bei Shadern um externe Dateien handelt, müssen diese zunächst in das System importiert werden, bevor sie verwendet werden können. Um die Shader intern zu verwalten benutzt die AiRmob-Engine die beiden Klassen VertexShader und FragmentShader. Diese sind bis auf den Namen identisch und beinhalten eine Integer-Zahl für die Adresse des Shaders in OpenGL sowie den String des Pfades von welchem der Shader importiert wurde. Damit kann der ResourceManager überprüfen, ob sich ein Shader bereits im System befindet, um ihn nicht unnötig importieren zu müssen. Instanzen der beiden Klassen werden folgendermaßen angelegt: 52

54 Erstellen einer Instanz der Klasse VertexShader VertexShader vertexshader = new VertexShader ( Pfad ) ; Aus jeweils einem Vertex- und Fragmentshader wird in OpenGL ein Programm erstellt. An dieses werden sämtliche Werte von Modellen und Lichtquellen übergeben, um sie zu zeichnen. In der AiRmob-Engine übernimmt der ResourceManager das Erstellen der Programme und erledigt dies gleichzeitig mit dem Importieren der Shader mit folgender Anweisung: Generieren eines OpenGL-Programms aus Instanzen der Klassen VertexShader und FragmentShader i n t program = resourcemanager. createprogram ( vertexshader, fragmentshader ) ; Dies wird für die in den Einstellungen festgelegten Shader durchgeführt, für die in Abschnitt genannten Shadertypen. Es kann auch von Programmierern außerhalb der Engine verwendet werden um Shader zur Laufzeit zu ändern, indem ein so erzeugtes Shaderprogram beispielsweise die Hauptshader der Engine ersetzt, also der int-wert von renderer.mprogram geändert wird. Dies setzt natürlich voraus, dass die Namen der Uniforms und Attributes innerhalb der Shader gleich sind. 4.5 Funktionen Im Folgenden sollen einige Funktionen beschrieben werden, die alle direkt beim Erstellen und Verändern eines Renderers oder in einem jeden Zeichendurchlauf dessen ausgeführt werden. Die hier beschriebenen Funktionen befinden sich insbesondere alle in der Klasse Renderer onsurfacecreated Mit der von Android bereitgestellten Funktion onsurfacecreated können Anweisungen beim Erstellen der OpenGL-Oberfläche ausgeführt werden. Die Kosten dieser Funktion treten also nur einmal beim Laden der Engine auf und beeinflussen nicht wie viele Bilder pro Sekunde gerendert werden können. Abbildung 18 zeigt den Ablauf der onsufacecreate-funktion in ihrer Implementation in der AiRmob-Engine. 53

55 Szene importieren Haupt- und Textshader laden Tracking aktiv? Ja Nein Viewmatrix berechnen Szenengraph aufbauen Outlines aktiv? Nein Ja Outline Shader laden Picking aktiv? Nein Schatten aktiv? Nein Post-processing? Nein Ja Ja Ja Pick. Shader laden Depth Shader laden und Texturen anlegen PP Shader laden und Textur anlegen OpenGL Einstellungen setzen Framework Abschluss mitteilen Abbildung 18: Ablauf der Funktion onsurfacecreated 54

56 Zuerst wird die dem Renderer mitgeteilte Szene angelegt. Sämtliche an der Szene hängenden Objekte werden zu diesem Zeitpunkt erstellt und die für sie nötigen Dateien importiert. Hierzu muss vom Programmierer die Funktion putscene überschrieben werden. Das ist nötig, da nur innerhalb der drei Funktionen onsurfacecreated, onsurfacechanged und ondrawframe direkter Zugriff auf OpenGL besteht. Als nächstes müssen Haupt- und Textshader importiert werden. Sie werden in jedem Fall importiert, da sie unabhängig von den Einstellungen benötigt werden. Falls das Tracking deaktiviert ist, wird an dieser Stelle noch eine initiale Viewmatrix gesetzt, die die Kamera auf den Mittelpunkt ausrichtet. Die Matrix kann nachträglich verändert werden indem man die Variable mview- Matrix des Renderers ändert. Um die Kamera dabei wie gewohnt mit Position, Eye- und Up-Vektor zu setzen, kann die folgende OpenGL-Funktion benutzt werden (siehe auch[mat]): Manuelles Einstellen der Kamera bei deaktiviertem Tracking Matrix. setlookatm ( mviewmatrix, 0, eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz ) ; Anschließend wird der Szenengraph zum ersten Mal aufgebaut. Danach sind dem Renderer alle zu zeichnenden Modelle und Lichter bekannt und alle Matrizen gesetzt. Wenn ein neues Objekt hinzugefügt wird oder sich die bestehenden Objekte verschieben, muss der Szenengraph neu aufgebaut werden. Hierauf wird im übernächsten Abschnitt noch einmal eingegangen. Nachdem nun klar ist welche Objekte gezeichnet werden müssen und die dazu nötigen Ressourcen importiert wurden sowie die in jedem Fall benötigten Shader im System sind, können noch optionale Shader geladen werden. Je nach Einstellungen werden Shader für Picking, Outlines, Shadowmaps und Post-Processing importiert. Wenn Schatten gezeichnet werden sollen, werden neben den Shadern noch Texturen für die in den Einstellungen definierte maximale Anzahl Lichtquellen angelegt. Für das Post- Processing wird eine Textur angelegt, in welcher das Ergebnis des Renderdurchlaufs gespeichert wird. Die Shader zum Zeichnen des Fullscreenquad (also eines einfachen Vierecks (respektive zweier Dreiecke die ein Viereck bilden), das die gesamte Sicht ausfüllt) werden ebenfalls geladen, falls eine Tiefentextur gezeichnet oder das Bild der Kamera als Hintergrund benutzt werden soll. Für das Post-Processing werden die jeweils benötigten Shader geladen, also die für Bloom oder Blur. Danach werden die initialen OpenGL-Einstellungen vorgenommen. Hier wird der Tiefentest und Faceculling aktiviert sowie die Clearcolor gesetzt. 55

57 Zuletzt wird dem Framework noch der Abschluss der Funktion mitgeteilt, damit gegebenenfalls Ladebildschirme passend beendet werden können. Zusätzlich wird die benötigte Zeit gemessen onsurfacechanged Die Funktion onsurfacechanged wird einmal zu Beginn, nachdem onsurfacecreated beendet ist, aufgerufen und im Folgenden immer dann, wenn sich die Größe der Oberfläche ändert. Das tritt bei Handheld-Geräten insbesondere dann ein, wenn das Gerät gedreht wird und das Bild von hochkant zu quer wechselt. Als Parameter wird der Funktion die neue Breite und Höhe in Pixeln mitgeteilt. In der AiRmob-Engine werden die Internen Felder für Breite und Höhe mit diesen Werten neu gesetzt. Zusätzlich müssen sämtliche von diesen Werten abhängenden Parameter neu gesetzt und berechnet werden. Abbildung 19 zeigt den Ablauf dazu. Zunächst müssen also OpenGL die neuen Dimensionen des Viewports mitgeteilt werden. Da die Projektionsmatrix ebenfalls von der Höhe und Breite abhängig ist, wird sie bei deaktiviertem Tracking an dieser Stelle berechnet. Android stellt hierzu keine Funktion out-of-thebox bereit, weshalb dies mit einer eigenen durchgeführt. Die Framebufferobjects für Picking, die einzelnen Lichtquellen bei aktiviertem Schatten und das Postprocessing sind ebenfalls von der Breite und Höhe abhängig und müssen somit bei einer Änderung neu erstellt werden. Zuletzt teilt die onsurfacecreated-funktion den Abschluss und die benötigte Zeit der Engine mit. 56

58 Höhe und Breite ändern Viewport anpassen Tracking aktiv? Ja Picking aktiv? Nein Schatten aktiv? Nein Post-processing? Nein Nein Ja Ja Ja Projektionsmatrix berechnen Pick. FBO erstellen Depth FBOs erstellen PP FBO erstellen Framework Abschluss mitteilen Abbildung 19: Ablauf der Funktion onsurfacechanged ondrawframe In der Funktion ondrawframe findet das eigentliche Zeichnen statt. Sie wird zum Zeichnen eines jeden Frames aufgerufen. Die Kosten dieser Funktion sind also maßgeblich für die Framerate der Engine. Abbildung 20 zeigt den Ablauf für einen Zeichendurchlauf. 57

59 Aktuelle Zeit messen Viewprojectionmatrix berechnen Szene geändert? Nein Ja Szenengraph neu aufbauen Ja Distanzsortierung? Nein Sortieren nach Distanz Picking aktiv? Nein Schatten aktiv? Nein Ja Ja Picking Textur zeichnen und an Koord. testen Depthmaps erstellen Alle Objekte der Szene zeichnen Post-processing? Nein Ja PP-Shader anwenden und Ergebnis auf Fullscreenquad zeichnen Zeiten messen und Framecount erhöhen Abbildung 20: Ablauf eines Zeichendurchlaufs 58

60 Zu Beginn und Abschluss eines jeden Durchlaufs wird die aktuelle Zeit gemessen und die globalen Felder zum Messen der bis zu diesem Zeitpunkt verstrichenen Zeit und Frames erhöht. Diese werden zum einen von Animationen genutzt, um das aktuell zu zeichnende Modell zu ermitteln. Zum anderen werden mit ihnen die Frames per second (FPS) berechnet. Hierbei werden die synchronisierten FPS und die pro Durchlauf der ondrawframe- Methode benötigte Zeit mit den daraus resultierenden unsynchronisierten FPS unterschieden. Erstere sind nach oben hin durch Android (bzw. durch die Spezifikationen des Bildschirms) begrenzt. Die Funktion wird also nicht mehr als bspw. 60 mal pro Sekunde aufgerufen. Die unsynchronisierten FPS zeigen hingegen wie viele Durchläufe möglich wären. Das Framework und Android führen ebenfalls für jeden Zeichendurchlauf Operationen aus oder arbeiten parallel an anderen Operationen. Daher können die beiden Zahlen auch für Werte unterhalb der Begrenzung unterschiedlich sein, je nachdem welche anderen zu Operationen zu diesem Zeitpunkt ausgeführt werden. Die Berechnung der beiden Werte wird alle 100 Zeichendurchläufe durchgeführt und kann in den Einstellungen aktiviert werden. In jedem Durchlauf wird die aktuelle Viewprojection-Matrix berechnet. Falls die Szene sich seit dem letzten Frame geändert hat wird anschließend der Szenengraph neu aufgebaut. Relevante Änderungen sind das Hinzufügen neuer oder das Transformieren alter Objekte. Auch wenn der Szenengraph nicht neu gebaut werden muss, muss die Sortierung nach Distanz (falls sie aktiviert ist) trotzdem durchgeführt werden. Das kommt daher, dass die Distanzen relativ zur Kamera sind, die sich unabhängig von der Szene ständig bewegen kann. Danach sind dem Renderer alle zu zeichnenden Modelle und Lichter mit ihren jeweiligen Matrizen bekannt. Falls Picking aktiviert ist und vom Framework eine Pickinganfrage gesendet wurde wird nun die Picking Textur gezeichnet und die Koordinaten des Klicks überprüft. Wie dies geschieht wird in Abschnitt erläutert. Als nächstes wird geprüft ob Schatten aktiviert sind. Falls dies der Fall ist müssen vor dem eigentlichen Zeichnen der Szene die Depthmaps erzeugt werden, um diese den Hauptshadern bereitstellen zu können. Hierauf wird in Abschnitt eingegangen. Nun kann das eigentliche Zeichnen der Szene stattfinden. Hierzu wird die Funktion drawallobjects aufgerufen, welche im nächsten Abschnitt näher beleuchtet wird. Diese zeichnet die gesamte Szene entweder in den Hauptframebuffer, welcher dann auf dem Gerät angezeigt wird oder einen extra Framebuffer, welcher das Ergebnis des Zeichendurchlaufs bis zu dieser Stelle in eine Textur speichert. Auf die Textur können dann noch weitere Postprocessing-Shader angewendet werden, wie in Abschnitt beschrieben. 59

61 4.5.4 drawallobjects Die Funktion drawallobjects wird aufgerufen, um sämtliche Objekte mit den Hauptshadern zu zeichnen. Bevor mit dem Zeichnen begonnen wird, muss zunächst ermittelt werden, ob in den Hauptframebuffer oder einen extra FBO gezeichnet werden soll. Dieser FBO würde verwendet werden, um das Ergebnis des Zeichnens in einer Textur zu speichern. Auf dieser wird Post-Processing durchgeführt. Zusätzlich kann das Kamerabild des Gerätes als bildschirmfüllendes Rechteck an dieser Stelle als Hintergrund gezeichnet werden. Falls dies gewünscht ist werden zunächst Depth- und Colorbuffer gelöscht, das Fullscreenquad mit dem Kamerabild als Textur gezeichnet und anschließend der Depthbuffer erneut gelöscht. Andernfalls werden beide Buffer nur einmal gelöscht und direkt fortgefahren sowie das Kamerabild vom Framework in einer anderen SurfaceView gezeichnet. Dies kann in den Settings mit der Boolean cameratex aktiviert werden und das Kamerabild wird der Engine vom Framework mit der Funktion setvideobackground gesendet. Anschließend kann es an das Zeichnen der Szene gehen. Es werden hierzu zunächst alle vom SzeneManager bereitgestellten Lichter an die Shader übermittelt. Da diese bereits in einer Liste sind, können sie der Reihe nach an die Funktion drawlight übergeben werden, welche sich darum kümmert sie an die Shader zu übermitteln. Als nächstes wird die Liste der Modelle abgearbeitet. In ihr werden zunächst sämtliche undurchsichtigen und daraufhin die transparenten Modelle, welche wie bereits erwähnt nach Distanz sortiert sein können, eingeordnet. Schließlich werden die Texte in die Liste einsortiert. Aus dieser Liste wird nun der Reihe nach ein Modell/Text herausgenommen und für dieses/diesen bestimmt, wie weiter zu verfahren ist. Wenn ein Model3D (bzw. eine Unterklasse) vorliegt, kann mit diesem direkt die Funktion drawmodel aufgerufen werden, welche wiederum die Kommunikation mit den Shadern durchführt. Im Fall einer ModelGroup müssen sämtliche in ihr enthaltenen Modelle gezeichnet werden. Sollte eine ModelAnimation vorliegt, muss der aktuell zu zeichnende Frame bestimmt werden. Falls die Animation Zeichendurchlauf-basiert ist, wird dabei der bisherige Framecount mit dem der Animation und ihrem Startframe verrechnet und der Framecount der Animation anschließend um eins erhöht. Bei Zeit-Animationen wird die Startzeit der Animation von der globalen bisher verstrichenen Zeit abgezogen und das Ergebnis mit dem FPS-Wert der Animation multipliziert. Eine gestoppte Animation wird in beiden Fällen nicht gezeichnet. Bei einer pausierten Animation wird der beim Pausieren gespeicherte Wert zum Ermitteln des zu zeichnenden Frames herangezogen und bei Animationen, die auf Zeichendurchläufen basieren der Framecount nicht erhöht. Für Texte wird eine extra Funktion aufgerufen und beim erstmaligen Auf- 60

62 treten eines Textes die Haupt- mit den Textshadern als aktuelles Programm gewechselt. Die Funktion zum Zeichnen eines Textes unterscheidet sich nicht von der zum Zeichnen eines Modelles, außer das zusätzlich eine Farbe und dafür einige andere Werte (wie die Normalen und Texturkoordinaten) nicht mitgegeben werden. Die Shader zum Zeichnen von Texten setzen für den Farbwert direkt die für den Text gesetzte Farbe. Text wird also nicht beleuchtet oder texturiert. In den Einstellungen können noch Outlines (Umrandungen) aktiviert werden. Diese können insbesondere mit Cell-Shading dazu benutzt werden, um einen Comicartigen-Effekt zu erzeugen. Falls das gewünscht ist werden vor der Übergabe der Lichter und Modelle an die Hauptshader sämtliche Modelle ohne Texturen, Materialien oder Lichter mit den Outlineshadern gezeichnet. Dabei wird ein jedes um einen in den Einstellungen festgelegten Wert skaliert. Nach dem Zeichnen wird der Tiefenpuffer gelöscht, damit sich die Outlines stets unter den Modellen befinden. Auch wird dabei das Culling auf Front-Faces umgestellt. Es werden folglich die Rückseiten der Modelle gezeichnet, während die Vorderseiten gelöscht werden. Zum Zeichnen der einzelnen Modelle wird die Methode drawmodelforoutline aufgerufen, die die reduzierten Werte der Modelle und eine Farbe übergibt, mit welcher die Outlines in den Shadern gezeichnet werden. Die Farbe lässt sich in den Einstellungen verändern drawlight In dieser Funktion werden den Hauptshadern die Werte der Lichter übermittelt. Für jede Lichtquelle sind in den Shadern feste Uniforms vorhanden, an die die Engine die Werte gibt. Daher kann auch nur eine festgelegte, maximale Anzahl Lichtquellen pro Szene verarbeitet werden. Die AiRmob- Engine unterstützt maximal 8 Lichtquellen. Für jede der Lichtquellen werden in der Funktion drawlight die in Abschnitt genannten Werte übertragen. Diese werden in den Shadern gespeichert und dann für jedes Modell bei der Beleuchtung angewendet drawmodel Wie bereits erwähnt wird die Funktion drawmodel für jedes Modell aufgerufen um es zu zeichnen. Als erstes werden dazu die Modelviewprojectionund die invertierte Modelview-Matrix berechnet. Die hierzu verwendeten Viewprojection- und Modelmatrizen wurden in der Methode drawallobjects und vom SzeneManager berechnet. Diese Matrizen werden dann an die Shader übergeben. Danach werden die Materialwerte des Modells übergeben. Falls Bump- oder Shadowmapping aktiviert sind, werden für diese die passenden Texturen übermittelt. Die Bumpmapping-Textur ist dabei die des 61

63 Modells selbst. Die Shadowmapping-Texturen sind die Tiefentexturen, die für jede Lichtquelle in einem vorherigen Zeichendurchlauf erstellt wurden. Als nächstes werden die Vertices und Indices übermittelt. Dabei werden entweder die Java-Buffer der Modelle verwendet oder die für diese erstellten Vertex Buffer Objects. Bei diesem Vorgang werden, falls die Texturkoordinaten gesetzt sind und eine Farbtextur vorhanden ist, diese ebenfalls an die Shader gegeben. Zuletzt wird ein jedes Modell mit drawelements, also dem OpenGL- Befehl zum Zeichnen von Dreiecken ( GL_TRIANGLES ) mit indizierten Vertexlisten, gezeichnet. Um den Shadern die getroffenen Einstellungen mitzuteilen, werden noch einige zusätzliche Variablen übergeben Picking Picking bedeutet Modelle, die sich im 3D-Raum befinden, durch einen Fingertipp auf die Geräteoberfläche auszuwählen. Hierbei sendet die Activity eine Pickinganfrage an den Renderer mit den Bildschirmkoordinaten der Position auf die getippt wurde. Diese speichert der Renderer, um sich ihrer im nächsten Draw-Durchlauf anzunehmen. Das bedeutet zwar eine geringe Verzögerung zwischen dem Aufruf und dem Selektieren, sie sollte bei durchschnittlichen Frameraten allerdings nicht ins Gewicht fallen. Auf die Schnittstelle zu der Activity wurde bereits in Abschnitt 3.2 eingegangen. Um die individuelle Unterscheidung von Modellen zu ermöglichen, wird beim Anhängen eines Modells an eine Group ein Identifier erstellt. Dieser Identifier erfragt von der Szene, an der die Group direkt oder indirekt hängt, eine ColorID und erhöht sie danach um eins. Dadurch hat jede Instanz eines Modells objektorientiert einen eigenen Identifier und für das Picking eine eigene ColorID. Für das Picking werden im nächsten Draw-Aufruf nach Eingang der Anfrage alle in der Szene befindlichen Identifier in einen extra Framebuffer, bzw. dessen Renderbuffer, einfarbig gezeichnet. Der Zeichenvorgang läuft dabei wie für das normale Zeichnen beschrieben ab. Es wird mit der Methode drawpickingtexture wie in der Methode drawallobjects über sämtliche Modelle gegangen und für jedes die Methode drawmodelforpicking zum Zeichnen aufgerufen. Im Gegensatz zum normalen Zeichnen werden dabei Texte komplett ignoriert und sämtliche Werte für Beleuchtung und Texturierung nicht an die Shader übergeben. Zusätzlich wird für jeden Identifier eine eigene eindeutige Farbe übermittelt, welche im Shader direkt zum Zeichnen verwendet wird. Die Farbe ergibt sich aus der ColorID. Um dies mit OpenGL ES unter Android durchzuführen, sind einige Umrechnungen nötig. So gibt man die Farbwerte als Float-Zahlen an die Shader. Wenn man sie jedoch mittels glreadpixels(...) aus dem Renderbuffer ausliest, ist es in OpenGL ES nur möglich, den Rückgabewert als unsigned 62

64 Byte zu erhalten. Da Java allerdings von einem signed Byte-Wert ausgeht, müssen die Farbwerte zunächst auf signed umgerechnet werden. Hierzu werden sie mit einer binären AND-Operation und dem Wert 0xFF umgerechnet. Damit erhält man dann Werte von 0-255, welche für die folgende Umrechnung noch auf 0-15 umgerechnet werden, da ja in der AiRmob- Engine nur 16 Farbwerte pro Kanal unterschieden werden können (siehe Abschnitt 3.2.1). Somit haben wir für den Rot, Grün- und Blau-Kanal des ausgelesenen Pixels jeweils 16 Werte. Um nun eine große Anzahl von Farben unterscheiden zu können, wird die ColorID der Identifier hexadezimal auf die Farbwerte umgerechnet. Dabei sind Rotwerte einfach, Grünwerte 16-fach und Blauwerte 255-fach gewertet. Da die Werte als Float-Werte übergeben werden müssen, werden sie vor der Übergabe an die Shader noch durch 16 geteilt. Zum Ausgleichen von Rundungsfehlern beim Schreiben und Auslesen die Werte zuvor noch um 0.5 erhöht. In Pseudocode sähe die Umrechnung einer ColorID in einen Farbwert also wie folgt aus: Pseudocode zur Umrechnung der ColorID in einen Farbwert Blau = ganzzahliger Anteil von ( ColorID / 255) R e s t = ColorID modulo 255 Grün = ganzzahliger Anteil von ( Rest / 16) Rest = Rest modulo Rot = Rest Rot = ( Rot ) / 16 Grün = ( Grün ) / 16 Blau = ( Blau ) / 16 Gebe für a k t u e l l e n I d e n t i f i e r ( Rot / Grün / Blau ) a l s Farbe an Shader Umgekehrt sähe das Auslesen eines Pixels aus dem FBO und die Umrechnungen in Pseudocode folgendermaßen aus: Pseudocode zur Umrechnung der ColorID in einen Farbwert Lese P i x e l von Bildschirmkoordinate aus und speichere s i e in Array p i x e l 63

65 for ( i = 0 ; i <= 4 ; i ++){ p i x e l [ i ] = ( p i x e l [ i ] & 0xFF ) / 17 } ColorID = p i x e l [ 0 ] + p i x e l [ 1 ] 16 + p i x e l [ 2 ] 255 Die errechnete ColorID wird mit der aller Identifier der Szene verglichen. Wenn ein passender Kandidat gefunden wurde, wird dieser zurückgegeben. Falls sich nichts an der Stelle an der getippt wurde befindet, wird dies der Activity mitgeteilt. Da beim Zeichnen der Picking-Textur der Tiefenpuffer automatisch das vorderste Objekt zeichnet, muss man sich hierbei nicht um Sortierung kümmern. Eine so erzeugte Picking-Textur sieht beispielsweise wie in Abbildung 21 aus. Abbildung 21: Ansicht einer PickingTexture für 100 Affenköpfe Da die Erzeugung des FBO- und RBO-Speichers innerhalb der ondrawframe- Methode zu teuer wären, werden diese bei aktiviertem Picking bereits in der onsurfacecreated-methode erstellt. Des Weiteren wird zum Zeichnen der Picking-Textur ein eigener Shader verwendet, dem nur die Punkte und errechneten Farbwerte übertragen werden. Hierdurch soll Performance gespart werden, da beim Erstellen der Picking-Textur Normalen, Texturen und so fort nicht benötigt werden. Neben einfachem Picking lässt sich in den Einstellungen der AiRmob-Engine noch extendedpicking mit einer beliebigen Integer-Zahl aktivieren. Hierdurch wird nicht nur der Pixel, welcher gedrückt wurde, für den Pickingtest herangezogen, sondern sämtliche Pixel aus einem Bereich um ihn her- 64

66 um. Dieser Bereich entspricht einem Quadrat mit der Seitenlänge des gewählten Wertes mal zwei plus eins. Wenn extendedpicking auf 1 gestellt wird, werden 3 * 3, also 9 Pixel herangezogen. Für jeden Pixel innerhalb dieses Quadrats wird die oben beschriebene Prozedur durchgeführt und das Auftreten verschiedener ColorIDs gezählt. Jene die am häufigsten auftritt wird schließlich gewählt und mit denen aller Identifier der Szene verglichen. Bevor alle Pixel des Quadrates geladen und untersucht werden, wird noch der Pixel, der sich direkt unter den angeklickten Koordinaten befindet, getestet. Wenn sich dort ein Modell befindet wird auf das erweiterte Picking verzichtet, da ja direkt ein Modell getroffen wurde. Für das erweiterte Picking lässt sich mit weightedpicking noch eine Gewichtung der Werte nach ihrer Distanz zum Mittelpunkt des Quadrates aktivieren. Hierzu wird einfach die Wurzel aus der Summe der quadrierten Distanzen in x- und y-richtung gebildet. Eine fortgeschrittenere Implementierung könnte die Distanzen mit der gaußschen Normalverteilung gewichten. Möchte man ein Modell nicht-anwählbar machen, also beim Picking unberücksichtigt lassen, kann man das erreichen mit: Deaktivierung des Pickings für einen bestimmten Identifier b e i s p i e l I D. d e a c t i v a t e P i c k i n g ( ) ; Dadurch wird die colorid des Identifiers auf -1 gesetzt (die alte ColorID wird gespeichert und bei Reaktivierung wieder übernommen). In der Pickingfunktion wird dieser Wert ignoriert Shadowmap Wenn Schatten gezeichnet werden sollen, werden vor dem eigentlichen Zeichnen der Szene noch die Depthmaps erstellt. Hierzu werden für jede Lichtquelle sämtliche Modelle aus der Sicht dieser Lichtquelle gerendert. Für jede Lichtquelle wird in einen separaten Framebuffer gezeichnet. Dazu wird in der Funktion drawdepthmap zunächst für jede Lichtquelle zu einem der in onsurfacechanged erstellten Framebuffer gewechselt. Dann werden wie für das Zeichnen mit dem Hauptshader (drawallobjects) die zu zeichnenden Modelle ausgewählt und an die Funktion drawmodelfor- DepthTexture gegeben. Diese übernimmt dann wiederum die Kommunikation mit den Shadern. Dabei werden keine Normalen, Materialwerte, Texturkoordinaten und Texturen übermittelt, da sie nicht benötigt werden. Einziger Unterschied bei der Auswahl der Modelle ist, dass Texte schlichtweg ignoriert werden, sie werfen also keine Schatten. Die so entstandenen Texturen werden bei dem eigentlichen Zeichnen an die Hauptshader übergeben. Zum Testen der Ergebnisse kann in den Ein- 65

67 stellungen noch eine der Depthmaps ausgewählt werden, um anstatt des normalen Zeichenergebnisses angezeigt zu werden. Hierbei wird die Clear- Color auf weiß gesetzt, um das Ergebnis besser zu erkennen. Die Umsetzung des Shadowmappings in den Shadern und die Theorie dahinter wird in der Arbeit von Philipp Brandt erläutert Post-Processing Bei aktiviertem Post-Processing wird das Ergebnis des Zeichnes mit den Hauptshadern in eine Textur gespeichert. Die Textur wird, je nachdem welche Post-Processing Shader aktiviert sind, an diese übergeben. Die verschiedenen Shader, die hier verwendet werden können, wurden in Abschnitt vorgestellt und sind ausführlicher Teil der Arbeit von Philipp Brandt. Nachdem die Post-Processing Effekte angewendet wurden, wird die Ergebnistextur auf ein Fullscreenquad gelegt und dieses gezeichnet. 4.6 Settings Immer wenn in den vorherigen Abschnitten von Einstellungen die Rede war, handelte es sich um die Klasse Settings. Mit ihr soll es Programmierern schnell und leicht möglich sein, die wichtigen Einstellungen der AiRmob-Engine vorzunehmen. In den jeweiligen Abschnitten wurden bereits häufig Beispiele für Einstellungsmöglichkeiten genannt. Die Felder der Klasse Settings können über den Renderer mit renderer.settings erreicht werden. Beim Erstellen eines Renderers werden für jeden Wert Standardeinstellungen initialisiert. Die folgenden Tabellen zeigen sämtliche in den Settings vornehmbaren Einstellungen mit ihren Standardwerten und einer kurzen Erläuterung nach ihren Aufgaben gruppiert. Typ und Name der V. Standardwert Beschreibung bool. tracking true View- und Projectionmatrix des Trackers verwenden bool. usevbo true Vertex Buffer Objects zum Speichern von Vert. und Ind. bool. activatepicking true Selektieren von Modellen mittels Pickingtextur aktiv. int extendedpicking 100 Erweitert den Pickingbereich um x Pixel zu beiden Seiten bool. weightedpicking false Verwendung von gewichtetem Picking (nach Distanz) bool. sortbydistance false Sortierung von transparenten Modellen nach Distanz bool. autosorting false Engine aktiviert Sortierung falls 2 oder mehr trans. Mod. bool. camerabg false Kamerabild wird als Textur für Hintergrund verwendet bool. measurefps true Ausgabe von FPS und anderen Zeiten über LogCat Abbildung 22: Allgemeine Einstellungsmöglichkeiten der Settings der AiRmob- Engine 66

68 Typ und Name der V. Standardwert Beschreibung bool. usespotlights false Stellt ein welche Art von Lichtquellen verwendet wird int lightingmode int maxlights = Gouraud, 1 = Phong, 2 = Cell-Shading Maximale Anzahl an LQ, mehr als 8 nicht möglich bool. drawshadowmap false Schatten mit Shadowmapping zeichnen bool. showshadowmap int showsmnum false 0 Tiefentextur anstatt des normalen Ergebnisses zeigen Tiefentextur welcher Lichtquelle wird gezeigt (0-7) int mappingmode 0 0 = kein Mapping, 1 = BumpMapping, 2 = Parallax float[] globalamb.col. {1, 1, 1, 1} Farbe des globalen ambienten Terms Abbildung 23: Einstellungsmöglichkeiten für Beleuchtungseffekte Typ und Name der V. Standardwert Beschreibung bool. postprocessing false Post-processing aktivieren, sonst keiner der folg. Effekte bool. antialiasing false Anti-aliasing aktivieren bool. bloom false Bloom aktivieren bool. blur false Blur aktivieren float blurringmode 1 0 = simples Blurring, 1 = Gauß-Blurring float blurradius 4 Blurring-Distanz für den Algorithmus in den Shadern float sigma 2 Verändert das Gauß-Blurring Abbildung 24: Einstellungsmöglichkeiten für Post-Processing Zusätzlich können noch die in Abschnitt beschriebenen von der AiRmob- Engine verwendeten Shader ausgetauscht werden. Dazu können einfach die Pfade der zu importierenden Shader-Dateien geändert werden. Dies sind mainvertexshadersource und mainfragmentshadersource für die Hauptshader und dementsprechend weitere String-Variablen für die anderen Shader. Die Standardwerte und Aufgaben dieser Shader wurden ebenfalls in dem genannten Abschnitt beschrieben. 67

69 5 Techdemo Autoren: Philipp Brandt, Florian Kathe, Nils Lichtenberg und Axel Peter Die Techdemo dient dazu, die Fähigkeiten des Frameworks auf der technischen Ebene zu präsentieren. Hierzu gehören Funktionalitäten, die die AiRmobActivity direkt anbietet, verschiedene Shader, Leistungen der Engine und Trackingverfahren. Renderer und Tracker werden im Hauptmenü festgelegt und anschließend geladen. Je nach Renderer sind verschiedene Voreinstellungen der Shader möglich, zur Laufzeit können sie aber stets geändert werden. Es sind dabei verschiedene Renderer verfügbar, die jeweils von der Klasse Renderer der AiRmob-Engine abgeleitet sind und die Funktion putscene zum Anlegen der Szene überschreiben. Die Szenen und Einstellungen dieser Renderer sollen verschiedene Effekte und Vorgehensweisen der AiRmob-Engine demonstrieren. Im Folgenden sollen die verschiedenen auswählbaren Renderer und das was sie jeweils demonstrieren sollen kurz erläutert werden. Der zum Erzeugen dieser Renderer benötigte Quellcode sowie Screenshots der Ergebnisse werden in Abschnitt 6 dieser Arbeit dargelegt. Free Choice: Nach der Auswahl dieses Renderers erscheint ein weiteres Menü.In diesem kann eines der externen Modelle gewählt werden, die sich im Ordner models. Dieses wird mit den Standardeinstellungen der AiRmob-Engine sowie einer Standardlichtquelle gezeichnet. Insbesondere können hier natürlich auch die OBJ-Dateien eigener Modelle schnell und unkompliziert getestet werden. Tres Amigos: Die Szene dieses Renderers besteht aus drei der vorgegebenen Modelle der AiRmob-Engine sowie einer Lichtquelle. Bei den Modellen handelt es sich um den Blender-Affenkopf Suzanne, den Utah-Teapot sowie einem einfachen Würfel, also Instanzen der Klassen modelsuzanne, modelteapot und modelcube. Diese werden in rot, grün und blau nebeneinander angezeigt. Hier soll der Umgang mit den vorgegebenen Modellen präsentiert werden. Transparent Businesses: Die Modelle des vorherigen Renderers werden in diesem leicht versetzt hintereinander und transparent gezeichnet. Dabei würden sie von vorne nach hinten gezeichnet werden, falls die Sortierung nach Distanzen deaktiviert ist. Das würde zu Fehlern führen, die verdeckten Modelle wären nicht sichtbar. Bei aktivierter Sortierung nach Distanzen ist die Ansicht korrekt. Die Sortierung kann im Menü de-/aktiviert werden. Dementsprechend soll in diesem Renderer die Sortierung transparenter Objekte nach Distanzen demonstriert werden. 68

70 100 Monkeys: Dieser Renderer zeichnet 100 Instanzen der Klasse model- Suzanne, also des Blender-Affenkopfes, in einem Raster verteilt um den Marker. Hier können die verschiedenen Picking-Einstellungen verändert und getestet werden. Trackingtest: Es wird ein einfaches Rechteck in Markergröße gezeichnet. Darauf wird eine Textur gelegt die einen rötlichen Rahmen passend auf den Marker legt, sowie ein Kreuz in dessen Mitte. Animation: In diesem Renderer wird eine Animation importiert und angezeigt. Diese zeigt einen Würfel der sich Frame für Frame zu einer Kugel verändert. Durch tippen auf den Bildschirm lässt sich die Animation pausieren. Sie befindet sich in einer Endlosschleife. Tres Amigos with multiple lights: Hier wird die Szene des Renderers Tres Amigos um mehrere Lichtquellen ergänzt. Dazu wird die maximale Anzahl der Lichtquellen erhöht und der Szene neue hinzugefügt. Bumpmapping: In diesem Renderer wird das Bumpmapping gezeigt. Es kann über die normalen Einstellungsmöglichkeiten zu Paralaxmapping umgestellt werden. Texts: In diesem Renderer werden die beiden Textarten präsentiert. Zum einen ist ein weißer Text der statisch zur Kamera gerichtet ist zu sehen. Zum anderen sind ein blauer und ein grüner Text im 3D-Raum sichtbar. Diese drei Texte können über das Menü zur Laufzeit durch Eingabe eines neuen Textes verändert werden. Neben den verschiedenen Renderern können wie bereits erwähnt auch verschiedene Tracker gewählt werden. Der markerbasierte Tracker von AndAR ist als Defaultwert festgelegt. Wählt man den AiRmob-Tracker, welcher auf Featuredetection basiert, muss diesem noch ein Imagetarget zugewiesen werden. Das kann entweder aus der Anwendung heraus und von der SD-Karte des Geräts geladen oder mit der Kamera selbst aufgenommen werden. Schießt man ein neues Foto, kann dieses entweder komplett als Imagetarget verwendet oder per Hand zugeschnitten werden. Dazu werden im Originalbild vier Punkte definiert, die die Eckpunkte des Ergebnisbildes angeben. Abbildung 25 zeigt ein Beispiel. Das aufgenommene Bild wird zunächst auf Displaymaße gestreckt. Die Eckpunkte werden dann gegen den Uhrzeigersinn, beginnend in der oberen linken Ecke, festgelegt. Zur Weiterverarbeitung werden die Punkte zuletzt von Display- auf Bildmaße umgerechnet. 69

71 Abbildung 25: Zuschneiden eines Imagetargets Bevor eine Szene endgültig geladen wird, muss der Benutzer noch die Kameraauflösung einstellen. Dazu kann er entweder drei vom Framework vorgeschlagene Werte benutzen oder manuell einen Eintrag aus den von der Kamera unterstützten Einstellungen festlegen. In Abbildung 26 ist eine Beispielszene der Techdemo zusammen mit dem Optionsmenü zu sehen. Am oberen Bildschirmrand werden die Auflösung der Kamera und die in der Szene vorhandene Anzahl an Dreiecken, Vertices und Indices angezeigt. Am unteren Rand werden die aktuelle Tracking- und Framerate, die maximal mögliche Framerate ohne Synchronisierung sowie deren Durchschnittswerte angezeigt. Die Durchschnittswerte können vom Benutzer zu jeder Zeit zurückgesetzt werden, z. B. um passende Werte zu einer neuen Shadereinstellung zu erlangen. Diese Einstellungen sind ebenfalls im Optionsmenü zu erreichen. Durch Auswahl von ToggleFreeze wird das Kamerabild entweder angehalten oder wieder fortgeführt. Unter Pipeline können die vom Framework angebotenen Pipelinevarianten ausgewählt werden. Zuletzt ist unter Description eine Beschreibung der aktuellen Szene zu finden. 70

72 Abbildung 26: Optionen und Ansicht der Techdemo Um die Eingabeoperationen des AiRmob-Frameworks zu testen, kann ein 3D-Objekt angewählt und dann rotiert oder verschoben werden. Abbildung 27 zeigt das Auswahlmenü. Im Hintergrund ist zu sehen, wie die Markierung bereits vom Marker wegbewegt und rotiert wurde. Abbildung 27: Objektinteraktion 71

73 6 Schluss Zum Schluss dieser Arbeit werden die Ergebnisse anhand der Beispiele aus der Techdemo präsentiert. Danach werden sie, sowie die Vorgehensweise und die umgesetzten Konzepte bewertet, um zuletzt in einem Ausblick denkbare Verbesserungsmöglichkeiten für die AiRmob-Engine aufzuzeigen, die nicht mehr Teil dieser Arbeit sind. Die im folgenden Abschnitt aufgeführten Zeiten wurden auf einem Samsung Galaxy S2 mit Android gemessen. Abbildung 28 zeigt die wichtigsten technischen Daten [sam] [wik]. CPU RAM Speicher Auflösung GPU 1.2 GHz dual core ARM Cortex-A9 1 GB 16 GB 800 x 480 Pixel ARM Mali-400 MP Abbildung 28: Technische Daten des Galaxy S2 6.1 Ergebnisse Im Folgenden sollen einige der in der Techdemo vorhanden Renderer anhand von Screenshots gezeigt werden. In den Screenshots sind bereits einige Angaben enthalten. Im oberen Bildteil sind dies Auflösung, Dreieck-, Vertice- und Indiceanzahl der zu zeichnenden Szene. Die Anzahlen beziehen sich dabei auf die vorhandenen Modelle, aber nicht auf jeden Identifier. Multiinstanziierungen erhöhen folglich diese Anzahl nicht, wodurch in diesen Fällen in Wahrheit mehr gezeichnet wird. Im unteren Bildteil der Screenshots befinden sich jeweils die aktuelle sowie die durchschnittliche Anzahl der Tracks (TPS) und mit diesen synchronisierte Draw-Aufrufe als auch die realen Frames pro Sekunde (FPS). Wie bereits erwähnt handelt es sich bei den realen FPS um die zum Ausführen der ondrawframe-methode benötigten Zeit. Die synchronisierten FPS sind hier über die Einstellungen des Rendermodus im Framework direkt an die TPS gebunden. Zusätzlich sollen noch die benötigte Zeit für das Erstellen des Renderers und für einige der Quelltext zum Anlegen der Szene gezeigt werden. Bei jedem der Renderer ist Phong-Beleuchtung aktiviert und Post-Processing deaktiviert. Es wird das Andar-Markertracking verwendet. Die synchronisierten FPS-Angaben sind dabei direkt an die Tracks pro Sekunde gebunden (kann im Framework umgestellt werden). Es werden VBOs verwendet. Bei den Screenshots ist anstatt des Kamerabildes ein schwarzer Hintergrund gesetzt, was bei der normalen Ausführung der Techdemo nicht der Fall ist. Der Beispielrenderer Tres Amigos zeigt (wie in Abschnitt ) drei der 72

74 vorgegebenen Modelle eingefärbt und verschoben. Der zum Erstellen dieser Szene benötigte Quellcode wurde bereits in dem obigen Abschnitt gezeigt. Zum Importieren der Modelle und dem Anlegen des Renderers werden 3-4 Sekunden benötigt. Abbildung 29 zeigt das Ergebnis dieses Renderers. Abbildung 29: Renderer Tres Amigos aus der AiRmob-Techdemo Im Renderer Text examples werden zwei Texte im 3D-Raum sowie einer statisch zur Kamera angelegt. Sie können alle über das Menü und eine Texteingabe zur Laufzeit geändert werden. Da beim Erstellen eines Textes die OpenGL-Umgebung bekannt sein muss, ist dazu die Methode on- DrawFrame um die entsprechenden Methoden ergänzt. Sie werden immer aufgerufen wenn die jeweilige Boolean-Flag dies angibt. Die Flags werden vom Framework durch eine Runnable zusammen mit der Eingabe gesetzt. In dem Quelltext dieses Beispielrenderers soll daher auch nicht nur das Erzeugen der Szene gezeigt werden, sondern ebenfalls das Erweitern einer der drei Android-Funktionen zur Kommunikation mit OpenGL ES. So wäre das gleiche Vorgehen für die Methoden onsurfacecreated und on- SurfaceChanged möglich. Abbildung 30 zeigt zunächst das Ergebnis dieses Renderers. 73

75 Abbildung 30: Renderer Text examples aus der AiRmob-Techdemo Zum Verändern des Textes wird der alte Text aus der Szene entfernt und ein neuer hinzugefügt. Wie bereits erläutert muss dazu die OpenGL-Umgebung bekannt sein. Im Folgenden Quelltext ist dabei nur der Code zur Erzeugung und Veränderung des statischen Textes (der Code für die anderen beiden Texte ist nahezu identisch): Auf einen Text reduzierter Code des Renderers Text examples I d e n t i f i e r s t a t i c T e x t I D ; f l o a t [ ] white = { 1. 0 f, 1. 0 f, 1. 0 f, 1. 0 f } ; S t r i n g s t a t i c T e x t = " S t a t i c t e s t t e x t " ; boolean statictextchanged = f a l s e ; public void ondrawframe ( GL10 glunused ) { i f ( statictextchanged ) { t h i s. updatestatictext ( s t a t i c T e x t ) ; statictextchanged = f a l s e ; } } super. ondrawframe ( glunused ) public void putscene ( ) { 74

76 samplescene = new Scene ( t h i s ) ; t h i s. scene = samplescene ; Light l i g h t = new Light ( ) ; samplescene. add ( l i g h t ) ; Text texttocamera = new Text ( this, s t a t i c T e x t, 10, white, true, 0. 0 f, 0.9 f ) ; } s t a t i c T e x t I D = samplescene. add ( texttocamera ) ; public void u p d a t e S t a tictext ( S t r i n g input ) { samplescene. remove ( s t a t i c T e x t I D ) ; Text texttocamera = new Text ( this, input, 10, white, true, 0. 0 f, 0.9 f ) ; s t a t i c T e x t I D = samplescene. add ( texttocamera ) ; } Der Beispielrenderer 100 monkeys wird nun als letztes Beispiel ausführlicher vorgestellt. In ihm werden 100 Instanzen des Beispielmodells ModelSuzanne angelegt. Diese werden durch Transformationen gleichmäßig verteilt. Die Angabe der Dreiecke, Vertices und Indices im Bild gibt hierbei nur die Anzahl der importierten Daten an. Gezeichnet wird dementsprechend das Hundertfache, also Dreiecke, Vertices und Indices. Die Methode onsurfacecreated benötigt bei diesem Renderer im Schnitt 0,4 Sekunden. 75

77 Abbildung 31: Renderer 100 monkeys aus der AiRmob-Techdemo Die Szene in diesem Renderer wurde dabei wie folgt angelegt: Auf einen Text reduzierter Code des Renderers Text examples Light l i g h t = new Light ( ) ; samplescene. add ( l i g h t ) ; f l o a t [ ] red = { 1. 0 f, 0. 0 f, 0. 0 f, 1. 0 f } ; f l o a t [ ] red2 = { 0. 5 f, 0. 0 f, 0. 0 f, 1. 0 f } ; ModelSuzanne suzanne = new ModelSuzanne ( t h i s ) ; suzanne. setmaterialambient ( red2 ) ; suzanne. s e t M a t e r i a l D i f f u s e ( red ) ; LinkedList < I d e n t i f i e r > monkeys = new LinkedList < I d e n t i f i e r > ( ) ; i n t x = 250; i n t y = 250; for ( i n t i = 0 ; i < ; i ++) { i f ( x > 200) { x = 250; y = y ; } x += 5 0 ; monkeys. add ( samplescene. add ( suzanne ) ) ; monkeys. get ( i ). s c a l e ( 1 5, 15, 1 5 ) ; 76

78 } monkeys. get ( i ). t r a n s l a t e ( x, y, 0 ) ; Im Folgenden werden Screenshots der anderen Techdemo-Beispiele unkommentiert gezeigt. Abbildung 32: Renderer transparency aus der AiRmob-Techdemo. Bei deaktivierter Sortierung nach Distanzen werden verdeckte Modelle hier überzeichnet. Abbildung 33: Renderer Tres Amigos with multiple lights aus der AiRmob- Techdemo 77

79 Abbildung 34: Renderer Bumpmapping aus der AiRmob-Techdemo. Bumpmapping kann über die Einstellungen deaktiviert werden. 6.2 Bewertung Die in Abschnitt 4.1 gesetzten Ziele sind in der AiRmob-Engine umgesetzt worden. Die gewünschten Features sind alle implementiert und funktionsfähig. Besonders hervorgehoben wurde das Ziel der leichten Bedienbarkeit. In dieser Arbeit wurde mehrfach gezeigt wie mit der AiRmob-Engine programmiert werden kann, zuletzt im vorherigen Abschnitt für einige der Beispielrenderer. Die Befehle zum Umgang mit den Klassen sind so simpel wie möglich gehalten, und zum Teil gibt es mehrere Alternativen, um unnötige Hindernisse zu vermeiden. So sind bspw. mehrfach überladene Konstruktoren vorhanden mit denen sich Klassen mit mehr oder weniger Angaben erstellen lassen, wie denen für Animationen, die zeit- oder zeichendurchlauf-basiert sind. Für öffentliche Methoden wurden größtenteils mittels Javadoc Beschreibungen über deren Funktion und Inputs geschrieben, um ein leichtes Arbeiten mit der Engine zu ermöglichen. Die Ergebnisse in Hinsicht auf Performance zu bewerten ist schwieriger. Da ein großer Teil der Kosten beim Zeichnen in den Shadern entsteht und diese in der Arbeit von Philipp Brandt entstanden und beschrieben sind, werden die Kosten der verschiedenen Shader dementsprechend auch dort bewertet. Des Weiteren ist die Engine in das AiRmob-Framework eingebunden und somit laufen stets auch dessen andere Prozesse parallel dazu, insbesondere das Tracking. Für die Szenarien einer Augmented-Reality- Anwendung in der zumeist keine gesamte Umgebung sondern einige Modelle vor dem Kamerahintergrund gezeigt werden, ist die Engine gut geeignet. Hierbei können Tracking und Engine problemlos parallel laufen. Meist ist das Tracking sehr viel langsamer als die Engine, also die Anzahl 78

Übung: Verwendung von Java-Threads

Übung: Verwendung von Java-Threads Übung: Verwendung von Java-Threads Ziel der Übung: Diese Übung dient dazu, den Umgang mit Threads in der Programmiersprache Java kennenzulernen. Ein einfaches Java-Programm, das Threads nutzt, soll zum

Mehr

GeoPilot (Android) die App

GeoPilot (Android) die App GeoPilot (Android) die App Mit der neuen Rademacher GeoPilot App machen Sie Ihr Android Smartphone zum Sensor und steuern beliebige Szenen über den HomePilot. Die App beinhaltet zwei Funktionen, zum einen

Mehr

Datensicherung. Beschreibung der Datensicherung

Datensicherung. Beschreibung der Datensicherung Datensicherung Mit dem Datensicherungsprogramm können Sie Ihre persönlichen Daten problemlos Sichern. Es ist möglich eine komplette Datensicherung durchzuführen, aber auch nur die neuen und geänderten

Mehr

Anleitung über den Umgang mit Schildern

Anleitung über den Umgang mit Schildern Anleitung über den Umgang mit Schildern -Vorwort -Wo bekommt man Schilder? -Wo und wie speichert man die Schilder? -Wie füge ich die Schilder in meinen Track ein? -Welche Bauteile kann man noch für Schilder

Mehr

Präsentation Von Laura Baake und Janina Schwemer

Präsentation Von Laura Baake und Janina Schwemer Präsentation Von Laura Baake und Janina Schwemer Gliederung Einleitung Verschiedene Betriebssysteme Was ist ein Framework? App-Entwicklung App-Arten Möglichkeiten und Einschränkungen der App-Entwicklung

Mehr

4.1 Download der App über den Play Store

4.1 Download der App über den Play Store 4 4.1 Download der App über den Play Store Die App TopSec Phone kann über den Play Store auf dem Smartphone oder über das Internet an Ihrem Computer heruntergeladen werden. Um Inhalte laden zu können,

Mehr

Dokumentation IBIS Monitor

Dokumentation IBIS Monitor Dokumentation IBIS Monitor Seite 1 von 16 11.01.06 Inhaltsverzeichnis 1. Allgemein 2. Installation und Programm starten 3. Programmkonfiguration 4. Aufzeichnung 4.1 Aufzeichnung mitschneiden 4.1.1 Inhalt

Mehr

Kostenstellen verwalten. Tipps & Tricks

Kostenstellen verwalten. Tipps & Tricks Tipps & Tricks INHALT SEITE 1.1 Kostenstellen erstellen 3 13 1.3 Zugriffsberechtigungen überprüfen 30 2 1.1 Kostenstellen erstellen Mein Profil 3 1.1 Kostenstellen erstellen Kostenstelle(n) verwalten 4

Mehr

Handbuch B4000+ Preset Manager

Handbuch B4000+ Preset Manager Handbuch B4000+ Preset Manager B4000+ authentic organ modeller Version 0.6 FERROFISH advanced audio applications Einleitung Mit der Software B4000+ Preset Manager können Sie Ihre in der B4000+ erstellten

Mehr

Sie werden sehen, dass Sie für uns nur noch den direkten PDF-Export benötigen. Warum?

Sie werden sehen, dass Sie für uns nur noch den direkten PDF-Export benötigen. Warum? Leitfaden zur Druckdatenerstellung Inhalt: 1. Download und Installation der ECI-Profile 2. Farbeinstellungen der Adobe Creative Suite Bitte beachten! In diesem kleinen Leitfaden möchten wir auf die Druckdatenerstellung

Mehr

Objektorientierte Programmierung für Anfänger am Beispiel PHP

Objektorientierte Programmierung für Anfänger am Beispiel PHP Objektorientierte Programmierung für Anfänger am Beispiel PHP Johannes Mittendorfer http://jmittendorfer.hostingsociety.com 19. August 2012 Abstract Dieses Dokument soll die Vorteile der objektorientierten

Mehr

S/W mit PhotoLine. Inhaltsverzeichnis. PhotoLine

S/W mit PhotoLine. Inhaltsverzeichnis. PhotoLine PhotoLine S/W mit PhotoLine Erstellt mit Version 16.11 Ich liebe Schwarzweiß-Bilder und schaue mir neidisch die Meisterwerke an, die andere Fotografen zustande bringen. Schon lange versuche ich, auch so

Mehr

Technische Dokumentation SilentStatistikTool

Technische Dokumentation SilentStatistikTool Technische Dokumentation SilentStatistikTool Version 1.0 Marko Schröder 1115063 Inhalt Einleitung... 3 Klasse Program... 3 Klasse ArgumentHandler... 3 Bereitgestellte Variablen... 3 Bereitgestellte Methoden...

Mehr

Kommunikations-Management

Kommunikations-Management Tutorial: Wie importiere und exportiere ich Daten zwischen myfactory und Outlook? Im vorliegenden Tutorial lernen Sie, wie Sie in myfactory Daten aus Outlook importieren Daten aus myfactory nach Outlook

Mehr

Eigenen Farbverlauf erstellen

Eigenen Farbverlauf erstellen Diese Serie ist an totale Neulinge gerichtet. Neu bei PhotoLine, evtl. sogar komplett neu, was Bildbearbeitung betrifft. So versuche ich, hier alles einfach zu halten. Ich habe sogar PhotoLine ein zweites

Mehr

OpenGL. (Open Graphic Library)

OpenGL. (Open Graphic Library) OpenGL (Open Graphic Library) Agenda Was ist OpenGL eigentlich? Geschichte Vor- und Nachteile Arbeitsweise glscene OpenGL per Hand Debugging Trend Was ist OpenGL eigentlich? OpenGL ist eine Spezifikation

Mehr

Lineargleichungssysteme: Additions-/ Subtraktionsverfahren

Lineargleichungssysteme: Additions-/ Subtraktionsverfahren Lineargleichungssysteme: Additions-/ Subtraktionsverfahren W. Kippels 22. Februar 2014 Inhaltsverzeichnis 1 Einleitung 2 2 Lineargleichungssysteme zweiten Grades 2 3 Lineargleichungssysteme höheren als

Mehr

Beschreibung und Bedienungsanleitung. Inhaltsverzeichnis: Abbildungsverzeichnis: Werkzeug für verschlüsselte bpks. Dipl.-Ing.

Beschreibung und Bedienungsanleitung. Inhaltsverzeichnis: Abbildungsverzeichnis: Werkzeug für verschlüsselte bpks. Dipl.-Ing. www.egiz.gv.at E-Mail: post@egiz.gv.at Telefon: ++43 (316) 873 5514 Fax: ++43 (316) 873 5520 Inffeldgasse 16a / 8010 Graz / Austria Beschreibung und Bedienungsanleitung Werkzeug für verschlüsselte bpks

Mehr

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

Binäre Bäume. 1. Allgemeines. 2. Funktionsweise. 2.1 Eintragen Binäre Bäume 1. Allgemeines Binäre Bäume werden grundsätzlich verwendet, um Zahlen der Größe nach, oder Wörter dem Alphabet nach zu sortieren. Dem einfacheren Verständnis zu Liebe werde ich mich hier besonders

Mehr

1 topologisches Sortieren

1 topologisches Sortieren Wolfgang Hönig / Andreas Ecke WS 09/0 topologisches Sortieren. Überblick. Solange noch Knoten vorhanden: a) Suche Knoten v, zu dem keine Kante führt (Falls nicht vorhanden keine topologische Sortierung

Mehr

Folgeanleitung für Klassenlehrer

Folgeanleitung für Klassenlehrer Folgeanleitung für Klassenlehrer 1. Das richtige Halbjahr einstellen Stellen sie bitte zunächst das richtige Schul- und Halbjahr ein. Ist das korrekte Schul- und Halbjahr eingestellt, leuchtet die Fläche

Mehr

Durchführung der Datenübernahme nach Reisekosten 2011

Durchführung der Datenübernahme nach Reisekosten 2011 Durchführung der Datenübernahme nach Reisekosten 2011 1. Starten Sie QuickSteuer Deluxe 2010. Rufen Sie anschließend über den Menüpunkt /Extras/Reisekosten Rechner den QuickSteuer Deluxe 2010 Reisekosten-Rechner,

Mehr

Grundfunktionen und Bedienung

Grundfunktionen und Bedienung Kapitel 13 Mit der App Health ist eine neue Anwendung in ios 8 enthalten, die von vorangegangenen Betriebssystemen bislang nicht geboten wurde. Health fungiert dabei als Aggregator für die Daten von Fitness-

Mehr

Kara-Programmierung AUFGABENSTELLUNG LERNPARCOURS. Abb. 1: Programmfenster. Welt neu erstellen; öffnen; erneut öffnen; speichern; speichern unter

Kara-Programmierung AUFGABENSTELLUNG LERNPARCOURS. Abb. 1: Programmfenster. Welt neu erstellen; öffnen; erneut öffnen; speichern; speichern unter Kara-Programmierung AUFGABENSTELLUNG LERNPARCOURS Abb. 1: Programmfenster Welt neu erstellen; öffnen; erneut öffnen; speichern; speichern unter Programmfenster anzeigen Einstellungen öffnen Kara direkt

Mehr

INFOnline SZM-Checker Ergänzung zum Manual

INFOnline SZM-Checker Ergänzung zum Manual INFOnline SZM-Checker Ergänzung zum Manual Aktivierung mobiler Geräte für Tests zur InApp- Befragungsfunktionalität INFOnline GmbH Forum Bonn Nord Brühler Str. 9 53119 Bonn Tel.: +49 (0) 228 / 410 29-0

Mehr

Programmieren in Java

Programmieren in Java Programmieren in Java objektorientierte Programmierung 2 2 Zusammenhang Klasse-Datei In jeder *.java Datei kann es genau eine public-klasse geben wobei Klassen- und Dateiname übereinstimmen. Es können

Mehr

Abamsoft Finos im Zusammenspiel mit shop to date von DATA BECKER

Abamsoft Finos im Zusammenspiel mit shop to date von DATA BECKER Abamsoft Finos im Zusammenspiel mit shop to date von DATA BECKER Abamsoft Finos in Verbindung mit der Webshopanbindung wurde speziell auf die Shop-Software shop to date von DATA BECKER abgestimmt. Mit

Mehr

3D Objekte in einen Clip integrieren

3D Objekte in einen Clip integrieren 3D Objekte in einen Clip integrieren Benötigt wird: MAXON Cinema 4D R14 Adobe After Effects CS6 (im Folgenden mit C4D bezeichnet) (im Folgenden mit AE bezeichnet) Unter der Cloud-Lösung Adobe CC gibt es

Mehr

OP-LOG www.op-log.de

OP-LOG www.op-log.de Verwendung von Microsoft SQL Server, Seite 1/18 OP-LOG www.op-log.de Anleitung: Verwendung von Microsoft SQL Server 2005 Stand Mai 2010 1 Ich-lese-keine-Anleitungen 'Verwendung von Microsoft SQL Server

Mehr

DOKUMENTATION VOGELZUCHT 2015 PLUS

DOKUMENTATION VOGELZUCHT 2015 PLUS DOKUMENTATION VOGELZUCHT 2015 PLUS Vogelzucht2015 App für Geräte mit Android Betriebssystemen Läuft nur in Zusammenhang mit einer Vollversion vogelzucht2015 auf einem PC. Zusammenfassung: a. Mit der APP

Mehr

teischl.com Software Design & Services e.u. office@teischl.com www.teischl.com/booknkeep www.facebook.com/booknkeep

teischl.com Software Design & Services e.u. office@teischl.com www.teischl.com/booknkeep www.facebook.com/booknkeep teischl.com Software Design & Services e.u. office@teischl.com www.teischl.com/booknkeep www.facebook.com/booknkeep 1. Erstellen Sie ein neues Rechnungsformular Mit book n keep können Sie nun Ihre eigenen

Mehr

SWT II Projekt. Chat - Anwendung. Pflichtenheft 2000 SWT

SWT II Projekt. Chat - Anwendung. Pflichtenheft 2000 SWT SWT II Projekt Chat - Anwendung Pflichtenheft 2000 SWT i Versionen Datum Version Beschreibung Autor 3.11.2000 1.0 erste Version Dietmar Matthes ii Inhaltsverzeichnis 1. ZWECK... 1 1.1. RAHMEN... 1 1.2.

Mehr

Robot Karol für Delphi

Robot Karol für Delphi Robot Karol für Delphi Reinhard Nitzsche, OSZ Handel I Version 0.1 vom 24. Januar 2003 Zusammenfassung Nach der Einführung in die (variablenfreie) Programmierung mit Robot Karol von Freiberger und Krško

Mehr

Übungen zur Softwaretechnik

Übungen zur Softwaretechnik Technische Universität München Fakultät für Informatik Lehrstuhl IV: Software & Systems Engineering Markus Pister, Dr. Bernhard Rumpe WS 2002/2003 Lösungsblatt 9 17. Dezember 2002 www4.in.tum.de/~rumpe/se

Mehr

Enigmail Konfiguration

Enigmail Konfiguration Enigmail Konfiguration 11.06.2006 Steffen.Teubner@Arcor.de Enigmail ist in der Grundkonfiguration so eingestellt, dass alles funktioniert ohne weitere Einstellungen vornehmen zu müssen. Für alle, die es

Mehr

malistor Phone ist für Kunden mit gültigem Servicevertrag kostenlos.

malistor Phone ist für Kunden mit gültigem Servicevertrag kostenlos. malistor Phone malistor Phone ist die ideale Ergänzung zu Ihrer Malersoftware malistor. Mit malistor Phone haben Sie Ihre Adressen und Dokumente (Angebote, Aufträge, Rechnungen) aus malistor immer dabei.

Mehr

Simple SMS SMS Gateway

Simple SMS SMS Gateway Simple SMS SMS Gateway Kontakte-Verwaltung Bei Fragen kontaktieren Sie bitte die Simple SMS Service- Hotline: Telefon: 0800 20 20 49 (aus Österreich) Telefon: 00800 20 20 49 00 (aus DE, CH, FR, GB, SK)

Mehr

Folgeanleitung für Fachlehrer

Folgeanleitung für Fachlehrer 1. Das richtige Halbjahr einstellen Folgeanleitung für Fachlehrer Stellen sie bitte zunächst das richtige Schul- und Halbjahr ein. Ist das korrekte Schul- und Halbjahr eingestellt, leuchtet die Fläche

Mehr

Konfiguration VLAN's. Konfiguration VLAN's IACBOX.COM. Version 2.0.1 Deutsch 01.07.2014

Konfiguration VLAN's. Konfiguration VLAN's IACBOX.COM. Version 2.0.1 Deutsch 01.07.2014 Konfiguration VLAN's Version 2.0.1 Deutsch 01.07.2014 In diesem HOWTO wird die Konfiguration der VLAN's für das Surf-LAN der IAC-BOX beschrieben. Konfiguration VLAN's TITEL Inhaltsverzeichnis Inhaltsverzeichnis...

Mehr

AUF LETZTER SEITE DIESER ANLEITUNG!!!

AUF LETZTER SEITE DIESER ANLEITUNG!!! BELEG DATENABGLEICH: Der Beleg-Datenabgleich wird innerhalb des geöffneten Steuerfalls über ELSTER-Belegdaten abgleichen gestartet. Es werden Ihnen alle verfügbaren Belege zum Steuerfall im ersten Bildschirm

Mehr

Dokumentation für das Spiel Pong

Dokumentation für das Spiel Pong Dokumentation für das Spiel Pong BwInf - Turnierserver Didaktik der nformatik BWINF KI Wettbewerbs-Plattform Stand: 02.09.2014 Grundlagen In diesem KI-Turnier programmiert ihr einen Schläger für das Retro-Spiel

Mehr

Artikel Schnittstelle über CSV

Artikel Schnittstelle über CSV Artikel Schnittstelle über CSV Sie können Artikeldaten aus Ihrem EDV System in das NCFOX importieren, dies geschieht durch eine CSV Schnittstelle. Dies hat mehrere Vorteile: Zeitersparnis, die Karteikarte

Mehr

Auto-Provisionierung tiptel 30x0 mit Yeastar MyPBX

Auto-Provisionierung tiptel 30x0 mit Yeastar MyPBX Allgemeines Auto-Provisionierung tiptel 30x0 mit Yeastar MyPBX Stand 21.11.2014 Die Yeastar MyPBX Telefonanlagen unterstützen die automatische Konfiguration der tiptel 3010, tiptel 3020 und tiptel 3030

Mehr

VB.net Programmierung und Beispielprogramm für GSV

VB.net Programmierung und Beispielprogramm für GSV VB.net Programmierung und Beispielprogramm für GSV Dokumentation Stand vom 26.05.2011 Tel +49 (0)3302 78620 60, Fax +49 (0)3302 78620 69, info@me-systeme.de, www.me-systeme.de 1 Inhaltsverzeichnis Vorwort...2

Mehr

Grundlagen von Python

Grundlagen von Python Einführung in Python Grundlagen von Python Felix Döring, Felix Wittwer November 17, 2015 Scriptcharakter Programmierparadigmen Imperatives Programmieren Das Scoping Problem Objektorientiertes Programmieren

Mehr

Nie wieder eine Sitzung verpassen unser neuer Service für Sie!

Nie wieder eine Sitzung verpassen unser neuer Service für Sie! Nie wieder eine Sitzung verpassen unser neuer Service für Sie! Bisher war es nicht immer leicht, den Überblick über die Ammersbeker Sitzungstermine zu behalten. Entweder man hat die Bekanntmachung übersehen

Mehr

CALCOO Lite. Inhalt. 1. Projekt anlegen / öffnen. 2. Projekt von CALCOO App importieren

CALCOO Lite. Inhalt. 1. Projekt anlegen / öffnen. 2. Projekt von CALCOO App importieren CALCOO Lite Hier finden Sie eine Kurzanleitung zu den einzelnen Projektschritten von CALCOO Light. Nach dem Lesen wissen Sie die grundlegenden Funktionen zu bedienen und können ein Projekt erstellen. Inhalt

Mehr

Virtueller Seminarordner Anleitung für die Dozentinnen und Dozenten

Virtueller Seminarordner Anleitung für die Dozentinnen und Dozenten Virtueller Seminarordner Anleitung für die Dozentinnen und Dozenten In dem Virtuellen Seminarordner werden für die Teilnehmerinnen und Teilnehmer des Seminars alle für das Seminar wichtigen Informationen,

Mehr

Guideline. Facebook Posting. mit advertzoom Version 2.3

Guideline. Facebook Posting. mit advertzoom Version 2.3 Guideline Facebook Posting mit advertzoom Version 2.3 advertzoom GmbH advertzoom GmbH Stand November 2012 Seite [1] Inhalt 1 Facebook Posting Schnittstelle... 3 1.1 Funktionsüberblick... 3 2 Externe Ressource

Mehr

.htaccess HOWTO. zum Schutz von Dateien und Verzeichnissen mittels Passwortabfrage

.htaccess HOWTO. zum Schutz von Dateien und Verzeichnissen mittels Passwortabfrage .htaccess HOWTO zum Schutz von Dateien und Verzeichnissen mittels Passwortabfrage Stand: 21.06.2015 Inhaltsverzeichnis 1. Vorwort...3 2. Verwendung...4 2.1 Allgemeines...4 2.1 Das Aussehen der.htaccess

Mehr

! " # $ " % & Nicki Wruck worldwidewruck 08.02.2006

!  # $  % & Nicki Wruck worldwidewruck 08.02.2006 !"# $ " %& Nicki Wruck worldwidewruck 08.02.2006 Wer kennt die Problematik nicht? Die.pst Datei von Outlook wird unübersichtlich groß, das Starten und Beenden dauert immer länger. Hat man dann noch die.pst

Mehr

2. ERSTELLEN VON APPS MIT DEM ADT PLUGIN VON ECLIPSE

2. ERSTELLEN VON APPS MIT DEM ADT PLUGIN VON ECLIPSE 2. ERSTELLEN VON APPS MIT DEM ADT PLUGIN VON ECLIPSE 2.1 Die Einrichtung der Benutzeroberfläche Das Einrichten einer Android-Eclipse-Entwicklungsumgebung zur Android-Entwicklung ist grundsätzlich nicht

Mehr

Der naldo-offline-handyfahrplan

Der naldo-offline-handyfahrplan Der naldo-offline-handyfahrplan Erste Schritte mit dem neuen naldo-offline-handyfahrplan Bedienungsanleitung Inhaltsverzeichnis: 1. Erster Programmstart 2. Die Programmbedienung 3. Favoriten 4. Meine Fahrten

Mehr

Objektorientierte Programmierung. Kapitel 12: Interfaces

Objektorientierte Programmierung. Kapitel 12: Interfaces 12. Interfaces 1/14 Objektorientierte Programmierung Kapitel 12: Interfaces Stefan Brass Martin-Luther-Universität Halle-Wittenberg Wintersemester 2012/13 http://www.informatik.uni-halle.de/ brass/oop12/

Mehr

Android VHS - Weiterbildungskurs Ort: Sulingen

Android VHS - Weiterbildungskurs Ort: Sulingen Kontakte Neuen Kontakt anlegen Um einen neuen Kontakt anzulegen, wird zuerst (Kontakte) aufgerufen. Unten Rechts befindet sich die Schaltfläche um einen neuen Kontakt zu erstellen. Beim Kontakt anlegen

Mehr

Er musste so eingerichtet werden, dass das D-Laufwerk auf das E-Laufwerk gespiegelt

Er musste so eingerichtet werden, dass das D-Laufwerk auf das E-Laufwerk gespiegelt Inhaltsverzeichnis Aufgabe... 1 Allgemein... 1 Active Directory... 1 Konfiguration... 2 Benutzer erstellen... 3 Eigenes Verzeichnis erstellen... 3 Benutzerkonto erstellen... 3 Profil einrichten... 5 Berechtigungen

Mehr

Bauteilattribute als Sachdaten anzeigen

Bauteilattribute als Sachdaten anzeigen Mit den speedikon Attributfiltern können Sie die speedikon Attribute eines Bauteils als MicroStation Sachdaten an die Elemente anhängen Inhalte Was ist ein speedikon Attribut?... 3 Eigene Attribute vergeben...

Mehr

Schnittstelle DIGI-Zeiterfassung

Schnittstelle DIGI-Zeiterfassung P.A.P.A. die kaufmännische Softwarelösung Schnittstelle DIGI-Zeiterfassung Inhalt Einleitung... 2 Eingeben der Daten... 2 Datenabgleich... 3 Zusammenfassung... 5 Es gelten ausschließlich unsere Allgemeinen

Mehr

FastBill Automatic. Dokumentation Versand. FastBill GmbH. Holteyer Straße 30 45289 Essen Telefon 0201 47091505 Telefax 0201 54502360

FastBill Automatic. Dokumentation Versand. FastBill GmbH. Holteyer Straße 30 45289 Essen Telefon 0201 47091505 Telefax 0201 54502360 FastBill GmbH Holteyer Straße 30 45289 Essen Telefon 0201 47091505 Telefax 0201 54502360 FastBill Automatic Dokumentation Versand 1 Inhaltsverzeichnis: 1. Grundlegendes 2. Produkteinstellungen 2.1. Grundeinstellungen

Mehr

1. Software installieren 2. Software starten. Hilfe zum Arbeiten mit der DÖHNERT FOTOBUCH Software

1. Software installieren 2. Software starten. Hilfe zum Arbeiten mit der DÖHNERT FOTOBUCH Software 1. Software installieren 2. Software starten Hilfe zum Arbeiten mit der DÖHNERT FOTOBUCH Software 3. Auswahl 1. Neues Fotobuch erstellen oder 2. ein erstelltes, gespeichertes Fotobuch laden und bearbeiten.

Mehr

Im Folgenden wird Ihnen an einem Beispiel erklärt, wie Sie Excel-Anlagen und Excel-Vorlagen erstellen können.

Im Folgenden wird Ihnen an einem Beispiel erklärt, wie Sie Excel-Anlagen und Excel-Vorlagen erstellen können. Excel-Schnittstelle Im Folgenden wird Ihnen an einem Beispiel erklärt, wie Sie Excel-Anlagen und Excel-Vorlagen erstellen können. Voraussetzung: Microsoft Office Excel ab Version 2000 Zum verwendeten Beispiel:

Mehr

Nach der Anmeldung im Backend Bereich landen Sie im Kontrollzentrum, welches so aussieht:

Nach der Anmeldung im Backend Bereich landen Sie im Kontrollzentrum, welches so aussieht: Beiträge erstellen in Joomla Nach der Anmeldung im Backend Bereich landen Sie im Kontrollzentrum, welches so aussieht: Abbildung 1 - Kontrollzentrum Von hier aus kann man zu verschiedene Einstellungen

Mehr

Albert HAYR Linux, IT and Open Source Expert and Solution Architect. Open Source professionell einsetzen

Albert HAYR Linux, IT and Open Source Expert and Solution Architect. Open Source professionell einsetzen Open Source professionell einsetzen 1 Mein Background Ich bin überzeugt von Open Source. Ich verwende fast nur Open Source privat und beruflich. Ich arbeite seit mehr als 10 Jahren mit Linux und Open Source.

Mehr

Anleitung für den Euroweb-Newsletter

Anleitung für den Euroweb-Newsletter 1. Die Anmeldung Begeben Sie sich auf der Euroweb Homepage (www.euroweb.de) in den Support-Bereich und wählen dort den Punkt Newsletter aus. Im Folgenden öffnet sich in dem Browserfenster die Seite, auf

Mehr

12. Dokumente Speichern und Drucken

12. Dokumente Speichern und Drucken 12. Dokumente Speichern und Drucken 12.1 Überblick Wie oft sollte man sein Dokument speichern? Nachdem Sie ein Word Dokument erstellt oder bearbeitet haben, sollten Sie es immer speichern. Sie sollten

Mehr

Handbuch Groupware - Mailserver

Handbuch Groupware - Mailserver Handbuch Inhaltsverzeichnis 1. Einführung...3 2. Ordnerliste...3 2.1 E-Mail...3 2.2 Kalender...3 2.3 Kontakte...3 2.4 Dokumente...3 2.5 Aufgaben...3 2.6 Notizen...3 2.7 Gelöschte Objekte...3 3. Menüleiste...4

Mehr

Ablaufbeschreibung für das neu Aufsetzen von Firebird und Interbase Datenbanken mit der IBOConsole

Ablaufbeschreibung für das neu Aufsetzen von Firebird und Interbase Datenbanken mit der IBOConsole Lavid-F.I.S. Ablaufbeschreibung für das neu Aufsetzen von Firebird und Interbase Datenbanken mit der Lavid Software GmbH Dauner Straße 12, D-41236 Mönchengladbach http://www.lavid-software.net Support:

Mehr

Programmierkurs Java

Programmierkurs Java Programmierkurs Java Dr. Dietrich Boles Aufgaben zu UE16-Rekursion (Stand 09.12.2011) Aufgabe 1: Implementieren Sie in Java ein Programm, das solange einzelne Zeichen vom Terminal einliest, bis ein #-Zeichen

Mehr

Kommunikations-Management

Kommunikations-Management Tutorial: Wie kann ich E-Mails schreiben? Im vorliegenden Tutorial lernen Sie, wie Sie in myfactory E-Mails schreiben können. In myfactory können Sie jederzeit schnell und einfach E-Mails verfassen egal

Mehr

Advanced Rendering Interior Szene

Advanced Rendering Interior Szene Advanced Rendering Interior Szene in Cinema 4D 11-11.5 Als erstes, sollten Sie ihre Szene in Cinema 4D öffnen. vergewissern sie sich, ob alle Licht quellen die evtl. mit importiert wurden, aus der Szene

Mehr

Stellen Sie bitte den Cursor in die Spalte B2 und rufen die Funktion Sverweis auf. Es öffnet sich folgendes Dialogfenster

Stellen Sie bitte den Cursor in die Spalte B2 und rufen die Funktion Sverweis auf. Es öffnet sich folgendes Dialogfenster Es gibt in Excel unter anderem die so genannten Suchfunktionen / Matrixfunktionen Damit können Sie Werte innerhalb eines bestimmten Bereichs suchen. Als Beispiel möchte ich die Funktion Sverweis zeigen.

Mehr

SANDBOXIE konfigurieren

SANDBOXIE konfigurieren SANDBOXIE konfigurieren für Webbrowser und E-Mail-Programme Dies ist eine kurze Anleitung für die grundlegenden folgender Programme: Webbrowser: Internet Explorer, Mozilla Firefox und Opera E-Mail-Programme:

Mehr

ÖKB Steiermark Schulungsunterlagen

ÖKB Steiermark Schulungsunterlagen ÖKB Steiermark Schulungsunterlagen Fotos von Online-Speicher bereitstellen Da das hinzufügen von Fotos auf unsere Homepage recht umständlich und auf 80 Fotos begrenzt ist, ist es erforderlich die Dienste

Mehr

Arbeiten mit UMLed und Delphi

Arbeiten mit UMLed und Delphi Arbeiten mit UMLed und Delphi Diese Anleitung soll zeigen, wie man Klassen mit dem UML ( Unified Modeling Language ) Editor UMLed erstellt, in Delphi exportiert und dort so einbindet, dass diese (bis auf

Mehr

Tevalo Handbuch v 1.1 vom 10.11.2011

Tevalo Handbuch v 1.1 vom 10.11.2011 Tevalo Handbuch v 1.1 vom 10.11.2011 Inhalt Registrierung... 3 Kennwort vergessen... 3 Startseite nach dem Login... 4 Umfrage erstellen... 4 Fragebogen Vorschau... 7 Umfrage fertigstellen... 7 Öffentliche

Mehr

Folge 19 - Bäume. 19.1 Binärbäume - Allgemeines. Grundlagen: Ulrich Helmich: Informatik 2 mit BlueJ - Ein Kurs für die Stufe 12

Folge 19 - Bäume. 19.1 Binärbäume - Allgemeines. Grundlagen: Ulrich Helmich: Informatik 2 mit BlueJ - Ein Kurs für die Stufe 12 Grundlagen: Folge 19 - Bäume 19.1 Binärbäume - Allgemeines Unter Bäumen versteht man in der Informatik Datenstrukturen, bei denen jedes Element mindestens zwei Nachfolger hat. Bereits in der Folge 17 haben

Mehr

Suche schlecht beschriftete Bilder mit Eigenen Abfragen

Suche schlecht beschriftete Bilder mit Eigenen Abfragen Suche schlecht beschriftete Bilder mit Eigenen Abfragen Ist die Bilderdatenbank über einen längeren Zeitraum in Benutzung, so steigt die Wahrscheinlichkeit für schlecht beschriftete Bilder 1. Insbesondere

Mehr

Inkrementelles Backup

Inkrementelles Backup Inkrementelles Backup Im Gegensatz zu einer kompletten Sicherung aller Daten werden bei einer inkrementellen Sicherung immer nur die Dateien gesichert, die seit der letzten inkrementellen Sicherung neu

Mehr

1. Einführung. 2. Archivierung alter Datensätze

1. Einführung. 2. Archivierung alter Datensätze 1. Einführung Mit wachsender Datenmenge und je nach Konfiguration, kann orgamax mit der Zeit langsamer werden. Es gibt aber diverse Möglichkeiten, die Software wieder so zu beschleunigen, als würden Sie

Mehr

Dieser Ablauf soll eine Hilfe für die tägliche Arbeit mit der SMS Bestätigung im Millennium darstellen.

Dieser Ablauf soll eine Hilfe für die tägliche Arbeit mit der SMS Bestätigung im Millennium darstellen. Millennium SMS Service Schnellübersicht Seite 1 von 6 1. Tägliche Arbeiten mit der SMS Bestätigung Dieser Ablauf soll eine Hilfe für die tägliche Arbeit mit der SMS Bestätigung im Millennium darstellen.

Mehr

Handbuch Fischertechnik-Einzelteiltabelle V3.7.3

Handbuch Fischertechnik-Einzelteiltabelle V3.7.3 Handbuch Fischertechnik-Einzelteiltabelle V3.7.3 von Markus Mack Stand: Samstag, 17. April 2004 Inhaltsverzeichnis 1. Systemvorraussetzungen...3 2. Installation und Start...3 3. Anpassen der Tabelle...3

Mehr

Kapiteltests zum Leitprogramm Binäre Suchbäume

Kapiteltests zum Leitprogramm Binäre Suchbäume Kapiteltests zum Leitprogramm Binäre Suchbäume Björn Steffen Timur Erdag überarbeitet von Christina Class Binäre Suchbäume Kapiteltests für das ETH-Leitprogramm Adressaten und Institutionen Das Leitprogramm

Mehr

Web-Kürzel. Krishna Tateneni Yves Arrouye Deutsche Übersetzung: Stefan Winter

Web-Kürzel. Krishna Tateneni Yves Arrouye Deutsche Übersetzung: Stefan Winter Krishna Tateneni Yves Arrouye Deutsche Übersetzung: Stefan Winter 2 Inhaltsverzeichnis 1 Web-Kürzel 4 1.1 Einführung.......................................... 4 1.2 Web-Kürzel.........................................

Mehr

Reporting Services und SharePoint 2010 Teil 1

Reporting Services und SharePoint 2010 Teil 1 Reporting Services und SharePoint 2010 Teil 1 Abstract Bei der Verwendung der Reporting Services in Zusammenhang mit SharePoint 2010 stellt sich immer wieder die Frage bei der Installation: Wo und Wie?

Mehr

schnell und portofrei erhältlich bei beck-shop.de DIE FACHBUCHHANDLUNG mitp/bhv

schnell und portofrei erhältlich bei beck-shop.de DIE FACHBUCHHANDLUNG mitp/bhv Roboter programmieren mit NXC für Lego Mindstorms NXT 1. Auflage Roboter programmieren mit NXC für Lego Mindstorms NXT schnell und portofrei erhältlich bei beck-shop.de DIE FACHBUCHHANDLUNG mitp/bhv Verlag

Mehr

1373-1-8689 13.02.2015. Lizensierung ABB i-bus Newron Commissiong Tool

1373-1-8689 13.02.2015. Lizensierung ABB i-bus Newron Commissiong Tool 1373-1-8689 13.02.2015 Lizensierung ABB i-bus Newron Commissiong Tool Inhalt 1 Einleitung 3 2 Vorraussetzungen 3 3 MOOVnGROUP Light-Version 4 4 MOOVnGROUP Voll-Version 5 4.1 Bestellung MOOVnGROUP Dongle

Mehr

Wichtige Hinweise zu den neuen Orientierungshilfen der Architekten-/Objektplanerverträge

Wichtige Hinweise zu den neuen Orientierungshilfen der Architekten-/Objektplanerverträge Wichtige Hinweise zu den neuen Orientierungshilfen der Architekten-/Objektplanerverträge Ab der Version forma 5.5 handelt es sich bei den Orientierungshilfen der Architekten-/Objektplanerverträge nicht

Mehr

Wir wünschen Ihnen viel Freude und Erfolg mit Ihrem neuen X-PRO-USB-Interface. Ihr Hacker-Team

Wir wünschen Ihnen viel Freude und Erfolg mit Ihrem neuen X-PRO-USB-Interface. Ihr Hacker-Team Installationsanleitung Hacker X-PRO-USB-Controller V2 Software + Interface Sehr geehrter Kunde, wir freuen uns, dass Sie sich für das X-PRO-USB-V2-Interface aus unserem Sortiment entschieden haben. Sie

Mehr

HANDBUCH PHOENIX II - DOKUMENTENVERWALTUNG

HANDBUCH PHOENIX II - DOKUMENTENVERWALTUNG it4sport GmbH HANDBUCH PHOENIX II - DOKUMENTENVERWALTUNG Stand 10.07.2014 Version 2.0 1. INHALTSVERZEICHNIS 2. Abbildungsverzeichnis... 3 3. Dokumentenumfang... 4 4. Dokumente anzeigen... 5 4.1 Dokumente

Mehr

Um ein solches Dokument zu erzeugen, muss eine Serienbriefvorlage in Word erstellt werden, das auf die von BüroWARE erstellte Datei zugreift.

Um ein solches Dokument zu erzeugen, muss eine Serienbriefvorlage in Word erstellt werden, das auf die von BüroWARE erstellte Datei zugreift. Briefe Schreiben - Arbeiten mit Word-Steuerformaten Ab der Version 5.1 stellt die BüroWARE über die Word-Steuerformate eine einfache Methode dar, Briefe sowie Serienbriefe mit Hilfe der Korrespondenzverwaltung

Mehr

Einrichtung des Cisco VPN Clients (IPSEC) in Windows7

Einrichtung des Cisco VPN Clients (IPSEC) in Windows7 Einrichtung des Cisco VPN Clients (IPSEC) in Windows7 Diese Verbindung muss einmalig eingerichtet werden und wird benötigt, um den Zugriff vom privaten Rechner oder der Workstation im Home Office über

Mehr

Qt-Projekte mit Visual Studio 2005

Qt-Projekte mit Visual Studio 2005 Qt-Projekte mit Visual Studio 2005 Benötigte Programme: Visual Studio 2005 Vollversion, Microsoft Qt 4 Open Source s. Qt 4-Installationsanleitung Tabelle 1: Benötigte Programme für die Qt-Programmierung

Mehr

Rillsoft Project - Installation der Software

Rillsoft Project - Installation der Software Rillsoft Project - Installation der Software Dieser Leitfaden in 6 Schritten soll Sie schrittweise durch die Erst-Installation von Rillsoft Project führen. Beachten Sie bitte im Vorfeld die nachstehenden

Mehr

Benutzeranleitung Superadmin Tool

Benutzeranleitung Superadmin Tool Benutzeranleitung Inhalt 1 Einleitung & Voraussetzungen... 2 2 Aufruf des... 3 3 Konto für neuen Benutzer erstellen... 3 4 Services einem Konto hinzufügen... 5 5 Benutzer über neues Konto informieren...

Mehr

2 Open BIM Workflow ARCHICAD und DDS-CAD

2 Open BIM Workflow ARCHICAD und DDS-CAD 2 Open BIM Workflow ARCHICAD und DDS-CAD Dieses Handbuch gibt Ihnen einen Überblick, welche Einstellungen Sie tätigen müssen, um die besten Ergebnisse im IFC-Datenaustausch zwischen den Disziplinen Architektur

Mehr

Universal Gleismauer Set von SB4 mit Tauschtextur u. integrierten Gleismauerabschlüssen!

Universal Gleismauer Set von SB4 mit Tauschtextur u. integrierten Gleismauerabschlüssen! Stefan Böttner (SB4) März 2013 Universal Gleismauer Set von SB4 mit Tauschtextur u. integrierten Gleismauerabschlüssen! Verwendbar ab EEP7.5(mitPlugin5) + EEP8 + EEP9 Abmessung: (B 12m x H 12m) Die Einsatzhöhe

Mehr

Getting Started Guide CRM Online, 2013 & 2015 xrm1 Verpflegungspauschalen

Getting Started Guide CRM Online, 2013 & 2015 xrm1 Verpflegungspauschalen Getting Started Guide CRM Online, 2013 & 2015 xrm1 Verpflegungspauschalen 1 Download und Import der Lösung 2 Import der aktuellenverpflegungspauschalen 3 Weitere Informationen und Problembehandlung 1 Download

Mehr

Kleines Handbuch zur Fotogalerie der Pixel AG

Kleines Handbuch zur Fotogalerie der Pixel AG 1 1. Anmelden an der Galerie Um mit der Galerie arbeiten zu können muss man sich zuerst anmelden. Aufrufen der Galerie entweder über die Homepage (www.pixel-ag-bottwartal.de) oder über den direkten Link

Mehr

Einrichten einer Festplatte mit FDISK unter Windows 95/98/98SE/Me

Einrichten einer Festplatte mit FDISK unter Windows 95/98/98SE/Me Einrichten einer Festplatte mit FDISK unter Windows 95/98/98SE/Me Bevor Sie die Platte zum ersten Mal benutzen können, muss sie noch partitioniert und formatiert werden! Vorher zeigt sich die Festplatte

Mehr

Klausur zur Einführung in die objektorientierte Programmierung mit Java

Klausur zur Einführung in die objektorientierte Programmierung mit Java Klausur zur Einführung in die objektorientierte Programmierung mit Java im Studiengang Informationswissenschaft Prof. Dr. Christian Wolff Professur für Medieninformatik Institut für Medien-, Informations-

Mehr