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 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.
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.
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 Bilddateien, sondern auch Bilddaten 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.