Was ist VRML ?

Mit dem Durchbruch von HTML (Hyper Text Markup Language) haben Informationsdienste über das Internet/World-Wide-Web (WWW) eine grosse Verbreitung gefunden. Allerdings bietet HTML nur 2 dimensionale Text/Bild Informationen. Für die anspruchsvolle Visualisierung von Daten benötigt man allerdings eine Möglichkeit zur Darstellung 3 dimensionaler Bilder.
Natürlich läßt sich das Problem über ein Java Programm lösen, das ähnlich wie das Übungsprogramm im Java Praktikum statt 2D Daten, 3D Daten darstellt. Das Übungsprogramm benutzt jedoch ein Bildformat, um nicht jeden Bildpunkt einzeln auf den Schirm schreiben zu müssen.
Etwas ähnliches (statt von "Bild" redet man von "Welt") existiert auch für 3 dimensionale Daten. Für eine 3 dimensionale Erweiterung des World Wide Web liegt es also sehr nahe, ein solches etabiliertes 3 dimensionales Datenformat heranzuziehen. Damit wird es sehr einfach, vorhandene 3D Daten (die z.B. aus CAD Programmen stammen können) über bereits vorhandene Konvertierungsprogramme im World Wide Web darzustellen.
Als Grundlage der entstandene Virtual Reality Modeling Language (kurz VRML) Version 1.0 wurde das "Inventor"-format der gleichnamigen Graphikbibleothek des Marktführers SGI benutzt. Wie man sich leicht überzeugen kann, sind Webpages im VRML 1.0 -Format immer irgendwie langweilig.

Umgang mit VRML

Um ein Beispiel für VRML Version 1.0 anzuschauen (falls Ihr webbrowser das kann), führen Sie den Befehl (Windows oder SGI)
   netscape http://home.netscape.com/eng/live3d/howto/1crab2.wrl 

bzw.
(Windows)
   iexplorer http://home.netscape.com/eng/live3d/howto/1crab2.wrl 
aus.
Für VRML-Dateien wird bei diesen Web-Browsern ein sogenanntes Plugin (ein zur Laufzeit nachladbares Programmteil) benötigt. Diese Plugin Technik macht es möglich, dass Erweiterungen der Funktionalität eines Programms sogar von einem anderen Softwarehersteller kommen kann. Für VRML gilt der Cosmoplayer Plugin zu Zeit als der stabilste.

Leider ist für Linux zur Zeit kein Cosmoplayer Plugin verfügbar. Unter den zahlreichen Alternativen raten wir zur Zeit zur Software LibVRML97/Lookat Obwohl lookat eigentlich nur ein Beispielsprogramm für LibVRML97 und noch nicht ganz vollständig ist, scheint es zur Zeit der brauchbarste VRML noch erhältliche Viewer für Linux zu sein (der vermutlich am weitesten entwickelte VRML Browser "liquid reality" wurde wegen einer Firmenübernahme durch Microsoft vom Markt genommen). Wenn Sie lookat benutzen wollen, sollten Sie sich seine Kommandobelegung ausdrucken....
Mit Hilfe des Xswallow Plugins für netscape haben wir lookat in auf dem Pool des ICA direkt in Netscape integriert, so daß man eigentlich nur auf einen www Link einer VRML-Seite zu klicken müsste. Leider versagt häfig die MIME-Type Erkennung und das VRML-File wird als Text dargestellt. In diesem Fall schnappen Sie sich die URL ("Webadresse") per Cut und Paste der Maus und geben sie als Argument dem Programm "xmlookat" an. In unserem VRML 1.0 Beispiel wäre das:

   xmlookat http://home.netscape.com/eng/live3d/howto/1crab2.wrl
Aber VRML 1.0 ist inkompatibel zu neueren VRML-Versionen. Deshalb kann nicht jeder moderne VRML-Viewer das "richtige" VRML 1.0 Beispiel http://home.netscape.com/eng/live3d/howto/1crab2.wrl darstellen. Auch das auf dem Linux CIP-Pool installierte LibVRML97/Lookat versagt hier.

Existierende VRML-Browser basieren technisch auf der OpenGL Graphikbibleothek. Sie ist ein Industriestandard für technische Visualisierung. Auf dem Markt existieren Graphikkarten mit 3D Unterstützung. Mit einer solchen Karte wird die CPU des Rechners stark von Rechenarbeit entlastet, so dass die Hardware eines Rechners einen grossen Einfluss auf die Darstellung des Rechners haben kann. 3D-Fähigkeit der Graphikkarte allein reicht aber nicht aus: GL-Karten sind häufig für Welten mit vielen Ecken konzipiert, während bei PC-Spiele-Karten häfig für Welten mit vielen Texturen (2D-Bilder, mit denen man glatte Flächen einer 3D-Welt "bekleben" kann) gebaut werden.

VRML 2.0/VRML 97

Um die langweiligen VRML 1.0 Welten abzulösen wurden in VRML 2.0 und in der davon abgeleiteten Version VRML 97 neue Features aufgenommen: Animation, Multimediafähigkeit und Interaktion. Spätens hier vollzog sich aber der wichtige Schritt vom 3D Datenformat zur Programmierung.
Allerdings handelt es sich bei VRML nicht um die gewohnte prozedurale Programmierung, wie Sie es von C, C++, Fortran, Pascal, Basic, Java usw. gewohnt sind. Bei dieser Prozeduralen Programmierung wird ein Programm mit einzelnen Schritten in der Zeitachse abgearbeitet.
Bei der deklarativen Programmierung hingegen wird das Problem lediglich vollständig beschrieben. Der Sprachinterpreter/compiler übernimmt dann den Rest der Arbeit, um das gewünschte Ergebnis zu erreichen.
Bezogen auf die Welt der Musik und sieht man die Musiker als Sprachinterpreter an, ist das komponieren eines Musikstücks auf einem Notenblatt eine ganz klar eine prozedurale Programmierung, während der Wunsch an den Dirigenten alle Stücke der Gruppe ACDC zu spielen, eher deklaritivie Programmierung ist.

Übung 1:

Speichern Sie das folgende einfache VRML Version 2.0 File in ein eigenes File und stellen Sie es dar.

#VRML V2.0 utf8

# Der Kommentar der ersten Zeile ist zwingend vorgeschrieben

# Einfaches Hello World Programm das einen String darstellt und 
# einen Link ins World Wide Web darauf legt

Anchor 
   {
   children 
      [
      Shape 
         {
         geometry Text 
            {
            string ["Hello World"]
            }
         }
      ]
      description "Hello World"
      url "http://www.fourmilab.ch/cgi-bin/uncgi/Earth?imgsize=320&opt=-l&lat=0.184093&ns=North&lon=359.53&ew=West&alt=1000000&img=learth.evif"
   }

# dieser Befehl gestaltet lediglich das Aussehen des Browsers

NavigationInfo { type "EXAMINE" }
Download HelloWorld.wrl

VRML Syntax

Um die VRML Syntax zu verstehen, kommt man um den Ausdruck "Scenengraph" nicht herum. Ein Scenengraph hat für die moderne 3D Visualisierung in etwa die Bedeutung wie das Nassi-Shneiderman Diagramm für die prozedurale Programmierung. Soweit zu erfahren ist, gibt es aber keine normierte Darstellung für einen Scenengraph...
In einem Scenengraph werden ausgehend vom graphischen Ursprung ("Nullpunkt") alle graphischen Knoten in Baumform angeordnet.
Zusätzlich zu den Knoten werden in den Scenengraph auch noch Events eingetragen. Events sind Ereignisse, die von Knoten an andere Knoten geschickt werden und so Nachrichten übertragen.

Der Scenengraph für die bekannte "HelloWorld.wrl" Welt sieht so aus:

Am graphischen Ursprungsknoten (für den es keinen extra VRML-Befehl gibt), hängt (neben dem weggelassenen weil unwichtigen "NavigationInfo"-Knoten) der "Anchor"-Knoten für einen Link ins World Wide Web. Der "Anchor"-Knoten enthält einen "Shape"-Knoten, der ein sichtbares Object beschreibt. Der "Shape"-Knoten enthält einen "geometry" Knoten, der den Text "Hello World" beschreibt.

Eine kleine Knotenkunde

Die wichtigste Knotenform ist der "Shape" Knoten, der einen 3-dimensionalen Körper beschreibt. Er enthält einen "geometry" Knoten, der die geometrische Form des Körpers beschreibt. Er kann auch einen "appearance" Knoten enthalten, der das Aussehen (z.B. Farbe, Durchsichtigkeit, aufgeprägtes Muster ("Textur") usw.) dieses Körpers beschreibt.
Als geometrische Form stehen ausser einfachen Formen wie Quadrat, Kugel, Zylinder, Kegel usw. auch kompliziertere Formen wie Flächen- (Linien-, Punkte-) Ansammlungen und Ausstülpungen zur Verfügung.
Mit Flächenansammlungen lassen sich beliebige Körper darstellen. Am einfachsten geht das, indem man einen Körper mit Dreiecken überzieht (sogenannte "Trianglulierung"). Um zu verhindern, dass zu viele Dreiecke benötigt werden, können die Reflexionseigenschaften der einzelnen Flächen so beeinflußt werden, daß die Kanten schwer zu sehen sind.

Übung 2:

Benutzen Sie das Programm ac3d (shareware, http://www.comp.lancs.ac.uk/computing/users/andy/ac3d.html) um ein Kugelsegment und eine benachbarten volle Kugel zu erzeugen:

Laden Sie das erzeugte VRML-File in ihren Browser, und schauen Sie sich die erzeugten Objecte etwas genauer an. Zum Vergleich sollten Sie sich auch mal die gleichen Objekte mit dem Renderer Povray anschauen, der auch spiegelnde Oberflächen beherrscht.


Mit einem kleinen Befehl Spiegelung einschalten

gawk '{f=1}/#declare ac3d_col_1 / {sub("finish {","finish { reflection 0.3");print ;f=0} {if(f==1) print}' Povrayfile.pov > kugeln2.pov 

Povray aufrufen
x-povray +ikugeln2.pov +d +v +w400 +h300 +x +p +a0.3 +R9

Weitere wichtige Knotentypen sind zum Beispiel Tranformationsknoten (um einen Körper zu verschieben, zu rotieren oder in der Grösse zu verändern) oder der "Anchor" Knoten der einen Verweis auf eine Adresse ("URL" == Unified Resource Location") im World Wide Web enthält.
Knoten, die das Keyword "children" enthalten (das sind z.B. der "Group"-Knoten, wie auch Transformations- und Anchorknoten) können benutzt werden, um mehrere Knoten zusammenzufassen.

Eine weitere wichtige Gruppe von Knoten sind die Sensorknoten. Sie werden für die Interaktion mit dem Benutzer (bzw. der Knoten untereinander) benutzt. Es gibt zum Beispiel Sensoren für Mausbewegungen, für Sichtbarkeit, für Betreten oder Verlassen eines Bereichs und für Kollisionen zwischen Körpern. Auch die wichtige Timerfunktion zählt als Sensorknoten. Sensoren sind die Quellen für Events.

Die nächste Gruppe von Knoten sind Interpolatoren. Sie werden benutzt, um bestimmte Werte (Farbe, Oberflächenreflexion, geometrische Position, Bewegung und Drehung) "durchdrehen" zu können. Sie empfangen ein Event, (typsicherweise aus einem Timersenor) und wählen dadurch ein Event eines bestimmten Typs (z.B. Farbe, Oberflächenreflexion usw.) aus einer Liste aus. Damit lassen sich Animationen leicht verwirklichen.
Ein einfaches Beispiel für Interpolatoren aus einem VRML-Tutorial im Internet lässt sich unter http://www.vapourtech.com/vrmlguide/tutorial/worlds/tut19.wrl bewundern.

Mit dieser Methode wird nun das Hello-World Beispiel animiert:

#VRML V2.0 utf8

# Der Kommentar der ersten Zeile ist zwingend vorgeschrieben

# Einfaches Hello World Programm das einen String darstellt und 
# einen Link ins World Wide Web darauf legt
# Animiert ueber einen Tranformknoten

DEF SCHRIFT  Transform
   {
   children
      [
      Anchor 
         {
         children 
            [
            Shape 
               {
               geometry Text 
                  {
                  string ["Hello World"]
                  }
               }
            ]
            description "Hello World"
            url "http://www.fourmilab.ch/cgi-bin/uncgi/Earth?imgsize=320&opt=-l&lat=0.184093&ns=North&lon=359.53&ew=West&alt=1000000&img=learth.evif"
         }
      ]
   }
   
DEF ROTOTATOR OrientationInterpolator 
   {
   key [0, 0.5, 1]
   keyValue 
      [
      0 1 0 0, 
      0 1 0 3.14, 
      0 1 0 6.28 
      ]
   }

DEF TIMER TimeSensor {
        cycleInterval 10
        loop TRUE
}


ROUTE TIMER.fraction_changed TO ROTOTATOR.set_fraction
ROUTE ROTOTATOR.value_changed TO SCHRIFT.set_rotation

   
# dieser Befehl gestaltet lediglich das Aussehen des Browsers

NavigationInfo { type "EXAMINE" }
      
Download HelloWorld_animated.wrl

Im Scenengraph sind jetzt neue Element hinzugekommen.

Die rot gemalten Verbindungen symbolisieren die Events der ROUTE Befehle. Die ROUTE Befehle sind so zu interpretieren: Der Timesensor spuckt dauernd Werte zwischen 0 und 1 aus (welche Werte das sind, hägt davon ab, wie schnell die Welt dargestellt wird). Diese Werte werden in den Orientation Interpolator geroutet. Damit werden vom anhand von 3 Punkten Zwischenwerte errechnet. Der resultierende Vektor der Dimension 4 der zum Transformknoten (zustädig für Position, Rotation und Scalierung) geroutet wird, representiert eine Drehung: Die ersten 3 Werte beschreiben eine Drehachse, der 4. Wert representiert einen Winkel.

Aufgabe: Programmieren Sie das VRML-File so um, dass bei der Drehung die Schrift auf dem Kopf steht. Benutzen Sie auch mal willkühlich gewählte Werte um die Schrift ins Taumeln zu bringen.

Das Schreiben von ROUTE Befehlen erfordert die Kenntnis der Interna der einzelnen Knoten. Schlagen Sie in einer Knotenliste die Interna der an den Routes beteiligten Knoten Transform, OrientationInterpolator und TimeSensor nach.
Wie sie sehen, haben die entsprechenden Events einen Datentyp, dessen Korrektheit von VMRL-Broswer überprüft wird. Drucken Sie den Scenengraph aus und tragen Sie die Datentypen ein.

Es gibt noch weitere Knotenformen und entsprechende Erweiterungen im Scencengraph für Geräusche, Lichter, Kameraposition, Knoten zum Abschalten anderer Knoten, Knoten für eine "ungenaue Ansicht" (z.B. aus grosser Entfernung), Nebel, den Bildschirmhintergrund, die Betrachtungsposition, die Werkzeuge des VRML Viewers (lassen Sie einfach mal den "NavigationInfo"-Knoten weg, wenn Sie den cosmoplayer benutzen...) usw.
Sie werden gegebenenfalls im weiteren Verlauf diskutiert.

Softwareengeneering

Ein wichtiger Knotentyp wurde bisher nicht angesprochen und das aus gutem Grund: Er durchbricht das Prinzip der deklarativen Programmierung. Obwohl in VRML sehr eindrucksvolle Animationen mit rein deklarativer Programmierung möglich sind (z.B. ), geht es doch nicht immer ganz ohne die gewohnte prozedurale Programmierung.

Prozedurale Programmierung ist implementiert als spezieller Script-Knoten, der Programme einer prozeduralen Programmiersprache, nämlich Java aufnimmt. Beide Java-Implementierungen sind möglich: "richtiges" Bytecode-Java in Form einer Java-Klasse als auch interpretiertes Javascript mit seinen eingeschr&aum;nkten Fähigkeiten. Wir benutzen Javascript, da es zur Zeit von den eingesetzen VRML-Viewern als normiertes "vrmlscript" besser unterstützt wird.

Um zu zeigen, wie Javascript eingesetzt wird, muss das folgende VRML-Programm umgeschrieben werden.

#VRML V2.0 utf8

# Der Kommentar der ersten Zeile ist zwingend vorgeschrieben

# Einfaches Hello World Programm das einen String darstellt und 
# einen Link ins World Wide Web darauf legt
# Animiert ueber einen Tranformknoten

DEF SCHRIFT_POSITION Transform
   {
   children
      [
      DEF SCHRIFT  Transform
         {
         children
            [
            Anchor 
               {
               children 
                  [
                  Shape 
                     {
                     geometry Text 
                        {
                        string ["Hello World"]
                        }
                     }
                  ]
                  description "Hello World"
                  url "http://www.csv.ica.uni-stuttgart.de/homes/js/javakurs/HelloWorld2.wrl"
               }
            ]
         }
      ]
   }
      
DEF ROTOTATOR OrientationInterpolator 
   {
   key [0, 0.5, 1]
   keyValue 
      [
      0 1 0 0, 
      0 1 0 3.14, 
      0 1 0 6.28 
      ]
   }

DEF POSITIONATOR Script
   {
   eventIn SFFloat eingang_float
   eventOut SFVec3f ausgang_3D_float_vektor
   url "vrmlscript:
   function initialize()
      {
      }
   function eingang_float(val)  
      {
      ausgang_3D_float_vektor[0]=0;
      ausgang_3D_float_vektor[1]=0;
      ausgang_3D_float_vektor[2]=10*val;
      }
   "
   }


DEF TIMER TimeSensor {
        cycleInterval 10
        loop TRUE
}


ROUTE TIMER.fraction_changed  TO ROTOTATOR.set_fraction
ROUTE ROTOTATOR.value_changed TO SCHRIFT.set_rotation

ROUTE TIMER.fraction_changed               TO POSITIONATOR.eingang_float
ROUTE POSITIONATOR.ausgang_3D_float_vektor TO SCHRIFT_POSITION.set_translation

   
# dieser Befehl gestaltet lediglich das Aussehen des Browsers

NavigationInfo { type "EXAMINE" }      
Download HelloWorld_script.wrl Unser Shapeknoten wird nun nicht nur gedreht, sondern zusätzlich bewegt. Der Scenengraph enthält dazu einen neuen Transformknoten.

Prinzipiell lassen sich beide Events auch in einen einzigen Transformknoten umleiten. Allerdings erhebt sich dann die Frage, welcher Event zuerst bearbeitet wird. Vertauschen Sie also einfach mal bei den ROUTE Befehlen die Transformknoten und vergleichen Sie die Bewegung.

Anstelle der langweiligen Bewegung vor und zuruück soll der Shapeknoten auf eine Kurvenbahn geschickt werden.
Die Position einer Kreisbahn in der X-Z-Ebene ist:

Bedenken Sie, dass Sie mit Java Programmieren und Sie deswegen Math.sin(),Math.cos() und Math.PI benutzen müssen.

Ersetzen Sie jetzt den langweilig gewordenen Shape-Knoten mit der Schrift mit diesem interessanteren Box Knoten, der mit einer Textur beklebt ist.

Shape { appearance Appearance { texture ImageTexture { url "a149.png" } } geometry Box {} }

Um Modular programmieren zu können, enthält VRML auch Bestandteile, Programme auf mehrere Files auszuteilen. Die einfachste Konstruktion ist dabei die Inline-Konstruktion.

Benutzen Sie
Inline { url "das_file_aus_ac3d.wrl" }
statt dem Shapeknoten, um den schon oben benutzten VRML 2 Output von AC3D zu animieren.

VRML besitzt mit dem PROTO Konstrukt auch die Möglichkeit, funktionsähnliche Konstruktionen für wiederverwendbare Software zu schreiben und diese Bestandteile mit dem EXTERN PROTO Konstrukt in einer Art nutzbaren Sourcecodelibrary abzuspeichern. Allerdings führt die Besprechung dieser Konstruktionen hier zu weit...

Abschlussaufgabe

Als Abschlussaufgabe sollen Sie mit folgendem VRML-Script beschäftigen:

#VRML V2.0 utf8

# Der Kommentar der ersten Zeile ist zwingend vorgeschrieben

# Einfaches Hello World Programm das einen String darstellt und 
# einen Link ins World Wide Web darauf legt
# Animiert ueber einen Tranformknoten

DEF POSITION Transform
   {
   children
      [
      DEF QUERACHSE  Transform
         {
         children
            [
            DEF HOCHACHSE  Transform
               {
               children
                  [
                  Anchor 
                     {
                     children 
                        [
                        DEF SCHALTER Switch 
                           {
                           choice 
                              [
                              Transform 
                                 {
                                 scale 0.1 0.1 0.1
                                 children 
                                    [
                                    Inline { url "http://vrml.km-cd.com/Objects/Aircraft/Paper_Airplane.wrl" }                                
                                    ]
                                 }
                              Shape 
                                 {
                                 geometry Text 
                                    {
                                    string ["Zensiert !"]
                                    }
                                 }
                              ]

                           }
                        ]
                     description "Hello World"
                     url "http://www.csv.ica.uni-stuttgart.de/homes/js/javakurs/HelloWorld2.wrl"
                     }
                  ]
               }
            ]
         }
      ]
   }

DEF HOCHROTATION OrientationInterpolator 
   {
   key [0, 0.25, 0.375, 0.5, 0.75, 0.875, 1]
   keyValue 
      [
      0 -1 0 3.14,    
                  # 0     - 0.25
      0 -1 0 3.14,    
                  # 0.25  - 0.375
      0 -1 0 -1.57, 
                  # 0.375 - 0.5
      0 -1 0 0,    
                  # 0.5   - 0.75
      0 -1 0 0, 
                  # 0.75  - 0.875
      0 -1 0 1.57, 
                  # 0.875 - 1
      0 -1 0 3.14,    
      ]
   }

DEF QUERROTATION OrientationInterpolator 
   {
   key [0, 0.25, 0.375, 0.5, 0.75, 0.875, 1]
   keyValue 
      [
      0 0 0 0,    
                  # 0     - 0.25
      0 0 0 0,    
                  # 0.25  - 0.375
      1 0 0 -1.57, 
                  # 0.375 - 0.5
      0 0 0 0,    
                  # 0.5   - 0.75
      0 0 0 0, 
                  # 0.75  - 0.875
      1 0 0 1.57, 
                  # 0.875 - 1
      0 0 0 0,    
      ]
   }

DEF POSITIONATOR Script
   {
   eventIn SFFloat eingang_float
   eventOut SFVec3f ausgang_3D_float_vektor
   field SFFloat radius 2
   field SFFloat laenge 4
   url "vrmlscript:
   function initialize()
      {
      }
   function eingang_float(val)  
      {
      if (val<0.25)
         {
         ausgang_3D_float_vektor[0]=0;
         ausgang_3D_float_vektor[1]=0;
         ausgang_3D_float_vektor[2]=0;
         }
      else if (val<0.5)
         {
         ausgang_3D_float_vektor[0]=radius*Math.cos((val-0.25)*4*Math.PI);
         ausgang_3D_float_vektor[1]=0;
         ausgang_3D_float_vektor[2]=radius*Math.sin((val-0.25)*4*Math.PI)
                                    +laenge;
         }
      else if (val<0.75)
         {
         ausgang_3D_float_vektor[0]=0;
         ausgang_3D_float_vektor[1]=0;
         ausgang_3D_float_vektor[2]=0;
         }
      else       if (val<1)
         {
         ausgang_3D_float_vektor[0]=radius*Math.cos((val-0.5)*4*Math.PI);
         ausgang_3D_float_vektor[1]=0;
         ausgang_3D_float_vektor[2]=radius*Math.sin((val-0.5)*4*Math.PI);
         }
      }
   "
   }

DEF AUSWAHL Script 
   {
    eventIn SFFloat eingang_float
    eventOut SFInt32 output
    url "vrmlscript:
    function initialize() 
       {
       }
    function eingang_float(val)  
      {
      if (val<0.25)
         {
         output=-1;
         }
      else if (val<0.5)
         {
         output=0;
         } 
      else if (val<0.75)
         {
         output=1;
         }
      else       if (val<1)
         {
         output=0;
         }
       }
    "
    }



DEF BOX Transform
   {
   scale 0.5 0.5 0.2
   children
      [
      DEF touched TouchSensor {}
      Shape
         {
         appearance Appearance
            {
            texture ImageTexture { url "a149.png" }
            }
         geometry Box {}
         }
      ]
   }

DEF TIMER TimeSensor  
   {
   cycleInterval 10
   loop TRUE
   }


ROUTE TIMER.fraction_changed  TO HOCHROTATION.set_fraction
ROUTE HOCHROTATION.value_changed TO HOCHACHSE.set_rotation


ROUTE TIMER.fraction_changed  TO QUERROTATION.set_fraction
ROUTE QUERROTATION.value_changed TO QUERACHSE.set_rotation


ROUTE TIMER.fraction_changed               TO POSITIONATOR.eingang_float
ROUTE POSITIONATOR.ausgang_3D_float_vektor TO POSITION.set_translation

ROUTE touched.hitPoint_changed TO BOX.set_translation

ROUTE TIMER.fraction_changed TO AUSWAHL.eingang_float
ROUTE AUSWAHL.output TO SCHALTER.whichChoice
   
# dieser Befehl gestaltet lediglich das Aussehen des Browsers

NavigationInfo { type "EXAMINE" }      
Download HelloWorld_aufgabe.wrl Es simuliert den Flug eines Flugzeugs. Liefert der Timesensor eine Zeit von 0 bis 0.25 oder 0.5 bis 0.75 sollte das Flugzeug geradeausfliegen und an den Endpunkten der Kurvenbahnen ankommen. Der Geradeausflug ist allerdings gelöscht worden.