Données cartographiques vectorisées, extrudées et spatialisées.
Ou le pipeline GeoJSON, D3.js vers Three.js. Cela fait un moment que nous n'avions pas fait de projet Three.js ! Nous jouons surtout avec Unity, mais c'est toujours agréable de revenir…
Aujourd'hui, la réalité virtuelle (VR) est sans doute le sujet le plus brûlant pour les développeurs interactifs (la réalité augmentée sera sûrement la prochaine tendance d'ici quelques années). De nombreux constructeurs proposent leur propre casque de réalité virtuelle (HMD)…

Aujourd’hui, la réalité virtuelle (VR) est sans doute le sujet le plus brûlant pour les développeurs interactifs (la réalité augmentée sera très certainement la prochaine tendance d’ici quelques années). De nombreux constructeurs proposent leur propre casque de réalité virtuelle (HMD) : HTC & Valve avec le Vive, Oculus, avec son Oculus Rift et son Gear VR pour les mobiles Samsung, Google et son très bon marché Google Cardboard à monter soi-même, et bien d’autres encore. Naturellement, Unity, qui est le logiciel leader mondial de l’industrie du jeu vidéo (45% de parts de marché, 47% des développeurs), a rapidement proposé des fonctionnalités intégrées pour gérer certains de ces dispositifs de VR.
À la fin de l’année dernière, on nous a demandé de créer des outils Unity pour prototyper rapidement des visites virtuelles avec le Google Cardboard. C’était le projet parfait pour plonger plus profondément dans l’univers de la VR. Ici, les visites virtuelles étaient un ensemble de photo-spheres et de video-spheres, qui sont respectivement des photos et des vidéos projetées à l’intérieur de sphères, donnant l’impression d’être entouré par le décor (pensez à Google Street View). De plus, certaines parties des photo-spheres devaient être interactives et afficher du contenu additionnel comme des photos, des vidéos, du texte, …
À l’heure actuelle, Unity ne prend pas nativement en charge le Google Cardboard et vous devrez suivre quelques étapes avant de créer votre première application. Naturellement, Google a fourni un guide si vous voulez vous lancer avec le Cardboard. Patrick Catanzariti a également réalisé un très bon tutoriel pour des fonctionnalités plus avancées comme la détection du regard.
Mais, mais, mais, Clay Bavor, le vice-président de la division réalité virtuelle de Google, a annoncé lors du Vision Summit que les développeurs pourront utiliser le Cardboard directement dans Unity sans avoir besoin de plugins ou d’installations séparées. Victoire ! ✌🏻
Je vais ici parler un peu de la détection des zones interactives de nos photo-spheres. Comme ces zones doivent être précises, nous ne pouvions pas utiliser une méthode simple consistant à placer des colliders par exemple entre la caméra et la photosphère, ni utiliser un algorithme permettant de résoudre le problème du point dans un polygone (PIP). J’ai implémenté une solution basée sur la détection de la couleur des pixels d’une texture de “masque”.
Pour l’exemple, allons faire un tour au Palais de Hellbrunn en Autriche. Je m’intéresse beaucoup à trois tableaux et je veux les détecter. Je vais créer une texture où les trois zones sont colorées dans une couleur spécifique, le reste étant en noir. Ensuite, à chaque rotation de la caméra, un rayon est lancé depuis la caméra vers le centre de l’écran (représentant le regard de l’utilisateur). Quand le rayon rencontre le collider de la sphère représentant ma scène (sur laquelle la photo à 360° est mappée), je récupère la couleur du pixel de la texture de masque en utilisant [RaycastHit.textureCoord](http://docs.unity3d.com/ScriptReference/RaycastHit-textureCoord.html) et [Texture2D.GetPixelBilinear](http://docs.unity3d.com/ScriptReference/Texture2D.GetPixelBilinear.html). Si la couleur correspond à la couleur d’une zone interactive, je déclenche l’action associée à cette zone interactive !

Texture à 360° mappée sur une sphère aux normales inversées, et son masque associé
Pour indiquer à l’utilisateur qu’une action est possible s’il clique en regardant une zone interactive, j’utilise un shader que j’ai créé pour surligner la zone interactive survolée. Ce shader utilise la texture standard, la texture de “masque” et deux couleurs : la couleur de la zone à surligner, et la couleur de surlignage.
Tout d’abord, si vous prévoyez de créer une application / un jeu en VR, quel que soit l’appareil utilisé, gardez à l’esprit que la réalité virtuelle ne fonctionne pas comme n’importe quelle application / jeu classique. Vous devriez suivre certaines règles, joliment décrites par Google dans son guide 📄, ou dans son application 📱.
Voici quelques astuces à propos du plugin Google Cardboard pour Unity, en attendant que l’intégration native soit disponible :
CardboardMain dans toute votre application. Sinon, vous risquez d’avoir un flash blanc au chargement d’une nouvelle scène, ce qui est très désagréable pour l’utilisateuruiLayerEnabled à false. Vous pourrez toujours afficher la boîte de dialogue des paramètres en appelant `Cardboard.SDK.ShowSettingsDialog()`Cardboard.SDK.VRModeEnabled. Ajouter un delegate pour indiquer que le mode a changé peut être une bonne idéeAlors, qui a dit que la VR n’était réservée qu’à la réalité ? Une petite demande, mais intéressante, nous est parvenue, et nous avons pensé qu’elle valait la peine d’être mentionnée, car la VR peut être bien plus que ce qui est devenu banal aujourd’hui, comme les concerts en vidéo 360°, etc.
On nous a donné une large illustration 2D d’une ville en nous demandant si nous pouvions en faire quelque chose de “VR”. Nous avons relevé le défi.
L’illustration complète, que nous ne pouvons pas montrer telle quelle, présente simplement un ensemble de monuments du Caire au 14e siècle (si je ne me trompe pas). On y trouve des marchés, des pyramides, des mosquées à côté d’églises, beaucoup de sable, un peu de verdure et des gens partout. L’idée était d’afficher quelques informations sur ces monuments après les avoir regardés pendant quelques secondes - ce serait là tout l’intérêt de cette petite visite en réalité virtuelle de la ville dessinée à la main et sans respect d’échelle.
Projeter sur un carré ou un cercle était évidemment hors de question puisque l’image n’était pas prévue pour cela, mais elle semblait pouvoir être transformée en une simple vue panoramique à 180° (sur un cylindre). Nous avons donc d’abord essayé cette approche.
À partir de l’image aplatie, nous générions un mesh en forme de plan, que nous projetions sur un demi-cylindre. Cela permettait de regarder à 90° à droite et à gauche et de voir quelque chose d’intéressant, mais sans aucune profondeur.
Nous avons ensuite séparé les personnages de l’arrière-plan, retiré le véritable fond (ciel, sable) et utilisé une skybox par défaut ainsi qu’un terrain avec une texture de sable très subtile (presque une couleur unie pour correspondre à l’illustration).
Le mesh se retrouvait alors dans un environnement vide, mais c’était déjà mieux que rien. Nous avons aussi un peu sculpté le Terrain.
Puis une idée nous est venue à l’esprit. Pourquoi ne pas régénérer le mesh, mais cette fois en rapprochant certains sommets vers le centre du cylindre, de sorte que certains éléments de l’image soient plus proches que d’autres - donnant enfin un peu de profondeur à cette image 2D… Alors même que nous n’avions aucun modèle 3D.
Une heightmap grossière avec quelques dégradés a donc été créée : 
Comme nous avions divisé l’image en arrière-plan (monuments) et premier plan (personnages), une heightmap a également été créée pour ce dernier 
Nous avions donc 2 meshes à la même position, un pour chaque calque de l’image… Et nous avons enfin ressenti un peu de profondeur. Toujours pas de la vraie 3D… Mais plus ni plat ni sans vie non plus.
(Voici le mesh d’arrière-plan) <
Le point de vue se trouvait au centre du cylindre, de sorte que le spectateur ne voyait qu’un minimum d’étirement de texture, et nous n’avons pas poussé trop loin l’échelle de la heightmap.
Malgré tout, c’était mieux que rien et c’était acceptable. Il ne nous restait plus qu’à placer des colliders sur chaque monument et à créer une popup UI en world space pour l’utilisateur, à une distance agréable pour les yeux.
À ce stade cependant, une approche complètement différente a également été envisagée et testée, celle qui peut sembler la plus évidente aujourd’hui… En effet, jusque-là, nous voulions rester le plus proche possible de l’original tout en y introduisant de la profondeur, en n’ayant promis aucun miracle puisque nous n’avions aucune ressource pour la modélisation 3D, etc.
Mais on nous avait évidemment demandé une expérience VR. Nous avons donc mis cela de côté et sommes repartis de zéro… Notre client n’avait qu’une vague idée du résultat final, sans avoir formulé de demande particulière, mais était tout de même satisfait de ce que nous avions jusque-là. Nous nous sommes dit qu’autant faire quelque chose de radicalement différent tout en tirant le meilleur de cette image.
Chaque élément a donc été découpé de l’illustration originale, puis simplement placé dans le monde autour de l’utilisateur… et en mode Billboard, chaque élément (des sprites en somme) faisait toujours face à l’utilisateur, quoi qu’il arrive. (cela peut poser problème avec de grands sprites proches qui tournent visiblement lorsque vous tournez, donc attention).
Nous pouvions dupliquer des arbres, sculpter davantage le terrain, isoler la pyramide et la placer à une distance et une échelle considérables afin que tout paraisse beaucoup plus naturel en termes de perception de profondeur et d’échelle pour l’utilisateur, éliminant ainsi les incohérences que nous aurions eues avec l’approche du mesh unique… Le résultat, bien que personne n’ait été convaincu quand nous l’avons présenté - ce qui se comprend - était quelque chose sur lequel nous avions bien plus de contrôle, plus riche que tout ce que nous aurions pu faire autrement (sans avoir à toucher à un quelconque logiciel de modélisation 3D), et finalement une expérience VR digne de ce nom.

Pour être honnête, l’utilisateur se rend quand même compte qu’il a un tas de “personnages façon Paper Mario” autour de lui, mais c’est bien plus intéressant et immersif d’être entouré de gens, de lieux et de sons. Les personnes qui allaient découvrir cela étaient des gens qui, à l’époque, n’avaient probablement même jamais entendu parler de la VR.
Des sons (boucles et oneshots) ont été ajoutés dans l’espace 3D (marché, mosquée, zone portuaire) pour donner encore plus de vie à l’ensemble. À l’époque, nous n’utilisions pas de plugin audio pour l’audio binaural, mais nous avons quand même mis en place une forme basique de filtrage : selon l’angle de vue relatif à chaque objet sonore, cet objet sonore était filtré (filtre passe-bas) de sorte que les sons situés derrière le spectateur avaient moins de hautes fréquences… Cela n’a rien à voir avec ce qui se passe réellement dans la vraie vie… Mais cela aide à se concentrer sur ce que l’on regarde, puisque tout ce qui vous entoure, à l’exception de ce que vous regardez, est un peu “flouté auditivement”.
Voici une capture vidéo du résultat final (un peu tremblante et sans son malheureusement)
2D running with VR par Da Viking Code sur Vimeo.