Index Weiter Zurück Literatur 

3.4 Dynamisches VRML

Eine dynamische Veränderung der Szenerie wird bei VRML durch einen "trigger" ausgelöst. Dieser trigger kann eine direkte Veränderung bewirken oder zunächst einem Programm übermittelt werden, welches weitere Aktionen veranlaßt.

Normalerweise ist ein Trigger ein Sensor der einen "Event" abschickt, sobald der Benutzer eine bestimmte Aktion ausführt (z.B. einen Schalter anklickt oder einen Bereich betritt).
Die Grundlage für das Zusammenspiel zwischen Trigger und anderen Nodes bilden "Routes". Diese definieren, welche Events von welchem Node an welchen Node verschickt werden sollen. Über eine Route kann z.B. direkt ein Feldwert eines Nodes verändert werden.
Für das Ansprechen der Felder ist es nötig, den Nodes mittels DEF Namen zuzuweisen. Dann kann man die Felder über Nodename.Feldname referenzieren.

Hier sollen einmal beispielhaft 3 Trigger vorgestellt werden:

Touchsensor/Proximity Sensor

Der Touchsensor generiert einen Event touchTime, sobald der Benutzer eine angegebene Geometrie anklickt (und die Maustaste wieder losgelassen hat!). Wird keine Geometrie angegeben, hat der Sensor keine Wirkung!
Der Proximity Sensor sendet Events, sobald der Betrachter in einen definierten Bereich eintritt (enterTime). Dieser Bereich wird als Box (Quader) festgelegt.

Beispiel:

#VRML V2.0 utf8

Group {
  children [
    DEF Schalter TouchSensor { }
    Shape {
      appearance Appearance {
        material Material {
          diffuseColor 0 0 1
        }
      }
      geometry Box {
        size 5 5 5
      }
    }
  ]
}
DEF Licht PointLight {
  on        FALSE
  intensity 1
  location  8 8 8
}
ROUTE Schalter.isOver TO Licht.on

Zuerst wird der Sensor zusammen mit der Sensorfläche (einem Würfel) in einem Group-Node kombiniert. Anschließend wird eine Lichtquelle definiert, die zunächst inaktiv ist (on=FALSE). Die ROUTE zwischen Sensor und Lichtquelle bewirkt, daß das Licht aktiviert wird, sobald sich der Mauszeiger über dem Sensor befindet (d.h. der Würfel wird angestrahlt). Hier erkennt man gut, wie die Nodenamen (Schalter, Licht) beim Routen eingesetzt werden.
Anmerkung: Bei diesem Beispiel muß das "Headlight" im Browser abgeschaltet werden, sonst ist der Effekt nicht zu sehen!

Die Routen einer Szenerie kann man sich grafisch in Diagrammen aufzeichnen:

 Routing 1

Der Proximity Sensor arbeitet im Prinzip wie der TouchSensor. Der Hauptunterschied besteht darin, daß der Proximity Sensor aktiv wird, sobald sich der Benutzer in einen definierten Bereich (quaderförmiger Bereich) der Szene hineinbewegt.
 

Timer

Im Gegensatz zu den bisher beschriebenen Triggern ist der Timer in der Lage nicht nur einmalige Events zu verschicken, sondern auch in periodischen Abständen veränderte Werte (Zeitfragmente) zu senden.
Der Timer sendet - sobald er aktiviert wurde - in periodischen Abständen Events, bis eine gegebene Zeit abgelaufen ist. Die Abstände zwischen den Events sind keine garantierten Zeiteinheiten, sie sollten sich aber nach den Abständen richten, in denen das Bild aktualisiert wird (Framerate).
Wird der Timer gestartet, beginnt er den Event fraction_changed im Intervall [0;1] hochzuzählen, bis die in cycleInterval angegebene Zeit verstrichen ist (Angabe ist in Sekunden). Es besteht auch die Möglichkeit, nach Ablauf der Zeit den Timer automatisch neu zu starten (loop TRUE), dies ist aber defaultmäßig nicht der Fall.

Beispiel:

#VRML V2.0 utf8

Group {
  children [
    DEF Schalter TouchSensor { }
    Shape {
      appearance Appearance {
        material Material {
          diffuseColor 0 0 1
        }
      }
      geometry Box {
        size 5 5 5
      }
    }
  ]
}
DEF Licht PointLight {
  on        TRUE
  intensity 0
  location  8 8 8
}
DEF Timer TimeSensor { cycleInterval 2 }
ROUTE Schalter.touchTime TO Timer.startTime
ROUTE Timer.fraction_changed TO Licht.intensity

Hier wird der Timer durch anklicken des Würfels  gestartet und schickt dann 2 Sekunden lang eine aufsteigende Zahlenfolge (von 0 - 1) an das intensity Feld des Light-Nodes. D.h. der Würfel wird innerhalb von 2 Sekunden langsam heller bis zur vollen Intensität.
Hier sieht das Routing wie folgt aus:

 Routing 2

Skripts

Über die Einbindung von Skripten lassen sich die statischen VRML Welten mit "Leben", d.h. im wesentlichen Animationen, füllen. Im Gegensatz zum einfachen Nachrichtenaustausch zwischen Nodes können Skripte eingegangene Events analysieren, entsprechende Aktionen / Berechnungen ausführen und ggf. nötige Events wieder abschicken.
Es lassen sich damit vollautomatisch ablaufende Animationen aufbauen, aber auch interaktive Welten erstellen. Ein Beispiel wäre eine Tür die mit einem Codeschloß versehen ist und nur dann aufgeht, wenn die korrekte Kombination angeklickt wurde.
In der VRML Spezifikation wird keine bestimmte Skriptsprache vorgeschrieben, aber man kann davon ausgehen, daß bekannte Sprachen wie Java und Javaskript von den gängigen Browsern verstanden werden.
Um ein Skript einzubinden, müssen im Script Node die url, sowie alle benötigten Felder und ein-/ausgehende Events deklariert werden. Anschließend kann -wie bei Triggern- über Routes mit dem Skript kommuniziert werden.

Beispiel:

#VRML V2.0 utf8

Group {
  children [
    DEF SensorA TouchSensor {}
    DEF SensorB TimeSensor {cycleInterval 5}
    DEF GravInterpolator Script {
      url "GravInterp.class"
      eventOut SFVec3f value_changed
      eventIn  SFTime  set_time
    }
    DEF TransformA Transform {
      translation 0 10 0
      children [
        Shape {
          appearance Appearance {
            material Material {
              ambientIntensity 0
              diffuseColor     1 0 0
              shininess        0.9
            }
          }
          geometry Sphere {radius 2.5}
        }
      ]
    }
  ]
}
ROUTE SensorA.touchTime TO SensorB.startTime
ROUTE SensorB.time TO GravInterpolator.set_time
ROUTE GravInterpolator.value_changed TO TransformA.translation

Dieses Beispiel erzeugt eine Kugel die, nachdem sie angeklickt wurde, 5 Sekunden lang nach unten "fällt" und dabei immer schneller wird (Gravitation). Da der Timer immer linear hochzählt, kann er hier nicht für die Bewegung der Kugel eingesetzt werden. Die Bewegung übernimmt in diesem Fall ein JAVA-Programm. Die Kommunikation mit dem Programm erfolgt über den Script Node. In diesem wird die URL des JAVA/JAVAScript Programms angegeben und die Felder eventIn / eventOut. EventIn gibt an, welche Werte an das Programm übergeben werden können (hier time), eventOut dementsprechend, was vom Programm an den Browser zurückgeliefert wird (hier value_changed, ein Feld mit 3 Werten für x,y,z).

Grafik des Routing:

Routing 3
 
Sobald die Kugel angeklickt wird, startet der TouchSensor den TimeSensor. Dieser schickt fortan 5 Sekunden lang in periodischen Abständen die aktuelle Zeit an das Script (JAVA-Programm). Das Script berechnet anhand der vergangenen Zeit (Differenz zur letzten Übermittlung des Timers) die korrekte Position der Kugel und schickt diese an den Transform Node.
 


Index Weiter Zurück Literatur