VRML & Java

Grundlagen VRML   ('vermel')

Mit der Virtual Reality Modeling Language (VRML) ist man in der Lage komplexe 3D-Welten bzw. 3D-Objekte zu beschreiben. Diese Objekte können statisch oder animiert sein. Man kann dabei auf vordefinierte Objekte zurückgreifen oder sich benutzerdefinierte Objekte selbst erstellen. Objekte werden durch ihre Eigenschaften beschrieben (Aussehen, Material, Geometrie).

Skript-Knoten ermöglichen es auf Benutzereingaben (Ereignisse) zu reagieren.

Ereignisse werden über Sensoren (die an Objekte gebunden sind) ausgelöst.

Die Verarbeitung der Ereignisse kann dabei durch die Skript-Sprachen Java- bzw. VRML-Skript oder durch die Programmiersprache Java erfolgen.

Facts

Maßeinheiten


Aufbau einer VRML-Datei


File-Header

Eine VRML-Datei beginnt grundsätzlich mit folgendem File-Header

#VRML V2.0 utf8

Dieser Eintrag darf nicht fehlen, da die Datei ansonsten nicht vom VRML-Browser interpretiert wird !

#VRML Kennzeichnung, daß die Datei VRML-Code enthält
V2.0 konform zur VRML-Syntax 2.0
utf8 gecodet nach dem internationalen utf8-Zeichensatz
UCS (Universal Character Set) Transformation Format, 8-bit

Kommentare

# Ein Kommentar

Um die Lesbarkeit des Quellcodes zu verbessern, lassen sich Kommentare in den Text einfügen, die vom Browser nicht interpretiert werden. Ein Kommentar beginnt mit einem (#)-Zeichen und endet am Zeilenende.


Knoten (Nodes)

Box {

}

Eine VRML-Datei besitzt eine Baumstruktur ( Szenegraph ).

Jeder Knoten

Eingehende Ereignisse werden durch das Schlüsselwort set_   (set_color, set_position) und ausgehende Ereignisse durch das Schlüsselwort _changed beschrieben (color_changed, position_changed).

Über das Schlüsselwort DEF kann einem Knoten ein Name zugewiesen werden, der dann von einem anderen Knoten über das Schlüsselwort USE referenziert werden kann.

So ist es zum Beispiel möglich einer Box eine Farbe zuzuweisen und diesen Farbknoten zu benennen (Box1 ..... material DEF ROT Material...). Bei der Deklaration einer weiteren Box kann man dann auf diese Farbeigenschaft über USE zugreifen (Box2 ..... material USE ROT). Eine Änderung der Farbe der ersten Box zieht natürlich eine Änderung der Farbe der zweiten Box mit sich, da es sich um eine Referenzierung handelt.

Es ist wichtig, daß man seine Knoten benennt, da man so später durch die Verbindung der Knoten mit ROUTES eine Ereignisweiterleitung ermöglicht.

Man kann sich das folgendermaßen vorstellen:

"Angenommen man hätte einen Schalter, ein Kabel und eine Lampe. Würde man auf den Schalter drücken ohne vorher das Kabel mit dem Schalter und der Lampe zu verbinden, würde rein gar nichts passieren."


Felder

Box { height 2.0

}

Felder beschreiben Knotenattribute, d.h. sie sind vergleichbar mit den Variablen einer Programmiersprache.

Jedes Feld besitzt

Werden bei der Knotendeklaration Felder nicht parametrisiert, werden automatisch die dafür in der Spezifikation festgelegten Default-Werte genommen.

Felder werden weiterhin untergliedert in

ExposedFields können folgendermaßen beschrieben werden.

Die Deklaration von einem

    exposedField Name

ist äquivalent zu

    eventIn set_Name

    field Name

   eventOut Name_changed

 

event.jpg (16950 Byte)

Wenn z.B. ein Script-Knoten den Feldinhalt eines exposedField Name ändern will, kann man sich das folgendermaßen vorstellen:


Gruppenknoten

Gruppenknoten fassen mehrere Kind-Knoten zusammen Damit lassen sich komplexe Objekte beschreiben, die aus mehreren Geometrie-Knoten (Shapes) zusammengesetzt sind (Box, Sphere etc.). Man könnte natürlich auch alle Knoten (aus denen ein komplexes Gebilde besteht) einzeln deklarieren. Der Nachteil dabei wäre aber, daß man bei einer Bewegung des ganzen Objektes die Position der Knoten einzeln verändern müßte. Wenn allerdings die Position eines Gruppenknotens verändert wird, ändern sich automatisch alle Kind-Knoten relativ zum Gruppenknoten mit.

Es gibt folgende Gruppenknoten:

Hyperlinkfunktion zu anderen VRML-Welten
Ändern des lokalen Koordinatensystems in Abhängigkeit zur Bewegung des Benutzers
Kollisionserkennung
Gruppierungsknoten
Translation / Rotation / Skalierung von Objekten
Inhalt von anderen VRML-Dateien in den Quelltext einbinden
Level of Detail (steuert den Detailierungsgrad eines Objektes in Abhängigkeit von der Entfernung des Betrachters zum Objekt).
Beinhaltet mehrere Knoten, von denen jedoch nur einer angezeigt wird (je nach Auswahl).

Einer der am häufigsten verwendeten Gruppenknoten ist der Transform-Knoten. Wird z.B. ein neues Geometrie-Objekt erzeugt, so wird es im Mittelpunkt der VRML-Welt (Koordinaten 0 0 0) plaziert.

Über den Transform-Knoten wird es ermöglicht, die Position des Objektes relativ zum Vorgänger (in der Hierarchie) zu setzen/verändern - das betrifft natürlich auch die Kinder, die ein Knoten hat. Dieser Knoten ermöglicht auch die Rotation und Skalierung von Objekten.

Beschreibung


Blatt-Knoten

Blatt-Knoten bilden die untersten Ebenen eines Szenegraphen. Sie können keine Kinder mehr erzeugen, d.h. sie bilden die Endpunkte (Blätter) einer Baumstruktur (des Szenegraphen).

 

Die Objekte in einer VRML-Welt bestehen aus Shapes, die durch ihre Geometrie-Eigenschaft (geometry) und ihr Erscheinungsbild (apperance) beschrieben werden.

So ist es möglich entweder einfache geometrische Objekte (Box, Cone, Cylinder, Sphere) oder auch komplexere Gebilde wie Extrusionen (Extrusion) oder Verbundobjekte (IndexedFaceSet ...) zu erzeugen und diesen dann ein bestimmtes Erscheinungsbild zu geben (Materialeigenschaften [Farbe, Transparenz, Spiegelung] oder Oberflächeneigenschaften [Texturen]).

 

Mit Sound-Knoten kann die gesamte Soundkulisse definiert werden (Intensität, Richtung etc.) bzw. es können Musik / Samples abgespielt werden.

 

Über Sensoren ist es möglich Benutzereingaben zu erkennen, um dann Ereignisse auszulösen, die eine Veränderung der Welt herbeiführen sollen (Interaktivität).

 

 

Interpolatoren bieten eine einfache Möglichkeit Animationen durch Interpolation zu erzeugen.

 

Die unabhängigen Knoten haben vielfältige Eigenschaften. Sie definieren z.B. Lichtquellen, ermöglichen es verschiedene Kamerapositionen festzulegen, zwischen denen der Benutzer wechseln kann, oder erstellen einen Hintergrund für die Welt (Boden, Himmel etc.).
Der Script-Knoten letztendlich ist die Ein-Ausgabeschnittstelle für Script- bzw. Programmiersprachen.

Beispiel 1

Code

Beispiel


Sensoren, Routes & Events

Route´s

Eine ROUTE bildet eine explizite Verbindung zwischen zwei Feldern von zwei Knoten

Durch diese Verbindung können Ereignisse ( Events ) zwischen den verbundenen Knoten transportiert werden.

Voraussetzung

 

Zugriffsrechte

  • field
kein externer Zugriff möglich
  • eventIn
Schreibrechte
  • eventOut
Leserechte
  • exposedField
Lese - und Schreibrechte

 

Schreibweise

ROUTE fromNode.eventOutField TO toNode.eventInField

So wird ein Knoten (fromNode), der ein Ereignis senden kann, mit einem anderen Knoten (toNode), der ein Ereignis empfangen kann, verbunden.

ROUTES können in jeder beliebigen Reihenfolge im Quelltext stehen, jedoch müssen erst die zu verbindenden Knoten ( mit DEF ) benannt worden sein.

Ein Knoten kann auch mit mehreren ROUTES verknüpft sein, d.h. es können mehrere Verbindungen von einem Knoten wegführen (fan-out) oder mehrere Verbindungen zu einem Knoten hinführen (fan-in).

 

Sensoren

Sensoren reagieren auf das Eingabemedium des Anwenders und erzeugen so Ereignisse, die Veränderungen in der VRML-Welt zur Folge haben.

Man unterscheidet dabei folgende Sensoren

  • CylinderSensor
erlaubt eine zylindrische Rotationsbewegung des Objektes um seine Y-Achse
(isActive, rotation_changed)
  • PlaneSensor
erlaubt eine Verschiebung des Objektes in der X-Y Ebene
(isActive, translation_changed)
  • ProximitySensor
wird ausgelöst, wenn sich der Benutzer dem Sensor nähert
(enterTime, isActive, exitTime)
  • SphereSensor
erlaubt eine Rotationsbewegung um alle Achsen
(isActive, rotation_changed)
generiert Zeitereignisse, die zyklisch ausgelöst / gesendet werden
  • TouchSensor
reagiert auf die Berührung durch das Eingabemedium
(isOver, isActive, touchTime)
  • VisibilitySensor
überprüft, ob ein Objekt sichtbar ist oder nicht. Dadurch werden nur die Objekte berechnet, die sichtbar sind (CPU-Entlastung).
(enterTime, isActive, exitTime)

 

Ein Sensor ist allerdings kein Guppenknoten, sondern ein Blatt-Knoten und wird immer in der Gruppe plaziert, in der das Shape-Objekt deklariert wird, an das er gebunden werden soll. Ist ein Sensor an einen Gruppenknoten gebunden, dann reagieren auch alle Kinder dieses Knotens auf den Sensor.

Wenn sich unterschiedliche Sensoren im selben Gruppenknoten befinden, so reagieren sie alle auf einmal.

 

Ereignisse

Ereignisse ( Events ) werden über Sensoren erzeugt. Das geschieht entweder über den Anwender, indem er einen Sensor auslöst, oder durch ein zyklisch generiertes Event von einem TimeSensor.

Ereignisse setzen sich aus 2 Werten zusammen:

Der Zeitstempel speichert den Zeitpunkt, an dem das Event erzeugt worden ist. So wird die Reihenfolge festgelegt, in der die Events abgearbeitet werden.


Beispiel 2

Code

Beispiel


Interpolatoren

Mit Interpolatoren lassen sich in VRML ohne großen Aufwand Animationen erzeugen.

Man legt Start- Zwischen- und Endwerte fest und VRML berechnet die Zwischenschritte. Eine Berechnung erfolgt in einem bestimmten Zyklus - immer genau dann, wenn ein TimeSensor ein set_fraction Event an einen Interpolator routet. Der Interpolator vergleicht dann den erhaltenen Zeitwert mit der Schrittliste [key list], berechnet den Rückgabewert und sendet dann ein value_changed Event, an das zu animierende Objekt.

 

  • ColorInterpolator
wandelt Zeitereignisse in Farbänderungen um.
(Material node - set_diffuseColor, set_emissiveColor)
  • CoordinateInterpolator
Interpolationsmethoden, die mehrere Rückgabewerte liefern.
  • NormalInterpolator
  • OrientationInterpolator
wandelt Zeitereignisse in Rotationsbewegungen um.
(Transform node - set_rotation)
  • PositionInterpolator
wandelt Zeitereignisse in Translationen um.
(Transform node - set_translation, set_scale)
  • ScalarInterpolator
wandelt Zeitereignisse in Transparenz um.
(Material node - set_transparency)

Für eine Interpolation werden 2 Listen benötigt:

Beispiel (Zeitpunkte 0.0 und 1.0 sind vorgegeben)

Zeit Position
0.0 0.0  0.0  0.0 
  0.1 0.4  0.1  0.0
  0.2 0.8  0.2  0.0
  ... ...
1.0 4.0  1.0  0.0

PositionInterpolator {

key [ 0.0 , 1.0 ]
keyValue [ 0.0 0.0 0.0 , 4.0 1.0 0.0 ]

}


Beispiel Interpolatoren

Code

Beispiel


Benutzerdefinierte Knoten

PROTO / EXTERNPROTO

Bei Proto´s handelt es sich um benutzerdefinierte Knoten, die durch Instantiierung wiederverwendet werden können. (Konzept der Kapselung und Parametrisierung)

Dazu wird eine allgemeine Schnittstelle festgelegt, die aus mehreren Variablen bestehen kann.

PROTO KnotenName [

    field Datentyp Name Default
    exposedField Datentyp Name Default
    eventIn Datentyp Name
    eventOut Datentyp Name

                         ]

{ Quellcode }

Im Quellcode kann auf die in der Schnittstelle definierten Variablen über das Schlüsselwort IS zugegriffen werden.

Der Aufruf eines Prototyps erfolgt wie auch bei anderen Knoten durch Angabe des Namens gefolgt von einer Parameterliste in geschweiften Klammern.

KnotenName { Parameter }

 

Prototypen, die in anderen VRML-Dateien definiert sind, können auch importiert werden. Dazu muß lediglich die Schnittstelle des Prototypen (ohne Default-Werte) mit dem Schlüsselwort EXTERNPROTO angegeben werden, gefolgt von der URL, an der die Datei mit dem Prototypen zu finden ist.

EXTERNPROTO KnotenName [

    field Datentyp Name
    exposedField Datentyp Name
    eventIn Datentyp Name
    eventOut Datentyp Name

                         ]

"URL"

 

Index