|
|
# Ziel des Projekts
|
|
|
# Theoretischer Hintergrund
|
|
|
# Planung
|
|
|
Zu Beginn des Projekts wurde folgender Zeitplan aufgestellt:
|
|
|
|
|
|

|
|
|
|
|
|
Zuerst sollten die Grundlagen für die Umsetzung geschaffen werden: Ein extra Fenster und Unterstützung für das glTF-Format. Danach waren zwei Blöcke geplant in denen inkrementell die Funktionaliät der Konfiguration hinzugefügt werden sollte sowie die Benutzungsoberfläche und die Modelle erstellt werden sollten. Am Schluss sollte die Exportierfunktion implementiert werden.
|
|
|
|
|
|
Während sich manche Teile etwas nach hinten verschoben, konnte der Zeitplan einigermaßen eingehalten werden. Einzig die Erstellung des UIs wurde etwasspäter als geplant begonnen, da die Einarbeitung in CSS und HTML aufwändiger als gedacht war.
|
|
|
|
|
|
Die Einzige Funktion, die aus Zeitgründen nicht implementiert werden konnte, war der Export des Avatars als glTF-Datei. Der Export als Profilbild, sowie als Konfigurationsdatei ist jedoch vorhanden.
|
|
|
|
|
|
# Konzept
|
|
|
Zu Beginn des Projekts wurden einige Konzeptzeichnungen erstellt und erstest Feedback eingeholt.
|
|
|
|
|
|
## UI Zeichnungen
|
|
|
|
|
|
|
|
|
|
|
|
Die Idee war, den Konfigurator bewusst simpel zu halten, damit die Nutzer sich nicht zu sehr mit dem UI beschäftigen müssen und nebenher noch Dinge über sich erzählen können. Die kognitive Last sollte also möglichst gering gehalten werden.
|
|
|
|
|
|

|
|
|
|
|
|
Der Avatar sollte mit verschiedenen, vordefinierten Kleidungsstücken ausgestattet werden können.
|
|
|
|
|
|

|
|
|
|
|
|
Die Farbe der Körperteile sollte sowohl schnell mit vorgegebenen Farben am Rand verändert werden können, als auch auf Wunsch mit einem Farbregler individuell angepasst werden können.
|
|
|
|
|
|
## Technisches Konzept
|
|
|
|
|
|
Technisch sollte sich der Konfigurator an dem bereits existierenden 3D-Viewer orientieren. Dieser nutzt SocketIO um die Kameraposition des Moderators an alle Clients zu schicken. Auf Grund des Feedbacks aus der ersten Präsentation musste dieses Konzept allerdings deutlich erweitert werden.
|
|
|
|
|
|

|
|
|
|
|
|
Um eine Idee für die Umsetzung zu erhalten wurde zuerst der 3D-Viewer Analysiert. Auf Basis dessen wurde nun ein eigenes Konzept für den Konfigurator erstellt:
|
|
|
|
|
|

|
|
|
|
|
|
In diesem Konzept ist allerdings das Feedback aus der ersten Präsentation noch nicht eingearbeitet.
|
|
|
|
|
|
## Feedback
|
|
|
|
|
|
Es war zuerst geplant, dass nur der Moderator den Avatarkonfigurator starten kann und dann alle Mitglieder den gleichen Avatar sehen, während nur der Moderator den Avatar verändern konnte. In der ersten Feedbackrunde wurde aber klar, dass es interessanter wäre, wenn jeder Teilnehmer seinen eigenen Avatar konfigurieren kann und gleichzeitig die Avatare der anderen Teilnehmer sehen kann. So würde die Awareness gesteigert und gleichzeitig die Konversation angeregt.
|
|
|
|
|
|
|
|
|
# Technische Umsetzung
|
|
|
|
|
|
## Allgemein
|
|
|
Der Avatarkonfigurator ist, wie der 3D-Viewer, eine [ThreeJS](https://threejs.org) Anwendung, die in einem eigenen IFrame läuft. Das UI des Konfigurators ist im `AvatarConfigurator/index.html` Dokument spezifiziert.
|
|
|
|
|
|
Da ein IFrame ein eigenes Dokument darstellt muss mit Hilfe von `inject*` Funktionen dem Konfigurator der eigene Nutzer, der aktuelle Raum und der SocketIO-Socket übergeben werden.
|
|
|
|
|
|
Ursrünglich war geplant, den Server nicht zu verändern um Merge-Konflikten vorzubeuen. Im Laufe der Zeit zeigte sich aber, dass dies nicht möglich war, da SocketIO auf eine Client-Server Struktur setzt und daher Clients nicht direkt miteinander kommunizieren können.
|
|
|
|
|
|
## Laden des Avatar Configurators
|
|
|
|
|
|
Um den Avatar Configurator anzuzeigen wird, wie beim 3D Viewer ein IFrame Objekt genutzt. Dieses lädt beim Aufruf des Konfigurators in Accelerator die entsprechende Hauptseite des Konfigurators: `public/AvatarConfigurator/index.html`
|
|
|
|
|
|

|
|
|
|
|
|
Um dem Konfigurator mitzuteilen, wer der eigene Nutzer ist, in welchem Raum er sich befindet und welcher SocketIO Socket zur Kommunikation verwendet werden soll, werden von `public/js/uiEvents.js` die Funktionen `injectUser`, `injectRoomImIn` und `injectSocket` aufgerufen. Diese werden wiederum durch `public/AvatarConfigurator/main.js` im IFrame `window` Objekt definiert.
|
|
|
|
|
|
## Modulbeschreibungen
|
|
|
|
|
|
### main.js
|
|
|
Bindet Methoden für das Einfügen des eigenen Nutzers, des eigenen Raumes und des SocketIO-Sockets an das DOM `window` Objekt. Diese werden dann von `uiEvents.js` beim Laden des Konfigurators mit den entsprechenden Parametern aufgerufen.
|
|
|
|
|
|
Ausserdem fügt main.js Avatare für bereits vorhandene Client im Raum hinzu.
|
|
|
|
|
|
### Rendering/Rendering.js
|
|
|
Übernimmt die Initialisierung von ThreeJS und das Rendering. Dazu zählen:
|
|
|
* Beleuchtung
|
|
|
* Kamerablickfeld
|
|
|
* Kamerabewegung durch die Maus
|
|
|
|
|
|
### UI/ConfigurationHandling.js
|
|
|
Übernimmt den Down- und Upload von Avatarkonfigurationen.
|
|
|
|
|
|
### UI/Editing.js
|
|
|
Übernimmt die Körperteilauswahl und deren Färung. Reagiert auf click-Events der Auswahl für die Körperteile und deren Farben.
|
|
|
|
|
|
### UI/FocusManagement.js
|
|
|
Übernimmt das Wechseln zwischen den verschiedenen Avataren.
|
|
|
|
|
|
### UI/ProfilePicHandling.js
|
|
|
Übernimmt das Erstellen und Weiterverarbeiten von Screenshots. Die Screenshots können als Profilbild gesetzt werden und heruntergeladen werden.
|
|
|
|
|
|
### Users/UserManagement.js
|
|
|
Übernimmt das Verwalten des eigenen Nutzers.
|
|
|
|
|
|
### AvatarManagement.js
|
|
|
Verwaltet die Avatare. Fügt neue Avatare für neue Clients hinzu und löscht Avatare für Clients, die den Raum verlassen. Hier wird auch die Körperteil- und Farbverwaltung der Avatare realisiert. Sendet ausserdem entsprechende Netzwerkupdates via SocketHandling.js
|
|
|
|
|
|
### SocketHandling.js
|
|
|
Übernimmt das Senden und Empfangen von SocketIO-Events. Sendet auch die Nachricht um das Profilbild zu aktualisieren.
|
|
|
|
|
|
<div class="panel panel-warning">
|
|
|
**Warning**
|
|
|
{: .panel-heading}
|
|
|
<div class="panel-body">
|
|
|
|
|
|
Alle SocketIO-Events werden in window DOM Events umgewandelt. Dadurch muss kein Modul direkt mit SocketHandling.js verbunden sein, sondern kann mit `window.addEventListener` unabhängig auf Events reagieren.
|
|
|
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
|
|
|
## Kommunikation zwischen Clients und mit dem Server
|
|
|
|
|
|
Zur Kommunkation wirden drei SocketIO Events und zwei expressjs-Routen verwendet.
|
|
|
|
|
|
| Event | Ausgelöst von | Behandelt in |
|
|
|
|-------|---------------|--------------|
|
|
|
| addPeer | server.js | SocketHandling.js |
|
|
|
| removePeer | server.js | SocketHandling.js |
|
|
|
| avatarConfiguratorMessage | SocketHandling.js | SocketHandling.js |
|
|
|
|
|
|
`addPeer` und `removePeer` sind Events die vom Server gesendet werden, sobald ein neuer Teilnehmer einen Raum betritt bzw. verlässt. `avatarConfiguratorMessage` ist ein Meta-Event, das zur Kommunikation der Konfiguratoren untereinander verwendet wird. Innerhalb von `avatarConfiguratorMessage` wird das eigentliche Event spezifiziert. Dieser Ansatz wurde gewählt, um möglichst wenig am Server-Code ändern zu müssen, da der Server jedliche Events weiterleiten muss und Clients nicht direkt miteinander kommunizieren sollten.
|
|
|
|
|
|
| Route | Verb | Aufgerufen von | Request behandelt in | Antwort behandelt in |
|
|
|
|-------|------|--------|--------------|-------------|
|
|
|
| /rooms | GET | UserManagement.js | server.js | UserManagement.js
|
|
|
| /upload | POST | ProfilePicHandling.js | server.js | _keine Anwort vorgesehen_
|
|
|
|
|
|
Die Route `/rooms` wurde dem Server hinzugefügt, um alle Räume abfragen zu können. Dies ist nötig um auch Teilnehmer die vor einem anderen Client bereits im Raum waren, im Konfigurator anzeigen zu können.
|
|
|
|
|
|
Die bereits exisitierende Route `/upload` ist unter Anderem für das Setzen des eigenen Profilbildes verantwortlich. Um nicht nur mit Bild*dateien*, sondern auch Bild*daten* in Form von einer base64 enkodierten DataURLs umgehen zu können, wurde der Server um die entsprechende Funktion erweitert.
|
|
|
|
|
|
## Zustandsverwaltung der Avatare auf dem Server
|
|
|
|
|
|
Um die Zustände von bereits exisitierenden Avataren an neu hinzugekommene Clients schicken zu können, wurde im Server dem `allRoomAttr` für jeden Raum ein neues Objekt `avatarStates` hinzugefügt. Diese Zustände werden mit jedem entsprechenden `avatarConfiguratorMessage`-Event aktualisiert. Verlässt ein Client einen Raum wird auch dessen Avatarzustand gelöscht.
|
|
|
|
|
|
## Anlaufstellen für Veränderungen (Ich will...)
|
|
|
|
|
|
### Einen neuen Button in das UI einfügen
|
|
|
Das UI wird in `index.html` definiert. Das Styling bezieht sich immer auf absolute Koordinaten, da auch das Fenster des IFrames eine feste Größe hat. Auf Events wird in den `UI/*` Modulen reagiert. Hier werden am Anfang vom Code immer die ID's der UI-Elemente definiert, welche dann mit `document.querySelector` abgerufen werden und mit `addEventListener` auf ein Event reagiert werden kann.
|
|
|
|
|
|
### Die Darstellung der Szene ändern (Kamera, Beleuchtung)
|
|
|
Die Darstellung und die Hauptkamera wird in `Rendering.js` definiert.
|
|
|
|
|
|
### Die Erstellung von Profilbildern verändern
|
|
|
Dies wird von `UI/ProfilePicHandling` übernommen. Dazu definiert das Modul eine eigene Kamera, mit der dann nur ein einzelner Frame gerendert wird. Die Bilddaten werden in Form einer DataURL mit PNG-Encoding weiterverwendet.
|
|
|
|
|
|
### Die Materials der 3D Objekte verändern
|
|
|
Alle Objekte werden von `AvatarManagement.js` verwaltet. Wichtig ist, dass jedesmal, wenn ein neues Objekt hinzugefügt wird, die Materials geklont werden, da sonst mehrere Avatare auf das gleiche Event reagieren würden. Dies geschieht in `addUser` und `updateAvatarFromStateIndices`.
|
|
|
|
|
|
### Ein neues Körperteil hinzufügen oder ein altes verändern
|
|
|
Alle 3D Modelle sind in `public/AvatarConfigurator/Models` im glTF-Format gespeichert. **Es wird auch nur glTF als Format unterstützt!** Welche Modelle tatsächlich geladen werden, wird von `public/AvatarConfigurator/configuration.json` bestimmt. Wichtig ist, dass das Objekt `configuration.baseModelAttachments` beim Aufruf von `AvatarManagement.initialize` gelöscht wird. Dieses Vorgehen wurde gewählt, damit die Struktur von `configuration.json` direkt mit der Struktur von `AvatarManagement.models` übereinstimmt. Es können in den einzelnen Kategorieen also beliebig Modelle hinzugefügt, verändert oder entfernt werden. Wird allerdings die Struktur von `configuration.json` verändert, muss dies auch in `AvatarManagement` beachtet werden.
|
|
|
|
|
|
### Eine neue Körperteilkategorie hinzufügen
|
|
|
Das Zuteilen der Körperteile ist indexbasiert. Will man eine neue Kategorie einfügen, so muss dies in `AvatarManagement` and folgenden Stellen geschehen:
|
|
|
* `AvatarManagement.models`
|
|
|
* `AvatarManagement.modelStateIndices`
|
|
|
* `AvatarManagement.modelColors`
|
|
|
* `AvatarManagement.updateAvatarFromStateIndices`
|
|
|
* `AvatarManagement.setBodyPartColor`
|
|
|
* `AvatarManagement.loadModelsFromConfig`
|
|
|
|
|
|
Zugleich muss auch die Struktur von `public/AvatarConfigurator/configuration.json` entsprechen angepasst werden.
|
|
|
|
|
|
# Evaluation
|
|
|
|
|
|
## Bekannte Probleme
|
|
|
* Die Konfiguratoransicht wird immer dann, wenn der Moderator eine andere Ansicht (Präsentation, Youtube etc.) wählt, ausgeblendet.
|
|
|
# Fazit |
|
|
\ No newline at end of file |