VRML

Aus Debacher-Wiki
Zur Navigation springenZur Suche springen

Die Virtual Reality Modeling Language (VRML, gesprochen Wörml) ist eine Skriptsprache bzw. eine HTML-Erweiterung, die es erlaubt dreidimensionale Szenen darzustellen. Aktuell ist die Version 2.0 dieser Sprache.

Eine Reihen von Beispielen findet sich auf der Seite VRML-Beispiele

Für die Darstellung der Szene benötigt man einen geeigneten Browser oder ein Plug-In für einen der Standardbrowser. Weit verbreitet auf diesem Sektor ist der Cortona-Player von Parallelgraphics (http://www.parallelgraphics.com/products/cortona/), der als Plug-In für Mozilla, Firefox bzw. den Internet-Explorer geeignet ist und für Linux auch FreeWrl.

Ein sehr einfaches Beispiel wäre das folgende:

#VRML V2.0 utf8

Shape {
 appearance Appearance {
   material Material {}
 }
geometry Box {}
}

Im Browser betrachten

Die erste Zeile taucht in genau dieser Form in jedem VRML 2.0 Dokument auf. Es handelt sich um eine Kommentarzeile (‚#‘ am Zeilenbeginn), die angibt, in welcher Weise der Rest des Dokumentes auszuwerten ist. Dieser Anfang ist von Scriptsprachen wie Perl bekannt. Auch wenn die Zeile als Kommentar gekennzeichnet ist, kommt es auf die exakte Schreibweise an!

Danach folgen dann als eigentlicher Inhalt die Objekte, die in VRML als Knoten bezeichnet werden. Hauptknoten ist hier Shape, der Knotentyp der für die Gestaltung von sichtbaren Objekten zuständig ist.

Vom Knotentyp Shape werden hier zwei Unterknoten mit angegeben, nämlich appearance und geometry. Für die Form des Objektes wird die geometry Box ausgewählt. Dabei handelt es sich um einen Würfel, mit der Kantenlänge mit der Kantenlänge 2.0, da wir keine anderen Angaben gemacht haben. Beim Erscheinungsbild wählen wir die vordefinierte Einstellung Appearance aus, ändern dort aber den Subknoten material, in dem wir die vordefinierte Einstellung Material angeben.

Im Browser sieht das folgendermaßen aus:

Vrml-001.png

Genau in der Mitte des Bildschirmes ist der Würfel zu sehen. Am unteren und linken Rand des Bildes befinden sich die Navigationselemente des Players, die eine Bewegung sowohl des Objektes als auch des Betrachters durch die Szene erlauben.

Vrml-002.png


1. Grundlagen der VRML-Syntax

Die VRML-Syntax ist recht stark objektorientiert, obwohl dieser Begriff kaum irgendwo auftaucht. Bei VRML spricht man stattdessen viel von Knoten.

Es gibt nur wenige Datentypen und vordefinierte Bezeichner. Trotzdem werden Listings schnell sehr unübersichtlich, da die Zahl der Objekte (Knoten) in der Regel schnell groß wird. Man sollte daher von Anfang an auf eine übersichtliche Struktur und gute Kommentierung achten, sonst sind die Listings nicht wartbar.

Alle Zeichen, die nach „#“ folgen, werden als Kommentar betrachtet. Man kann also auch Kommentare an jede Codezeile anhängen.


Knoten
Zentraler Begriff ist der des Knotens. Bei den Knoten kann man drei Typen unterscheiden:
  • Gruppenknoten
  • Blattknoten
  • Untergeordnete Knoten


1.1. Gruppenknoten

Ein Gruppenknoten kann andere Knoten enthalten, entweder wieder Gruppenknoten oder Blattknoten.

Zu den Gruppenknoten gehören:

Group
Der Gruppenknoten fasst mehrere Kindknoten zu einem Objekt zusammen. Das hilft bei der Strukturierung, hat aber auch Einfluss auf den Schwerpunkt des Objektes. Da man Objekte oft auch verschieben möchte, verwendet man meist den Transform-Knoten


Transform
Eine Erweiterung des Gruppenknotens, bei dem zusätzlich noch eine Verschiebung, eine Rotation bzw. eine Skalierung erfolgen kann.
#VRML V2.0 utf8
Background  {skyColor 1.0 1.0 1.0}

Transform {
  children [

    Shape {
      appearance Appearance {
         material Material {}
    }
    geometry Box {}
    }
  ]
  translation 2.0 0 0
}

Im Browser betrachten

Wichtigster untergeordneter Knoten ist hier children, eine Liste von Kindknoten. Falls die Liste, wie im vorliegenden Beispiel, nur aus einem Kindknoten besteht, können die eckigen Klammern entfallen.
Als weiterer Kindknoten ist hier translation, für die Verschiebung angegeben. Danach kommen die Werte, um die verschoben werden soll, in der Reihenfolge x-, y-, z-Verschiebung.
Von Bedeutung sind die untergeordneten Knoten:
  • children []
  • translation 0.0 0.0 0.0 (x, y, z Verschiebung)
  • rotation 0.0 0.0 0.0 0.0 (x, y, z, Winkel Rotation)
  • scale 0.0 0.0 0.0 (x, y, z Skalierung)

Hinweis: die kursiv gesetzten Werteangaben stellen die Voreinstellungen dar. Wenn man mit der Voreinstellung zufrieden ist, dann kann der jeweilige untergeordnete Knoten weggelassen werden.

Inline
Mit diesem Knoten kann eine komplette VRML-Welt über die Angabe einer URL in die Szenerie integriert werden. Dies erlaubt einen stark modularen Aufbau, der die Übersichtlichkeit und Wartbarkeit der Listings erhöht.
Inline {
  url  "hansa.wrl"
}
Man könnte hiermit auch Standardknoten wie den Hintergrund, die Beleuchtung und Höhenprofile aus den Listings heraushalten.

1.2. Blattknoten

Sie treten in einer Datei als eigenständige Knoten auf, oder sind Kindknoten in einem Gruppenknoten. Dazu gehören:

Shape
Ohne den Gestaltungsknoten Shape käme wohl kein Listing aus. Er verfügt über zwei untergeordnete Knoten, nämlich
  • appearance NULL
  • geometry NULL
die das Aussehen und die geometrische Form des Objektes beschreiben.
Beispiel s.o.


DirectionalLight
Alle Lichtquellen sind eigenständige Blattknoten, sie sind nicht an irgendein geometrisches Objekt gebunden.
Beispiel mit allen Lichtquellen
Hier handelt es sich um paralleles gerichtetes Licht, das dem Sonnenlicht entspricht. Es stehen die untergeordneten Knoten
  • ambientIntensity 0.0 (0.0 bis 1.0, Licht von anderen Quellen)
  • color 1.0 1.0 1.0 (Farbe des Lichtes mit den drei Werten für r, g und b)
  • direction 0.0 0.0 -1.0(Richtungsvektor des Lichtstrahles x, y, z)
  • intensity 1.0(0.0 bis 1.0, Intensität)
  • on TRUE(TRUE, FALSE, Zustand des Lichtschalters)

Gefunden habe ich für die resultierende Intensität, dass sie von der Farbe, der ambientIntensity und der intensity abhängt, aber mal als Summe, mal als Produkt.


PointLight
Licht, das sich punktförmig von einer Quelle aus in alle Richtungen ausbreitet. Es gibt die untergeordneten Knoten:
  • ambientIntensity 0.0 (0.0 bis 1.0, unklar, Licht von anderen Quellen)
  • attenuation 1.0 0.0 0.0 (Abschwächung des Lichtes)
  • color 1.0 1.0 1.0 (Farbe des Lichtes mit den drei Werten für r, g und b)
  • intensity 1.0(0.0 bis 1.0, Intensität)
  • location 0.0 0.0 0.0(Position der Lichtquelle x, y, z)
  • on TRUE(TRUE, FALSE, Zustand des Lichtschalters)
  • radius 100(Radius, in dem andere Knoten beleuchtet werden)
Für die Abschwächung des Lichtes gilt:
Die Vorgabe ergibt eine Intensität von 1.0.


SpotLight
Kegelförmiger Lichtstrahl, der von einer punktförmigen Lichtquelle ausgeht.
  • ambientIntensity 0.0 (0.0 bis 1.0, unklar, Licht von anderen Quellen)
  • attenuation 1.0 0.0 0.0 (Abschwächung des Lichtes)
  • beamWidth 1.570796(Öffnungswinkel des Lichtkegels mit konstanter Intensität 0.0 bis 1.570796=π/2=90°)
  • color 1.0 1.0 1.0 (Farbe des Lichtes mit den drei Werten für r, g und b)
  • cutOffAngle 0.785398(äußerer Mantel des Lichtkegels 0.0 bis π/2)
  • direction 0.0 0.0 -1.0(Richtungsvektor des Lichtstrahles x, y, z)
  • intensity 1.0(0.0 bis 1.0, Intensität)
  • location 0.0 0.0 0.0(Position der Lichtquelle x, y, z)
  • on TRUE(TRUE, FALSE, Zustand des Lichtschalters)
  • radius 100(Radius, in dem andere Knoten beleuchtet werden)
BackGround
Der normale voreingestellte Hintergrund ist schwarz und langweilig. Mit diesem Knoten kann man Farbverläufe für den Himmel und den Boden der virtuellen Welt angeben oder auch Grafiken für die Innenflächen der (würfelförmigen) Welt.
  • groundAngle [](Liste von Winkelangaben)
  • groundColor [](Liste von Farbwerten für den Boden)
  • skyAngle [](Liste von Winkelangaben)
  • skyColor [](Liste von Farbwerten für den Himmel)
Statt einer langwierigen Erklärung ein kleines Beispiel:
Background  {
  skyColor  [
     0.0 0.1 0.8,
     0.0 0.5 1.0,
     1.0 1.0 1.0
  ]
  skyAngle [0.785, 1.571]

  groundColor [                            
     0.0 0.0 0.0,
     0.3 0.3 0.3,
     0.5 0.5 0.5
  ]
  groundAngle [0.785, 1.571]
}
Im Browser betrachten
Für die Himmelsfarben werden hier definiert ein sehr dunkles Blau, ein helleres Blau und Weiß. Der leichte Grünanteil macht den Farbeindruck „natürlicher“. Von 0° (über dem Kopf) bis 45° verläuft die Farbe vom dunklen Blau bis zum hellen Blau. Von 45° bis 90° (Horizont) kommt dann der Verlauf vom hellen Blau bis zum Weiß.
Vrml-003.png
Für die Grundfarben ist Schwarz, dunkles Grau und Grau definiert. Von 0° (unter den Füßen) bis 45° verläuft die Farbe von Schwarz zum dunklen Grau. Von 45° bis 90° (Horizont) verläuft dann die Farbe zum Grau.
Will man einfach nur einen weißen Hintergrund haben, statt des schwarzen, so kann man verkürzen zu:
Background  {skyColor 1.0 1.0 1.0}
Es gibt noch sechs weitere untergeordnete Knoten:
  • backUrl []
  • bottomUrl []
  • frontUrl []
  • leftUrl []
  • rightUrl []
  • topUrl []
Werte in diesen Listen sind jeweils Referenzen auf Grafikdateien, die als Panorama für die entsprechenden Innenflächen des Welt-Würfels dienen.


Viewpoint
Beobachtungspunkte sind vordefinierte Positionen innerhalb der Welt, die über ein Auswahlmenü angesteuert werden können.
  • description ““(Zeichenkette, die den Viewpoint beschreibt)
  • jump TRUE(als aktuelle Benutzersicht einstellen)
  • orientation 0.0 0.0 1.0 0.0(Drehachse 0 0 1 und Drehwinkel um die Achse)
  • position 0.0 0.0 10.0(Betrachterposition innerhalb der Welt)
Wir erweitern das letzte Beispiel um:
Viewpoint {
 description "Meine Sicht"
 orientation 0 0 1 0.785
}
Im Browser betrachten
Es ergibt sich nebenstehendes Bild, eine Drehung der Welt um 45° um den Vektor in Blickrichtung.
Vrml-004.png

Das folgende Beispiel zeigt weitere Möglichkeiten des Knotens Viewpoint und ebenfalls von WorldInfo und NavigationInfo.

1.3. Untergeordnete Knoten I (geometrische Knoten)

In dieser Rubrik finden sich u.a. auch die geometrischen Knoten, ohne die eine VRML-Welt langweilig wäre.


Box
Es handelt sich hierbei geometrisch betrachtet um einen Quader, dessen Zentrum sich im Ursprung des Koordinatensystems befindet. Texturen werden einzeln auf jede Seite des Quaders gemappt.
  • size 2.0 2.0 2.0 Die Abmessungen des Quaders


Cone
Ein Kegel, dessen Zentrum im Ursprung des Koordinatensystems liegt, die y-Achse ist seine zentrale Achse. Texturen werden unabhängig auf Mantel und Grundkreis gemappt
  • bottomRadius 1.0Radius des Grundkreises
  • height 2.0Höhe des Kegels
  • side TRUEWird der Kegelmantel dargestellt?
  • bottom TRUEWird der Grundkreis dargestellt?


Cylinder
Auch das Zentrum des Cylinders liegt im Ursprung und zentrale Achse ist wieder die y-Achse. Texturen werden getrennt auf die Teilflächen gemappt.
  • radius 1.0Radius des Cylinders
  • height 2.0Höhe des Cylinders
  • bottom TRUEWird die Grundfläche dargestellt?
  • top TRUEWird die Deckfläche dargestellt?
  • side TRUEWird der Mantel dargestellt?


Sphere
Die Kugel wird recht häufig in VRML Welten benötigt. Ich Zentrum befindet sich im Ursprung des Koordinatensystems und Texturen bedecken die gesamte Oberfläche.
  • radius 1.0Der Radius


Text
Auch einfacher Text lässt sich in einer VRML-Welt als Objekt darstellen. Texturen werden über den gesamten Textbereich gemappt, aber nur auf den Buchstaben dargestellt.
  • string []Eine oder mehrere Zeichenketten in doppelten Anführungszeichen
  • fontStyle NULLHier kann ein FontStyle-Knoten angegeben werden, der Schriftart, -göße, ... festlegt
  • length 0.0Länge der Zeichenkette. Bei Werten verschieden von 0.0 führt dies zu einer Skalierung
  • maxExtent 0.0Obergrenze für die Ausdehnung der Zeichenketten des Knotens. Ein von 0.0 verschiedener Wert führt also gegebenenfalls zu einer Skalierung.


ElevationGrid
Hierbei handelt es sich um einen Knoten, mit dem man Geländeformationen darstellen kann. Benutzt wird dabei eine Art Schachbrett-Muster (muss nicht quadratisch sein) als Grundlage. Auf die einzelnen Felder können Quader mit frei wählbarer Höhe gestellt werden. Dadurch ergibt sich ein Höhenprofil, das noch zur Glättung interpoliert wird.

Texturen bedecken die gesamte Fläche.

  • color NULLColorknoten mit Farbwerten pro Eckpunkt oder Flächenelement
  • height []Zweidimensionale Liste mit den einzelnen Höhenwerten
  • xDimension 0Anzahl der Felder in x-Richtung
  • xSpacing 0.0Ausdehnung eines Feldes in x-Richtung
  • yDimension 0Anzahl der Felder in y-Richtung
  • ySpacing 0.0Ausdehnung eines Feldes in y-Richtung
  • zSpacing 0.0Ausdehnung eines Feldes in z-Richtung
Statt einer langen Erklärung lieber gleich wieder ein Beispiel:
Shape {
 appearance Appearance {
   material Material {}
 } 
 geometry ElevationGrid {
    xDimension 5
    zDimension 5
    xSpacing 1.0
    zSpacing 1.0
    height [
     0.0 0.0 0.0 0.0 0.0,
     0.0 1.0 1.5 1.0 0.0,
     0.0 0.5 2.5 1.5 0.0,
     0.0 1.0 3.0 1.0 0.0,
     0.0 0.0 0.0 0.0 0.0
    ]
 }
}
Im Browser betrachten

Vrml-005.pngVrml-006.png

Bei den folgenden Knoten handelt es sich um solche, die man für kompliziertere geometrische Objekte benötigt, die sich nicht einfach aus den bisher genannten Grundobjekten aufbauen lassen

PointSet
Eine Liste bzw. Wolke von Punkten. Diese Listen werden selten unabhängig benötigt, sondern meistens für die Definition von Linien bzw. Flächen.
  • color NULLKann einen Color-Knoten enthalten, mit einer Liste von Farbwerten für jeden Punkt
  • coord NULLKann einen Coordinate-Knoten enthalten, mit einer Liste von Punkten.


IndexedLineSet
Eine Liste von Linien, die sich durch das systematische Verbinden von Punkten ergibt.-
  • color NULLKann einen Color-Knoten enthalten, mit einer Liste von Farbwerten für jede Linie
  • colorIndex []Will man nicht für jeden Punkt eine andere Farbe benutzen, so kann man im Color-Knoten die Farben definieren und hier nur die Farbnummer den Linien zuordnen.
  • coord NULLKann einen Coordinate-Knoten enthalten, mit einer Liste von Punkten.
  • coordIndex []Liste von Linienzügen, die über die Nummern der Punkte beschreiben werden. Ein Linienzug endet mit -1
Das folgende Listing beschreibt das Gittermodell eines Würfels
Shape {
 appearance Appearance {
   material Material {}
 }
 geometry IndexedLineSet {
   coord Coordinate {
    point [
      -1.0  1.0  1.0,      #0 links oben vorn
      -1.0 -1.0  1.0,       #1 links unten vorn
       1.0 -1.0  1.0,       #2 rechts unten vorn
       1.0  1.0  1.0,       #3 rechts oben vorn
      -1.0  1.0 -1.0,       #4 links oben hinten
      -1.0 -1.0 -1.0,       #5 links unten hinten
       1.0 -1.0 -1.0,      #6 rechts unten hinten
       1.0  1.0 -1.0        #7 rechts oben hinten
    ]
   }
   coordIndex [
     0, 1, 2, 3, 0, -1,     # vorderes Quadrat
     4, 5, 6, 7, 4, -1,     # hinteres Quadrat
     0, 3, 7, 4, 0, -1,     # oberes Quadrat
     1, 2, 6, 5, 1, -1,     # unteres Quadrat
     3, 2, 6, 7, 3, -1,     # rechtes Quadrat
     0, 1, 5, 4, 0          # linkes Quadrat
   ]
 }
}
Im Browser betrachten


IndexedFaceSet
Hiermit kann man (nahezu) beliebige geometrische Objekte aus einzelnen Flächenstücken definieren. Die Verwendung von Texturen ist möglich, aber aufwendig steuerbar.
  • color NULLKann einen Color-Knoten enthalten, mit einer Liste von Farbwerten für jede Linie
  • colorIndex []Will man nicht für jeden Punkt eine andere Farbe benutzen, so kann man im Color-Knoten die Farben definieren und hier nur die Farbnummer den Linien zuordnen.
  • coord NULLKann einen Coordinate-Knoten enthalten, mit einer Liste von Punkten.
  • coordIndex []Liste von Linienzügen, die über die Nummern der Punkte beschreiben werden. Ein Linienzug endet mit -1
  • solid TRUEDie Polygonstuktur wird bei TRUE als Festkörper behandelt, verdeckte Flächen werden nicht dargestellt. Will man das Objekt vernünftig drehen können, so muss der Wert auf FALSE gesetzt werden.
Shape {
 appearance Appearance {
   material Material {}
 }
 geometry IndexedFaceSet {

   solid FALSE

   coord Coordinate {
    point [
      -1.0  1.0  1.0,      #0 links oben vorn
      -1.0 -1.0  1.0,       #1 links unten vorn
       1.0 -1.0  1.0,       #2 rechts unten vorn
       1.0  1.0  1.0,       #3 rechts oben vorn
      -1.0  1.0 -1.0,       #4 links oben hinten
      -1.0 -1.0 -1.0,       #5 links unten hinten
       1.0 -1.0 -1.0,      #6 rechts unten hinten
       1.0  1.0 -1.0       #7 rechts oben hinten
    ]
   }
   coordIndex [
     0, 1, 2, 3, 0, -1,     # vorderes Quadrat
     4, 5, 6, 7, 4, -1,     # hinteres Quadrat
     0, 3, 7, 4, 0, -1,     # oberes Quadrat
     1, 2, 6, 5, 1, -1,     # unteres Quadrat
     3, 2, 6, 7, 3, -1,     # rechtes Quadrat
     0, 1, 5, 4, 0          # linkes Quadrat
   ]
 }
}
Im Browser betrachten
Ein so beschriebener Würfel ist von einem mit der geometry Box optisch nicht zu unterscheiden. Unterschiede treten erst dann auf, wenn es um das Anbringen von Texturen geht.


Extrusion
Geht man von einem Flächenstück aus und verschiebt dieses entlang einer Linie im Raum, so lässt sich damit ein Körper beschreiben. Der Begriff ist der Fertigungstechnik entlehnt, bei der Körper entstehen, indem der Kunststoff durch eine flache Form gepresst wird.
Man kann sich aber auch einen Spritzbeutel vorstellen, aus dem Sahne herausgedrückt wird. Als Flächenstück kommt ein beliebiger, nicht unbedingt geschlossener, Linienzug zum Einsatz (die Form der Düse). Die Linie für die Verschiebung (der Weg des Spritz­beutels) kann aus mehreren Zwischenschritten bestehen. Bei jedem Zwischenschritt kann das Flächenstück zusätzlich skaliert und gedreht werden.

Texturen werden wie beim Zylinder aufgebracht.

  • CrossSection [1 1, 1 -1, -1 -1, -1 1, 1 1]Der Linienzug, hier ein Quadrat, der als Querschnitt für das Objekt dienen soll.
  • spine [0 0 0, 0 1 0]Linienzug, der die Verschiebung beschreibt. Es können hier beliebig viele Punkte benutzt werden.
  • beginCap TRUEBei TRUE wird der Anfangsdeckel des Objektes mit dargestellt. Bei FALSE nicht.
  • endCap TRUEBei TRUE wird der Enddeckel des Objektes mit dargestellt. Bei FALSE nicht.
  • scale [1 1]Legt für jeden Verschiebungsschritt die Skalierungsfaktoren fest.
  • convex TRUEBei TRUE ist der Körper nach außen gewölbt.
  • creaseAngle 0.5Ist der Winkel zwischen zwei Flächenstücken kleiner als dieser Wert, so wird weich schattiert, was den Knick „wegbügelt“. Ansonsten wird hart schattiert.
  • solid TRUEBei TRUE gilt der Körper als massiv.
  • orientation [0 0 1 0]Beschreibt eine Drehung für jeden der Verschiebungs­-schrit­te. Wird nur ein Wert angegeben, so gilt er für alle Schritte.
Ein paar kleine Bespiele:
Shape{ 
 appearance Appearance {
   material Material {}
 }  
 geometry Extrusion {  
   crossSection [ 1 2, 
                 1 -2, 
                 -1 -2, 
                 -1 2, 
                  1 2 ]  
   spine [        0 0 0, 
            0 3 0 ] 
 }  
}
Im Browser betrachten
Beschreibt einen Quader mit den Abmessungen 2x4x3.
Bei dem folgenden Objekt wird die Fläche bei der Verschiebung (Extrusion) auch noch um 180° gedreht.
Shape{ 
 appearance Appearance {
   material Material {}
 }  
 geometry Extrusion{  
   crossSection [  1  2, 
                   1 -2, 
                  -1 -2, 
                  -1  2, 
                   1  2 ]  
   spine  [        0 -1 0,
                   0 1 0   ] 
   orientation[    0 1 0 0, 
                   0 1 0 3.14] 
 }  
} 
Im Browser betrachten
Vrml-007.png

1.4. Untergeordnete Knoten II (Hilfsknoten)

Diese Knoten beschreiben Eigenschaften von geometrischen Objekten.


Color
Kann eine Liste von Farbangaben im RGB-Format beinhalten. Zu beachten ist, dass Texturen Vorrang besitzen gegenüber Farben.
  • color []Farbwert im RGB-Format, drei Zahlen zwischen 0.0 und 1.0


Coordinate
Koordinaten von Punkten, wie man sie für PointSet, IndexedLineSet IndexedFaceSet benötigt.
  • point []Liste von Punkten, die jeweils mit drei Gleitkommazahlen beschrieben werden.


Normal
Fast jeder Oberstufenschüler hat schon einmal mit Normalenvektoren zu tun gehabt. Mit Hilfe dieser Vektoren werden vom Browser z.B. die Brechungen und Schattierungen berechnet. Man kann die Normalenvektoren aber auch konkret angeben.
  • vector []Der Normalenvektor sollte ein Einheitsvektor, also skaliert sein.


TextureCoordinate
Hiermit wird festgelegt, wie Texturen auf die Oberfläche von Objekten gemappt werden. Angegeben wird ein virtuelle, zweidimensionales Koordinatensystem, das mit dem s,t-Koordinatensystem des Objektes zur Deckung gebracht wird.
  • point []Texturkoordinaten, bestehend aus zwei Gleitkommazahlen.


1.5. Untergeordnete Knoten III (Aussehen von geometrischen Objekten)

Entscheidend für das Aussehen von geometrischen Objekten ist der Appearance-Knoten, der über eine Zahl von spezifischen Unterknoten verfügt.

Appearance
Der Knoten der das Aussehen von geometrischen Objekten beschreibt.
  • material NULLHier kann ein Material-Knoten eingebunden werden, der Eigenschaften wie Reflektion, Transparenz oder Leuchtkraft beschreibt.
  • texture NULLLegt Muster fest, die auf die Oberfläche des Objektes gemappt werden. Möglich sind Knoten vom Typ ImageTexture, MovieTexture und PixelTexture.
  • textureTransform NULLBeschreibt Operationen, die mit der Textur vor dem Mappen vorgenommen werden sollen.


Material
Der Material-Knoten beschreibt Objekt-Eigenschaften wie Reflektion, Transparenz oder Leuchtkraft.
  • ambientIntensity 0.2Beschreibt, wie stark der Körper diffuses Licht reflektiert.
  • diffuseColor .8 .8 .8Farbe des vom Objektreflektierten Lichtes.
  • emissiveColor 0 0 0Farbe des vom Objekt abgestrahlten Lichtes.
  • shininess 0.2Glanz des Objektes.
  • specularColor 0 0 0Reflektionswert für jede der drei Grundfarben
  • transparency 0Transparenz des Objektes. Für normale Fensterscheiben sind Werte ab 0.5 geeignet.


ImageTexture
Eine Grafikdatei im gif-, jpg- oder png-Format kann auf die Oberfläche eines Objektes gelegt werden. Transparente gif-Dateien werden richtig berücksichtigt.
  • url []Liste von Abbildungen, die als Textur benutzt werden sollen. Die erste gefundene Datei wird benutzt.
  • repeatS TRUESoll die Textur in s-Richtung wiederholt werden?
  • repeatT TRUESoll die Textur in t-Richtung wiederholt werden?
Beispiel im Browser betrachten
MovieTexture
Analog zur Grafikdatei kann auch eine Videodatei auf ein Objekt abgebildet werden. Dabei ist bisher nur das MPEG1-Format zulässig.
  • url []Liste von Filmen, die als Textur benutzt werden sollen. Die erste gefundene Datei wird benutzt.-
  • repeatS TRUESoll die Textur in s-Richtung wiederholt werden?
  • repeatT TRUESoll die Textur in t-Richtung wiederholt werden?
  • loop FALSEBei TRUE wird das Abspielen des Videos unendlich wiederholt.
  • speed 1Wiedergabegeschwindigkeit für das Video.


PixelTexture
Einfache Punktmuster muss man nicht als gif- oder jpg-Datei angeben, sonder kann sie direkt in das Listing integrieren.
  • image 0 0 0Folge von Zahlenwerten, die das Bild beschreibt. Die ersten beiden Zahlen beschreiben Breite und Höhe des Bildes. Die dritte Zahl beschreibt die Farbtiefe bzw. den Farbmodus. Danach kommt dann pro Bildpunkt 1 bis 4 Bytes je nach Farbtiefe. Das Muster wird normalerweise auf die Größe des Objektes gestreckt.
  • repeatS TRUESoll die Textur in s-Richtung wiederholt werden?
  • repeatT TRUESoll die Textur in t-Richtung wiederholt werden?


TextureTransform
Mit diesem Knoten kann man die Abbildung der Textur auf die Oberfläche des Objektes steuern. Die Textur kann skaliert, rotiert und verschoben werden.
  • center 0 0Ursprungspunkt für Skalierung und Rotation
  • rotation 0Winkel, der die Drehung der Textur beschreibt
  • scale 1 1Skalierungsfaktoren in s- bzw. t-Richtung. Es wird aber nicht die Textur skaliert, sondern das virtuelle Koordinatensystem. Ein Wert von 2 halbiert also die Größe der Textur. Beim Skalieren sind die Repeat-Felder der Texturen wichtig dafür, ob Gekachelt wird oder nicht.
  • translation 0 0Verschiebung der Textur.

2. Mehrfachverwendung von Knoten

Für größere Projekte ist es hilfreich, wenn man Objekte an einer Stelle definieren und dann innerhalb des Projektes mehrfach verwenden kann. Idealerweise trennt man sogar zwischen Definition und Verwendung in verschiedene Dateien.


2.1. DEF

Jeder Knoten innerhalb einer VRML-Definition kann benannt werden. Dazu setzt man das Schlüsselwort DEF gefolgt von dem Namen vor die Knotendefinition.

DEF kasten Shape {
 geometry Box {
   size 1 2 3
 }
}

definiert ein Objekt „kasten“, das also ein Quader mit den Abmessungen 1x2x3 darstellt.

Will ich dieses Objekt später noch einmal nutzen, so wird es mit

USE kasten

erneut instanziiert.

Ein ausführliches Beispiel zur Kombination DEF/USE zeigt die folgende Seite.

2.2. Prototypen

Effektiver als einfache Definitionen sind richtige Prototypen. Hier können sich die einzelnen Instanzen dann sogar in Werten unterscheiden, die als Parameter übergeben werden.

Zuerst ein kleines Beispiel:

PROTO  kasten [
 field        SFVec3f  size 1.0 1.0 1.0
 exposedField   SFColor  color  .8  .8  .8
]

{
  Shape {
    appearance Appearance {
       material Material {
         diffuseColor IS color
       }
    }
    geometry Box {
     size IS size
    }

 }
} # Ende PROTO Kasten

Definiert einen Prototyp „kasten“. Es wird eine Default-Größe und eine Default-Farbe festgelegt.

Instanziiert man „kasten“ folgendermaßen:

kasten {
 size 1 2 3
}

so wird ein grauer Kasten mit den Abmessungen 1x2x3 erzeugt. Die Prototyp- Definition allein erzeugt noch kein sichtbares Objekt.


Eine Prototypdefinition ist folgendermaßen aufgebaut:

PROTO <prototypname> 
[
             <Schnittstelle>
] 
{
      <Implementierung>
}

Im Interface-Teil werden angegeben die Schlüsselfelder

  • exposedField
  • field

gefolgt von einem Feldtyp, einem Feldnamen und dem Default-Wert. Der Unterschied zwischen field und exposedField besteht darin, dass auf ein exposedField auch Ereig­nisse einwirken können. Field kann immer benutzt werden, exposedField nur dann, wenn die Zuweisung des Wertes zu einer Größe erfolgt, die entsprechend definiert ist. Im obi­gen Beispiel ist die size-Feld einer Box nicht exposed, das color-Field von Material aber.

Die Default-Werte werden immer dann angenommen, wenn bei der Instanziierung keine Werte angegeben werden.

Im Implementierungsteil werden die Bezeichner aus dem Interfaceteil mittels

<feld> IS <parameter> eingesetzt.

Ein sehr allgemeiner Prototyp zum Erzeugen von geometrischen Objekten könnte folgen­der­maßen aussehen:

PROTO  objekt [
 exposedField   SFVec3f  trans 0 0 0
 exposedField   SFColor  color  .8  .8  .8
 exposedField   MFString tex [ ]
 exposedField   SFNode geom Sphere {}
]

{
 Transform {
   children [
     Shape {
       appearance Appearance {
         material Material {
           diffuseColor IS color
         }
         texture ImageTexture {
           url IS tex
         }
       }
       geometry IS geom
     }
   ]   
   translation IS trans
 }
} # Ende PROTO objekt

Eine Kugel kann dann einfach mittels:

objekt {
}

erzeugt werden und ein Würfel mittels:

objekt {
 geom Box {}
}


2.3. Externe Prototypen

Wie bereits beschrieben, kann es sinnvoll seine Prototypen in einer eigenen Datei zu sam­meln. Für diese Datei ist nichts besonders zu beachten. Will man aber einen Prototyp in eine andere Datei einbinden, so benötigt. man dazu zuerst eine EXTERNPROTO-Zeile, bevor man den Prototyp wie gewohnt nutzen kann.

EXTERNPROTO kasten [  
 field        SFVec3f  size 
 exposedField   SFColor  color ] 
     "prototypen.wrl#kasten"

Hier muss im Prinzip der vollständige Interface-Teil wiedergegeben werden, bis auf die Angabe der Default-Werte.

Ein ausführlich dokumentiertes Beispiel zur Verwendung von Prototypen zeigt die folgende Seite.

3. Animationen

Mit VRML sind wir nicht nur in der Lage komplexe Objekte im Raum zu erstellen, son­dern sie auch noch zu animieren.

Bevor wir die Animationen systematisch angehen ein einfaches Beispiel:


#VRML V2.0 utf8
# Animation

Background { skyColor 1 1 1 }

DEF Wuerfel Transform {
 children [
  Shape {
   appearance Appearance {
    material Material {}
   }
   geometry Box {}
  }
 ]
}

DEF Uhr TimeSensor {
 cycleInterval 5.0
 loop TRUE
}

DEF Interpolator PositionInterpolator {
 key [ 0.0 0.75 1.0 ]
 keyValue [
   0.0 0.0 0.0,
   0.0 2.0 0.0,
   0.0 0.0 0.0
 ]
}

ROUTE Uhr.fraction_changed TO Interpolator.set_fraction

ROUTE Interpolator.value_changed TO Wuerfel.set_translation

Im Browser betrachten

Es erscheint ein einfacher Würfel, der sich regelmäßig auf dem Bildschirm nach Oben und wieder in die Ausgangsposition bewegt.

Die Animation ersteht durch das Zusammenspiel von den drei Objekten

  • Wuerfel
  • Uhr
  • Interpolator.

Der „Wuerfel“ ist das Objekt, das bewegt werden soll. Das Objekt „Uhr“ liefert den Zeit­takt für die Animation, der komplette Durchlauf beträgt 5 Sekunden und wird unendlich oft wiederholt. Der Interpolator errechnet in Abhängigkeit von Eingabewerten Punkte. Bei der Eingabe 0.0 liefert er 0.0 0.0 0.0 zurück, bei 0.75 liefert er 0.0 2.0 0.0 zurück und bei der Eingabe 1.0 wieder die Ausgabe 0.0 0.0 0.0. Die Zwischenwerte errechnet er selbstständig.

Gekoppelt werden die drei Objekte über die zwei Routen. Die Uhr liefert über das Feld fraction_changed einen Wert zwischen 0.0 und 1.0 zurück. Dieser Wert wird an das Feld set_fraction des Interpolators übergeben, der daraufhin einen neuen Ausgabewert errechnet und über sein Feld value_changed an das Feld set_translation des Objektes „Wuerfel“ übergibt.

Die ungleichförmige Bewegung, abwärts geht es schneller, als aufwärts, rührt daher, dass im Feld „key“ ungleiche Abstände angegeben werden


3.1. Bestandteile einer Animation

Eine Animation besteht meist aus folgenden Komponenten:

  • (geometrisches) Objekt bzw. zugehöriger Transform-Knoten
  • Sensor (reagiert auf Ereignisse und löst Ereignisse aus)
  • Interpolator (berechnet Zwischenwerte zu den Key-Frames)
  • Routen zwischen den Objekten

Routen kann man nun zwischen benannten Objekten definieren, insofern ist es wichtig, dass alle Objekte mittels „DEF“ benannt werden.

Ziel bei geometrischen Objekten werden normalerweise die Felder

  • translation
  • rotation
  • scale

sein. Es gibt noch einige Möglichkeiten mehr, man kann Kindknoten hinzufügen bzw. entfernen, darauf soll hier aber nicht eingegangen werden.


3.2. Routen

In VRML gehört zu einem Feld eines Objektes eine Zugriffsart. Mögliche Zugriffsarten sind:

  • field
  • eventIn
  • eventOut
  • exposedField

Bei der Zugriffsart „field“ gehören keinerlei Ereignisse zu dem Feld. Bei der Art „exposedField“ können sowohl Ereignisse empfangen, als auch ausgelöst werden. Bei den beiden anderen Arten ist jeweils nur eine Richtung möglich.

Kann das Feld „name“ Ereignisse empfangen, so wird der aktuelle Wert über „set_name“ geändert.

Kann das Feld „name“ Ereignisse auslösen, so steht das Ereignis in „name_changed“ zur Verfügung.

Eine Route verknüpft Felder die Ereignisse auslösen mit Feldern, die Ereignisse empfangen.

Vrml-010.png

In der Route steckt implizit auch eine Bedingung. Nur wenn sich beim Ausgabefeld etwas ändert, dann erfolgt die Eingabe beim Eingabefeld.

Von einem Feld können mehrere Routen ausgehen, genauso können bei einem Feld mehrere Routen ankommen. Über einen einzigen Timesensor könnte man also mehrere Bewegungen auslösen.

3.3. Interpolatoren

Alle Interpolatoren haben den gleichen Aufbau:

  • key[]Liste mit Stützwerten (z.B. Zeitwerten) auf der Eingabeseite. Die Liste muss aufsteigend sortiert sein
  • keyValue []Liste mit Stützwerten auf der Ausgabeseite. Die Art der Werte hängt vom Interpolator ab. Die Anzahl der Werte muss mit der im key-Feld übereinstimmen.
  • set_fractionEingabefeld
  • value_changedAusgabefeld

Die einzelnen Interpolatoren unterscheiden sich nur in der Art der Werte in der Liste mit den Stützwerten auf der Ausgabeseite.


PositionInterpolator
Die Werte im Feld keyValue sind vom Typ MFVec3F, also Positionsangaben.
keyValue [
    0.0 0.0 0.0,    # Grundposition
    0.0 0.2 0.0,    # nach Oben
    0.0 0.0 0.0     # zurück
]


OrientationInterpolator
Die Werte im Feld keyValue sind vom Typ MFRotation, beschreiben also Drehungen um eine Achse.
keyValue [
    0.0 0.0 1.0 0.00,    # 0° Grundposition
    0.0 0.0 1.0 3.14,    # 180°
    0.0 0.0 1.0 6.28    # 360° Grundposition (warum dürfte hier nicht  wieder 0° stehen?)
]


ColorInterpolator
Die Werte im Feld keyValue sind vom Typ MFColor, also Farbangaben.
keyValue [
    0.0 1.0 0.0,    # Grün
    1.0 0.0 0.0,    # Rot
    0.0 1.0 0.0     # wieder Grün
]


Scalarinterpolator
Die Werte im Feld keyValue sind vom Typ MFFloat, also Gleitkommazahlen. Damit könnte man z.B. die Transparenz eines Objektes beeinflussen.
keyValue [
    0.0,    # undurchsichtig
    1.0,    # durchsichtig
    0.0     # undurchsichtig
]


Analog zum PositionInterpolator gibt es noch CoordinationInterpolator und NormalInterpolator.


3.4. Sensoren

Einen Sensor haben wir bereits kennen gelernt, den TimeSensor. Daneben gibt es eine Zahl von weiteren Sensoren:

  • TimeSensorZeitgeber
  • TouchSensorReagiert auf Berührungen mit dem Mauszeiger
  • VisibilitySensorRegistriert die Sichtbarkeit eines Objektes durch den Betrachter
  • ProximitySensorReagiert auf Annäherung des Betrachters
  • PlaneSensordient derVerschiebung eines Objektes in der xy-Ebene durch Ziehen mit der Maus
  • SphereSensorRollen eines Objektes um den Ursprung des Koordinatensystems durch Ziehen mit der Maus
  • CylinderSensorRotation um die y-Achse durch Ziehen mit der Maus


TimeSensor
Ein eingebauter Timer, der auf der Systemuhr basiert.
Felder
  • cycleInterval 1Zeitintervall für einen vollständigen Durchlauf
  • enabled TRUEIst der Timer aktiv?
  • loop FALSEBei TRUE wird der Timer nach jedem Durchlauf neu gestartet
  • startTime 0Startzeit für die Aktivität des Sensors
  • stopTime 0Zeitpunkt zu dem der Timer seine Aktivität beendet
Ereignisse
  • cycleTimeWird mit jedem neuen Durchlauf erzeugt
  • fraction_changedHier werden kontinuierlich Zeitwerte zwischen 0 und 1 augegeben


TouchSensor
Reagiert auf Berührungen des Objektes durch die Maus
Felder
  • enabled TRUEBei TRUE reagiert der Sensor auf Berührungen
Ereignisse
  • isOverWird TRUE, wenn der Zeiger das Objekt berührt, ansonsten FALSE
  • isActiveWird TRUE, wenn die Linke Maustaste während einer Berührung gedrückt ist, ansonsten FALSE.

Das folgende Listing, eine Erweiterung des Beispiels aus 3., koppelt beide Sensoren miteinander:


#VRML V2.0 utf8
# Animation 2

Background { skyColor 1 1 1 }
DEF Wuerfel Transform {
 children [
   Shape {
     appearance Appearance {
        material Material {}
     }
     geometry Box {}
   }
 ]
}

DEF Interpolator PositionInterpolator {
 key [ 0.0 0.75 1.0]
 keyValue [
   0.0 0.0 0.0,
   0.0 2.0 0.0,
   0.0 0.0 0.0
 ]
}

DEF Uhr TimeSensor {
 enabled FALSE
 cycleInterval 5.0
 loop TRUE
}

DEF Schalter TouchSensor {}

ROUTE Schalter.isActive TO Uhr.set_enabled

ROUTE Uhr.fraction_changed TO Interpolator.set_fraction
ROUTE Interpolator.value_changed TO Wuerfel.set_translation

Im Browser betrachten

So wird die Animation erst aktiv, wenn man mit der Maus auf den Würfel zeigt und die linke Maustaste drückt.

Dass die Uhr schon vorher lief, kann man daran erkennen, dass der Würfel meist einen Sprung auf eine Zwischenposition macht. Der Timer lief zwar schon vorher, hat aber keine Ereignisse geliefert.


VisibilitySensor
Ermittelt, ob ein quaderförmiger Bereich für den Betrachter ganz oder teilweise sichtbar ist. Der Abstand spielt keine Rolle. Hiermit kann man Animationen abschalten, wenn der Betrachter sie nicht wahrnehmen kann.
Felder
  • center 0 0 0Mittelpunkt des quaderförmigen Bereiches
  • enabled TRUENur bei TRUE werden Ereignisse geliefert
  • size 0 0 0Ausdehnungen des Quaders
Ereignisse
  • isActiveLiefert TRUE beim Sichtbarwerden des Bereiches, sonst FALSE.


ProximitySensor
Ermittelt, ob der Betrachter in einen quaderförmigen Bereich eingedrungen ist.
Felder
  • center 0 0 0Mittelpunkt des quaderförmigen Bereiches
  • enabled TRUENur bei TRUE werden Ereignisse geliefert
  • size 0 0 0Ausdehnungen des Quaders
Ereignisse
  • isActiveLiefert TRUE beim Eindringen des Betrachters in den Bereich, FALSE beim Verlassen.
  • position_changedLiefert Positionsveränderungen des Betrachters im Bereich des Sensors (Typ SFVec3f)
  • orientation_changedLiefert Änderungen der Betrachterorientierung im Bereich des Sensors (Typ SFRotation).

Die letzten drei Sensoren dienen dazu mit der Maus Objekte im Raum zu bewegen. Dazu werden unterschiedliche Freiheitsgrade für das jeweilige Objekt zur Verfügung gestellt.


PlaneSensor
Mit der Maus wird das Objekt in der xy-Ebene verschoben. In einer VRML-Welt könnte man hiermit Schiebetüren realisieren, die vom Benutzer geöffnet bzw. geschlossen werden können.
Felder
  • autoOffset TRUEBei der Einstellung TRUE beginnt eine neue Verschiebung an der aktuellen Position, bei FALSE an der Ursprungsposition. Der Wert wird in offset gespeichert.
  • offset 0 0 0Wenn autoOffset auf TRUE gestellt ist, wird hier die relative Verschiebung zum Ursprung gespeichert.
  • enabled TRUENur bei TRUE werden Ereignisse geliefert
  • maxPosition -1 -1Rechte obere Ecke des gedachten Rechtecks, das den Bewe­gungsbereich beschränkt. Sind die Werte kleiner als die von minPosition, so ist die Translation nicht begrenzt.
  • minPosition 0 0Linke untere Ecke des Rechtecks, das den Bewegungs­bereich beschränkt.
Ereignisse
  • isActiveLiefert TRUE beim Drücken der Maustaste über dem Objekt, FALSE beim Loslassen.
  • trackPoint_changedLiefert Positionsveränderungen des Mauszeigers (Typ SFVec3f). Die Beschränkungen durch das Rechteck spielen hier keine Rolle.
  • translation_changedLiefert Positionsveränderungen des Objektes (Typ SFVec3f). Die Beschränkungen durch das Rechteck spielen hier eine Rolle.

Unser bisheriges Beispiel hierauf angepasst sieht folgendermassen aus:

#VRML V2.0 utf8
# Animation 2

Background { skyColor 1 1 1 }

DEF Wuerfel Transform {
 children [
   Shape {
    appearance Appearance {
      material Material {}
    }
    geometry Box {}
   }
 ]
}

DEF Verschiebe PlaneSensor {
 maxPosition 1 1
 minPosition -1 -1
}

ROUTE Verschiebe.translation_changed TO Wuerfel.set_translation

Im Browser betrachten

CylinderSensor
Dieser Sensor erlaubt nur Rotationen um die y-Achse. Hiermit lassen sich „normale“ Türen realisieren, die vom Benutzer geöffnet und geschlossen werden können.
Felder
  • autoOffset TRUEBei der Einstellung TRUE beginnt eine neue Drehung an der aktuellen Position, bei FALSE an der Ursprungsposition. Der Wert wird in offset gespeichert.
  • offset 0Wenn autoOffset auf TRUE gestellt ist, wird hier die relative Drehung zum Ausgangswert gespeichert.
  • enabled TRUENur bei TRUE werden Ereignisse geliefert
  • maxAngle -1Größter erlaubter Drehwinkel.. Ist der Wert kleiner als der von minAngle, so ist die Rotation nicht begrenzt.
  • minPosition 0 0Minimaler Wert für den Drehwinkel.
Ereignisse
  • isActiveLiefert TRUE beim Drücken der Maustaste über dem Objekt, FALSE beim Loslassen.
  • trackPoint_changedLiefert Positionsveränderungen des Mauszeigers (Typ SFVec3f). Die Beschränkungen spielen hier keine Rolle.
  • rotation_changedLiefert Positionsveränderungen des Objektes (Typ SFRotation). Die Beschränkungen durch das Rechteck spielen hier eine Rolle.


SphereSensor
Erlaubt die freie Drehung eines Objektes um den Ursprung des lokalen Koordinaten­systems.
Felder
  • autoOffset TRUEBei der Einstellung TRUE beginnt eine neue Drehung an der aktuellen Position, bei FALSE an der Ursprungsposition. Der Wert wird in offset gespeichert.
  • offset 0 1 0 0Wenn autoOffset auf TRUE gestellt ist, wird hier die relative Drehung zum Ausgangswert gespeichert.
  • enabled TRUENur bei TRUE werden Ereignisse geliefert
Ereignisse
  • isActiveLiefert TRUE beim Drücken der Maustaste über dem Objekt, FALSE beim Loslassen.
  • trackPoint_changedLiefert Positionsveränderungen des Mauszeigers (Typ SFVec3f). Die Beschränkungen spielen hier keine Rolle.
  • rotation_changedLiefert Positionsveränderungen des Objektes (Typ SFRotation). Die Beschränkungen durch das Rechteck spielen hier eine Rolle.

3.5. Beispiele

Zum Abschluss ein paar Beispiele für grundlegende Animationseffekte.

Ein einfacher Propeller:

Vrml-008.png

#VRML V2.0 utf8
DEF Propeller Transform {
  children [
    Shape {
      appearance Appearance {
        material Material {}
      }
      geometry Box {size 5 0.1 0.1 }
    }
    Shape {
      appearance Appearance {
        material Material {}
      }
      geometry Box {size 0.1 5 0.1 }
    }
    Shape {
      appearance Appearance {
        material Material {}
      }
      geometry Box { size 0.1 0.1 1 }
    }
  ]
}
DEF Uhr TimeSensor {
  cycleInterval 2.0
  loop TRUE
}
DEF Interpolator OrientationInterpolator {
  key [0.0 0.5 1.0]
  keyValue [
    0 0 1 0.0,
    0 0 1 1.57
    0 0 1 3.14
  ]
}
ROUTE Uhr.fraction_changed TO Interpolator.set_fraction
ROUTE Interpolator.value_changed TO Propeller.set_rotation

Im Browser betrachten

Ein blinkendes Blaulicht

#VRML V2.0 utf8

Transform {
  children [
    Shape {
      appearance Appearance {
        material DEF Meinmat Material {
      diffuseColor 0.8 0.8 0.8
    }
      }
      geometry Cylinder {
        radius 2
    height 1
      }
    }
  ]
  translation 0 0 0
}
DEF Uhr TimeSensor {
  cycleInterval 1.0
  loop TRUE
}
DEF Interpolator ColorInterpolator {
  key [ 0 0.5 1 ]
  keyValue [ 0 0 0,
             0 0 1,
             0 0 0]
}
ROUTE Uhr.fraction_changed TO Interpolator.set_fraction
ROUTE Interpolator.value_changed TO Meinmat.set_diffuseColor
ROUTE Interpolator.value_changed TO Meinmat.set_emissiveColor

Im Browser betrachten

Ein Pendel

Vrml-009.png

#VRML V2.0 utf8

DEF Propeller Transform {
  children [
    Shape {
      appearance Appearance {
        material Material {}
      }
      geometry Box {
        size 0.1 0.1 1
      }
    }
    Transform {
      children [
        Shape {
          appearance Appearance {
            material Material {}
          }
          geometry Box {
            size 0.1 6 0.1
          }
        }
      ]
      translation 0 -3 0
    }
    Transform {
      children [
        Shape {
          appearance Appearance {
            material Material {}
          }
          geometry Sphere {
            radius 0.5
          }
        }
      ]
      translation 0 -6 0
    }
  ]
  translation 0 3 0
}

DEF Uhr TimeSensor {
  cycleInterval 5.0
  loop TRUE
}

DEF Interpolator OrientationInterpolator {
  key [0.0 0.25 0.5 0.75 1.0]
  keyValue [
    0 0 1 0.0,
    0 0 1 1.2,
    0 0 1 0.0,
    0 0 1 -1.2,
    0 0 1 0
  ]
}

ROUTE Uhr.fraction_changed TO Interpolator.set_fraction
ROUTE Interpolator.value_changed TO Propeller.set_rotation

Im Browser betrachten