# Ansätze zur Kombination mehrerer Listener für Interaktion



## Marco13 (4. Aug 2011)

Hi

Wie einige vielleicht wissen arbeite ich zur Zeit (wieder mal) an Swogl . Damit kann man Swing-Components auf 3D-Flächen pappen und die dann frei im Raum anordnen. Im speziellen geht es jetzt darum, wie man den möglichen Benutzern der Bibliothek die Möglichkeit geben kann, die Interaktion mit Swogl bequem und trotzdem flexibel zu konfigurieren.

In der ersten alpha-Version gab es einige Möglichkeiten zur Interaktion, aber die waren durch die Implementierung festgelegt: Standardmäßig gingen alle Mouse Events an die Swing-Componenten. Mit CTRL+MouseDrags konnte man die Kamera bewegen. Mit ALT+MouseDrags konnte man das Layout der 3D-Komponenten im Raum verändern - abhängig davon, welcher 3D-LayoutManager gerade aktiv war. 

So hat z.B. das "WheelLayout3D", das die Komponenten wie in einem Rad angeordnet hat, dieses Rad naheliegenderweise entsprechend der Rotation des Mausrades gedreht. Jemand anderes würde das Rad aber vielleicht gerne durch Ziehen mit der Linken Maustaste drehen. Und vielleicht nur wenn gleichzeitig noch CTRL und SHIFT gedrückt sind :autsch: Deswegen habe ich als erstes das "Verhalten" der LayoutManager, Kamerasteuerung und sonstigen Interaktionsmöglichkeiten von der Eventverarbeitung getrennt. 

Trotzdem gibt es für jedes mögliche Interaktionsmuster verschiedene Listener, die benötigt werden: Manche Interaktionen brauchen MouseListener, andere MouseWheelListener, andere KeyListener bzw. InputMaps, oder auch beliebige Kombinationen davon. Je nachdem, wie viele "Aspekte" die Interaktion umfasst. Bei der Kamera kann man schon Drehen+Bewegen+Zoomen, und das jeweils mit dem Mausrad oder Mausbewegungen oder Mausdrags...

Dass es einen gewissen Trade-off zwischen einfacher Anwendbarkeit und feingranularer Konfigurierbarkeit gibt ist wohl klar. Inzwischen habe ich einen ganzen Haufen mehr oder weniger ausgearbeiteter Ansätze, aber die kann ich schwer alle hier posten. Insgesamt habe ich aber das Gefühl, dass alles, was "genug" Konfigurierbarkeit bietet, mindestens genauso kompliziert ist, wie die Listener alle per Hand zu implementieren und zu verdrahten. 

Deswegen wollte ich mal fragen, ob jemand eine Idee hat, wie man das Problem angehen könnte (oder ... ob die einhellige Meinung ist, dass das ohnehin vollkommen egal ist, und der Benutzer das selbst implementieren sollte  )

bye
Marco


----------



## Kr0e (5. Aug 2011)

Ohne jetzt deine Gedankengänge als "überflüssig" erscheinen zulassen (das ist nicht mein Ziel!), aber ich wäre als Entwender ein Typ, der sowieso schon begeistert genug von der Technik wäre und alles Nötige zusammenbauen würde.

Ich weiß nicht, inwiefern ich dir helfen könnte, da du dir sicher viele Gedanken darüber gemacht hast... Aber ich könnte vlt das Prinzip der jME hier einbringen:

Man trennt dort strikt den Input vom eigentlichen Befehl. Der Input wird dort in Analog- und ActionListern unterteilt. Analog wäre das was ständig benachrichtigt wird: z.B. eine Mausbewegung und Action wären On/Off befehle: Button pressed / released... Also wenn du in deinem Projekt auf ein Mousedragged - Event reagieren willst, wäre eine Kombination aus Analog- und ActionListener deine 1. Wahl. Den Befehlen kannst du dann Namen geben, welche Art Input diese Befehle aber im Endeffekt triggert, ist vollkommen dem Entwickler überlassen. Somit wärst du vom eigentlich Mouse/Key-Input gelöst und könntest abstrakt arbeiten.

Aber wie gesagt, dass wäre jetzt nur meine Idee und keine Ahnung inwiefern das auf dein System übertragbar ist, bzw. sinnvoll wäre...

Schönen Gruß,

Chris


----------



## muckelzwerg (5. Aug 2011)

Versteh ich nicht. Wieso implementierst DU sowas?
Diese "Layouts" sind doch eigentlich schon konkrete Anwendungen. Wenn ich Swing-Menüs in 3D verarbeiten will (was ich in einem meiner Projekte tatsächlich mache) dann würde ich eine Sammlung von Funktionen haben wollen, mit denen ich schnell und straightforward das 3D-Verhalten bestimmen kann.

Ein 3D-Wheel-Layout würde ich dann doch selbst bauen und dafür Swoogl benutzen?
Dafür hätte ich gerne eine "Bühne" auf der ich Positionen setzen kann, Einstellungen abspeichern kann (= Keyframes), zwischen diesen Einstellungen mit bereits vorhandenen Funktionen umschalten kann (= Tweens) und lauter solche Dinge.
Und dann will ich doch, dass mir diese Szene mit den Events in irgendeinem Listener klingelt.
Es gibt dann halt noch eine Ebene mehr für den Rahmen um die mutliplen Swingflächen, aber vom Aufbau her bin ich das ja schon gewohnt.

Die Ereignisse sind weitgehend durch die Eingabegeräte begrenzt.
Ich würde erwarten, dass mir der "3D-Frame" die üblichen Maus und Tastaturereignisse anbietet. Dann würde ich gerne noch wählen können, ob die obersten Listener am Frame immer reagieren, auch wenn es einen konkreteren Empfänger (ein Swing Menü) gibt, oder ob es direkt an die konkrete Komponente weitergereicht wird.  
Bei den höheren Listenern würde ich in 3D denken und einen "Stapel" mit den getroffenen Objekten erwarten. 
So kann ich dann z.B. den Mauscursor ändern, wenn er über die gekippte Fläche eines Swing-Menüs fährt, auf den Klick hin die Bühne umschalten und das ausgewählte Menü z.B. ins Vollbild schalten (schön mit einem Tween aufgeblättert) und dann die nächsten Mausereignisse direkt an die Komponenten "durchfallen" lassen. 
Da steht dann in meinem 3D-Frame-MouseListener sowas wie 
"handleEvent(Event e){ if(Mode.SWINGMAXIMIZED == m_3DFrame.mode) { pushdown(e); }}"
Praktisch wäre es wie gesagt, wenn ich das nur einmal umschalten müsste, so dass jedes Event, welches zwar den 3D-Frame aber auch das maximierte Menü trifft nur noch an das Menü geschickt wird.


----------



## Marco13 (6. Aug 2011)

Kr0e hat gesagt.:


> Aber ich könnte vlt das Prinzip der jME hier einbringen:
> 
> Man trennt dort strikt den Input vom eigentlichen Befehl. Der Input wird dort in Analog- und ActionListern unterteilt. Analog wäre das was ständig benachrichtigt wird: z.B. eine Mausbewegung und Action wären On/Off befehle: Button pressed / released...



Ja, den grundsätzlichen Ansatz die Eingaben davon zu trennen, was durch die Eingaben bewirkt werden soll, habe ich schon verfolgt. So weit wie möglich versuche ich, die Funktionalität auf der einen Seite bereitzustellen, und diese dann "beliebig" ansteuerbar zu machen. 

Den Input-Teil von JME hatte es mir schonmal grob angesehen, aber noch nicht wirklich damit gearbeitet. Dort sind ja einige (IMHO nicht so schöne, aber - das kann ich nicht beurteilen - für das verfolgte Ziel evtl. doch angemessene oder unvermeidbare) Aspekte, die sehr spezifisch für das spezielle Input-Handling bei JME zu sein scheinen (Mouse, Device & Co), und das ist ja schon ziemlich anders aufgebaut als bei Swing. 

Das generelle Konzept von JME, ein Mapping von Input zu Actions zu haben, ist ja nichts neues. Bei Swing ist das sehr direkt durch InputMaps und ActionMaps abgebildet, aber nur für KeyStrokes. Für den schwierigen Fall der Erweiterung dieses Ansatzes auf "Kontinuierliche" (d.h. MouseMoved) Eingaben hatte ich an anderer Stelle schonmal philosophiert, was ja auch etwas ähnliches erreichen sollte wie
addAction(InputActionInterface inputAction, java.lang.String triggerCommand, boolean allowRepeats)
bei JME. Darüber hinaus kann dieser Ansatz noch erweitert werden - z.B. scheinen die dort ja eine "Linked List von Triggern" zu verwenden. Für Swogl dachte ich schon an eine "Chain of reponsibility", wo ein Event reingeworfen wird, und jeder selbst schaut, ob er sich dafür interessiert, aber das ist alles noch viel zu schwammig. Trotzdem sollte ich wohl meine bisherigen Ansätze (zumindest die, die auf einer Form von "Mapping" basieren) nochmal durchdenken, ob man die nicht doch noch in eine passende Form bringen könnte.




muckelzwerg hat gesagt.:


> Versteh ich nicht. Wieso implementierst DU sowas?



Auch wenn es anmaßend klingt: Ich implementiere das WheelLayout3D, weil es bei Swing auch schon ein GridLayout gibt, und nicht nur das rohe LayoutManager-Interface  

Vielleicht ist mir aber auch noch nicht klar, was du mit dem "3D-Verhalten" meinst. Die Kamera ist erstmal nur ein rohes, funktionsarmes Kameramodell. Die SwoglComponents sind nur geometrische Objekte, die man mit einer Matrix im Raum anordnen kann. Das ist das "unterste" Level, das jeder benutzen kann, wie er will. Aber damit wäre die Verwendung ziemlich aufwändig.

Deswegen sollte es über dem Low-Level interface eine Abstraktion geben, die einem zumindest einen Teil der ekligen Mathematik abnehmen. Eine Arcball-Kamerasteuerung soll nicht jeder neu implementieren müssen. Ein paar einfache, vorgefertigte Layouts sollte es auch schon geben. Und das Bewegen von SwoglComponents im Raum will man vielleicht auch nicht durch händische Matrizenrechnung machen. Da sollte es Klassen geben, die diese Funktionalitäten bereitstellen (nochmal: Unabhängig davon, durch welche Events die angesteuert werden).

Nochmal ein paar grob anskizzierte Beispiele, was das sein könnte:

```
// Components im 3D-Raum drehen
class ComponentRotation {
    void startRotation(Point o) { }
    void doRotation(Point o) { }
}

// Vergrößerungsglas für eine Component
class MagnifyingGlass {
    void magnifyAt(Point p) { ... }
}

// WheelLayout
class WheelLayout {
    void rotateWheel(int steps) { ... }
}
```
und eine vorläufige Implementierung für die Arcball-Kamerasteuerung gibt es schon, unter ArcballCameraBehavior (Swogl - Swing meets OpenGL)

Und wie oben schon angedeutet geht es primär um die Frage, wie man die Events an die Klassen weiterleiten kann, die diese Funktionen anbieten. Ich würde eben gerne erreichen, dass die Verwendung möglichst nah an Pseudocode herankommt wie

```
cameraControl.moveWith(leftMouseButtonAndShift);
cameraControl.rotateWith(leftMouseButtonAndCtrl);
cameraControl.zoomWith(nothing); // No zooming allowed

wheelLayoutControl.rotateWheelWith(mouseWheelOfCourse);

magnifyingGlassControl.setPositionWith(mouseMovementAndAlt);

someComponent.passAllEventsTo(
    cameraControl, wheelLayoutControl, magnifyingGlassControl);
```

Grob in die Richtung gehen einige meiner Ansätze schon, aber natürlich sind sie etwas komplizierter, und ich bin mir nicht sicher, ob sie damit nicht 
1. fast so kompliziert sind, wie wenn man das alles per Hand mit MouseListener & Co machen würde
2. sie vielleicht doch einfacher und praktischer sind, aber trotzdem eine "Barriere" darstellen: MouseMotionListeners kennt jeder, aber eine ausgefeilt-abstrakt-allgemeingültige API mit Controls und Behaviors und MouseEventConditions muss man erstmal nachvollziehen. 
(Obwohl, um das nochmal zu betonen, natürlich immernoch die Möglichkeit bestünde, alles mit MouseListenern per Hand anzusteuern - ich würde es dem Benutzer nur gerne einfacher machen...)


Was du mit den Positionen und Keyframes beschrieben hast klingt nach dem weiten Feld der _Animation_, aber das ist nochmal ein eigenes package, und hoffentlich weitgehend unabhängig davon. (Aber wenn du irgendwelche konkreten Ideen oder Use-cases hast: Immer her damit  )




> Dann würde ich gerne noch wählen können, ob die obersten Listener am Frame immer reagieren, auch wenn es einen konkreteren Empfänger (ein Swing Menü) gibt, oder ob es direkt an die konkrete Komponente weitergereicht wird.
> Bei den höheren Listenern würde ich in 3D denken und einen "Stapel" mit den getroffenen Objekten erwarten.


Das ist natürlich der erste Punkt, quasi die "Wurzel des Entscheidungsbaums": Man kann zwei "Condition"-Objekte angeben, die bei eingehenden MouseEvents prüfen, ob der Event an die angezeigten Swing-Components weitergeleitet werden soll, oder an die Listener, die an der Render-Component hängen. Aber wenn der Event an die Listener geht, muss man eben auch sagen können, dass SHIFT+LeftMouseDrag die Camera rotieren und ALT+RightMouseDrag das WheelLayout weiterdehen soll. 




> Da steht dann in meinem 3D-Frame-MouseListener sowas wie
> "handleEvent(Event e){ if(Mode.SWINGMAXIMIZED == m_3DFrame.mode) { pushdown(e); }}"
> Praktisch wäre es wie gesagt, wenn ich das nur einmal umschalten müsste, so dass jedes Event, welches zwar den 3D-Frame aber auch das maximierte Menü trifft nur noch an das Menü geschickt wird.



Wie oben erwähnt gibt es immer die Möglichkeit, auf unterster ebene MouseEvents abzugreifen und daraufhin per Hand Matrizen zu multiplizieren, um eine 3D-Component zu bewegen. Aber ich hätte schon gerne eine davon abstrahierende Zwischenschicht, die einfach zu verwenden ist, aber trotzdem möglichst wenig die Flexibilität einschränkt, die man mit dem Low-Level Ansatz hat.


----------



## Kr0e (6. Aug 2011)

Hey!

Vlt kurz mal eben du deiner "chain of responsibility"... Es gibt EventBus was einen publish/subscribe Mechanismus für Eventhandling implementiert. Die Library ist extra auf Swing zugeschnitten, allerdings nicht darauf begrentzt. Vermutlcih kennst du den Link bereits, aber falls nicht, dann jetzt 

Hier ist eine ganz nette Slideshow um die Einsatzmöglichkeiten zu verdeutlichen:

Einführung in den EventBus


Gruß,

Chris


----------



## Marco13 (6. Aug 2011)

Als ich das mit der "Chain of Responsibility" geschreiben habe, hatte ich den EventBus schon im Hinterkopf  Ich habe ihn mir zwar noch nicht im Detail angesehen, wußte aber, dass der "sowas" macht, und hätte ggf. geprüft, inwieweit der hier anwendbar wäre (auch wenn ich eigentlich gerne vermeiden würde, zu viele Abhängigkeiten zu weiteren Libs dort reinzubringen...)

Bisher klang es aber als würde die Meinung eher in die Richtung gehen, dass die Anwender diese "Verdrahtung" selbst mit Listenern implementieren sollten... :bahnhof:


----------



## muckelzwerg (6. Aug 2011)

Die Arcball-Metapher hat aber doch eigentlich nichts mit verschiedenen Inputs zu tun. Die nimmt im Prinzip "Drag&Drop" entgegen.
Da hat der Benutzer doch trotzdem einen Listener und will das Cursoricon anpassen ("offene Hand" vs. "greifende Hand") usw.
Wenn Du den erleichtern willst, solltest Du eher Methoden wie "rotateTo()" oder "startGrab()" usw. anbieten. 
Mit welchem Peripherieereigniss das dann angestoßen wird, kann Dir doch schnurz sein.

Meiner Meinung nach bist Du bereits auf einer viel zu hohen Ebene angekommen. Das was Du da beschreibst sollte doch eigentlich in den Ordner "examples" gehören und zeigen was man mit Swoogl alles machen kann.
Für mich sind das schon relativ konkrete Anwendungen und keine Hilfsfunktionen mehr.

Wenn ich eine 3D-Anwendung machen möchte, dann hab ich ja auch wenigstens ein Bisschen Ahnung von 3D.
Und wenn ich nur 3D-Effekte haben will, dann benutze ich ein fertiges Swoogl-3D-Widget und gebe dem meine Menüs.
Nimm Dir doch mal den Cube-Desktop von Android als Beispiel.
Wie würde ich den in Swoogl implementieren?
Da würde ich sagen "3D-Cube-Layout" instanziieren,
Oberflächen hinzufügen (nur horizontal, oder auch vertikal?),
die funktionen rotate(...) oder switch(...) benutzen um den Würfel zu drehen.
Ob Taste, Maus, Stift ... oder ob überhaupt durch Peripherie gesteuert hängt doch vom Benutzer ab.


Natürlich ist eine 3D-Kamerasteuerung keine einfache Sache. Bei vielen Projekten geht da sehr viel Zeit drauf. 
Deshalb würde ich es sehr attraktiv finden, wenn Swoogl mir Szenen anbietet, in denen ich bereits eine Menge machen kann, ohne dass ich die Kamera bewusst steuern muss.
Feste Kamera + Bewegungspfade ist doch schon ein ziemlich cooler Schritt.
Ich gebe einen "GeneralPath" an indem ich bestimme Punkte in der 3D Szene hinzufüge.
Und dann lass ich meine Swoogl-Oberflächen auf diese Pfad entlangrauschen.
Mit Vorspulen, Rückspulen, Position ansteuern ... 
Dann noch Funktionen zur Ausrichtung der Flächen, Billboards oder lieber "DVD-Regal" ...?
Aber auch da sehe ich nicht, wieso Du Peripherieereignisse abfangen solltest. 
Du bietest doch etwas an, das gesteuert wird und nicht selbst steuert.

Du kannst ja immernoch Standardlistener schreiben, die man verwenden kann, um z.B. die Maus mit dem "swipe left" zu verkabeln.
Aber wer selbst das nicht selbst machen will, der programmiert doch eigentlich nicht, sondern benutzt nur ein fertiges "3D-Programm"?


----------



## Wildcard (7. Aug 2011)

Ohne jetzt den ganzen Thread gelesen zu haben:



> In der ersten alpha-Version gab es einige Möglichkeiten zur Interaktion, aber die waren durch die Implementierung festgelegt: Standardmäßig gingen alle Mouse Events an die Swing-Componenten. Mit CTRL+MouseDrags konnte man die Kamera bewegen. Mit ALT+MouseDrags konnte man das Layout der 3D-Komponenten im Raum verändern - abhängig davon, welcher 3D-LayoutManager gerade aktiv war.


Lass es doch so, hört sich doch gar nicht verkehrt an. Ich würde es einfach sauber von der Komponente abtrennen. Nennen wir das Ding mal 'Behaviour'. Du implementierst ein paar schöne Default Behaviours und initialisierst deine Komponenten dann schon gleich mit dem passenden. Der User der Lib darf es dann gerne austauschen.
Das Ziel muss ja sein, das häufige Requirements einfach umsetzbar sind, und komplexere umsetzbar, da muss es nicht mehr einfach sein.
Sinnvolle Defaults, austauschbar bei Bedarf, und je mehr Use-Cases du von Usern mitbekommst, umso klarer sollte dir werden welche Behaviours du mitlieferen solltest.


----------



## Marco13 (7. Aug 2011)

muckelzwerg hat gesagt.:


> Mit welchem Peripherieereigniss das dann angestoßen wird, kann Dir doch schnurz sein.
> ...
> Das was Du da beschreibst sollte doch eigentlich in den Ordner "examples" gehören und zeigen was man mit Swoogl alles machen kann.



Das erstgenannte Ziel habe ich im Prinzip schon erreicht, indem ich die Funktionalität von den ankommenden Events getrennt habe. Und auch das zweite have ich schon für anderen Teile vorgesehen: In den Examples-Ordner kommen Klassen, die die Low-Level-API verwenden. Wenn sich diese Examples als "gut" herausstellen, können sie (ggf. angepasst, erweitert und verbessert) irgendwann Teil der offiziellen high-level API werden. Allerdings habe ich das vielleicht an einigen Stellen noch nicht so konsequent durchgezogen, wie ich sollte. Ich fand halt, dass zumindest ein paar Grundfunktionalitäten (wie Kamerasteuerung) schon enthalten sein sollte...



> Nimm Dir doch mal den Cube-Desktop von Android als Beispiel.
> ...
> die funktionen rotate(...) oder switch(...) benutzen um den Würfel zu drehen.


Bis hierhin volle Zustimmung, so ist es ja eigentlich schon.... aber... das geht jetzt zum Kommentar aus der nächsten Antwort über:



Wildcard hat gesagt.:


> Lass es doch so, hört sich doch gar nicht verkehrt an. Ich würde es einfach sauber von der Komponente abtrennen. Nennen wir das Ding mal 'Behaviour'. Du implementierst ein paar schöne Default Behaviours und initialisierst deine Komponenten dann schon gleich mit dem passenden.



Die Dinge, die im Moment "Behavior" heißen, sind die, die die Funktionalität bereitstellen. Die Dinge, die "Control" heißen, verwenden Events, um die Methoden der Behavior anzusteuern. Ich glaube, das meintest du schon... Aber nochmal das Beispiel: In 
ArcballCameraBehavior (Swogl - Swing meets OpenGL)
steht, was die Klasse an Funktionalität bietet.
Die Klasse
ArcballCameraControl (Swogl - Swing meets OpenGL)
kann verwendet werden, um die "Behavior" mit einem bestimmten Standardverhalten anzusteuern. Das ist dann schon recht kompakt und einfach:

```
ArcballCameraBehavior behavior = new ArcballCameraBehavior(view, camera);
ArcballCameraControl control = new ArcballCameraControl(behavior);
control.attachTo(someComponent);
```

Das besagte "Standardverhalten" der Kamera ist hier dann
- Links-MouseDrags zum Rotieren
- Right-MouseDrags zum Verschieben 
- MouseWheel zum zoomen

Wenn jemand nun eine vermeintlich kleine Änderung will, wie z.B. 
- ALT+Recht-MouseDrags zum Rotieren
- ALT+Links-MouseDrags zum Verschieben 
- MouseWheel zum zoomen

dann müßte er sich seine komplett eigene Control-Klasse schreiben. Das könnte sehr aufwändig sein, je nachdem um wie viele Behaviors es geht (z.B. neben der Kamera auch noch Layout usw). Ich fände es eben schön, wenn er diese Änderung ganz einfach erreichen könnte, indem er sowas schreibt wie

```
ArcballCameraBehavior behavior = new ArcballCameraBehavior(view, camera);
ArcballCameraControl control = new ArcballCameraControl(behavior);

// Standardverhalten ändern:
control.rotateWith(altAndRightMouseDrags);
control.moveWith(altAndLeftMouseDrags);

control.attachTo(someComponent);
```
Wie gesagt, so ist das Pseudocode, aber man kann da schon recht nah drankommen. 

Als vorläufiges Resümee: Es wäre wohl am besten, die defensivst-mögliche Strategie zu fahren - auch in Anlehnung an Josh Bloch's Mantra zu APIs: "If in doubt, leave it out!". Also erstmal alles, was nicht mit den Kernaufgaben von Swogl zu tun hat, in einen Demo-Ordner, und nur das, was sich etabliert und "festgerüttelt" hat, in die API mit aufnehmen.







muckelzwerg hat gesagt.:


> Feste Kamera + Bewegungspfade ...
> Ich gebe einen "GeneralPath" .... Und dann lass ich meine Swoogl-Oberflächen auf diese Pfad entlangrauschen.
> Mit Vorspulen, Rückspulen, Position ansteuern ...
> Dann noch Funktionen zur Ausrichtung der Flächen, Billboards oder lieber "DVD-Regal" ...?



Wie oben schon angedeutet geht das schon deutlich über den eigentlichen Kern der ursprünglichen Frage hinaus. Das bezieht sich ja schon auf allgemeine Animationen und Pfade. Im Moment gibt es dafür wirklich nichts offizielles: Man kann die Components mit [c]component.setTransform(matrix);[/c] im Raum anordnen, wie man will. Wer eine Animation will, muss die selbst basteln. Aber erste Überlegungen und Experimente dazu habe ich auch schon angestellt. Woanders wurde vorgeschlagen, dafür das Timing Framework &mdash; Java.net zu verwenden, weil es schon viel der Funktionalität abdeckt. Aber aus 2 Gründen bin ich davon noch nicht vollständig überzeugt:
1. Das TimingFramework ist für 2D gedacht. Auch wenn es für 3D verwendet werden könnte, wird es vermutlich einige Aspekte nicht abdecken
2. Ich würde ungern eine Abhängigkeit zu eine Lib herstellen, die für die eigentliche Kernaufgabe von Swogl ja auch nicht benötigt wird. Die Animationen braucht man ja auch nur für spezielle, spezifische Anwendungen, in denen eben "komplexe" Animationen vorkommen sollen.
Deswegen würde vermutlich auch alles, was mit Animationen zu tun hat, erstmal nur im "Demos"-Ordner landen.
Insgesamt scheinst du aber schon ein paar ziemlich konkrete Ideen für Use-Cases zu haben, mit denen der Demos-Ordner gefüllt werden könnte


----------



## muckelzwerg (7. Aug 2011)

Naja, Du machst das sowieso besser so, wie Du es für richtig hältst!
Ich habe nur das Gefühl, dass da ziemlich viel Java-Strukturkram entsteht, der mich eher bremsen und abschrecken würde.
Ein Arcball ist doch eigentlich eine ziemlich simple Sache. So wie sich das bisher liest, wird es bei Jogl nicht unbedingt leichter, als 
NeHe Productions: ArcBall Rotation
Du ersparst die Matrizen, gut. Aber dafür muss ich dann ein ArcballControl ableiten und überschreiben, nur um zu entscheiden, ob Arcball.startDrag(...) von der linken oder rechen Maustaste gestartet wird.
Das wäre mir persönlich unangenehm viel "Zeug". 

Was passiert denn, wenn ich eine Galerie mit gleichzeitig sichtbaren Objekten habe und jedes der Objekte mit einem Arcball gedreht werden soll? Ich will ja vielleicht mal mehr als nur ein einzelnes Objekt mit Arcballs drehen.
Muss ich dann für jeden ein eigenes Control schreiben und die Offsets der Mauskoordinaten mit einbauen?
Oder muss ich dann im Control einen fetten Switch machen, auf die Liste der Objekte?

Da würde ich gern einfach die Arcballmetapher an jedes Objekt drankleben und in meinem eigenen Listener beim linken oder rechten Mausklick schauen, ob ich ein Objekt getroffen habe, dass eine Arcballmetapher besitzt. 
Wenn ja, hol ich mir das ArcballObjekt und sage "startDrag(...)". 


Was würde ich denn an der Software noch selbst machen, wenn ich nicht mehr entscheide welcher Klick zu welcher Aktion führt?
Dann brauch ich doch wirklich nur noch Swingmenüs in das jeweilige Behaviour-Control-Dingsbums einfügen und fertig.
Für mich fühlt sich das an, als würdest Du da mehrere 3D-Browser oder 3D-Desktops bauen.
Ist ja eine coole Sache, aber dann brauchst Du den Benutzer auch nicht zum Programmierknecht machen und ihn "createArcballBehaviour()" jedesmal selbst schreiben zu lassen. 
Dann kann er auch "createArcBallBrowser()" und "addJFrame(...)" verwenden.


Vielleicht solltest Du mal ein paar Beispiele ausprobieren und schauen, wie gut die sich umsetzen lassen.
Ich hab das Gefühl, Du sitzt zwischen den Stühlen. 
Meist haben solche Systeme doch nur zwei Ebenen. Die Userebene mit "benutz die fertigen Hilfsklassen aus der Doku"
und die Bastlerebene mit 
"ja dann mach halt gleich alles selbst".
Wenn Du jetzt dazwischengehst, sieht das vielleicht attraktiv aus für einen "ambitionierten User, der aber eigentlich doch nicht wirklich lernen will, wie es im Detail funktioniert".
Ob es denn aber wirklich gibt und man den unterstützen will, ist halt die Frage. 
Es besteht die Gefahr, dass es für den Bastler bremsend und umständlich wird, weil er 100 Zeilen Code schreiben muss, um die Maustaste an einem Arcball zu ändern, den er sogar selbst hätte schreiben können.


----------



## Marco13 (7. Aug 2011)

So ganz hab' ich an einigen Stellen nicht verstanden, worauf du raus willst. Der Arcball (der im Moment auch nur die Kamera, und keine anderen Objekte steuert) ist eben etwas, was IMHO nicht jeder neu implementieren sollte. Aber zumindest das hier


> Da würde ich gern einfach die Arcballmetapher an jedes Objekt drankleben und in meinem eigenen Listener beim linken oder rechten Mausklick schauen, ob ich ein Objekt getroffen habe, dass eine Arcballmetapher besitzt.
> Wenn ja, hol ich mir das ArcballObjekt und sage "startDrag(...)".


klang, als würdest du das genauso sehen. 

Vielleicht nochmal den Punkt zusammengefasst: Man kann z.B. einen Arcball und ein WheelLayout erstellen, und die dann per Hand mit den gewünschten Events verbinden. Zum Beispiel zum Rotieren der der Kamera und Drehen des WheelLayouts: 

```
final ArcballCameraBehavior behavior = new ArcballCameraBehavior(view, camera);
final WheelLayout3D wheelLayout = new WheelLayout3D();

final Point prevPoint = new Point();
someComponent.addMouseListener(new MouseAdapter()
{
    @Override
    public void mousePressed(MouseEvent e)
    {
        int flags0 = MouseEvent.BUTTON1_DOWN_MASK | InputEvent.ALT_DOWN_MASK;
        if ((e.getModifiersEx() & flags0) == flags0)
        {
            behavior.startRotate(e.getPoint());
        }
        int flags1 = MouseEvent.BUTTON3_DOWN_MASK | InputEvent.CTRL_DOWN_MASK;
        if ((e.getModifiersEx() & flags1) == flags1)
        {
             prevPoint.setLocation(e.getPoint());
        }
    }
});

someComponent.addMouseMotionListener(new MouseMotionAdapter()
{
    @Override
    public void mouseDragged(MouseEvent e)
    {
        int flags0 = MouseEvent.BUTTON3_DOWN_MASK | InputEvent.ALT_DOWN_MASK;
        if ((e.getModifiersEx() & flags0) == flags0)
        {
            behavior.doRotate(e.getPoint());
        }
        int flags1 = MouseEvent.BUTTON1_DOWN_MASK | InputEvent.CTRL_DOWN_MASK;
        if ((e.getModifiersEx() & flags1) == flags1)
        {
             int dy = e.getY() - prev.getY();
             wheelLayout.rotateAbout(dy);
             prevPoint.setLocation(e.getPoint());
        }
    }
});
```

Meine Kristallkugel sagt mir, dass sich das jetzt niemand durchgelesen hat, niemand weiß, welche Aktion welche Funktion ansteuert, und niemand erkannt hat, wo der Fehler in diesem Code liegt (sind vielleicht mehrere, war nur aus dem Kopf hingeschrieben)  . Wenn man jetzt eins der beiden noch mit einem Flag ein- und ausschaltbar machen will, oder ein weiterer Eingabeaspekt dazukommt, z.B. ein Hotkey, wo man mit InputMaps und ActionMaps rumhantieren muss, oder ein weiteres Layout, und man zwischen diesem und dem WheelLayout umschalten kann, wird das sehr unübersichtlich - zumindest fände ich es schöner, wenn man das schreiben könnte als

```
ArcballCameraControl control = new ArcballCameraControl(new ArcballCameraBehavior(view, camera));
control.rotateWith(altAndLeftMouseDrags);
control.attachTo(someComponent);

WheelLayoutControl wheelLayoutControl = new WheelLayoutControl(new WheelLayout3D());
wheelLayoutControl.rotateWith(ctrlAndRightMouseDrags);
wheelLayoutControl.attachTo(someComponent);
```

Ähnliche Aspekte werden z.B. bei der JME auch abgedeckt: Es gibt einen ThirdPersonHandler (jME API) , der ja auch kein Hexenwerk ist, aber offenbar doch recht komplizert, weil man dort auch die "KeyInputActions" für die einzelnen Bewegungen selbst setzen kann....




> Was würde ich denn an der Software noch selbst machen, wenn ich nicht mehr entscheide welcher Klick zu welcher Aktion führt?


Da gibt's sicher noch genug  aber abgesehen davon ging es ja gerade darum, dass der Benutzer das (wenn er vom Standardverhalten abweichen will) noch selbst entscheiden kann, aber eben nicht über das oben angedeutete Verdengeln von MouseListenern, sondern über ein einfaches [c]someControl.forThisAction(useThisMouseInput);[/c]




> Es besteht die Gefahr, dass es für den Bastler bremsend und umständlich wird, weil er 100 Zeilen Code schreiben muss, um die Maustaste an einem Arcball zu ändern, den er sogar selbst hätte schreiben können.



Diese Möglichkeit besteht immer. Er kann die Matrizensachen selbst ausrechnen. Wenn man das nicht will, dann verwendet er den vorgefertigten Arcball. Den kann er dann ansteuern, indem er selbst die Events und deren Modifiers abfragt und in Steuerbefehle umwandelt. Und ich dachte eigentlich, dass es cool wäre, wenn er auch das nicht so kompliziert machen müßte, sondern die Verdrahtung zwischen Eingabe und Aktion mit wenigen, übersichtlichen, sprechenden Zeilen vornehmen könnte. 

Aber ich werde wohl erstmal konservativ nur das nötigste in die API aufnehmen, und auf eventuelles Feedback zu den Demos warten.


----------



## muckelzwerg (8. Aug 2011)

Sicher hab ich mir das durchgelesen. Ich bin jetzt noch stärker der Meinung, dass Du konkrete Beispiele anschauen solltest.
Du scheinst Dich sehr stark auf klassische Kamerasteuerung zu konzentrieren. 
Ich weiß nicht, wofür Swogl letztlich verwendet werden soll, aber ich glaube die Art der Kamerasteuerung wie Du sie da verbaust, ist dann nicht mehr Swing auf OpenGL sondern eher OpenGL mit Swing-Shader.

Wenn Du es so machen magst, wie Du beschrieben hast, dann tu das doch einfach. 
Die Ereigniskombinatioen zuzuordnen ist doch technisch nicht so schwer, oder?

ICH finde das einen seltsamen Ansatz. Aber vielleicht liegt das auch daran, dass ich gerade etwas (ungefähr) Ähnliches mache aber überhaupt keine Maus mehr habe, die in 3D irgendwas steuert. 
Da liegt mir der Schnitt irgendwie an der falschen Stelle.
Swogl ist für mich das Zeichnen von Swing-Menüs auf Flächen in OpenGL. Wenn ich sowas verwenden will, dann möchte ich Hilfsfunktionen, um diese Flächen zu organisieren. Aber ich möchte nicht unbedingt von der Metapher einer Desktopanwendung weg in eine komplette 3D-Szene.
Denn für letzteres wäre mir Swogl dann wohl im Weg. Eine komplette 3D-Szene bei der halt irgendwo mal ein Menü auf einem Polygon liegt, würde im Prinzip einen "TextureRenderer" und eine Übertragung der Mauskoordinaten brauchen, mehr aber nicht.
Ich seh einfach nicht, wofür ich das benutzen sollte. 
Wenn ich bereits 3D mache, dann habe ich Bibliotheken dafür und dann kann Swogl mit denen sowieso nicht mithalten. (und soll es auch nicht)
Wenn ich aber von 2D komme und meinem ehemals platten Swing jetzt die dritte Dimension beibringen will, dann möchte ich im Wesentlichen neue Darstellungsfunktionen in Bezug auf die bisherige Ansicht.
Also ein Zoom, oder eine Kaskadendarstellung von Menüs, oder ein Würfeldesktop oder ... 
Und da würde ich etwas ähnliche erwarten, wie ich es in 2D gewohnt bin.


----------



## Kr0e (8. Aug 2011)

Um nochmal meine kleine Meinung einzubringen:

Ich hab ja von Anfang an gesagt, dass ich die Funktion Swing-To-openGL schon cool genug finde und garnicht mehr erwartet würde, im Gegenteil jedes Weitere feature wäre für mich mehr Arbeit zur Einarbeitung.

Also ich sehe eigentlich nur EINEN Vorteil davon Swing auf OpenGL Textures zu bringen: Man kann ein starkes 2D GUI mit openGL nutzen, ohne jetzt iwie JGLPanel zu benutzen und OpenGL + Swing Komponenten zu mischen -> Lahm und ineffizient!

Also im Endeffekt, würde ich vermutlich Swing auch nur im glOrtho Modus verwenden... Das ansich ist aber doch schon genial genug! Ich meine, in Bezug auf Java + OpenGL Gui gibts noch keine richtige all-überzeugende Meinung.... Klar es gibt pure OpenGL Libs wie Nifty oder TWL, welche auch schneller sind als Swing und erstrecht als SwingToOpenGL aber eben auch viel benutzerunfreundlicher!

Das ist nur meine Meinung und ich finde es beachtlich, was du da auf die Beine gestellt hast!


Gruß,

Chris


----------



## Marco13 (8. Aug 2011)

muckelzwerg hat gesagt.:


> Sicher hab ich mir das durchgelesen. Ich bin jetzt noch stärker der Meinung, dass Du konkrete Beispiele anschauen solltest.


Welche Beispiele meinst du genau? Real-World-Anwendungen von Swogl? Da kenne ich nur eine, und dort wird Swogl eigentlich nur verwendet, um Swing (2D!) in einem GLCanvas darzustellen...



> Ich weiß nicht, wofür Swogl letztlich verwendet werden soll, aber ich glaube die Art der Kamerasteuerung wie Du sie da verbaust, ist dann nicht mehr Swing auf OpenGL sondern eher OpenGL mit Swing-Shader.



Vielleicht ist das ein Problem: Ich weiß auch nicht, wofür Swogl verwendet werden soll  Aber im Ernst: Mit der aktualisierten Version soll es eigentlich zwei (wenig konkrete) Use-Cases abdecken: 
- Einerseits soll es die Möglichkeit bieten, Swing-Components (auf 3D-Flächen) in bestehende Programme einzubetten. Um zum Beispiel ein JLabel mit HTML-Text zu verwenden, um 3D-Objekte zu beschriften, oder einfache Swing-Elemente wie Buttons oder Slider um Einstellungen "direkt AN 3D-Objekten" machen zu können (und nicht in einem Menü rechts, wo man den Zusammenhang zu den 3D-Objekten der Szene nicht mehr erkennt). 
- Der zweite Use-Case sollte aber schon sein, dass man leicht eine Swing-Anwendung erstellen kann, bei der ursprünglich einzelne Components in Tabs eines JTabbedPanes oder in JInternalFrames lagen, und die mit Swogl dann eben hübsch 3D im Raum angeordnet sein können. Vielleicht auch, um Dinge in einer Form gestalten zu können, die in 2D nicht möglich wäre, und wo die dritte Dimension wirklich einen konkreten _Nutzen_ bringt. Im Zweifelsfall aber zumindest für die gleiche Form frivol-nutzloser Verschwendung von Rechenleistung wie das "Anwendungs-Browsing" bei Windows oder der "Coverflow" bei diesen iPhone-Musik-Browsing-Apps... (Weil man's KANN :smoke:  )

Und für letzteres sollte dann eben schon eine gewisse "Infrastruktur" bereit stehen. Inzwischen haben mich die Kommentare und Einwände hier (und natürlich auch die Festigung meiner anfänglichen Bedenken, die mich zu diesem Thread veranlasst haben) eher zu der Einstellung gebracht, dass es vermutlich besser wäre, die Low-Level API zu trennen von besagter High-Level Infrastruktur. Im Zweifelsfall, ganz pragmatisch, in Form zweier JARs wie "swogl-core.jar" und "swogl-sceneUtils.jar" oder so...

Meint ihr, dass das Sinn machen würde...?



> Wenn Du es so machen magst, wie Du beschrieben hast, dann tu das doch einfach.
> Die Ereigniskombinatioen zuzuordnen ist doch technisch nicht so schwer, oder?



Programmieren ist prinzipbedingt IMMER schwer. Wenn es leicht wäre, würde man so sehr versuchen, es besser zu machen, dass es doch wieder schwer wäre. (Aber es kann schon sein, dass ich es mir manchmal schwerer mache, als es sein müßte... )

Trotzdem erkenne ich in dem, was du sagst, keine klare Richtung oder Kernaussage. Vielleicht ist ein falscher Eindruck entstanden, dadurch, dass ich den Arcball so als Beispiel verwendet habe. Vielleicht reden wir auch teilweise aneinander vorbei, weil wir beide scheinbar ähnliche Projekte mit unterschiedlichen Ansätzen und Absichten verfolgen...


> Swogl ist für mich das Zeichnen von Swing-Menüs auf Flächen in OpenGL. Wenn ich sowas verwenden will, dann möchte ich Hilfsfunktionen, um diese Flächen zu organisieren. Aber ich möchte nicht unbedingt von der Metapher einer Desktopanwendung weg in eine komplette 3D-Szene.
> ...
> Wenn ich aber von 2D komme und meinem ehemals platten Swing jetzt die dritte Dimension beibringen will, dann möchte ich im Wesentlichen neue Darstellungsfunktionen in Bezug auf die bisherige Ansicht.
> Also ein Zoom, oder eine Kaskadendarstellung von Menüs, oder ein Würfeldesktop oder ...
> Und da würde ich etwas ähnliche erwarten, wie ich es in 2D gewohnt bin.



Aber genau das WÄRE doch eine "komplette 3D-Szene"?! (Vielleicht mit fixer Kamera, aber das ist ja nur ein Detail). Die "organisation der Flächen" wäre ja gerade ein 3D-Layout... und die soll man ja irgendwie verwenden steuern können...? Oder ging es dabei jetzt genau um das, was oben schon angeklungen ist, nämlich dass z.B. die 3D-Layouts schon enthalten sein sollen, aber keine vordefinierte Möglichkeit, damit zu interagieren (sondern nur Methoden, die Anwender mit ihren MouseListenern aufrufen können, wenn sie wollen) ? 



Kr0e hat gesagt.:


> Also im Endeffekt, würde ich vermutlich Swing auch nur im glOrtho Modus verwenden... Das ansich ist aber doch schon genial genug! Ich meine, in Bezug auf Java + OpenGL Gui gibts noch keine richtige all-überzeugende Meinung.... Klar es gibt pure OpenGL Libs wie Nifty oder TWL, welche auch schneller sind als Swing und erstrecht als SwingToOpenGL aber eben auch viel benutzerunfreundlicher!



Nun, vielleicht haben die einfach nur ein spezifischeres und klarer definierbares Einsatzgebiet (und dafür SIND sie wohl benutzerfreundlich). Und wenn Swogl wirklich nur für die reine Einbettung von 2D Swing in einen GLCanvas verwendet werden würde: Dafür gäbe es sicher einfachere Lösungen...


----------



## Kr0e (8. Aug 2011)

Also ich habe die "bekanntesten" GUI Libs mal angeschaut. Nifty und TWL sind ein Kramp, in jeder Weise... Keine Ahnung welchen Anwendungsfall es geben könnte, wie diese beiden Libs benutzerfreundlich wären... 

Der PUNKT ist: Es gibt kaum OpenGL GUI Libs... Ein Spiel z.B. brauch eigentlcih keine 3D Menüs, aber es will einfahc Menüs haben mit komplexen Elementen wie einer Tabelle z.B. (Bietet fast kein existierendes Projekt, bei Nifty müsste mans sich zusammenschustern aus Labels, Panels und Images -.-) Und Swing ist einfach SEHR umfangreich und daher finde ich persönlich alleine schon den Einsatz (auch wenn dir dann Swogl vlt unterfordert vorkäme :-/) als normales 2D UI innerhalb von OpenGL praktisch. Ich meine man kann die Menüs mit MAtisse oder Window BUilder Pro erstellen, das spart unheimlich viel Zeit =)!

Normalerweise schrecken viele SPieleprogrammierer in Java sowieso vor diesen arg merkwürdigen Libs zurück und machen das komplett selbst, sofern sie sich mit ein paar Textboxen / Buttons zufrieden geben..

PS: Die Einbettung von Swing in ein AWT Canvas ist keine wirkliche Lösung... Da kanns viele Probleme geben. Ich hatte bei so einem Versuch mal mit Keyboardfokus unter Mac arge Probleme. Habs nicht gelöst bekommen =(


----------



## muckelzwerg (8. Aug 2011)

Bei Beispielen denke ich an Sachen wie 3D Desktops, 3D-Browser usw.
Zum Beispiel das Durchblättern von Bilderalben mit 3D-Effekten.
Swogl bietet mir doch den Vorteil, dass ich Transformationen schnell anwenden kann und bspw. mehrere Swing-Menüs stapeln und mit Transparenz durchschalten kann.
Oder es bietet mir die Möglichkeit Shaderprogramme auf die Swingoberfläche anzuwenden.
Oder vielleicht das Explodieren von Menüs in verschiedene Elemente, die sich neu organisieren.
Oder die typischen Gags mit "Menü umdrehen und Notiz auf die Rückseite schreiben".
...
Sowas sehe ich nicht als "komplette 3D-Szene".
Wir hatten vor ein paar Jahren mal eine Demo von der SecondLife Engine. Da hattest Du z.B. eine "komplette 3D-Szene" in der Du mit dem Avatar rumgelaufen bist und in der irgendwo eine Anzeigentafel stand, auf der ein Browserfenster zu sehen war.
Sowas meinte ich. Und sowas würde ich mit Swogl wohl nicht machen. 


Die Trennung, die Du da ansprichst klingt für mich sehr sinnvoll.

Swogl für das Bemalen von Flächen in sonst reinen 3D-Programmen erscheint mir ziemlich sinnlos.
Ein JLabel oder HTML-Text macht nur Sinn, wenn er sich dynamisch ändert. Ansonsten kleb ich das als Textur mit gewöhnlichen Boardmitteln drauf. Ich baue nicht extra eine Lib wie Swogl ein, um ein Bild auf ein Polygon zu schieben.
Dynamische Inhalte gibt es sonst meist mit Texture-Rendering für Bilder die mit Graphics2D gezeichnet werden. 
Ich kann mir absolut nicht vorstellen, dass Swogl außer von Neulingen und "Weils halt da ist"-Typen ernsthaft für ingame Menüs in 3D-Spielen verwendet wird. 
Ich sehe die Stärken von Swogl darin, Swing um 3D zu erweitern und nicht 3D um Swing zu erweitern.


----------



## Marco13 (8. Aug 2011)

Kr0e hat gesagt.:


> PS: Die Einbettung von Swing in ein AWT Canvas ist keine wirkliche Lösung... Da kanns viele Probleme geben. Ich hatte bei so einem Versuch mal mit Keyboardfokus unter Mac arge Probleme. Habs nicht gelöst bekommen =(



Ich meinte damit, dass man da etwas machen könnte, was so ähnlich funktioniert wie Swogl, aber vieeel einfacher gestrickt ist, weil man sich ja alles spart, was mit Geometrie usw. zu tun hat.




muckelzwerg hat gesagt.:


> Ich sehe die Stärken von Swogl darin, Swing um 3D zu erweitern und nicht 3D um Swing zu erweitern.



Damit sind die beiden Möglichkeiten, die Swogl bieten sollte, gut zusammengefasst (und im Nachhinein sieht's so einfach aus   )

Ursprünglich war Swogl NUR ersteres: Man könnte eine Swogl-Anwendung erstellen, in der man 3D-Swing-Components einfügen konnte. Da wurde aber seht schnell danach gefragt, wie man diese "Szene" noch um eigene gerenderte Objekte erweitern könnte. Das fängt bei der Beleuchtung an und geht weiter bis zu kompletten 3D-Umgebungen.




muckelzwerg hat gesagt.:


> Swogl bietet mir doch den Vorteil, dass ich Transformationen schnell anwenden kann und bspw. mehrere Swing-Menüs stapeln und mit Transparenz durchschalten kann.
> Oder es bietet mir die Möglichkeit Shaderprogramme auf die Swingoberfläche anzuwenden.
> Oder vielleicht das Explodieren von Menüs in verschiedene Elemente, die sich neu organisieren.
> Oder die typischen Gags mit "Menü umdrehen und Notiz auf die Rückseite schreiben".
> ...



Ja, aber ich finde es schwer, dort eine "harte" Trennlinie zu ziehen. Wenn nun jemand die angesprochenen Funktionen nutzt (bzw. einbaut - sie sind noch(!) nicht alle in dieser Form unterstützt), dann wäre das keine "komplette 3D-Szene". Wenn jemand aber so einen "Stapel Notiz-Swing-Components" gerne auf einem Schreibtisch liegen hätte, von einer Schreibtischschlampe beleuchtet (was mir schon als Demo im Hinterkopf rumschwebt) dann wäre das schon eine "komplette 3D-Szene" - auch wenn man nicht mit einem Avatar durch eine Second-Life-Artige 3D-Welt läuft...




muckelzwerg hat gesagt.:


> Swogl für das Bemalen von Flächen in sonst reinen 3D-Programmen erscheint mir ziemlich sinnlos.
> Ein JLabel oder HTML-Text macht nur Sinn, wenn er sich dynamisch ändert. Ansonsten kleb ich das als Textur mit gewöhnlichen Boardmitteln drauf. Ich baue nicht extra eine Lib wie Swogl ein, um ein Bild auf ein Polygon zu schieben.



Hm... es ging schon um dynamische Inhalte und auch um Swing Components, die eine _Funktion_ haben. Z.B. das Bild (das vermutlich nicht ewig auf der Webseite liegen wird, d.h. dieser Link wird irgendwann ungültig, aber für den Moment füge ich es mal hier ein) von der Gears-Demo, wo ein paar Swing-Components eingefügt wurden:






Dort könnte man z.B. Labels an die Zahnräder hängen, die die (verschiedenen) Winkel anzeigen, und einen Start/Stop-Button oder Slider zum drehen oder so... Zugegeben: Ich kann mir auch kaum vorstellen, dass jemand sowas "ernsthaft" nutzt, aber... es sollte gehen 




muckelzwerg hat gesagt.:


> Die Trennung, die Du da ansprichst klingt für mich sehr sinnvoll.



Ich werde mal zusehen, wie man etwas grob in dieser Art umsetzen kann: Ein Swogl-Core mit dem Low-Level-Teil, und eine Sammlung von "Scene Demos", aus denen sich dann vielleicht irgendwann eine API herauskristallisiert.


----------



## muckelzwerg (8. Aug 2011)

Marco13 hat gesagt.:


> Ja, aber ich finde es schwer, dort eine "harte" Trennlinie zu ziehen.


Wie wäre es mit "feste Kamera" bzw. "fester Viewport" als Grenze?
Das ist es doch, was ich bei Swing gewohnt bin. Oben links pappt die 0/0.
Wenn ich jetzt festlege, dass ich durch ein Fenster in eine 3D-Welt schaue und vor diesem Fenster machen kann, was ich will, dann wäre das doch eine ziemlich direkte Übertragung.
Ich hab die Tiefe dazubekommen, muss über den Öffnungswinkel nachdenken, aber ich muss nichts von einer Kamera wissen.
So wie ich bei Swing meine Panels und Labels und ... platziere und vielleicht bewege, so mache ich das jetzt mit Swogl-Components und einer zusätzlichen Ebene.

Ungefähr sowas meinte ich mit "Bühne". Die Kamera hat dann eine feste Position und bietet erstmal nur ihre intrinsischen Werte an.
Ich könnte dann zoom oder winkel verändern, bleibe aber in der einen konkreten "Szene".
Bewege ich ein Objekt von der Bühne herunter (aus dem Frustrum raus) dann ist das so, als würde ich in Swing eine Komponente bei negativen Koordinaten zeichnen. 

Ich kann meine Akteure (Swogl-Components) auf der Bühne platzieren, verändern, bewegen und mit ihnen interagieren.
Hier egeben sich vielleicht ein paar sehr Interessante neue Objekte, wie z.B. ein "Vorhang" mit dem man Teile der Szene verdeckt. Vielleicht habe ich die mp3s auf wie bei einem CD-Wechsler auf einem Kreis angeordnet und dann stell ich in die Mitte des Kreises einen "Vorhang", um den hinteren Teil zu verbergen, oder sowas.
Dazu kommen dann Lichteffekte und die Möglichkeit Shader auf die Swogl-Components anzuwenden.
Die extrinsischen Kameraparameter kann ich dann erstmal nicht verändern, weil jede Szene/Einstellung eine feste Kameraposition hat. Ein "Kamerawackeln" als Gag, oder ein Zoom sollte aber schon gehen.
--> Damit lassen sich fast alle diese "DesktopDemos" abbilden, weil dort der Viewport eigentlich kaum verändert wird. Auch 3D-Browser für Musik, Bilder usw. gehen damit gut.

Eine Ebene höher arbeite ich dann nicht mehr nur mit einer Szene sondern mit einer ganzen Bühne.
Ich kann die Kamera in verschiedenen "Einstellungen" platzieren. So wie bei VRML zum Beispiel.
Da wäre es cool, wenn man die life zurechtnavigieren und dann abspeichern könnte.
So baue ich mir ein paar Kamerapositionen für die Bühne und kann zwischen denen umschalten, oder hin- und herfahren usw.
Da brauche ich dann immernoch Listener für die Kamerasteuerung zu schreiben, sondern starte einfach nur die Transition, die mir Swogl dann ausführt.
--> Damit kann ich dann schon etwas mehr machen. Vielleicht trennt man in "Szene" = Die Objekte auf der Bühne (es gibt dann ein entsprechendes Control für jede Szene) 
und in "Einstellung" = die Kameraposition (von denen kann es auch pro Szene mehrere geben)

Und noch eine Ebene höher benutze ich ein eigenes Bühnen-Objekt, oder verwende die Kamera ohne Bühne. (je nach dem, wie das API gemacht ist)
Und erst dort würde ich mir gedanken über "glRotate" machen müssen.

Ich weiß, das klingt ziemlich nach Theatertechnik und Flash. Da kommt es auch her. Aber solche gegenständlichen Schnittstellen bieten eigentlich eine schön greifbare und intuitive Art der Kontrolle.
Die mental workload ist bei 3D ja sowieso schon hoch genug.


----------



## Marco13 (9. Aug 2011)

Das könnte schwierig werden - und es könnte sogar sein, dass gerade die Kamera noch im "swogl-core" enthalten sein wird. Die Kamera beschreibt (zusammen mit der View) die Sicht auf die Szene - sowas wie Zoom und FOV machen ohne Kamera ja keinen Sinn (neben near- und far clipping plane und viewport, die in der View stecken). Oder so: Wenn man Swogl ohne Kamera und View anbieten wollte, wären sie immernoch DA, bestenfalls aber künstlich versteckt. 

Ich finde aber auch, dass das nicht geeignet ist, um damit die "Trennlinie" zu charakterisieren (ohne jetzt auf dieser Trennlinie zu sehr rumreiten zu wollen). Man kann ja jeden Effekt, den man durch Kamerabewegung erreichen kann, auch durch Bewegung der Szene erreichen. Als plakativ-Beispiel: Wenn jemand mit Swogl eine Bildergallerie bauen will, durch die man sich mit einem First-Person-Control durchbewegt, dann könnte er das auch erreichen ohne die Kamera zu bewegen, und man würde keinen Unterschied sehen (indem eben die "inverse Bewegung" auf alle Objekte angewendet wird). Aber die Kamera zu bewegen wäre dann doch leichter und intuitiver. 

Die Metapher der "Bühne" leuchtet zwar an sich ein, und wie gesagt, du scheinst eine recht konkrete Vorstellung zu haben. Ich bin mir nicht sicher, welche Aufteilung oder Struktur der API für welchen Anwendungsfall die geeignetste ist. Grundsätzlich dachte ich an mehrere Ebenen (unabhängig davon, ob sich die "nur" als Packages oder als eigene JARs manifestieren) :

- Core: Die rohe Funktionalität, Swing auf Flächen zu pappen. Man kann die Flächen (und, so war es bisher gedacht, auch die Kamera) durch explizite, händisch-programmatische Aufrufe von [c]component.setTransform(matrix);[/c] oder [c]camera.setViewPoint(point);[/c] positionieren. Das ganze umfasst keine Interaktion und keine Animation.

- Layout3D und Kamerasteuerung: Klassen, die Methoden anbieten, um Swogl-Components (oder auch die Kamera) anuzordnen oder zu bewegen. Auch hier NUR Methoden, die man aufrufen kann, aber immernoch getrennt von irgendwelchen Eingaben. Man kann z.B. in einem Thread [c]wheelLayout.rotateAbout(1)[/c] aufrufen, um das WheelLayout eine Folge von Bildern durchrotieren zu lassen. 

- Interaktion: Der ursprüngliche Grund für diesen Thread  Es gibt verschiedene Controls, die beliebig (und einfach und flexibel) kombiniert werden können, um die Layouts und die Kamera zu steuern.

- Animation: Das, was du jetzt schon einige Male angedeutet hast: Man kann Pfade definieren, an denen SwoglComponents oder die Kamera entlangfliegen. Das "gut" zu machen ist nochmal ein dickes Brett, an dem ich demnächst weiterbohren werde. Aber auch wenn die eigentlichen Layout3D-Implementierungen die Animationsklassen _verwenden_ könnten (und damit einfacher zu implementieren wären) hielt ich die eigentliche Funktionalität der Layouts und der Animationsklassen nach außen hin (!) für unabhängig voneinander. 




> Und noch eine Ebene höher benutze ich ein eigenes Bühnen-Objekt, oder verwende die Kamera ohne Bühne. (je nach dem, wie das API gemacht ist)
> Und erst dort würde ich mir gedanken über "glRotate" machen müssen.



Was ein 'glRotate' mit der obersten Ebene, die ja eigentlich von allem am weitesten abstrahieren soll, zu tun hat, hat sich mir jetzt nicht ganz erschlossen ... ???:L



> Ich weiß, das klingt ziemlich nach Theatertechnik und Flash. Da kommt es auch her. Aber solche gegenständlichen Schnittstellen bieten eigentlich eine schön greifbare und intuitive Art der Kontrolle.
> Die mental workload ist bei 3D ja sowieso schon hoch genug.



Hmja, ich bin nicht sicher, ob ich alles richtig verstanden habe. Es klang nach einer anderen Sicht- oder Herangehensweise. Als wäre die Trennung bzw. die "Ebenen" eher danach ausgerichtet, welche Arten von Szenen modelliert werden können, und teilweise welche Arten von Objekten in der Szene ansprechbar sind. Wie vielleicht aus den Stichpunkten oben deutlich wurde, hatte ich eher eine rein funktionale Trennung der Aspekte vorgesehen. Die ... Begründung dahinter (kann ich vielleicht nicht mal sooo konkret artikulieren, aber) geht in die Richtung, dass die Aspekte
- Objekte anzeigen (SwoglComponent und Camera)
- Objekte programmatisch bewegen (Layout3D und Arcball)
- Objekte interaktiv bewegen (Controls, die Layout3D und Arcball steuern) 
- Objekte automatisch bewegen (Mit Animationen)
aufeinander aufbauen, und eigentlich unabhängig davon sind, wie sie im Einzelfall kombiniert werden. Aber es stimmt schon, dass die Animation teilweise orthogonal zu den anderen ist und darauf Einfluß haben kann. Ich werde mal überlegen, die man den Animationsteil gestalten könnte, und dann schauen, wie das mit den anderen Teilen zusammenspielen könnte.


----------



## Marco13 (10. Aug 2011)

Hab' mal die aktuelle Version auf Swogl hochgeladen. Dort sind in der ZIP jetzt zwei getrennte JARs, eine für Swogl selbst, und eine "swogl-demos.jar" mit den inoffiziellen Hilfsklassen. Werde bei Gelegenheit mal schauen, wie man Animationen da reinbringen kann, und natürlich immernoch wie man die Sache mit den Interaktionen und Listenern (besser) gestalten kann. Vorschläge dazu sind immer gern gesehen.


----------

