Ein objektorientiertes 3D Graphiktoolkit
Vorstellung
Was ist Inventor?
Open Inventor ist ein objektorientiertes Toolkit zur Programmierung von dreidimensionalen Graphiken. Es besteht aus einer Sammlung von Objekten und Methoden, mit denen man interaktive 3D Graphikapplikationen erstellen kann. Das Toolkit ist in C++ geschrieben.
Open Inventor ist eine Sammlung von Bausteinen, aus denen man ganze Applikationen zusammensetzen kann. Diese Bausteine bedienen sich schneller Hardwareunterstuetzung und sind sehr systemnah programmiert. Obwohl diese Bausteine sehr umfangreich sein koennen, bringt ihre Verwendung nur minimalen Programmieraufwand mit sich.
Open Inventor basiert auf Open GL und ist somit auf verschiedensten Plattformen verfuegbar.
Warum Inventor?
Die Programmierung von 3D Graphikapplikation war seit jeher eine zeitaufwendige Aufgabe, die dem Programmierer gewaltiges Know How abverlangte. Um diese schwierige Aufgabe zu vereinfachen, haben Entwickler seit Anbeginn der Computergraphik immer wieder abstrahierende Funktionen geschaffen, die ueber den elementaren Graphikbefehlen lagen.
Bei diesen einfachen Loesungen kam aber immer die Interaktivitaet zu kurz. Die Anwendungen waren viel zu spezialisiert, um ein einfaches Manipulieren der Graphikdaten zu gestatten.
Ein echtes interaktives Toolkit sollte also eine gewisse Menge an 3D Objekten unterstuetzen, die dann aber auch einfach manipuliert werden koennen sollten. Einfach bedeutet hier, dafl der Anwender im gleichen Fenster, in dem er seine Graphikszene sieht, auch seine Veraenderungen durchfuehren kann.
Es gibt drei elementare Ebenen, auf denen solch ein Toolkit die Entwicklung von Graphikapplikationen ermoeglichen kann:
Die Repraesentation der Objekte
Dinge sollten als veraenderbare Graphikobjekte verwaltet werden, und nicht nur als eine Menge von Zeichenprimitiven. Das bedeutet, dass Applikationen, die dieses Toolkit verwenden, nur wissen muessen, "was" ihre Objekte sind, und nicht nur "wie" sie dargestellt werden muessen.
Interaktivitaet
Zusaetzlich zur graphischen Darstellung der Objekte muss es eine Moeglichkeit zur Verwaltung von Ereignissen (events) geben, damit auf die Darstellung der Szene und der Eigenschaften der Objekte (Position, Lage,...) in geeigneter Weise Einfluss genommen werden kann.
Die Architektur
Das Toolkit sollte nicht veraendert werden muessen, wenn man spezielle, komplexe Probleme damit loesen will. Das Toolkit sollte in seinem Funktionsumfang, den Moeglichkeiten der Einbindung und seiner Flexibilitaet ausreichen, um jedes graphische Darstellungsproblem zu loesen.
Aus diesen Anforderungen entstand Open Inventor.
Open Inventor verwaltet Objekte, keine Zeichnungen.
Ueberblick
Das Open Inventor Toolkit besteht aus drei Hauptbereichen:
Abbildung 1: Aufbau von Open Inventor
Die Szenendatenbank ist eine dynamische Repraesentation der darzustellenden Szene als Graph. Dieser Graph ist im Normalfall gerichtet und azyklisch. Objekte werden darin als Knoten (nodes) gespeichert. Von diesen Knoten gibt es verschiedene Klassen fuer geometrische Objekte, fuer die Eigenschaften dieser Objekte und fuer Transformationen. Eine weitere Knotenart kann eine Aktion sein. Solche Aktionen dienen zu verschiedenen Zwecken: zum Rendering, zum Auswaehlen von Objekten, zur Berechnung von Bounding Boxes, zur Verarbeitung von events und zur Dateiausgabe. Des weiteren existieren Objekte zur vereinfachten Erzeugung von Animationen.
Der Bereich der Interaktion beinhaltet Klassen fuer Events und sogenannte "smart nodes". Eventklassen dienen zum Beispiel zur Verwaltung von Maus-Button-Events oder reagieren auf bestimmte Tastenbetaetigungen. "Smart nodes" enthalten spezielle Intelligenz, die sie zur Ausfuehrung bestimmter Funktionen benaetigen. So kann zum Beispiel ein Knoten zur Selektion von Objekten ueber Mausevents das Picking ueberwachen und die selektierten Objekte farblich hervorgehoben darstellen.
Node Kits stellen sinnvoll zusammengefaflte Mengen von Knoten dar, die den Aufbau von komplexen und doch konsistenten Szenen ermoeglichen. Sinnvolle Arten von Knoten werden zu Subgraphen kombiniert. Fuegt man also ein Node Kit ein, so werden zum Beispiel automatisch ein Knoten fuer ein geometrisches Objekt, ein Materialknoten und eine Transformation gleichzeitig eingefuegt.
Auf Hardwareplattformen der Firma Silicon Graphics basiert Open Inventor auf Hilfsbibliotheken zur Fenstersteuerung unter X Windows oder Open GL. So existiert in einem Graphen immer ein Objekt "Renderarea", also ein Fenster, in dem die Szene dargestellt wird. Dieses Objekt kuemmert sich um ein automatisches Redraw, um eine Eventtransformation aus dem Windowsystem in das Toolkitsystem und um andere nuetzliche Dinge.
Auf Applikationslevel beinhaltet Open Inventor noch einige Hilfsprogramme wie zum Beispiel Editoren fuer Farbe, Material, Lichtquellen, sowie verschiedene Viewer, die spezielle Interaktionen des Benutzers ermoeglichen.
Knoten
Jeder Knoten in der Szenendatenbank hat eine spezielle Funktion. Shape Node repraesentieren geometrische oder physikalische Objekte. Property Knoten beschreiben vielfaeltige Attribute dieser Objekte. Group Knoten verbinden andere Knoten zu Graphen oder Subgraphen. Es existieren aber auch andere Arten von Knoten wie zum Beispiel Kameras oder Lichtquellen
Einige Beispiele aus den einzelnen Klassen:
Shape nodes Cone Cube Faceset TriangleStripSet Light/camera nodes Perspective Camera PointLight Group nodes Group Seperator Property nodes BaseColor Material Transform Font
Jede Instanz einer Objektklasse beinhaltet natuerlich bestimmte Nutzdaten. Diese Daten werden innerhalb des Objektes in Subobjekten (sog. Fields) gespeichert. Fields haben einen bestimmten Werttyp, der die Art der Daten beschreibt.
So kann zum Beispiel ein Objekt aus der Klasse Zylinder zwei Fields vom Typ "float" haben: Radius und Hoehe.
Zu diesen Fields existieren konsistente Methoden zum Editieren, Abfragen, Lesen, Schreiben und <berwachen dieser Instanzdaten.
Bestimmte Arten von Daten koennen sich von mehreren Objekten geteilt werden, um Speicherplatz zu sparen. Unter diese Kategorie von Daten fallen zum Beispiel Koordinatenangaben oder Normalvektoren.
Group Nodes verbinden Knoten in Graphen. Jede Group Node-Klasse bestimmt, ob und in welcher Weise ihre Knoten abgearbeitet werden und wie der Status der Abarbeitung an Nachfolgeknoten weitergegeben. Solche Informationen, die zum Beispiel momentan aktuelle Materialdaten, Ausgabeeigenschaften, usw. enthalten, werden fuer gew^hnlich von oben nach unten im Baum weitergereicht. Es werden aber nicht nur Nachfolgerknoten weiter unten im Baum versorgt, sondern auch Knoten, die sich auf gleicher Hoehe im Baum befinden. Einige wenige Group Nodes sind auch in der Lage, Informationen an Vorgaengerknoten zu vererben.
Sogenannte Seperator Nodes speichern den Zustand der Darstellungsweise, wenn wenn sie in der Abarbeitung des Szenegraphen an die Reihe kommen, und stellen diesen Zustand wieder her, wenn alle ihre Nachfolgerknoten abgearbeitet wurden. Auf diese Weise wird der Effekt der nachfolgenden Knoten auf die Szene isoliert.
Ein Switch Node ist eine spezielle Art von Seperator Node. Er waehlt nur einen seiner Nachfolgerknoten zur Abarbeitung aus. Diese Methodik kommt zum Beispiel sinnvoll zum Einsatz, wenn verschiedene Detailstufen in der Darstellung implementiert werden sollen.
Eine andere Art von Seperator Node ist zum Beispiel ein Array Knoten. Die Knotenklasse fuehrt ihre Nachfolgerknoten mehrmals aus, wobei sie jedesmal eine bestimmte Transformation auf den Subgraphen ausuebt.
Abbildung 2: Ein einfacher Szenengraph
Pfade
Knote k^nnen im allgemeinen mehrere Vorgaenger haben. Durch diese Erweiterung laesst sich Wiederverwendbarkeit erreichen. Soll zum Beispiel ein Auto dargestellt werden, so muss ein Rad nur einmal konstruiert werden, kann dann aber viermal mit einer geeigneten Transformation als Subgraph eingesetzt werden. Dieses Konzept fuehrt zu einer ueberschaubareren und kompakteren Szenenrepraesentation. Daraus ergibt sich aber auch ein gravierender Nachteil: es ist nicht mehr moeglich, mit der Angabe eines Knotens ein bestimmtes Objekt zu spezifizieren. Um hier Abhilfe zu schaffen, wurde das Konzept der Pfade eingefuehrt. Pfade zeigen immer von einem Ausgangsknoten nach unten durch den Baum weisend auf einen bestimmten Knoten. So kann zum Beispiel eine Pick Aktion einen Pfad vom Rootknoten bis zu dem ausgewaehlten Objekt liefern.
Abbildung 3: Der "Wheel" Knoten wird mehrfach instanziiert, zumal er ein Nachfolgerknoten von "FrontWheel" und "RearWheel" ist. Der Pfad (die dicke Linie) zeigt eindeutig vom Root Knoten auf das Objekt, welches das Hinterrad definiert. Innerhalb des Parallelogramms liegt der Subgraph, der von dem Pfad definiert wird.
Actions
sind Objekte, die den Szenegraphen in bestimmter Weise abarbeiten, zum Beispiel zum Rendering, fuer eine Bounding Box Berechnung, zum Suchen von bestimmten Objekten oder zur Dateiausgabe.
Als Beispiele wird hier Rendering und Picking behandelt.
Rendering
Die Darstellung der Szene durch eine Render Action sollte in Echtzeit ablaufen. Die Rendering Methoden der Knotenklassen muessen also auf Performance optimiert sein. Bestimmte Teile der Renderinginformationen fuer Subgraphen (wie zum Beispiel Display Lists) k^nnen in einem Cache-Speicher aufgehoben werden, wo sie fuer den naechsten Renderdurchgang dann wieder zur Verfuegung stehen.
Desweiteren kann der Renderingablauf an beliebiger Stelle unterbrochen werden, wenn fuer die geforderte Darstellung in Echtzeit nicht genug Rechenzeit zur Verfuegung steht, und allfaellige User-Events nicht rechtzeitig bearbeitet werden koennten.
Picking
ist ein elementarer Bestandteil von interaktiven Applikationen. Ein Knoten namens "RayPickAction" liefert zum Beispiel einen Pfad vom Rootknoten zum ersten Objekt, welches unter einem Mauscursor liegt, wenn die linke Maustaste gedrueckt wurde.
Seperator Knoten cachen zum Beispiel auch die Ergebnisse von Bounding Box Berechnungen. Die dadurch erzielte Beschleunigung ist gross genug, um zum Beispiel ein dynamische Highlighting unter einem sich bewegenden Mauscursor zu ermoeglichen.
Sensors
ueberwachen Veraenderungen von Knoten oder werden zur Implementierung von Animationen verwendet. Es gibt zwei Arten von Sensoren: Data und Time Sensors.
Data Sensors werden ausgeloest, wenn sich die Datan des angeschlossenen Knoten (oder die Daten seiner Kinder) aendern. Ueber solch einen Data Sensor kann zum Beispiel eine interaktiver Sensor Sliders oder andere Anzeigen aendern, wenn die zugehoerigen Objekte von anderen Programmobjekten veraendert wurden. Wenn ein Data Sensor am Root Knoten angeschlossen wird, so erkennt er Veraenderungen in der ganzen Szene. Dieses Verhalten kann zum Beispiel fuer ein bedingtes Redraw genutzt werden, bei dem die Szene nur neu gezeichnet werden muss, wenn sich etwas veraendert hat.
Time Sensors werden zu einem bestimmten Zeitpunkt oder in einem regelmaessigem Intervall ausgefuehrt. Ueber diese Funktionalitaet lassen sich leicht Animationen erzeugen.
Abbildung 4: Ein Szenengraph, der Sensors verwendet. Der Data Sensor beim Root
Knoten wird ausgeloest, wannimmer sich etwas an einem der nachfolgenden Knoten
aendert. Er wird verwendet, um ein erforderliches Neuzeichnen der
Szene auszuloesen.
Der Time Sensor, welcher mit einer Uhr verbunden ist,
triggert in regelmaessigen Abstaenden und animiert
derart die Rotation des Objektes rechts unten.
Events
Das Open Inventor Toolkit verwendet einen simplen Algorithmus, um User Events aus dem Windowing System auf die Knoten zu verteilen. Ein Event im Windowing System resultiert aus einer User Aktion, also zum Beispiel einer Mausbewegung, einem Tastendruck, usw. Sollte solch ein Event in einem Window der Renderarea aufgetreten sein, so wird der Event an dieses Objekt uebergeben. Das Renderareaobjekt kann den Event entweder selbst verarbeiten (ein Viewer koennte die Kamera mit der Mausbewegung verschieben...) oder den Event in einen Toolkitevent uebersetzen und ihn an die Objekte in der Szenendatenbank uebergeben, indem ein Handleevent-Objekt mit dem Rootknoten verbunden wird. Der Event wird dann durch den Baum weitergereicht und verteilt. Jeder interessierte Knoten kann auf den Event reagieren und den Eventstatus gegebenenfalls auf "handled" (=bearbeitet, keine weitere Bearbeitung noetig) setzen. Nur Knoten, deren Status noch nicht "handled" ist, werden durch den Baum weitergereicht.
Manipulatoren
sind interaktive Knoten, die einfach ueber das Eventmodell integriert werden koennen. Als Beispiel m^chte ich das Trackballobjekt anfuehren. Dieses legt eine unsichtbare Bounding Sphere um das angeschlossene Objekt, welches es manipuliert. Ueber diese Kugel werden Mausbewegungen in rotatorische Veraenderungen fuer das Objekt uebersetzt. Drei zylindrische Streifen um die Kugel erleichtern das Spezifizieren von Bewegungen um die Hauptachsen.
Simple Manipulatoren fuehren zum Beispiel nur einfache Tranlationen in einer Dimension durch oder werden zu komplexeren Manipulatoren wie dem Trackball kombiniert.
Node Kits
Zumal die Szene Graph Bibliothek allgemein genug gehalten ist, um optimale Performance und Flexibilitaet zu gewaehrleisten, kann sie auf unerfahrene User verwirrend wirken. Es gibt keine Berschraenkungen beim Erstellen von Graphen und so kann es oft vorkommen, dafl bizarre und sinnlose Konstruktionen entstehen, wenn nicht bestimmte strukturelle Richtlinien eingehalten werden.
Node Kits vereinfachen diese Problematik, indem sie eine konsistente Art der Graphkonstruktion erzwingen. Jedes Node Kit enthaelt einen strukturierten Subgraphen von Datenbankknoten. Ein Template, welches zum Node Kit geh^rt, gibt an, welche Knoten (falls notwendig) angefuegt werden k^nnen, und an welchen Stellen das geschehen sollte.
Als Beispiel moechte ich hier das SphereKit anfuehren, welches neben der Objektknotenklasse einer Kugel auch ein Template enthaelt, welches die Anbindung von Materialknoten, geometrischen Transformationen und anderen Eigenschaftsknoten an den richtigen Stellen gestattet.
Conclusion
Dieser <berblick stellt lediglich eine Einfuehrung in das Open Inventor System dar.
Folgende Konzepte wurden aufgezeigt:
Open Inventor verwendet Knoten, die in einer baumartigen Strukur organisiert werden, um Szenen zu repraesentieren. Diese Knoten koennen fuer geometrische Objekte, fuer Eigenschaften, fuer Transformationen oder andere Dinge stehen. Transformationen und Materialeigenschaften bleiben bei der Abarbeitung der einzelnen Knoten erhalten. Ist dieser Effekt unerwuenscht, so muessen Seperator Nodes eingefuegt werden.
Spezielle Arten von Knoten sind Events (reagieren auf Events aus dem Windowing-System), Actions (arbeiten Szenenbaum ab, zB Rendering), Sensors (reagieren auf Veraenderungen) und Manipulators (erlauben einfaches Veraendern von Objekten).
Node Kits erlauben das gleichzeitige Einfuegen einer Menge von semantisch sinnvoll zusammengehoerenden Knoten, zum Beispiel geometrisches Objekt, Material und Transformation.
Einmal konstruierte Objekte koennen mehrfach wiederverwendet werden (normalerweise ueber Transformationen an verschiedenen Stellen im Raum). Bestimmte Objekte koennen dann ueber Pfade eindeutig identifiziert werden.
Literaturverzeichnis
[1] The Inventor Mentor: Programming Object-Oriented 3D Graphics with Open Inventor,
Release 2, Josie Wernike, Addison Wesley, !994 (Release 2)
[2] Paul S. Strauss, Rick Carley "An Object-Oriented 3D Graphics Toolkit", Computer Graphics (SIGGRAPH `92 Proceedings) July 1992, pp 341-349