rapport

publicité
Romain V ERGNE
[email protected]
visualisation non-photoréaliste de scènes urbaines sur
terminaux mobiles
août 2007
Encadrant
:
Xavier G RANIER
INRIA Futurs,
LABRI, Domaine Universitaire, 351, cours de la Libération, 33405 TALENCE
Contexte et objectifs du stage
L’objectif de ce stage est d’améliorer le rendu de façades stylisées de Quillet et al. [QTM05, QTG+ 06]
dans le cadre d’un contrat avec France Télécom. Leur travail consiste à utiliser les techniques de rendus
non photoréalistes pour détecter et afficher les lignes des façades sur un grand modèle 3D urbain. Il s’agit
d’un plugin de la plateforme Elkano [Mar04] dont le but est de visualiser rapidement une grande quantité de
données sur terminaux mobiles avec une approche client serveur. Leur méthode est la suivante :
1. détection des arêtes sur les textures des façades des batiments (précalculs),
2. vectorisation de ces arêtes : création de couples de points définissant le point d’origine et le point
d’arrivé de chaque ligne (précalculs),
3. pendant l’affichage, le serveur envoie ces couples sur le réseau,
4. le client reçoit les points et affiche les lignes correspondantes.
F IG . 1: Pipeline utilisé par Quillet et al. [QTM05, QTG+ 06].
Les points forts
– Une faible quantité de données transite sur le réseau. les lignes sont envoyées à la place d’une texture et
cela peut diminuer la taille des données à envoyer d’un facteur de 10.
– leur méthode est progressive. Le serveur n’envoit pas toutes les lignes d’un seul coup. L’affichage des
lignes coté client se fait donc petit à petit.
– Ils utilisent une approche multirésolution. Suivant la distance d’une façade par rapport à l’observateur,
le nombre de lignes affichées ne sera pas le même. Plus la façade est proche, plus il y aura de détails et
inversement.
Les points faibles
– Les lignes reçues par le client ne sont pas affichées sous forme de texture, mais avec des traits dans
l’espace 3D. Ils sont placés à coté des façades (car cela provoque des erreurs de gestion de profondeurs en
les positionnant exactement sur les murs), il y a donc un espace entre les façades et les lignes. Il en résulte
aussi un problème lié aux faces arrières. Lorsqu’on est positionné derrière un bâtiment, ses façades ne
s’affichent pas forcément, mais les traits le sont obligatoirement. Il apparait donc parfois les lignes d’un
bâtiment que l’on ne voit pas.
– Leur méthode est limitée à l’affichage des lignes. Elle ne permet pas de faire d’autres types de rendu
non-photoréalistes.
2
Objectifs du stage
– Généraliser les travaux de Quillet et al. [QTM05, QTG+ 06] en utilisant des textures vectorielles [Gro03].
Ces textures ont la particularité d’être indépendantes de la résolution souhaitée et sont généralement beaucoup moins volumineuses que les textures matricielles.
– Utiliser la spécification d’OpenVG [wg07] qui permettra d’obtenir un rendu rapide avec les clients dotés
d’un processeur graphique vectoriel.
– Créer de nouveaux rendus pour illustrer la généricité de la méthode.
Fonctionnement
Vue d’ensemble
La plateforme Elkano lit des fichiers vrml [vrm97] et fonctionne avec un graphe de scène. Il est possible de
personnaliser les noeuds du graphe de scène comme on l’a fait ici pour afficher des textures vectorielles.
Prenons l’exemple d’un fichier vrml simple :
DEF objet Transform {
children
Shape {
appearance Appearance {
texture ImageTexture {
url "grid.svg"
}
}
geometry
Box { size 3 3 3 }
}
translation
1 0 0
}
Un visualiseur quelconque ne pourrait pas lire ce fichier car il ne connait pas le format SVG pour une
texture. Nous avons mis en place un plugin permettant de les lire. Celui-ci est alors automatiquement appelé
lorsqu’une telle texture est trouvée. Le pipeline utilisé est illustré par la Figure 2 :
F IG . 2: Pipeline (simplifié) utilisé pour le plugin de rendu de textures vectorielles
Le serveur lit le fichier SVG (avec la bibliothèque libsvg [lib05]), récupère chacun des éléments dans un
tableau, puis les envoit au client (qui peut lui en demander seulement un certain nombre). Le client utilise
alors la biblothèque OpenVG [wg07] pour afficher les éléments dans une texture qui est ensuite plaquée sur
les façades des bâtiments.
3
Principales méthodes
La classe TextureVecNodeCreator contient les méthodes qui associent la plateforme Elkano à notre plugin
(PLGTextureVec). La méthode getExtensions permet de dire pour quel type de fichier un noeud TextureVecNode doit être créé. Il est aussi possible d’aller chercher des informations dans les fichiers de configuration.
Nous permettons au client d’influencer la taille des packets qui transitent sur le réseau car nos textures sont
progressives (fichier Magellan/Scripts/{Linux|Win32|WinCE}/client.cfg), nous y reviendrons plus tard.
La classe TextureVecNode contient les méthodes principales pour lire coté serveur et afficher coté client.
Voici une description des principales méthodes publiques utilisées :
– computeVS (héritée de MGFNode) : méthode appelée à chaque rendu et utilisée par le client pour demander un certain nombre d’éléments SVG au serveur.
– settleInPVS (héritée de MGFNode) : méthode utilisée pour créer et initialiser la texture qui sera affichée
(PVS=Potentially Visible Set). Au cas où on y passe plusieurs fois, on dispose d’une variable qui permet
de savoir si la texture concernée est déjà visible (et dans ce cas, pas besoins de la créer de nouveau).
– removeFromPVS (héritée de MGFNode) : destruction de la texture.
– serialize (héritée de MGFNodeRemote) : le serveur utilise cette méthode pour transmettre des données au
client via le réseau.
– unserialize (héritée de MGFNodeRemote) : le client reçoit les données du serveur.
– mergeImport (héritée de MGFProgressiveNode) : si ce n’est pas la première fois que le client reçoit des
données du serveur, alors le noeud du graphe de scène qui reçoit ces données n’est pas le client mais un
noeud temporaire. Cette méthode est donc utilisée par le noeud temporaire pour récupérer les variables
nécessaires au calcul de la progression dans le véritable client. Nous l’utilisons ici pour récupérer le
contexte EGL, obligatoire pour créer des éléments OpenVG. Cette fonction est bloquante, il ne faut donc
pas trop mettre de calculs à l’intérieur.
– mergeCompute (héritée de MGFProgressiveNode) : on vient de récupérer les variables avec la méthode
précédente ; on peut donc s’en servir ici. On l’utilise pour activer le contexte EGL associé aux éléments
que l’on veut créer (celui qui correspond au noeud du “vrai” client).
– mergeExport (héritée de MGFProgressiveNode) : méthode opposée à mergeImport. Le noeud temporaire
va envoyer les changements au client. Il demande au client de créer les éléments OpenVG qu’il a reçu
(fonction bloquante).
– activate (héritée de MGFTextureNode) : activation de la texture par le client.
– inactivate (héritée de MGFTextureNode) : désactivation de la texture par le client.
– refreshResident (héritée de MGFResidentNode) : méthode appelée à chaque rendu et utilisée par le client
pour raffraichir la texture (seulement si nécessaire : si on a desssiné de nouveaux éléments).
Seule la fonction serialize est utilisée par le serveur. Toutes les autres sont spécifiques au client.
Déroulement
Lorsqu’une texture SVG est détectée dans le fichier vrml, deux noeuds TextureVecNode sont créés : le premier pour le serveur et le second pour le client. Ces noeuds sont créés par le biais de la classe TextureVecNodeCreator qui va au préalable chercher la taille des paquets qui transitent sur le réseau dans le fichier de
configuration du client.
La fonction serialize du serveur est alors appelée pour envoyer les premières données au client. La première
fois que l’on passe dans cette fonction, le fichier SVG est parcouru grâce à la bibliothèque libsvg [lib05].
4
On dispose alors d’un graphe composé d’éléments svg. Ces élements sont placés dans un tableau (fonction
serializeRec) pour faciliter leur parcours. La méthode findSizeMinMax est ensuite utilisée pour calculer les
dimensions de la texture SVG : largeur, hauteur et taille totale en octets. En effet, une texture vectorielle
n’est pas forcément centrée sur l’origine. Une fois ces paramètres calculés, ils sont envoyés au client qui les
reçoit avec la fonction unserialize.
Celui-ci calcule le nombre d’éléments SVG qui doit être envoyé par le serveur dans chacun des paquets.
La client demandera toujours à recevoir au minimum un élément, même si la taille moyenne d’un élément
est plus grande que la taille d’un paquet. Il ne sert a rien de demander la moitié d’un élément puisqu’il ne
pourrait pas être affiché correctement. Le contexte EGL [wg05a] qui permet de mettre en place une surface
de dessin pour les méthode d’OpenVG [wg07] est alors créé. EGL permet de dessiner sur plusieurs types de
surfaces :
– dans une fenêtre existante (comme glut),
– dans un “pbuffer” qui, par exemple, peut être une image OpenVG ou une texture OpenGL ES,
– dans un “pixmap” (une grille).
On se sert ici d’un pixmap qui est simple d’utilisation et qui permet de transformer la grille en texture
OpenGL facilement, mais il faudra surement essayer les pbuffer pour dessiner directement dans une texture
(puisque c’est ce qu’on veut au final). Pour le moment il y a encore une petite transition entre le pixmap et
la texture que nous verrons plus loin. Le contexte ainsi créé doit enfin être activé. A noter qu’un élément
OpenVG créé dans un contexte ne peut pas être dessiné sur une surface qui est associée à un autre contexte.
Il faut donc penser à activer le contexte courant du noeud sur lequel on travaille avant d’utiliser les méthodes
OpenVG (un nouveau contexte est créé pour chacune des textures SVG du fichier vrml).
Si la façade du bâtiment est visible, la fonction settleInPVS est appelée. On y crée la texture OpenGL et
on l’associe au pixmap. C’est aussi dans cette méthode que l’on dit à Elkano que le noeud est résident,
de manière à ce que la fonction refreshResident soit appelée à chaque rendu (pas la peine de raffraichir la
texture si elle n’a pas encore été créée). La fonction activate est aussi appelée à chaque rendu pour activer la
texture qui correspond au noeud courant.
La méthode suivante est computeVS dans laquelle le client demande au serveur de lui envoyer des éléments,
par rapport au nombre d’éléments contenus dans un paquet et à ceux qui ont déjà été reçus. C’est ici que
le client recharge le noeud courant, de manière à ce que la méthode serialize du serveur soit appelée de
nouveau (et ceci, jusqu’à ce que tous les éléments soient reçu).
Coté serveur, c’est la seconde fois que la fonction serialize est appelée. On envoie donc le nombre d’éléments
souhaité par le client sur le réseau (fonctions serializeTable et serializeStyle). Une des contraintes du stage
a été de ne pas utiliser d’autres bibliothèques que OpenVG et OpenGL du coté du client pour que le plugin
puisse être utilisé par le plus grand nombre de clients possible. Il faut donc convertir les éléments SVG
du serveur (qui sont propres à la bibliothèque libsvg) avant de les envoyer. Chacun des éléments SVG est
associé à un style (taille des traits, couleur des traits, couleur de remplissage, ...) qui est aussi envoyé au
client. Pour le moment, nous avons mis en place un style minimal (couleurs et tailles des traits) et nous
traitons seulement les chemins et les rectangles pour les éléments.
Comme on l’a vu tout à l’heure, ce n’est pas le client qui reçoit ces éléments, mais un noeud temporaire (car
ce n’est pas la première fois que l’on passe dans la fonction unserialize). On crée alors un tableau d’éléments SVG avec une structure temporaire (voir fichier Inc/Plugin/svgData.h). On pourrait vouloir construire
directement les éléments OpenVG, mais cela est impossible car on ne connait pas le contexte qui doit leur
être associé. En effet, les fonctions relatives aux noeuds progressifs qui nous auraient permis de récupérer ce
5
contexte ne sont appelées qu’après, d’ou la nécessité de se servir de tableaux temporaires pour les éléments
et leur styles.
Seulement ensuite, les fonctions mergeImport, mergeCompute et mergeExport du noeud temporaire sont appelées successivement. On récupère alors le contexte dans la première, on l’active dans la seconde et on crée
les éléments OpenVG dans le client avec la troisième (sans oublier de détruire les éléments temporaires au
fur et à mesure). Les fonctions permettant de créer les éléments OpenVG sont createVGPaint (pour le type)
et createVGPath et createVGRect pour les éléments. Lorsque tous les éléments ont été créés, les variables
du client sont mises à jour (notamment le fait que la texture doit être rafraichie) et le noeud temporaire est
détruit.
Lorsque la fonction refreshResident du client est appelée, les nouveaux éléments sont dessinés dans le pixmap avec les fonction d’OpenVG (drawElements) et la texture associée est rafraichie. Le client peut alors
demander de nouveaux éléments s’il ne les a pas déjà tous reçu.
Travaux futurs
– Tester l’application sur un client disposant d’une accélération vectorielle. Pour le moment, le dessin des
éléments OpenVG est très lent (et c’est normal). Pour essayer sous Linux ou Windows, il serait intéressant
d’utiliser la bibliothèque AmanithVG [ama06] qui est entièrement développée à partir d’OpenGL et qui
permet donc d’émuler l’accélération vectorielle. C’est impossible pour le moment car cette bibliothèque
utilise son propre système de fenêtrage pour dessiner, mais elle devrait implémenter les fonctionnalités
d’EGL sous peu. A suivre ...
– La texture actuellement utilisée est une texture OpenGL. Elle devra être convertie en texture OpenGL ES
pour pouvoir être utilisée avec des clients tels que les PDA ou les téléphones mobiles. Cette conversion
devrait être très rapide : les fonctions utilisés sont toutes présentes (à quelques différences près) dans la
spécification d’OpenGL ES [wg05b].
– Utiliser un pbuffer (et non un pixmap) comme surface EGL et l’associer à OpenGL ES pour dessiner les
éléments OpenVG directement dans une texture OpenGL ES (c’est expliqué dans la spécification d’EGL
[wg05a]). Les données contenues dans les pixmaps sont stokées sous la forme ABGR, il est donc nécessaire de les modifier avant de créer la texture pour obtenir des pixels RGBA. Pour contourner ce problème
il serait possible d’utiliser l’extension GL_EXT_abgr que possède la plupart des cartes graphiques pour le
format des textures. Néanmoins, l’utilisation d’une texture OpenGL ES comme surface éviterait l’appel à
glTexImage2D et permettrait un rendu plus rapide que l’utilisation de pixmaps.
– Seule la génération automatique des mipmaps est utilisée pour afficher les textures. Celle-ci n’est pas
toujours la plus efficace, notamment pour l’affichage des lignes dans lesquelles les mipmaps provoquent
un effet de flou avec des lignes qui deviennent grises lorsque les textures s’éloignent de l’observateur. Par
exemple, le rendu correspondrait beaucoup plus à nos attentes avec la méthode de Barla et al. [BTS05]. Ils
permettent de fusionner des lignes sans pour autant changer leur densité lorsque les textures s’éloignent.
– Lire le fichier SVG dans son intégralité. Pour le moment, on ne s’occupe que des chemins et des rectangles.
Ils existe beaucoup d’autres éléments possibles : cercles, ellipses, lignes, textes et images. Même chose
pour le style associé à chacun des éléments. Pour le moment, on ne s’occupe que des couleurs simples. Il
faut gérer les couleurs de type “gradient” et “pattern”, ainsi que les différents styles d’écriture, de jointures
pour les lignes, ...
– Compresser les données qui transitent sur le réseau pour gagner en vitesse.
6
Compilation / exécution
Bibliothèques nécessaires
Les bibliothèques doivent être placées dans le répertoire Libraries de Magellan
– Expat (version 2.0.1) [exp07] : utile pour libsvg et disponible sur http ://expat.sourceforge.net/ en précompilé. Il existe aussi des packages pour Linux.
– libsvg (version 0.1.4) [lib05] : utile au serveur pour lire le fichier SVG et disponible sur http ://cairographics.org/. Cette bibliothèque est disponible sous forme de packages pour Linux. Néanmoins, il est
préférable d’utiliser la version donnée avec Elkano car elle contient les fichiers utiles à la compilation
sous windows. De plus, on utilise ici un fichier interne à la bibliothèque (fichier svgint.h) qui n’est pas
disponible en installant simplement un package.
– OpenVG (version 1.0.1) [wg07] : utile au client pour dessiner les éléments SVG et disponible sur
http ://www.khronos.org/openvg/. Cette bibliothèque est disponible en précompilée seulement pour Windows. Elle a été légèrement modifiée pour compiler sous Linux. Il est donc encore une fois conseillé
d’utiliser celle qui est fournie avec Elkano.
Compilation du plugin
La compilation se fait de la même manière que pour les autres plugins : répertoire Bld/vc8.0/ pour Windows
et répertoire Bld/Unix/ pour Linux.
Exécution
Avant tout, mettre à jour les variables d’environnement dans les scipts d’exécution (répertoire
Magellan/Scripts/{Linux|Win32|WinCE}/). Par exemple, sous Linux, il faut ajouter les lignes
setenv LD_LIBRARY_PATH ${LD_LIBRARY_PATH}:${EXTERN_LIB_DIR}/ri_package/lib
setenv LD_LIBRARY_PATH ${LD_LIBRARY_PATH}:${EXTERN_LIB_DIR}/libsvg-0.1.4/lib
setenv LD_LIBRARY_PATH ${LD_LIBRARY_PATH}:${PLUGINS_DIR}/PLGTextureVec/Lib/${TARGET}
dans les fichiers client, server, builder, clientLt et clientSW
Il faut aussi ajouter l’existence du plugin dans les fichiers de configuration (dans le même répertoire). Ajouter
les lignes
<Plugin url="plgTextureVec.so">
</Plugin>
dans les fichiers builder.cfg et server.cfg, et les lignes
<Plugin url="plgTextureVec.so" >
<nodeCreator name="TextureVec">
<packetSize val= 512/>
</nodeCreator>
</Plugin>
dans le fichier client.cfg, en modifiant si besoins la taille des paquets qui transitent sur le réseau.
Modifier aussi le chemin du répertoire contenant les modèles 3D dans le fichier server.cfg :
7
<Config>
<!-- Path to a vrml base -->
<rootPath value="{votre répertoire}/projects/protected/Bases" />
<!-- <rootPath value="Y:\" /> -->
</Config>
Enfin, mettre à jour la base de données des modèles 3D qui se servent de ce plugin. Par exemple, ajouter les
lignes suivantes dans le fichier Bases/db.xml :
<Scene
<Scene
<Scene
<Scene
<Scene
<Scene
<Scene
url="Vectorial/wrl_test_image/testImage.wrl" desc="a textured image" />
url="Vectorial/wrl_test_image2/testImage.wrl" desc="2 textured cube" />
url="Vectorial/BordeauxToon/bordeaux.wrl" desc="city of bordeaux (toon)" />
url="Vectorial/BordeauxToonLines/bordeaux.wrl" desc="city of bordeaux (toon and lines)" />
url="Vectorial/BordeauxLines/bordeaux.wrl" desc="city of bordeaux (lines)" />
url="Vectorial/BordeauxLum/bordeaux.wrl" desc="city of bordeaux (intensity)" />
url="Vectorial/BordeauxLines2/bordeaux.wrl" desc="city of bordeaux (lines 2)" />
Il est maintenant possible d’exécuter l’application :
– Lancer le serveur (fichier Magellan/Scripts/{Linux|Win32|WinCE}/server)
– Cliquer sur le menu “Database”, puis sur “Generate” (les scènes du fichier db.xml doivent alors être
trouvées)
– Lancer le client (fichier Magellan/Scripts/{Linux|Win32|WinCE}/client)
– Cliquer sur le menu “File” puis “Browse server”
– Dans Url, mettre “mgf ://localhost”, puis cliquer sur Ok (ici encore le client doit trouver les scènes)
– Cliquer sur le menu Scenes, puis choisir celle que vous voulez afficher
Parmis les scènes disponibles, on distingue notamment des scènes de test et la scène de Bordeaux stylisée avec plusieurs méthodes : effet cartoon, détection des arêtes, seuillage. Pour transformer les textures
originales en textures SVG, nous nous sommes servis du logiciel Inkscape (www.inkscape.org).
8
Bibliographie
[ama06]
Amanithvg. 2006.
[BTS05]
Pascal Barla, Joëlle Thollot, and François Sillion. Geometric clustering for line drawing simplification. In Siggraph technical sketch : SIGGRAPH’2005, 2005.
[exp07]
The expat xml parser. 2007.
[Gro03]
The SVG Working Group. Scalable vector graphics (svg) 1.1 specification. 2003.
[lib05]
libsvg. 2005.
[Mar04]
Jean-Eudes Marvie. Visualisation interactive d’environnements virtuels complexes à travers des
réseaux et sur des machines à performances variables, oct 2004.
[QTG+ 06] Jean-Charles Quillet, Gwenola Thomas, Xavier Granier, Pascal Guitton, and Jean-Eudes Marvie. Using expressive rendering for remote visualization of large city models. In Web3D 2006 :
Proceedings of the 11th International Conference on 3D Web Technology. ACM, ACM Press,
apr 2006.
[QTM05] Jean-Charles Quillet, Gwenola Thomas, and Jean-Eudes Marvie. Client-server visualization of
city models through non photorealistic rendering. Technical report, INRIA, 2005.
[vrm97]
Vrml97 and related specifications. 1997.
[wg05a]
The Khronos EGL working group. Khronos native platform graphics interface (egl version 1.2).
2005.
[wg05b]
The Khronos OpenGL ES working group. Opengl es common profile specification 2.0. 2005.
[wg07]
The Khronos OpenVG working group. Openvg 1.0.1 specification. 2007.
9
Téléchargement