Open Source im professionellen Einsatz

Interaktive 3D-Welten mit Coin und Qt - Teil 3

Räumliche Malerei

In einem realitätsnahen 3D-Raum wird der Betrachter zum Akteur: Seine Aktionen führen zu Reaktionen, er hinterlässt seine Spuren in der virtuellen Realität. Mit Qt und Coin lassen sich solche animierten und interaktiven 3D-Welten schnell und einfach programmieren.

Eine dreidimensionale Szene wirkt wesentlich realistischer, wenn sie sich bewegt und der Benutzer mit ihr interagieren kann. Bereits der letzte Coin-Artikel[2] brachte Bewegung in die Szene: Die Erde rotierte unter einem Flugzeug. Der Betrachter konnte aber nicht aktiv in die Szene eingreifen, nichts verändern, sondern nur das Geschehen mit Hilfe des »SoQtExaminerViewer« aus verschiedenen Blickwinkeln betrachten.

Als interaktives Beispiel dient im Folgenden ein einfaches Zeichenprogramm. Der Benutzer malt dabei in einer 3D-Szene beliebige Punkte. Das Programm basiert auf einem Beispiel aus dem Inventor Mentor ([3], 10. Kapitel, zweites Beispiel), wurde aber erweitert und von Motif auf SoQt und Qt umgestellt.

Der Szenengraph des Malprogramms ist in Abbildung 1 zu sehen. Er benötigt nur vier Knoten, der Benutzer kann drei von ihnen dynamisch verändern (nur das Licht bleibt konstant). Durch einen Druck auf die mittlere Maustaste rotiert die Kamera um den Ursprung. Die interessantesten Knoten sind »punktKoordinaten« und »punkte«:

  • »punktKoordinaten« ist ein Objekt der Klasse »SoCoordinate3«, es nimmt eine beliebige Anzahl an 3D-Koordinaten auf.
  • »punkte« ist ein Objekt der Klasse »SoPointSet«, es zeichnet alle Koordinaten des »punktKoordinaten«-Knotens als Punkt in den Raum.

Mit der linken Maustaste setzt der Benutzer neue Punkte ein. Ein Klick auf die rechte Maustaste löscht alle Punkte aus der Szene.

Die richtige Wahl

Um die interaktiven Wünsche des Anwenders umzusetzen, muss das Programm einzelne Objekte im Szenengraphen auswählen und verändern. Das Beispiel fügt neue Punkte in »punktKoordinaten« ein und teilt dem Knoten »punkte« mit, dass er die Neulinge zeichnen soll.

Ein Knoten lässt sich durch seine Position im Graphen ansprechen und auswählen. Hierfür bietet jeder Gruppenknoten eine Methode »getChild()«. Abbildung 1 zeigt, wie das Programm die einzelnen Knoten über die Wurzel des Szenengraphen anspricht. Diese einfache Methode ist allerdings sehr fehleranfällig: Falls nachträglich Knoten in den Szenengraphen eingefügt werden, ändern sich die Indizes. Auch ist die Methode bei größeren Szenengraphen sehr unübersichtlich - in diesem Fall ist es besser, allen Knoten über ihre »setName()«-Methode eindeutige Namen zu geben. Ihre Position lässt sich dann durch ein Objekt der Klasse »SoSearchAction« finden und verändern.

Die Funktion »neuerPunkt()« in Listing 1 fügt einen neuen Punkt in die Szene ein. Als Parameter erhält sie einen Zeiger auf die Render-Fläche und die Koordinaten eines Punkts. Die Zeilen 5 bis 7 ermitteln die Zeiger für den dritten und vierten Knoten des Szenengraphen, ausgehend von der Wurzel. Anschließend ändern die Zeilen 10 und 12 die Eigenschaften der Knoten.

In der Szene punkten

Wenn der Benutzer Punkte in die Szene setzt, muss das Programm einen Zusammenhang zwischen der zweidimensionalen Mausposition im Fenster und der dreidimensionalen Position in der Szene herstellen. Das vorliegende Beispiel geht einen einfachen Weg: Es setzt alle Punkte auf eine Ebene, die durch den Ursprung geht.

Abbildung 2 zeigt die Geometrie des Volumens, das eine »SoPerspectiveCamera« als Ausschnitt der 3D-Szene sieht. Wenn sich die Sichtweite der Kamera bis ins Unendliche erstreckt, kann das Rendern sehr lange dauern. Deshalb schränken die Parameter »nearDistance« und »farDistance« das Volumen des Kamera-Sichtfelds ein. Im vorliegenden Beispiel ist die »nearDistance« auf den Wert »1« und die »farDistance« auf »7« gesetzt. Da die Entfernung der Kamera vom Ursprung »4« beträgt, liegt der Mittelpunkt der Szene genau in der Mitte von »nearDistance« und »farDistance«. Durch diesen Mittelpunkt verläuft auch die Ebene (grün eingezeichnet), auf der der Benutzer die Punkte zeichnen soll.

Die Entfernungseinheiten sind in Open Inventor per Default relativ zueinander angegeben. Sie können aber mit dem Knoten »SoUnit« zu einer bestimmten Längeneinheit gesetzt werden.

Diesen Artikel als PDF kaufen

Als digitales Abo

Als PDF im Abo bestellen

comments powered by Disqus

Ausgabe 07/2013

Preis € 6,40

Insecurity Bulletin

Insecurity Bulletin

Im Insecurity Bulletin widmet sich Mark Vogelsberger aktuellen Sicherheitslücken sowie Hintergründen und Security-Grundlagen. mehr...

Linux-Magazin auf Facebook