340 likes | 451 Views
Benutzer Interaktion (interaction):. die virtuelle Welt reagiert auf Benutzer Eingaben. Animation. die virtuelle Welt verändert sich im Laufe der Zeit Indirekte Auswirkungen von Benutzer Eingaben (billboard Verhalten). bewirkt. Stimulus. Änderung. Nicht im Tutorial:
E N D
Benutzer Interaktion (interaction): die virtuelle Welt reagiert auf Benutzer Eingaben Animation die virtuelle Welt verändert sich im Laufe der Zeit Indirekte Auswirkungen von Benutzer Eingaben (billboard Verhalten) bewirkt Stimulus Änderung
Nicht im Tutorial: Feststellen von Kollisionen
Reklametafel Verhalten (billboard = Reklametafel) sehr detaillierte Geometrien werden zu Texturen vereinfacht. Behavior sorgt dafür, daß die Tafel unabhängig vom Sichtwinkel immer senkrecht zum Beobachter steht LOD Verhalten Je näher der Betrachter den Dingen kommt, desto detaillierte visual object Geometrien werden verwendet. Behavior schaltet automatisch zwischen den unterschiedlichen Detaillierungsgraden (level of detail - LOD) um
Die Klasse Behavior Interaktion Animation
Verhaltensklassen selbst programmieren behavior ist abstrakte Klasse - aufgerufen wenn „live“ - Anfangstrigger Ereignis (WakeupCondition Objekt) spezifizieren Methode: wakeupOn(<WakeupCondition Objekt> ) -> drei Methoden implementieren: initialize processStimulus Konstruktor - aufgerufen wenn Trigger Ereignis, - Ereignis „entschlüsseln“, - „object of change“ ändern - Trigger erneut setzen !! - stellt Referenz zum „object of change“ her
import java.awt.event.*; import java.util.Enumeration; class SimpleBehavior extends Behavior{ private TransformGroup targetTG; private Transform3D rotation = new Transform3D(); private double angle = 0.0; SimpleBehavior(TransformGroup targetTG){ this.targetTG = targetTG; } void initialize(){ this.wakeupOn(new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED)); } void processStimulus(Enumeration criteria){ angle = angle + 0.1; rotation.rotY(angle); targetTG.setTransform(rotation); this.wakeupOn(new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED)); } }
Ausführungsbegrenzung (execution culling) Nur wenn sich activation volume der ViewPlatform und scheduling bonds des Behavior schneiden, wird das Verhalten ausgeführt Einfügen des Verhaltens Objekts in den Szene Graphen vrgl. folgendes Programmfragment
BranchGroup createSceneGraph() { BranchGroup objRoot = new BranchGroup(); TransformGroup objRotate = new TransformGroup(); objRotate.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); objRoot.addChild(objRotate); objRotate.addChild(new ColorCube(0.4)); SimpleBehavior myRotationBehavior = new SimpleBehavior(objRotate); myRotationBehavior.setSchedulingBounds(new BoundingSphere()); objRoot.addChild(myRotationBehavior); objRoot.compile(); return objRoot; } objRotate Objekt wird erst im Behavior eine rotierende TransformGroup !
Welches Problem könnte mit dieser „Aufhängung“ des Behavior Objekts auftreten, wenn nicht rotiert sondern translatiert wird ?
activation volume der ViewPlatform Bounds Objekt des Behavior Objekts scheduling Bereich Solange sich activation volume und scheduling Bereich schneiden, ist das Verhalten aktiv
activation volume der ViewPlatform Bounds Objekt des Behavior Objekts scheduling Bereich Würfel wird immer noch bewegt, selbst wenn er gar nicht mehr gesehen wird
activation volume der ViewPlatform Bounds Objekt des Behavior Objekts scheduling Bereich Würfel kann nicht mehr bewegt werden, obwohl der Benutzer ihn sehen kann
1. Lösung: 2. Lösung: Einsatz von BoundingLeaf void setSchedulingBoundingLeaf(BoundingLeaf bl)
Performanz Fallen „Memory Burn“: Unnötiges Erzeugen von Objekten. Bsp.: in processStimulus die Verwendung von new. Garbage Collector vernichtet alte Objekte -> Zeichnen wird unterbrochen Objekte nach Möglichkeit wiederverwenden. Unnötige Trigger Aufrufe Es gibt eine Methode, die den Trigger bei jedem Neuzeichnen des Bilds (rendering) aufruft. Dies ist oft nicht nötig.
Weitere Methoden von Behavior WakeupOnBehaviorPost void postId(int postId) Verkettet Behavior Möglichkeit Behavior auf inaktiv zu setzen, auch wenn es eigentlich aktiv ist void setEnable(boolean state) View getView() Es kann viele View Objekte geben, die das Verhalten aktivieren. Aber es gibt einen primaryView (der erste, der mit einer live Platform verknüpft wird). An diesem richtet sich das Verhalten (z.B. billboard) aus. getView liefert den primary View
Triggermechanismus eines Verhaltens KeyEvent.KEY_PRESSED „Trigger“ WakeupCondition Objekt: WakeupOnAWTEvent Behavior Objekt „Trigger“ processStimulus Methode wird ausgelöst
Behavior Objekt A Triggermechanismus zwischen verschiedenen Verhalten (Wache auf bei „Post“ vom Behavior) postID(1) Behavior Objekt B WakeupCondition Objekt: WakeupOnBehaviorPost „Trigger“ processStimulus Methode wird ausgelöst
Beispiel Tastendruck: -> Tür öffnet sich Erneueter Tastendruck: -> Tür schließt sich
class OpenBehavior extends Behavior{ private TransformGroup targetTG; private WakeupCriterion pairPostCondition; private WakeupCriterion AWTEventCondition; OpenBehavior(TransformGroup targetTG){ this.targetTG = targetTG; AWTEventCondition = new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED); } public void setBehaviorObjectPartner(Behavior behaviorObject){ pairPostCondition = new WakeupOnBehaviorPost(behaviorObject, 1); } public void initialize(){ this.wakeupOn(AWTEventCondition); } public void processStimulus(Enumeration criteria){ if (AWTEventCondition.hasTriggered()){ // make door open -- code excluded this.wakeupOn(pairPostCondition); postId(1); } else { this.wakeupOn(AWTEventCondition); } } } CloseBehavior hat analogen Code (auch mit postID = 1 !) Dekodieren: Wer hat getriggert: Taste oder anderes Behavior Triggern des anderen Behavior
Innerhalb einer Methode, die den Szene Graph zusammenbaut: TransformGroup doorTG = new TransformGroup(); OpenBehavior openObject = new OpenBehavior(doorTG); CloseBehavior closeObject = new CloseBehavior(doorTG); openObject.setBehaviorObjectPartner(closeObject); closeObject.setBehaviorObjectPartner(openObject); // Setze scheduling bounds für behavior Objekte -- code excluded
Kollisionsdetektion - weites Thema Wenn 2 Objekte kollidieren WakeupOnCollisionEntry WakeupOnCollisionMovement Wenn 2 Objekte sich während der Kollision bewegen WakeupOnCollisionExit Wenn 2 Objekte die Kollision beenden - Kollision kann so schnell sein, dass kein Trigger ausgelöst wird - Für ein Objekt kann zu einer Zeit nur eine Kollision behandelt werden ) WakeupOnCollision*( Bounds Node ScreneGraphPath [, int] [, USE_BOUNDS USE_GEOMETRY int]
Weiteres Aufwachen activation volume und scheduling bounds ohne Schnitt WakeupOnDeactivation() WakeupOnElapsedFrames(int frameCount) WakeupOnElapsedTime(long milliseconds) Sensor ist ein beliebiges Eingabegerät außer Tastatur und Maus WakeupOnSensorEntry / Exit(Bounds ...) Hier kann auch Verhalten mit einem Utility Verhalten koordiniert werden WakeupOnTransformChange(TransformGroup ...) WakeupOnViewPlatformEntry / Exit(Bounds ...)
Kombination von Aufwachbedingungen WakeupOn*
Bewegen der View Platform Der Beobachter wird durch die Virtuelle Welt bewegt Frage: Wie kommt man beim SimpleUniverse an die Transform Group der View Platform ? Behavior
Bewegen der View Platform ViewingPlatform vp = su.getViewingPlatform; TransformGroup vpt = vp.getViewPlatformTransform(); Mit dieser TransformGroup kann der Beobachter rotiert und verschoben werden su ist ein SimpleUniverse Objekt
AWTEvent Tastendruck Verhaltens Utility Klassen für die Tastatur Navigation wertet aus abstrakte Klasse Behavior KeyNavigator (wird vom Programmierer nicht beeinflußt) implementiert bedient sich KeyNavigatorBehavior processStimulus(...) Konstruktur nimmt (nur) TransformGroup entgegen
Verhaltens Utility Klassen für die Maus Navigation MouseBehaviorCallback Interface abstrakte Klasse MouseBehavior zu benutzen setTransformGroup(TransformGroup ...) zu implementieren: transformChanged(int type, Transform3D ...) type = MOUSE_ROTATE,... implementieren MouseZoom MouseRotate MouseTranslate setupCallback(MouseBehaviorCallback ...) BenutzerMouseBehaviorKlasse die transformChanged Methode dieser Klasse wird aufgerufen, wenn die MouseTranslate Klassen aktiviert werden
Customizing der Maus Navigation Möglichkeit A: Implementieren einer eigenen MouseBehavior Klasse (Extension von MouseBehavior) Möglichkeit B: Ableiten von MouseBehavior*, Überschreiben von transformChanged Möglichkeit C: Registrieren bei einer MouseBehavior* Klasse, implementieren vom Interface MouseBehaviorInterface d.h. der Methode transformChanged
„Anklicken“ oder Picking Das naheste Objekt wird selektiert (oder eine Liste mit geschnittenen Objekten wird geliefert) Der scene graph des selektierten Objekts wird zurückgeliefert (um z.B. den Knoten auszusuchen ,der geändert werden soll, z.B. TransformGroup für Rotieren)
Performanz Aspekte des Picking Schnittpunktsberechnung ist aufwendig Node Methode setPickable(boolean pickable)- wirkt auch auf alle Kinder ENABLE_PICK_REPORTING capability eines Node Objekts: dieser Node wird im zurückgelieferten scene graph path auf jeden Fall aufgeführt. - Sonst nur, wenn er zur eindeutigen Identifizierung des path benötigt wird. Im Konstruktor: USE_BOUNDS, oder USE_GEOMETRY
Beschränkung des pick testing auf den Teil des scene graph, der in Frage kommt: in pick utility Klassen kann eine Wurzel eines Untergraphen angegeben werden, der nur untersucht wird. Er sollte möglichst ausschließlich pickable Objekte enthalten. Wo die Maus sich bewegt Pick Utility Klassen PickRotateBehavior behavior = new PickRotateBehavior(root, canvas, bounds); root.addChild(behavior);
Bei picks geht‘s noch weiter: noch nicht gemacht: S.46 bis 58