Virtuelle Realität

Funktionale Modellierung in X3D

Dr. Thies Pfeiffer

AG Wissensbasierte Systeme, Technische Fakultät, Universität Bielefeld

Termin: Freitags, 10:15 Uhr

Raum: S2-121

Überblick

Inhalte dieser Veranstaltung

  • Umsetzung von funktionalen Elementen in der Simulation
  • Funktionale Modellierung in X3D
    • Einführung in die wesentlichen Techniken der funktionalen Modellierung
    • Felder
    • Routen
  • Scripting in X3D
    • Skriptknoten in JavaScript und Java
    • Externe Anbindung

Funktionale Modellierung - Stand der Vorlesung

Bisher

  • Modellierung von Geometrie, Vorlesungstermine 02 und 03
    • Punkte, Linien, Flächen
    • Einfache Objekte
    • Komposition von komplexeren Objekten über Transformationen
    • Einfacher Szenengraph
  • Modellierung von Geräuschen, Vorlesungstermin 04
    • Positionierung von 3D Sound über das Sound-Tag
  • Die bisherigen Modellierungen sind statisch und nicht interaktiv
    • Bis auf die vom Browser bereitgestellte Navigation

Funktionale Modellierung

Funktionale Modellierung

Warum benötigen wir eine funktionale Modellierung?

  • Unsere reale Welt verändert sich ständig und wir können Einfluß auf sie haben. Wenn eine virtuelle Welt natürlich vorkommen soll, dann sollte sie sich ebenfalls verändern und vom Benutzer verändert werden können.
  • Viele Sachverhalte, die mit Mitteln der Virtuellen Realität dargestellt werden sollen, sind in sich dynamisch.
  • Oft geht es z.B. um die Simulation von Prozessen mit Benutzer-Interaktion, z.B. bei Trainings oder Erprobungen. Dort muss sich die Situation dynamisch an die Entscheidungen des Benutzers anpassen.
  • Häufig werden sehr komplexe Daten dargestellt und daher ist während der Exploration der Daten eine Auswahl und Manipulation durch den Benutzer erforderlich, z.B. zur Auswahl von Kriterien als Filter für die Darstellung.
  • Inhalte, die bestimmten Mustern folgen, können über funktionale Modellierung einfacher/kompakter ausgedrückt werden (Design-Time Vorteil).

Funktionale Modellierung

Rahmenbedinungen

  • Die Darstellung der Virtuellen Welt erfolgt in diskreten Zeitschritten. Diese können für die unterschiedlichen Modalitäten verschieden sein
    • Framerate der visuellen Darstellung (Ziel: > 25 Hz)
    • Samplerate der auditiven Darstellung (Ziel: > 44 kHz)
    • Updaterate der taktilen Darstellung (Ziel: > 1 kHz)
  • Die funktionale Modellierung muss diesen Umstand berücksichtigen und sollte für eine entsprechende konsistente Aktualisierung der Weltbeschreibung sorgen.
    • Entkopplung von Simulationszeit und Framerate: nur so kann die Simulation auch unter ungünstigen Bedingungen noch valide Ergebnisse zeigen, wenn auch dann vielleicht nicht mehr in interaktiven Frameraten.

Funktionale Modellierung in X3D

Der Szenengraph von X3D

X3D Szenengraph

  • X3D ist eine objektorientierte Szenenbeschreibungssprache (ähnlich wie Java3D, VRML, OpenInventor)
  • Graphische Darstellung umfasst vier Basisknoten
    • Wurzelknoten/root: Die Basis des Szenengraphen. Es kann nur einen geben!
    • Gruppenknoten: Fassen eine beliebige Anzahl an Knoten zusammen, die sog. Kinder/Children
    • Kindknoten: Sind keine Gruppenknoten, können aber eine Komposition einzelner Objektknoten umfassen (Bsp: Shape)
    • Objektknoten: Sind keine Kindknoten oder Gruppenknoten und haben selbst auch keine untergeordneten Knoten mehr (Bsp. ImageTexture)
Basis-Knotentypen für die Darstellung von X3D Szenengraphen

Der Szenengraph von X3D

X3D Szenengraph: Beispiel

Einfaches Beispiel für einen Szenengraphen in X3D

Der Szenengraph von X3D

X3D Szenengraph: Felder

  • Knoten in X3D besitzen Felder
  • Einige haben wir schon genutzt, aber noch nicht kennen gelernt
    • children
    • geometry
    • Die Hierarchie des X3D-XML Dokumentes wird also auf Felder der X3D Knoten abgebildet.
  • Andere haben wir schon genutzt
    • Transform:translation
    • Transform:rotation
    • Transform:scale
Beispiel für einen Szenengraphen in X3D mit Darstellung der versteckten Felder

Der Datengraph: Felder

Der Datengraph

  • Orthogonal zum Szenengraph lässt sich in X3D ein Datengraph definieren.
  • Im Datengraph werden einzelne Felder miteinander verbunden (Ausgangsfeld $\to$ Zielfeld).
  • Eine Änderung des Feldinhalts im Ausgangsfeld wird dann in das Zielfeld übertragen (aber nicht automatisch auch umgekehrt).
  • Um die Verbindungen syntaktisch abzusichern, werden für jedes Feld Zugriffsrechte und Typ festgelegt.
Beispiel für einen Datengraph in X3D: die rotation-Felder der beiden Transformationsknoten werden verbunden, so dass die lokale (!) Rotation der Box stets auch auf die Sphere übertragen wird. Dies gilt jedoch nicht umgekehrt!

Der Datengraph: Felder

Zugriffsrechte

  • inputOnly: nur schreibender Zugriff
  • outputOnly: nur lesender Zugriff
  • inputOutput: schreibender und lesender Zugriff
  • initializeOnly: schreibender Zugriff nur bei Initialisierung des Knotens

Typen

  • Unterscheidung in Single-Fields (SF) und Multi-Fields (MF), letztere mit einfacher Array-Syntax
  • Folgende Typen sind definiert:
    • SFBool/MFBool, SFFloat/MFFloat, SFDouble/MFDouble, SFColor/MFColor, SFColorRGBA/MFColorRGBA, SFInt32/MFInt32, SFString/MFString, SFTime/MFTime
    • SFRotation/MFRotation, SFVec2f/MFVec2f, SFVec3f/MFVec3f
    • SFImage/MFImage, SFNode/MFNode

Der Datengraph: Routen

Felder verknüpfen: Routen

  • Die Verknüpfung der Felder geschieht durch Routen
  • Syntax: <ROUTE fromNode="" fromField="" toNode="" toField=""/>
  • Beispiel:
    <Transform DEF="T1" rotation="1 0 0 0.75"/>
    <Transform DEF="T2"/>
    <ROUTE
      fromNode="T1" fromField="rotation"
      toNode="T2" toField="rotation"/>
  • Routen sind keine Knoten des Szenengraphen (als Kennzeichnung komplett groß geschrieben), ihre Spezifikation wird direkt umgesetzt.
  • Daher wichtig: Die Route muss nach den Bezugsknoten definiert werden, da sonst die Referenzen unbekannt sind!

Der Datengraph: Animationen

Animationen mit dem Datengraph: TimeSensor

  • Neben Knoten zur Geometrie-Beschreibung gibt es in X3D auch Knoten, die Funktionen für den Datengraph bereitstellen.
  • Wichtigste Knoten für die Animation sind TimeSensor und Interpolatoren (nächste Seite)
  • Syntax: <TimeSensor
    • fraction_changed (SFTime, outputOnly): Wert zwischen 0 und 1.0, 0 beim Start, 1.0 bei Erreichen von cycleInterval nach dem Start
    • cycleInterval (SFTime, inputOutput): Dauer der Animation
    • loop (SFBool, inputOutput): Wenn gesetzt, unendliche Wiederholung, startet dann auch den TimeSensor
    • startTime (SFTime, inputOutput): wenn kleiner aktueller Zeit, startet der TimeSensor
    />

Der Datengraph: Animationen

Animationen mit dem Datengraph: Interpolatoren

    • Wichtige Interpolatoren: PositionInterpolator, OrientationInterpolator, ScalarInterpolator, ColorInterpolator ...
    • Syntax: <PositionInterpolator
      • set_fraction (SFFloat, inputOnly): Wert zwischen 0 und 1.0, als Index in die Schlüsseltabelle (Bsp. 0.7)
      • key (MFFloat, inputOutput): Schlüsseltabelle mit den Schlüsseln, muss gleiche Anzahl an Einträgen wie keyValue haben (Bsp. 0 0.5 1.0)
      • keyValue (MFVec3f, inputOutput): Schlüsselwerte, hier Vec3f (Bsp. 0 0 0, 1 0 0, 0 0 0)
      • value_changed (SFVec3f, outputOnly): aktueller Wert, ergibt sich als Wert in keyValue an der Position in key ab der noch set_fraction > key gilt (Bsp. 1 0 0)
      />

Der Datengraph: Interaktionen

Animationen mit dem Datengraph: Interaktionen

    • "Sensoren" zur Interaktion mit dem Benutzer: TouchSensor, PlaneSensor, CylinderSensor, SphereSensor, KeySensor, StringSensor
    • Syntax: <TouchSensor
      • isOver (SFBool, outputOnly): Wert true wenn Maus über Geometrie
      • isActive (SFBool, outputOnly): Wert true wenn Maus über Geometrie und Mausbutton geklickt
      • touchTime (SFTime, outputOnly): Zeitpunkt des letzten Klicks
      />
    • Routed man isActive in das loop Feld eines TimeSensors oder touchTime in startTime eines TimeSensors, so wird dieser gestartet und läuft mehrfach oder einfach durch.

Download als X3D-Datei

Dieses Beispiel in X3DOM ist derzeit (14. November 2011) nicht funktionsfähig, da die aktuelle Version von X3DOM keinen TouchSensor unterstüzt und der TimeSensor nicht das Standardverhalten zeigt. Eigentlich dürfte sich der Block nicht bewegen. Das Beispiel sollte jedoch im InstantPlayer laufen, dazu müssten die Tags jedoch alle mit einem Großbuchstaben anfangen und ROUTE ganz groß geschrieben werden.

Scripting

Der Script Knoten

  • Neben den Möglichkeiten des Datengraphen bietet X3D noch einen Script Knoten der entweder durch JavaScript oder durch Java implementiert werden kann.
  • Syntax: <Script
    • url (MFString, inputOutput): Array mit URLs zum Script-Code (falls nicht JavaScript inline als CDATA verwendet wird)
    • directOutput (SFBool, initializeOnly): Sollte auf true gesetzt werden, falls das Skript anders als durch Routen den Szenengraphen modifiziert.
    • mustEvaluate (SFBool, initializeOnly): Sollte auf true gesetzt werden, falls das Skript auf jeden Fall direkt ausgeführt werden soll und keine Werte für ein Batch-processing gecached werden dürfen.
    />

Scripting: JavaScript

Scripting mit JavaScript

  • Typischer Aufbau
    • function initialize() {}: wird beim Initialisieren des Scripts aufgerufen
    • function prepareEvents() {}: wird vor der Verarbeitung eingehender Events aufgerufen
    • function eventsProcessed() {}: wird nach der Verarbeitung eingehender Events aufgerufen
    • function shutdown() {}: wird beim Beenden des Scripts aufgerufen
  • Für jedes Skript können eigene Felder definiert werden
    • z.B. <field name="NAME" type="SFInt32/..." accessType="inputOnly/..."/>
    • Für jedes outputOnly-Feld wird eine entsprechend benannte Variable zur Ausgabe bereitgestellt
    • Für jedes inputOnly-Feld kann eine function NAME( value, timestamp ) {} definiert werden
    • Für jedes inputOutput-Feld wird eine les- und schreibbare Variable NAME bereitgestellt
    • Für jedes initializeOnly-Feld wird eine lesbare Variable NAME bereitgestellt

Scripting: JavaScript

Beispiel für Scripting mit JavaScript


<Script DEF="myAdd" mustEvaluate="true" directOutput="false">
 <field name="inA" type="SFInt32" accessType="inputOnly"/>
 <field name="inB" type="SFInt32" accessType="inputOnly"/>
 <field name="outResult" type="SFInt32" accessType="outputOnly"/>
 <![CDATA[
  ecmascript:
   var a, b;
   function initialize() {
   	a = 0; b = 0;
   }
   function inA( value, timestamp ) { a = value;  }
   function inB( value, timestamp ) { b = value;  }
   function eventsProcessed() {
   	outResult = a + b;
   }
 ]]></Script>
				
Download als X3D-Datei

Scripting: Java

Java als Scriptsprache

  • Java kann als Scriptsprache verwendet werden
  • Nicht inline, nur über Verweis auf Klassendatei (.class) über url-Feld
  • Deklaration der Felder wie bei JavaScript-Skriptknoten
  • Zugriff auf die Felder durch explizite API: SAI (Beispiel folgt)
  • Entsprechend wird ein Java-Interface benötigt, bei InstantReality instantreality.jar (meist im Bin-Verzeichnis der Installation)
    • Interface angelehnt an den Vorgänger für VRML
    • Packages vrml, vrml.field, vrml.node

Scripting: Java

Das Java Interface

  • Aufbau ähnlich dem JavaScript Interface
    • public void initialize() {}: wird beim Initialisieren des Scripts aufgerufen
    • public void prepareEvents() {}: wird vor der Verarbeitung eingehender Events aufgerufen
    • public void eventsProcessed() {}: wird nach der Verarbeitung eingehender Events aufgerufen
    • public void shutdown() {}: wird beim Beenden des Scripts aufgerufen
  • Zusätzlich noch
    • public void processEvent(Event e) {}: wird jedesmal aufgerufen, wenn ein Feldwert geändert wird

Scripting: Java

Beispiel für Scripting mit Java, analog zum JavaScript Beispiel


public class MyAddNode extends vrml.node.Script {
  int a, b;
  SFInt32 output;
  public void initialize() {
    a = 0; b = 0;
    output = (SFInt32) getEventOut("outResult");
  }
  public void processEvent(vrml.Event event)
  {
    if( event.getName().equals("inA") ) {
      a  = ((ConstSFInt32) event.getValue()).getValue();
    }
    if( event.getName().equals("inB") ) {
      b  = ((ConstSFInt32) event.getValue()).getValue();
    }
  }
  public void eventsProcessed() {
    output.setValue( a + b );
  }
}
				

Scripting: Java

Was gilt es zu beachten? Typische Probleme mit Java als Scriptsprache

  • Jeder Java-Skriptknoten läuft in eigener Sandbox mit eigenem Classloader (zumindest in InstantReality)
    • Problematisch bei der Verwendung von JNI
    • Achtung bei der Verwendung von Singletons und anderen statischen Variablen! Zwischen den Knoten kann damit keine Kommunikation abgewickelt werden.
  • Da Java-Skriptknoten in der Sandbox laufen, müssen Ausnahmen, wie für den Zugriff auf das Dateisystem oder das Öffnen von Ports, explizit in der java_policy freigegeben werden.
  • Die Aufrufe der Knoten-Interfacefunktionen (initialize, shutdown, processEvent, ...) erfolgen im Thread des jeweiligen X3D Browsers
    • Direkte Zugriffe auf Knoten/Felder und das Browser-Objekt sind nur in diesem Thread erlaubt!
    • Zugriffe aus anderen Java-Threads (die möglich sind) können im besten Fall das System stark ausbremsen, im schlimmsten Fall jedoch zu Speicherfehlern und Ausnahmen führen.
    • Dies gilt insbesondere für System.out/err Aufrufe, die in die Console im Browser umgeleitet werden.

Scripting: Remote

Andocken externer Prozesse

  • Über das VRML External Authoring Interface (EAI) können auch externe Prozesse angedockt werden
  • In der X3D Spezifikation gibt es auch das X3D Scene Access Interface (SAI), welches aber von InstantReality noch nicht unterstüzt wird
  • InstantReality bietet Implementierungen des EAI für Java und .net (C#, Visual Basic, etc.)
  • API ähnlich der des Skriptknotens, aber nun wird kein *neuer* Knoten implementiert!
  • Erster wesentlicher Schritt ist die Herstellung der Verbindung zum X3D Browser
java.net.InetAddress address = java.net.InetAddress.getByName("mypc");
vrml.eai.Browser browser = vrml.eai.BrowserFactory.getBrowser(address, 4848);
vrml.eai.Node scriptNode = browser.getNode("myAdd");				
vrml.eai.field.EventOutSFInt32 result = 
    (vrml.eai.field.EventOutSFInt32)scriptNode.getEventOut("outResult");
				

Scripting: Möglichkeiten

Weitere Möglichkeiten des Scriptings über Java/JavaScript

  • Bislang nur Zugriff auf den Szenengraph gesehen
  • Es können aber auch neue Routen über Browser.addRoute() angelegt werden
  • Erstellen von neuen Teilgraphen über Browser.createVrmlFromString()
    • Aber nur in alternativer VRML-Syntax möglich
    • Kann aber über Kommandozeilen-Tool aopt oder online mittels Konverter aus X3D Dateien gewonnen werden

Scripting: Weitere Möglichkeiten

Alternativen

  • Distributed Interactive Simulation (DIS)
    • IEEE Standard für physikalische verteilte Simulationen
    • wird z.B. in militärischen Simulationen verwendet
    • von InstantReality derzeit keine volle Unterstützung
  • Remote JavaScript/AJAX
    • Unter Verwendung von XMLHttpRequest in einem JavaScript-Skriptknoten können JavaScript Fragmente im AJAX-Stil von einem externen Server geladen werden.
  • Szenengraph ganz/teilweise überschreiben
    • Bei einer Benutzerinterkation könnte der Szenengraph auch teilweise/vollständig ersetzt werden
    • Dabei wird der neue Graph dann den alten ersetzen
    • Die Veränderungen können dann extern mit beliebiger Sprache erstellt werden
    • Alternative für komplexe Modelländerungen bzw. die Anbindung externer Software

Zusammenfassung

Zusammenfassung

Inhalte dieser Veranstaltung

  • Umsetzung von funktionalen Elementen in der Simulation
  • Funktionale Modellierung in X3D
    • Einführung in die wesentlichen Techniken der funktionalen Modellierung
    • Felder
    • Routen
  • Scripting in X3D
    • Skriptknoten in JavaScript und Java
    • Externe Anbindung

Ausblick

Termin 06 - Interaktion

  • Basisinteraktionen
    • Navigation
    • Selektion
    • Manipulation
  • Evaluation von Interaktionstechniken
  • Anbindung von Geräten
  • InstantIO: Integration von Geräten in den Szenengraphen mit X3D