DOC

Java 3D Seminardoc - Java 3D Seminar

By Gerald Carroll,2014-04-24 11:54
8 views 0
Java 3D Seminardoc - Java 3D Seminar

    Java 3D Seminar

    Interaktionen

    Henrik Hofmann

    henner_ho@gmx.de

    Copyright (c) 2002 Henrik Hofmann

     Permission is granted to copy, distribute and/or modify this document

     under the terms of the GNU Free Documentation License, Version 1.1

     or any later version published by the Free Software Foundation;

Vorwort

    Dieses Dokument bietet einen Überblick über die Einsatzmöglichkeiten der Java 3D Animations- und Interaktionstechniken. Es beschreibt zunächst die Konzepte und Einsatzmöglichkeiten und bietet einen Einstieg in die Programmierung von Interaktionen in Java 3D. Dabei wird jedoch kein Anspruch auf Vollständigkeit erhoben. Sollte ein näheres Interesse zu den vorgestellten Themen bestehen empfehle ich die Quellen am Ende des Dokumentes.

    In Ihnen wird die Thematik ausführlich behandelt und kann als Referenz für alle Java3D betreffenden Fragen angesehen werden.

1. Grundlagen der Interaktion

    Bisher bestand die Welt von Java 3D aus nahezu statischen Objekten. Um dies zu ändern sind Interaktion und Animationen nötig.

    Interaktion bezeichnet die Reaktion auf Einflüsse von Außen wie zum Beispiel dem Benutzer. Von Animation spricht man wenn sich der visuelle Zustand ändert, ohne dass der Benutzer eingreift. Solche Ereignisse werden zum Beispiel durch den Verlauf der Zeit ausgelöst.

    Um das oben beschriebene Verhalten zu modellieren wird bei Java 3D die Klasse Behavior verwendet.

    Die Klasse Behavior ist eine abstrakte Klasse. Sie beinhaltet Schnittstellen zur Beeinflussung des Scenegraphs.

    Mit einem Behaviorobjekt wird der Scenegraph in Reaktion auf ein Ereignis (Stimulus) beeinflusst. Eine Stimulanz kann zum Beispiel das drücken einer Taste oder die Bewegung der Maus sein. Diese Beeinflussung kann zum Beispiel das hinzufügen oder Entfernen von Objekten aus dem Scenegraph sein. Die Möglichkeiten werden nur durch die Begrenzungen des Scenegraphs beeinflusst.

    Ein Behavior bildet die Verbindung zwischen Ereignis und Reaktion.

    Folgende Tabelle kategorisiert die Kombinationen aus Aktion und Reaktion.

    Transform Stimulus Geometry Scene Graph View Group

    Interaktion anwendungsspezifisch anwendungsspezifisch Navigation Benutzer

    Objekte Objekte ändern Objekt verschwindet ändern View ändert sich Aussehen durch oder erscheint durch Kollision Orientierung durch Kollision Kollision Kollision oder Ort

    Animation Animation Animation Animation Zeit

     View billboard Level of detail anwendungsspezifisch anwendungsspezifisch Location

    Diese Tabelle bildet keine vollständige Auflistung aller Kombinationsmöglichkeiten. Einige wurden bereits beschrieben, anderen können auch unbekannt sein. Auf 2 möchte ich hierbei näher eingehen.

    Billboard: Bei dieser Technik werden sehr komplexe Objekte wie zum Beispiel Bäume oder Pflanzen durch Texturen ersetzt. Damit diese jedoch realistisch für den Anwender sichtbar sind, müssen sie immer senkrecht zum Betrachter stehen. Diese Ausrichtung erfolgt durch ein Behavior.

Level of detail:

    Mit der Level of detail Technik ändert man die Komplexität grafischer Objekte in Abhängigkeit ihres Abstands zum Betrachter. Dadurch lässt sich die Leistungsfähigkeit des Systems enorm steigern.

    Eine weiteren Überblick zum Einsatz von Behaviorobjekten bietet folgendes Diagramm. So basieren zum Beispiel auch die Interpolator Klassen die beispielsweise zur Erzeugung kontinuierlicher Drehungen verwendet werden.

    2. Die Klasse javax.media.j3d.Behavior

    Im vorherigen Abschnitt wurden die verschiedenen Anwendungsmöglichkeiten der Behavior Klasse beschrieben. Um diese richtig ausnutzen zu können ist es unbedingt erforderlich die programmiertechnischen Aspekte zu verstehen. Dieser Abschnitt soll sie näher erläutern. Dazu werde ich zunächst die Schnittstellen beschreiben. Danach werde ich in einem kleinen Beispiel exemplarisch die Implementierung beschreiben.

public void intialize()

    Über diese Methode lässt sich das Behavior Objekt initialisieren. Für gewöhnlich werden dabei die Ereignisse angemeldet auf die das Behavior Objekt reagieren soll. Um zum Beispiel auf einen Tastaturanschlag zu reagieren müsste in der eigenen Behavior Klasse folgender Code geschrieben werden.

public void initialize(){

     this.wakeupOn(new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED))

    }

public void processStimulus(Enumeration criteria)

    Über diese Methode werden auftretende Events/Stimuli bearbeitet. Dabei können bei einem Methodenaufruf auch mehrere Events gleichzeitig auftreten. Beispielsweise wenn 2 Tasten zur gleichen Zeit oder in Kombination mit der Maus gedrückt werden. Daher ist es nötig, sofern mehrere Eventtypen angemeldet wurden, zu überprüfen welches Event aufgerufen wurde.

public View getView()

    Diese Methode gibt den mit dem Behaviorobjekt assoziierten View zurück

void setEnable(boolean state)

Aktiviert bzw. Deaktiviert das Verhalten

void setSchedulingBoundingLeaf(BoundingLeaf region)

    void setSchedulingBounds(Bounds region)

    Über diese beiden Methoden werden die Bounds/Grenzen definiert: Wird das Event der hier definierten Region ausgelöst wird es asugeführt.

void wakeupOn(WakeupCondition crtiteria)

    Über diese Methode werden die Events/Stimuli definiert auf die das Behaviorobjekt reagiert.

    Die zu übergebenden Objekte sind vom Typ WakeupCondition. Im nächsten Kapitel werden diese näher beschrieben.

Es folgt ein kurzes Praxis Beispiel in dem ein einfaches, aber vollständiges Behavior erzeugt

    wird. Im zweiten Codeabschnitt wird gezeigt wie dieses Behavior im Scenegraphen

    eingebunden wird.

    Um das Beispiel auszuführen starten Sie bitte BehaviorExample1.

     public MyBehavior(Transf ormGroup t) { this.tg = t; } //Initialisierung des Behavior public void

    initialize() {

     //Das

    WakeupKriterium

    wird erzeugt

     criterion

    = new

    WakeupOnElapsedTi

    me(15);

//Kriterium wird

    angemeldet

wakeupOn(criterio

    n);

     }

     public void

    processStimulus(j

    ava.util.Enumerat

    ion enumeration)

    {

//Algorithmus zur

    Berechnung der

    Verschiebung

if(leaving &&

    dist < -30)

     {

     step = 0.2f;

leaving = false;

     public BranchGroup createSceneGraph() {

     // Create the root of the branch graph

     BranchGroup objRoot = new BranchGroup();

     //Grundverschiebung nach hinten für beide Würfel

     TransformGroup translation1 = new TransformGroup();

     Transform3D translate1 = new Transform3D();

     translate1.setTranslation(new Vector3d(0,0,0));

     translation1.setTransform(translate1);

translation1.setCapability(TransformGroup.ALLOW_TRANSFORM_WR

    ITE);

     objRoot.addChild(translation1);

     //diese Transformgroup wird bearbeitet-

     translation1.addChild(new ColorCube());

     //Erzeugen des Behaviors

     MyBehavior mbh = new MyBehavior(translation1);

     //Setzen des Bereiches in dem das Behavior aktiv ist (Radius 100 um den Ursprung)

     mbh.setSchedulingBounds(new BoundingSphere(new

    Point3d(0.0d,0.0d,0.0d),100.0d));

     //einfügen des Behaviors ind Branchgraphen

     objRoot.addChild(mbh);

     //Erzeugen des Graphischen objektes und einfügen

    hinter der Transformgroup

     translation1.addChild(new ColorCube());

     objRoot.compile();

     return objRoot;

3. WakeupConditions

Die Klasse WakeupCondition biete 2 Methoden an.

Enumeration allElements()

Über diese Methode erhält man eine Enumeration aller in dieser WakeupCondition

    erhaltene Kriterien

Enumeration triggeredElements()

Gibt eine Enumeration aller ausgelösten WakeupKriterien zurück.

    Bei WakeupCriterion handelt es sich um ein Interface die von allen WakeupKriterien

    implementiert wird.

    Die Schnittstelle besteht lediglich aus der Methode,

    boolean hasTriggered()

    Diese Methode gibt true zurück falls das Event ausgelöst wird. Der

    Anwendungsprogrammierer muss aber für gewöhnlich nicht darauf zugreifen.

WakeupOnActivation Wird ausgelöst sobald die ViewPlatform

    in die vom Behavior definierten

    Grenzen eintritt

    WakeupOnAWTEvent Beim Auslösen eines AWT Events

WakeupOnBehaviorPost Wenn ein Event durch ein anderes

     Behaviorobjekt ausgelöst wird WakeupOnCollisionEntry Beim ersten Auftreten einer Kollision

     des spezifizierten Objektes mit einem

    anderen Objekt des Scenegraphen WakeupOnCollisionExit Wird ausgelöst sobald die beiden

     Objekte nicht mehr kollidieren WakeupOnCollisionMovement Wird ausgelöst wenn sich die Objekte

     bei der Kollision bewegen WakeupOnDeactivation Wird ausgelöst wenn die Viewplatform

     die spezifizierten Grenzen verlässt WakeupOnElapsedFrames Wird ausgelöst wenn eine bestimmte

     Anzahl von Frames verstrichen ist WakeupOnElapsedTime Wir ausgelöst wenn eine bestimmte Zeit

     verstrichen ist. Diese Zeit kann in

    Millisekunden angegeben werden WakeupOnSensorEntry Wird ausgelöst wenn ein Sensor in den

     vorher bestimmten Bereich eintritt. WakeupOnSensorExit Wird ausgelöst wenn ein Sensor aus dem

     vorher bestimmten Bereich austritt. WakeupOnTransformChange Wird ausgelöst wenn sich eine

     Transformation in einer vorher

    bestimmten Transformgroup ändert WakeupOnViewPlatformEntry Wird ausgelöst wenn Viewplatform in

     einen bestimmten Bereich eintritt WakeupOnViewPlatformExit Wird ausgelöst wenn Viewplatform aus

     einem bestimmten Bereich austritt

Im folgenden werde ich zwei wichtige Eventtypen näher erklären.

WakeupOnAWTEvent

WakeupOnAWTEvent Kriterien werden durch Ihren Konstruktor näher bestimmt. Dazu gibt

    es zwei Möglichkeiten.

Über den Konstruktor WakeupOnAWTEvent(int AWTId)

Dabei können unteranderem folgende Konstanten übergeben werden.

KeyEvent.KEY_TYPED

    KeyEvent.KEY_PRESSED

    KeyEvent.KEY_RELEASED

    MouseEvent.MOUSE_CLICKED

    MouseEvent.MOUSE_PRESSED

    MouseEvent.MOUSE_RELEASED

    MouseEvent.MOUSE_MOVED

    MouseEvent.MOUSE_DRAGGED

Nachteil dieser Technik ist, dass jeweils nur ein Event angemeldet werden

    kann.

    Ist es dennoch nötig mehrere Typen gleichzeitig anzumelden kann

    WakeupOnAWTEvent(long eventMask)

    verwendet werden.

    Dabei können unter anderem folgende Konstanten durch ein bitweises OR verbunden und an den Konstruktor übergeben werden.

KEY_EVENT_MASK

    MOUSE_EVENT_MASK

    MOUSE_MOTION_EVENT_MASK

    Wurde das WakeupKriterium initialisiert kann es nun in der processStimulus() Methode des Behaviorobjektes verwendet und ausgewertet werden.

Dazu wird die Methode AWTEvent[] getAWTEvent() verwendet werden.

    Trotzdem muss weiterhin, wenn auf AWT Elemente wie zum Beispiel Buttons reagiert werden soll, auf die AWT Eventbehandlung zurückgegriffen werden um einen Stimulus zu erzeugen. Dies geschieht zum Beispiel über MouseListener oder ActionListener.

    Beispielhaft stelle ich ein einfaches Behavior vor das lediglich auf einen Tastaturanschlag reagiert, jedoch keine Unterscheidung zwischen den Tasten trifft.

Um das Beispiel auszuführen starten Sie bitte BehaviorExample2.

     //WakeupKriterium

     private WakeupCriterion criterion;

     //Zu verschiebende TransformGroup

     private RotationInterpolator rip;

     private boolean rotating = true;

     /** Creates a new instance of MyBehavior2 */

     public MyBehavior2(RotationInterpolator r) {

     this.rip = r;

     }

     //Initialisierung des Behavior

     public void initialize() {

     //Das WakeupKriterium wird erzeugt

     criterion = new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED);

     //Kriterium wird angemeldet

     wakeupOn(criterion);

     }

     public void processStimulus(java.util.Enumeration enumeration) {

     //Wenn es sich dreht stoppen, ansonsten wieder starten

     if(rotating)

     {

     rip.setMaximumAngle(0f);

     rotating = false;

     }

     else

     {

     rip.setMaximumAngle((float) Math.PI*2.0f);

     rotating = true;

     }

     wakeupOn(criterion);

     }

     TransformGroup

     rotTranslation =

    new WakeupOnCollisionEntry

    TransformGroup(); WakeupOnCollisionExit WakeupOnCollisionMovement Transform3D

     rotTranslate =

    new

    Java 3D kann in seinem virtuellen Universum die Kollision Transform3D();

    von Objekten wahrnehmen.

    Es gibt 3 WakeupCriterion Klassen die dabei nützlich sind. rotTranslate.setT

     ranslation(new

    WakeupOnCollisionEntry, WakeupOnCollisionMovement, und WakeupOnCollisionExit. Vector3d(0,0,0));

Beim Einsatz dieser drei WakeupKriterien gibt es jedoch ein paar Punkte zu beachten die rotTranslation.se

    vielleicht nicht auf den ersten Blick ersichtlich sind. tTransform(rotTra

     nslate);

    WakeupOnCollisionEntry wird nur beim ersten Auftreten einer Kollision ausgeführt.

Die CollisionDetection ist eine sehr rechenintensive Technik. Um die Performance bei rotTranslation.se

    größeren 3D Welten zu erhalten ist es wichtig nur die benötigten Objekte dafür zu aktivieren. tCapability(Trans

     formGroup.ALLOW_T

    Deaktiviert bzw. aktiviert werden können alle Objekte die vom Typ Node abgeleitet sind. RANSFORM_WRITE);

     Dies geschieht über die Methode setCollidable(boolean collidable).

    translation1.addC

    hild(rotTranslatiWird dieser Wert für einen Knoten auf true bzw. false gesetzt wirkt sich dies auch auf alle

    on); Childknoten aus.

     Transform3D

    yAxis = new

    Transform3D();

     Alpha

    rotationAlpha1 =

    new Alpha(-1,

    4000); rotationAlpha1.se tIncreasingAlphaD uration(2000);

     RotationInterpola

     tor rotator =

     new

    Rotation Interpol

    ator(rot

    ationAlp

    ha1,

    rotTrans

    lation,

Report this document

For any questions or suggestions please email
cust-service@docsford.com