Commit
This commit is contained in:
parent
f72fbd85b0
commit
1da915d263
|
@ -1,5 +1,5 @@
|
|||
\documentclass{scrartcl}
|
||||
\usepackage[utf8x]{inputenc}
|
||||
\usepackage{import}
|
||||
\usepackage[frenchb]{babel}
|
||||
\usepackage{amssymb}
|
||||
\usepackage{lmodern}
|
||||
|
@ -9,7 +9,12 @@
|
|||
\usepackage{graphicx}
|
||||
\usepackage{amsmath}
|
||||
\usepackage{multicol}
|
||||
\usepackage[hidelinks]{hyperref}
|
||||
% \usepackage[hidelinks]{hyperref}
|
||||
\usepackage[colorlinks = true,
|
||||
linkcolor = blue,
|
||||
urlcolor = blue,
|
||||
citecolor = blue,
|
||||
anchorcolor = blue]{hyperref}
|
||||
\usepackage{cpp}
|
||||
\usepackage{tikz}
|
||||
\usepackage{pgfplots}
|
||||
|
@ -45,8 +50,10 @@
|
|||
\newcommand{\hsc}[1]{{\Large\MakeUppercase{#1}}}
|
||||
\newcommand{\hscs}[1]{{\footnotesize\MakeUppercase{#1}}}
|
||||
|
||||
\newcommand{\threejs}{\href{http://threejs.org/}{Three.js}}
|
||||
\newcommand{\socketio}{\href{http://socket.io/}{Socket.IO}}
|
||||
\newcommand{\threejs}{\href{http://threejs.org/}{Three.js }}
|
||||
\newcommand{\socketio}{\href{http://socket.io/}{Socket.IO }}
|
||||
\newcommand{\jsdoc}{\href{http://usejsdoc.org/}{JSDoc }}
|
||||
\renewcommand{\include}[1]{\import{./}{#1.tex}}
|
||||
|
||||
\newcommand{\namedparagraph}[1]{\paragraph{#1}\mbox{}\\}
|
||||
|
||||
|
@ -55,6 +62,10 @@
|
|||
\draw (#1,-6) node[below]{#2};
|
||||
}
|
||||
|
||||
\makeatletter
|
||||
\@addtoreset{section}{part}
|
||||
\makeatother
|
||||
|
||||
\begin{document}
|
||||
|
||||
\begin{titlepage}
|
||||
|
@ -102,563 +113,21 @@
|
|||
\newpage
|
||||
|
||||
|
||||
\part*{Introduction}
|
||||
\include{intro}
|
||||
\newpage
|
||||
|
||||
\part{Choix des technologies et prise en main}
|
||||
\paragraph{}
|
||||
La première phase de stage était de choisir les technologies qui allaient être
|
||||
utilisées par la suite. Nous cherchions des technologies permettant la
|
||||
visualisation 3D sur un navigateur web afin de pouvoir faire une étude
|
||||
utilisateur simplement.
|
||||
|
||||
\section{Côté client}
|
||||
\paragraph{}
|
||||
Pour le côté client, il y avait plusieurs possibilités :
|
||||
\begin{itemize}
|
||||
\item WebGL, la spécification des fonctions permettant la 3D dans le
|
||||
navigateur
|
||||
\item Une librairie facilitant l'utilisation de WebGL
|
||||
\item Du code C++ compilé en JavaScript grâce à Emscripten
|
||||
\item N'importe quel moteur graphique qui puisse exporter vers JavaScript
|
||||
\end{itemize}
|
||||
|
||||
\paragraph{}
|
||||
La plupart des moteurs graphiques exportant vers JavaScript sont putôt lourd à
|
||||
prendre en main, et nous voulions garder des solutions simples, c'est pourquoi
|
||||
nous avons utilisé une librairie libre nommée \threejs permettant une
|
||||
utilisation facile de WebGL.
|
||||
|
||||
\paragraph{}
|
||||
Pour des raisons de simplicité, nous avons décidé de développer le code client
|
||||
pour Google Chrome et Firefox, les autres navigateurs ne sont donc pas
|
||||
(officiellement) supportés.
|
||||
|
||||
\section{Côté serveur}
|
||||
\paragraph{}
|
||||
Dans un premier temps, seul le côté client était pris en compte. Les programmes
|
||||
étaient écrits en JavaScript et ne nécessitaient pas de serveur. Quand les
|
||||
problématiques de dynamicité sont arrivées, il a fallu choisir une technologie
|
||||
pour le côté serveur, et là, tous les langages étaient possibles.
|
||||
|
||||
\paragraph{}
|
||||
Plusieurs langages et framework ont été téstés. Quand les problématiques
|
||||
étaient encore simples (passage d'un paramètre dans une requête), on a commencé
|
||||
par utiliser le php, puis on s'est tourné vers des scripts CGI en python. Quand
|
||||
de plus nombreuses pages ont été nécessaires, on a commencé à chercher un vrai
|
||||
framework, et on s'est penché sur Django (framework web pour Python) qui est
|
||||
très pratique mais assez coûteux en mémoire vive (le serveur était alors
|
||||
herbergé sur une petite machine de 512Mo de RAM).
|
||||
|
||||
\paragraph{}
|
||||
Quand les problématiques de streaming ont commencé à apparaître, nous avons
|
||||
choisi la simplicité en utilisant Node.js pour le côté serveur (un serveur
|
||||
écrit en JavaScript) à cause de la présence d'une librairie nommée \socketio
|
||||
qui s'avère très pratique pour la communication entre le client et le serveur.
|
||||
Pour des raisons pratiques, le serveur a été herbergé sur un cloud gratuit
|
||||
(OpenShift).
|
||||
|
||||
\section{Base de données}
|
||||
\paragraph{}
|
||||
Pour le système de gestion de base de données, nous avons choisi Postgres (qui
|
||||
est libre et qui a largement fait ses preuves). OpenShift propose d'héberger
|
||||
lui-même la base de données, mais la version gratuite ne proposant qu'1 Go
|
||||
d'espace de stockage, nous avons préféré l'héberger nous-même.
|
||||
|
||||
|
||||
\section{Développement, debug et déploiement}
|
||||
\paragraph{}
|
||||
Pour éviter d'avoir des fichiers trop longs, nous avons choisi de séparer les
|
||||
sources dans de nombreux fichiers de taille plus petite, et de les fusionner
|
||||
automatiquement. Pour le développement, ils seront simplement concaténés grâce
|
||||
à un script développé spécialement pour cela, qui mime les paramètres de
|
||||
Closure Compiler qui sera utilisé pour la fusion au moment du le déploiement
|
||||
(ce dernier permet non seulement la fusion des fichiers mais aussi la
|
||||
minification\footnote{la minification sert notamment à réduire la taille du
|
||||
script : n'oublions pas que nous parlons de serveur web, et il est donc
|
||||
intéressant de réduire la taille des programmes de sorte à les charger plus
|
||||
rapidement} (effacement des commentaires et des retours à la ligne,
|
||||
simplifications des noms de variables et plus \footnote{en JavaScript, il est
|
||||
plus court d'écrire \texttt{!0} pour \texttt{true} par exemple.}). Pour le
|
||||
développement, on a utilisé \href{https://github.com/remy/nodemon}{nodemon} et
|
||||
inotify, qui permettent de relancer le serveur local lorsqu'une modification
|
||||
est détectée (la fusion des fichiers est donc réeffectuée).
|
||||
|
||||
\paragraph{}
|
||||
En ce qui concerne le versionnage des fichiers, nous avons utilisé Git avec
|
||||
deux \emph{repositories} :
|
||||
\begin{itemize}
|
||||
\item le premier, hébergé sur
|
||||
\href{https://github.com/tforgione/3dinterface}{Github}, sert au
|
||||
développement, et contient les fichiers fractionnés ainsi que les
|
||||
outils permettant la génération des fichiers fusionnés.
|
||||
\item le deuxième, hebergé chez OpenShift, qui contient la version finale
|
||||
du programme, permet de déployer le code du serveur quand les
|
||||
\emph{commits} sont \emph{pushés}.
|
||||
\end{itemize}
|
||||
|
||||
\paragraph{}
|
||||
Pour nous aider au debug, nous avons utilisé \href{http://jshint.com/}{JSHint}
|
||||
qui nous aide à détecter les erreurs potentielles liées aux subtilités du
|
||||
langage.
|
||||
|
||||
\include{techno}
|
||||
\newpage
|
||||
\part{L'interface}
|
||||
\section{Interactions élémentaires}
|
||||
\paragraph{}
|
||||
La première interface a été pensée pour être la plus simple possible.
|
||||
L'utilisateur contrôle une caméra qui se déplace librement dans un modèle 3D.
|
||||
|
||||
\paragraph{}
|
||||
La translation de la caméra est contrôlée par le clavier : les touches Z, Q, S,
|
||||
et D servent respectivement à avancer, aller à gauche, reculer et aller à
|
||||
droite (de même que les touches fléchées).
|
||||
|
||||
\paragraph{}
|
||||
On peut pivoter la caméra de plusieurs manières :
|
||||
\begin{itemize}
|
||||
\item via le pavé numérique (2, 4, 6, et 8 pour tourner respectivement vers
|
||||
le bas, vers la gauche, vers la droite et vers le haut)
|
||||
\item via la souris, comme \emph{drag-n-drop}, en cliquant un point de la
|
||||
scène et en le déplaçant
|
||||
\item via la souris, en mode \emph{pointer-lock}, comme dans un jeu video
|
||||
de tir
|
||||
\end{itemize}
|
||||
|
||||
|
||||
\section{Les recommandations}
|
||||
\paragraph{}
|
||||
Les recommandations sont là pour suggérer des points de vue à l'utilisateur.
|
||||
Elles permettent d'aider la navigation. Elles sont affichées sous forme
|
||||
d'objets 3D ajoutés à la scène. Deux affichages ont été testés.
|
||||
|
||||
|
||||
\subsection{Les \emph{viewports}}
|
||||
\paragraph{}
|
||||
Les \emph{viewports} sont les affichages les plus simples : ils représentent
|
||||
une caméra, avec son centre optique et son plan image.
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[scale=0.275]{img/new/01.png}
|
||||
\caption{Une recommandation \emph{viewport}}
|
||||
\end{figure}
|
||||
Cette façon d'afficher une recommandation a l'avantage d'être simple, de ne pas
|
||||
beaucoup masquer le reste des modèles et suggère assez bien l'idée d'un
|
||||
\emph{point de vue recommandé}, mais elle a l'inconvéniant d'être ambigüe à
|
||||
cause de la perspective (dans cette image, il peut être difficile de savoir si
|
||||
le point de vue et vers le modèle ou vers nous).
|
||||
|
||||
|
||||
\subsection{Les flèches}
|
||||
\paragraph{}
|
||||
Les flèches sont supposées être plus intuitives pour un utilisateur qui n'a pas
|
||||
l'habitude des \emph{viewports} précédemment utilisés. Plutôt que de suggérer
|
||||
un point de vue, elles suggèrent le mouvemement qui va mener à ce point de vue.
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[scale=0.275]{img/new/02.png}
|
||||
\caption{Des recommandations flèches}
|
||||
\end{figure}
|
||||
|
||||
\subsection{Les interactions}
|
||||
\subsubsection{Au survol}
|
||||
\indent Cette fonctionnalité est inspirée des récents lecteurs video sur le
|
||||
web. Lorsque l'on regarde une video, on a la barre de \emph{seeking} en bas et
|
||||
passer le curseur sur cette barre affiche l'image de la vidéo à l'instant visé.
|
||||
Nous avons simplement adapté cette techniques à nos recommandations : lorsque
|
||||
le curseur survole une recommandation, une prévisualisation est affichée dans
|
||||
une petite boite au voisinage du curseur.
|
||||
|
||||
\begin{figure}[H] \centering
|
||||
\includegraphics[scale=0.275]{img/new/03.png}
|
||||
\caption{Une prévisualisation}
|
||||
\end{figure}
|
||||
|
||||
\subsubsection{Au clic}
|
||||
\indent Lors d'un clic sur une recommandation, la caméra suit un mouvement
|
||||
fluide jusqu'au point de vue recommandé. La trajectoire est définié par un
|
||||
polynôme interpolant tel que :
|
||||
\begin{itemize}
|
||||
\item la position initiale est la position de la caméra
|
||||
\item la position finale est la position de la recommandation
|
||||
\item la dérivée de la trajectoire à l'instant final est la direction de la
|
||||
recommandation
|
||||
\end{itemize}
|
||||
|
||||
\paragraph{}
|
||||
Ce mouvement fluide est là pour ne pas perturber l'utilisateur qui pourrait
|
||||
\emph{se perde} si jamais il était téléporté
|
||||
|
||||
\paragraph{}
|
||||
De plus, les recommandations se comportent comme des liens hypertextes : elles
|
||||
sont bleues si elles n'ont jamais été clicées, et deviennent violettes si
|
||||
l'utilisateur les a déjà consommées. Ceci est fait pour qu'un utilisateur
|
||||
puisse savoir par où il est passé, et ce qui lui reste encore à visiter.
|
||||
|
||||
|
||||
\section{Autres éléments de navigation}
|
||||
\paragraph{}
|
||||
Pour faciliter la navigation, quelques autres éléments de navigation sont
|
||||
présents.
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\begin{tikzpicture}[]
|
||||
\node (myfirstpic) at (0,0) {\includegraphics[scale=0.35]{img/new/buttons.png}};
|
||||
\tikzvline{-7}{1}
|
||||
\tikzvline{-5.8}{2}
|
||||
\tikzvline{-5.2}{3}
|
||||
\tikzvline{-4}{4}
|
||||
\tikzvline{-1.5}{5}
|
||||
|
||||
\draw (8,5) -- (7,5);
|
||||
\draw (8,5) node[right]{6};
|
||||
|
||||
\draw (-8,5) -- (-7,5);
|
||||
\draw (-8,5) node[left]{7};
|
||||
\end{tikzpicture}
|
||||
\caption{Les différents éléments de l'interface}
|
||||
\end{figure}
|
||||
|
||||
\include{interface}
|
||||
\newpage
|
||||
\paragraph{}
|
||||
\begin{enumerate}
|
||||
|
||||
\item \emph{Reset camera} : pour chaque scène, une position initiale est
|
||||
définie. Cliquer sur ce bouton ramène la caméra à sa position initiale.
|
||||
|
||||
\item \emph{Previous} : à chaque clic sur une recommandation, les positions
|
||||
intiales et finales sont sauvegardées. Cliquer sur ce bouton ramène à
|
||||
la position précédente.
|
||||
|
||||
\item \emph{Next} : cliquer sur ce bouton ramène à la position suivante.
|
||||
|
||||
\item \emph{Pointer lock} : permet de passer du mode \emph{pointer-lock} au
|
||||
mode \emph{drag-n-drop} et vice-versa.
|
||||
|
||||
\item \emph{Music} : un lecteur qui contrôle une petite musique qui permet
|
||||
de se mettre dans l'ambiance de la scène.
|
||||
|
||||
\item \emph{Coin gauge} : une jauge qui représente l'avancement de la
|
||||
récupération des pièces.
|
||||
|
||||
\item \emph{FPS counter} : indique la période de rafraîchissement du rendu.
|
||||
|
||||
\end{enumerate}
|
||||
|
||||
|
||||
\include{userstudy}
|
||||
\newpage
|
||||
\part{L'étude utilisateur}
|
||||
\paragraph{}
|
||||
Pour tester le comportement des utilisateurs face aux recommandations, nous
|
||||
avons dissimulé des pièces rouges à travers ces modèles, et nous avons demandé
|
||||
à des utilisateurs de les trouver.
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[scale=0.275]{img/new/04.png}
|
||||
\caption{Une pièce rouge}
|
||||
\end{figure}
|
||||
|
||||
\paragraph{}
|
||||
Pour éviter la dépendance entre les recomendations et les pièces rouges (si les
|
||||
recommandations visent les pièces rouges, il est évident qu'il sera très facile
|
||||
de les trouver avec les recommandations), un système de tirage aléatoire de
|
||||
pièces rouges a été fait.
|
||||
|
||||
\section{Déroulement de l'expérience}
|
||||
\subsection{Première page}
|
||||
La première page présente rapidement l'expérience. Elle vérifie aussi le
|
||||
navigateur : si le client est sur Google Chrome ou Firefox, un lien apparaîtra
|
||||
pour passer à la suite, sinon, un message d'erreur s'affichera.
|
||||
|
||||
\subsection{Identification}
|
||||
Cette page nous permet d'en savoir un peu plus sur l'utilisateur : nous allons
|
||||
demander l'age, le sexe et les habitudes en terme de jeux video de
|
||||
l'utilisateur (nous avons considéré que la capacité des utilisateurs à manier
|
||||
notre interface allait dépendre fortement de leur habitude aux jeux video).
|
||||
Nous leur demandons notamment de noter leurs capacités en terme de jeux videos
|
||||
(entre 1 et 5 étoiles).
|
||||
|
||||
\subsection{Tutoriel}
|
||||
Ensuite, nous demandons à l'utilisateur de suivre un tutoriel : c'est une sorte
|
||||
de réelle expérience mais guidée. Des messages indiquant les interactions à
|
||||
faire aideront l'utilisateur à s'habituer à cette interface. On y présente les
|
||||
moyens de déplacer la caméra, puis les recommandations et les différents
|
||||
boutons de l'interface.
|
||||
|
||||
|
||||
\subsection{Les trois vraies expériences}
|
||||
C'est ensuite que la \emph{vraie} partie de l'étude utilisateur commence : à 3
|
||||
reprises, l'utilisateur va se retrouver dans une scène avec certaines pièces
|
||||
rouges à trouver, et un certain style de recommandations\footnote{aucune
|
||||
recommandation sera considéré comme un style de recommandation, de sorte à
|
||||
comparer la présence à l'absence de recommandation pour la navigation} pour
|
||||
l'aider. Nous expliquerons dans la sous-section \ref{selection} comment le
|
||||
choix de la scène et du style de recommandation sera fait.
|
||||
|
||||
\paragraph{}
|
||||
Dans chacune des expériences, l'utilisateur devra chercher des pièces rouges,
|
||||
en s'aidant (ou pas) des recommandations. L'expérience se terminera soit quand
|
||||
l'utilisateur aura trouvé les huit pièces rouges, soit une minute après avoir
|
||||
trouvé la 6\up{ème} pièce rouge. Pour éviter que l'utilisateur soit
|
||||
\emph{frustré} de ne pas avoir trouvé toutes les pièces, nous n'indiquons pas
|
||||
clairement le nombre de pièces qu'il a, ou qu'il lui reste à trouver.
|
||||
Simplement, une \emph{vague} idée de sa progression.
|
||||
|
||||
\subsection{Le \emph{feedback}}
|
||||
Après avoir fini ces expériences, l'utilisateur se retrouvera sur un formulaire
|
||||
lui demandant son avis quand à la difficulté de l'interface, et l'utilité des
|
||||
recommandations pour se déplacer dans la scène.
|
||||
|
||||
\section{Choix de la scène et du style de recommandations\label{selection}}
|
||||
\paragraph{}
|
||||
Il y a trois scènes disponibles, et sur chaque scène, nous avons placé des
|
||||
pièces dans de nombreuses positions. Lorsqu'un utilisateur commence une
|
||||
expérience, l'algorithme de selection fonctionne de façon à faire des
|
||||
expériences sur les mêmes scènes avec les mêmes dispositions de pièces mais des
|
||||
styles de recommandations différents pour des utilisateurs de même niveau de
|
||||
sorte à pouvoir comparer l'efficacité des recommandations.
|
||||
|
||||
\paragraph{}
|
||||
Nous cherchons en fait des expériences qui permettraient de compléter les trio
|
||||
d'expériences avec des pièces identiques sur des scènes identiques mais avec
|
||||
des styles de recomendations différents. Si une telle expérience n'existe pas
|
||||
(les trios sont déjà complets, ou bien il n'existe pas d'expérience pour un
|
||||
niveau d'utilisateur donné), la scène, ainsi que les pièces à trouver et le
|
||||
style de recommandations seront choisi aléatoirement : on choisira une scène et
|
||||
un style de recommandations que l'utilisateur n'a pas encore effectué, et on
|
||||
choisira 8 pièces aléatoirement parmi les positions possibles que nous avons
|
||||
fixées au préalable.
|
||||
|
||||
\section{Positions possibles des pièces}
|
||||
Pour choisir les positions possibles des pièces dans chaque scène, un petit
|
||||
outil à été développé permettant de se déplacer dans une scène et des créer des
|
||||
pièces en cliquant. Cliquer sur une paroie de la scène crée une pièce devant
|
||||
cette paroie, et cliquer sur une pièce la supprime. Un bouton permet d'envoyer
|
||||
la liste des pièces par mail, lorsque l'on a fini de créer des pièces.
|
||||
|
||||
|
||||
\include{streaming}
|
||||
\newpage
|
||||
\part{Streaming de modèle 3D}
|
||||
Le but ultime de ce projet est de biaiser l'utilisateur avec les
|
||||
recommandations de sorte à être capable de prévoir ses déplacements futurs, et
|
||||
ainsi précharger les parties du modèle qui vont être vues. Cette section
|
||||
présente le travail qui a été réalisé dans le domaine du chargement de modèle.
|
||||
|
||||
\paragraph{}
|
||||
Évidemment, cette partie est celle qui comment après la fin de la première
|
||||
partie : il faut nous seulement connaître l'influence des recommandations sur
|
||||
l'utilisateur, ensuite être capable de prévoir le comportement de
|
||||
l'utilisateur, et enfin s'en servir pour précharger les bonnes parties du
|
||||
modèles. Tout ceci n'étant pas encore possible, le travail qui a été fait est
|
||||
nettement plus simpliste : il n'y aura aucune prévision du comportement ici.
|
||||
|
||||
\section*{Introduction}
|
||||
Notre problématique ici est de transférer des modèles 3D sur le réseau. Les
|
||||
modèles sont stockés sur le serveur au format \texttt{.obj} et sont constitués
|
||||
:
|
||||
\begin{itemize}
|
||||
\item des materiaux (\texttt{usemtl}) : cela définit le matériau utilisé
|
||||
pour les faces qui vont suivre
|
||||
\item de sommets (\emph{vertices}) : des points 3D
|
||||
\item de coordonnées de textures : des points en 2D qui référence un point
|
||||
d'une image
|
||||
\item de normales : des vecteurs en 3D
|
||||
\item de faces : une liste de 3 ou 4 sommets (représentés par leurs
|
||||
indices), avec éventuellement leurs coordonnées de textures et/ou
|
||||
normales
|
||||
\end{itemize}
|
||||
|
||||
\paragraph{}
|
||||
La seule contrainte d'ordre des éléments est qu'une face qui contient des
|
||||
sommets, coordonnées de textures ou normales n'arrive pas avant ses sommets,
|
||||
coordonnées de textures ou normales dans le fichier : si l'on parcourt les
|
||||
lignes du fichier, on doit déjà avoir toutes les informations sur la face.
|
||||
|
||||
\paragraph{}
|
||||
Généralement, le fichier \texttt{.obj} vient souvent avec un fichier
|
||||
\texttt{.mtl} qui contient la définition des matériaux (leurs noms, leurs
|
||||
textures, leurs constantes...).
|
||||
|
||||
\newpage
|
||||
\section{Streaming linéaire}
|
||||
La première étape de cette fonctionnalité a été de faire un système
|
||||
client-serveur permettant le streaming de modèle 3D. En effet, les
|
||||
\emph{loaders} de modèles présents dans la libraire \threejs ne permettent pas
|
||||
le chargement progressif : ils se content d'envoyer une requête vers le fichier
|
||||
contenant le modèle et à créer un modèle une fois que le fichier est chargé
|
||||
complètement.
|
||||
|
||||
\paragraph{}
|
||||
Pour commencer, nous avons donc utilisé \socketio, une librairie permettant de
|
||||
gérer les sockets facilement avec JavaScript et Nodejs, pour faire une première
|
||||
version simpliste du streaming : on travaillait sur un modèle ne contenant que
|
||||
des sommets et des faces (donc pas de textures ni de normales) et le protocole
|
||||
fonctionnait ainsi :
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\begin{tikzpicture}[]
|
||||
\draw (0,0) node[above]{Client};
|
||||
\draw (0,0) -- (0,-6);
|
||||
\draw (5,0) node[above]{Serveur};
|
||||
\draw (5,0) -- (5,-6);
|
||||
|
||||
\draw (2.5,-1.3) node[rotate=-12] {Path jusqu'au modèle};
|
||||
\draw[->] (0,-1) -- (5, -2);
|
||||
|
||||
\draw (2.5,-2.3) node[rotate=12] {Des éléments};
|
||||
\draw[<-] (0,-3) -- (5, -2);
|
||||
|
||||
\draw (2.5,-3.3) node[rotate=-12] {ACK};
|
||||
\draw[->] (0,-3) -- (5, -4);
|
||||
|
||||
\draw (2.5,-4.3) node[rotate=12] {D'autres éléments};
|
||||
\draw[<-] (0,-5) -- (5, -4);
|
||||
|
||||
\draw (2.5,-6) node{$\vdots$};
|
||||
\end{tikzpicture}
|
||||
\caption{Transmission élémentaire\label{transmission1}}
|
||||
\end{figure}
|
||||
|
||||
\paragraph{}
|
||||
Le serveur envoyait alors les éléments dans l'ordre dans lequel ils étaient
|
||||
présents dans le fichier du modèle 3D. Le gros inconvéniant de cette méthode
|
||||
est que souvent, les sommets sont présents au début du fichier, et les faces
|
||||
vers la fin : nous recevons donc des informations de sommets au début qui ne
|
||||
nous permettent rien d'afficher, puis toutes les faces d'un coup, ce qui fait
|
||||
que le streaming n'est pas aussi progressif que l'on souhaiterais.
|
||||
|
||||
\paragraph{}
|
||||
Dans le cas d'un modèle sans coordonnées de textures et sans normales, la seule
|
||||
condition pour pouvoir afficher une face est d'avoir envoyé les sommets qui la
|
||||
composent. On peut donc améliorer la fluidité en réarrangeant le fichier
|
||||
\texttt{.obj} : il suffit de faire apparaître les faces dès que les sommets
|
||||
sont disponibles.
|
||||
|
||||
\paragraph{}
|
||||
Dans le cas où l'on souhaite gérer les textures et les normales, utiliser cette
|
||||
technique est beaucoup plus compliqué puisqu'il faut aussi décider de l'ordre
|
||||
relatif entre les sommets, coordonnées de textures et normales : en effet, pour
|
||||
envoyer une face le plus tôt possible, il faut que toutes ces composantes
|
||||
soient envoyés, et il est donc nécessaire de mélanger les sommets, coordonnées
|
||||
de texture et normales.
|
||||
|
||||
\newpage
|
||||
\section{Streaming linéaire amélioré}
|
||||
La remarque précédente conduit directement à cette méthode. Le principe reste
|
||||
le même que celui précédent (figure \ref{transmission1}), mais les éléments
|
||||
seront envoyés différemment : on va en fait parcourir les faces directement.
|
||||
|
||||
\paragraph{}
|
||||
Le serveur va garder en mémoire ce qui a déjà été envoyé et ce qui ne l'a pas
|
||||
été, et envoyer les faces dans l'ordre : si certains éléments des faces n'ont
|
||||
pas encore été envoyé, on les enverra juste avant d'envoyer la face en
|
||||
question.
|
||||
|
||||
\paragraph{}
|
||||
On peut de cette façon à la fois gérer les coordonnées de texture et les
|
||||
normales, tout en envoyant les faces le plus tôt possible (on peut aussi noter
|
||||
que si certains sommets / coordonnées de textures / normales sont inutilisés
|
||||
dans les faces, ils ne seront pas envoyés et on s'évite donc de transférer des
|
||||
données inutiles).
|
||||
|
||||
\paragraph{}
|
||||
C'est dans cette version que nous avons commencé à nous intéresser à la façon
|
||||
de gérer les matériaux. Dans \threejs, un objet 3D est lié à un materiau, et
|
||||
nous sommes donc obligés de créer autant d'objets que de materiaux. Pour cela,
|
||||
nous avons légèrement modifié notre protocole :
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\begin{tikzpicture}[]
|
||||
\draw (0,0) node[above]{Client};
|
||||
\draw (0,0) -- (0,-8);
|
||||
\draw (5,0) node[above]{Serveur};
|
||||
\draw (5,0) -- (5,-8);
|
||||
|
||||
\draw (2.5,-1.3) node[rotate=-12] {Path jusqu'au modèle};
|
||||
\draw[->] (0,-1) -- (5, -2);
|
||||
|
||||
\draw (2.5,-2.3) node[rotate=12] {Liste des matériaux};
|
||||
\draw[<-] (0,-3) -- (5, -2);
|
||||
|
||||
\draw[dashed, ->] (-0.1,-3) -- (-0.1,-4);
|
||||
|
||||
\draw (2.5,-3.3) node[rotate=-12] {ACK};
|
||||
\draw[->] (0,-3) -- (5, -4);
|
||||
|
||||
\draw (2.5,-4.3) node[rotate=12] {Des éléments};
|
||||
\draw[<-] (0,-5) -- (5, -4);
|
||||
|
||||
\draw (2.5,-5.3) node[rotate=-12] {ACK};
|
||||
\draw[->] (0,-5) -- (5, -6);
|
||||
|
||||
\draw (2.5,-6.3) node[rotate=12] {D'autres éléments};
|
||||
\draw[<-] (0,-7) -- (5, -6);
|
||||
|
||||
\draw (2.5,-8) node{$\vdots$};
|
||||
\end{tikzpicture}
|
||||
\caption{Transmission avec gestion des matériaux}
|
||||
\end{figure}
|
||||
|
||||
\paragraph{}
|
||||
Les directives de matériau à utiliser (\texttt{usemtl}) seront ignorées, et les
|
||||
faces seront envoyées avec l'indice de l'objet auquel elles appartiennent, ce
|
||||
qui permettra au client de savoir dans quel objet (et donc avec quel matériau)
|
||||
elles doivent être ajoutées.
|
||||
|
||||
\newpage
|
||||
\section{Streaming intelligent}
|
||||
C'est la dernière version du streaming qui a été faite sur ce projet. À chaque
|
||||
transfert, le client envoie sa position au serveur (ainsi que les plans
|
||||
définissant son \emph{frustum}\footnote{les bords du champ de vision de la
|
||||
caméra}) et le serveur va parcourir les faces du modèle en cherchant celles qui
|
||||
apparaissent dans le \emph{frustum}\footnote{dans cette version, on considère
|
||||
qu'une face apparaît dans le \emph{frsutum} si un de ces sommets y appartient.
|
||||
Évidemment, une face très grande pourrait appraître dans le \emph{frustum}
|
||||
sans qu'aucun de ses sommets n'y soit, mais nous n'avons pas traité ce cas
|
||||
particulier ici.}. On évite ainsi d'envoyer les faces du modèle qui sont
|
||||
derrière la caméra et que l'utilisateur ne voit pas.
|
||||
|
||||
\paragraph{}
|
||||
Bien sûr, si il n'y a plus de faces dans le \emph{frustum} de la caméra, on va
|
||||
envoyer les faces en suivant la méthode de la section précédente.
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\begin{tikzpicture}[]
|
||||
\draw (0,0) node[above]{Client};
|
||||
\draw (0,0) -- (0,-8);
|
||||
\draw (5,0) node[above]{Serveur};
|
||||
\draw (5,0) -- (5,-8);
|
||||
|
||||
\draw (2.5,-1.3) node[rotate=-12] {Path jusqu'au modèle};
|
||||
\draw[->] (0,-1) -- (5, -2);
|
||||
|
||||
\draw (2.5,-2.3) node[rotate=12] {Liste des matériaux};
|
||||
\draw[<-] (0,-3) -- (5, -2);
|
||||
|
||||
\draw[dashed, ->] (-0.1,-3) -- (-0.1,-4);
|
||||
|
||||
\draw (2.5,-3.3) node[rotate=-12] {Caméra / \emph{frustum}};
|
||||
\draw[->] (0,-3) -- (5, -4);
|
||||
|
||||
\draw (2.5,-4.3) node[rotate=12] {Des éléments};
|
||||
\draw[<-] (0,-5) -- (5, -4);
|
||||
|
||||
\draw (2.5,-5.3) node[rotate=-12] {Caméra / \emph{frustum}};
|
||||
\draw[->] (0,-5) -- (5, -6);
|
||||
|
||||
\draw (2.5,-6.3) node[rotate=12] {D'autres éléments};
|
||||
\draw[<-] (0,-7) -- (5, -6);
|
||||
|
||||
\draw (2.5,-8) node{$\vdots$};
|
||||
\end{tikzpicture}
|
||||
\caption{Version finale}
|
||||
\end{figure}
|
||||
|
||||
\newpage
|
||||
\part*{Conclusion}
|
||||
\include{conclusion}
|
||||
|
||||
\label{end}\end{document}
|
||||
|
|
Loading…
Reference in New Issue