Logo Spiria

Développer pour HoloLens de Microsoft

20 juin 2016.
Cet article détaille les quelques problèmes techniques que nous avons rencontrés lors du développement d’une petite démonstration pour Hololens, démo qui a été déjà présentée sur ce blogue.

Cet article détaille les quelques problèmes techniques que nous avons rencontrés lors du développement d’une petite démonstration pour Hololens, démo qui a été déjà présentée sur ce blogue.

Le choix de Microsoft de faire équipe avec Unity a vraiment beaucoup simplifié la vie des développeurs sur Hololens. Si vous avez déjà quelques connaissances de Unity, vous pouvez progresser très rapidement.

Il y a cependant quelques surprises pour les non-initiés aux applications de réalité augmentée ou virtuelle. Nombre des obstacles que nous avons surmontés lors de la création de cette démo étaient liés à l’interface utilisateur. Elle nécessite en effet une approche très différente de celle des applications Unity traditionnelles.

Grâce à la nature multiplateforme de Unity, la plupart des autres fonctionnalités, comme la physique, l’animation et l’éclairage, ne nécessitent pas de modifications spécifiques pour Hololens

Il y a quelques étapes à passer pour avoir vraiment votre application Unity sur le périphérique Hololens : exporter la solution Visual Studio à partir de Unity, compiler la solution Visual Studio et déployer l’application résultante vers l’émulateur ou le périphérique physique.

Pour itérer rapidement lors du développement, nous avons créé une deuxième scène où nous avons utilisé un contrôleur de jeu à la première personne (first-person controller), un environnement de base avec des plans pour simuler une pièce, et un script d’entrée différent pour remplacer la fonctionnalité de regard (gaze functionality) qui n’est disponible que sur l’émulateur ou les lunettes Hololens.

decorative
Environnement simple

decorative
Vue rapprochée du cerveau

Problèmes d’interface utilisateur

Le réticule, ou pointeur

Microsoft fournit d’excellents tutoriels pour débuter sur Hololens. Dans le “tutoriel 101”, des scripts sont par exemple fournis pour utiliser un pointeur spécial en forme de cylindre, pointeur qui s’oriente de façon perpendiculaire à la surface visée par l’utilisateur.

Cela pourrait être utile pour certains types d’application, mais pour nos besoins, nous voulions un plus traditionnel curseur en superposition (overlay), qui reste fixe au centre de l’écran.

decorative
Pointeur dynamique

decorative
Pointeur fixe

Bon, vous penseriez que ce n’est pas bien grave : “Utilisons une image d’interface Unity en mode superposition”. Malheureusement, on se rend vite compte que cet élément d’interface Unity en superposition n’apparaît tout simplement pas sur le périphérique.

La deuxième tentative fut de placer un disque faisant face à l’utilisateur. Le disque était ajouté en tant que game object enfant de la caméra, de sorte qu’il reste toujours en face de l’utilisateur, peu importe où ce dernier regarde.

C’est là que nous avons heurté ce qui est une fondamentale différence propre aux applications de réalité virtuelle et augmentée. L’effet visuel de cette solution est très inconfortable pour l’utilisateur. Imaginez une pièce de monnaie à une vingtaine de centimètres de vos yeux, et gardez la mise au point sur la pièce tout en regardant l’arrière-plan… Ça ne marche pas. Vous avez besoin que le disque soit assez éloigné pour éviter ce désagréable effet.

L’étape suivante fut de déplacer le disque vers la position du RaycastHit. Le problème était alors que le disque rapetisse. La solution était donc d’éloigner suffisamment le disque et de mettre à l’échelle le disque en fonction de sa distance de la caméra, afin de conserver la taille perçue comme étant constante.

var headPosition = Camera.main.transform.position;
var gazeDirection = Camera.main.transform.forward;

RaycastHit hitInfo;

if (Physics.Raycast(headPosition, gazeDirection, out hitInfo))
{
    Vector3 hitRay = hitInfo.point - headPosition;
    Vector3 headOffset = gazeDirection * distanceToObject;

    if (headOffset.sqrMagnitude > hitRay.sqrMagnitude)
    {
        headOffset = hitRay;
    }

    transform.position = headPosition + headOffset;

    float rayLength = headOffset.magnitude;
    transform.localScale = new Vector3(rayLength, rayLength, rayLength);
}

Bulles de texte

Le problème que nous avons ensuite rencontré était l’affichage de bulles de texte. Nous avons utilisé la même stratégie que pour le disque, car cela aurait été visuellement inconfortable d’avoir le texte en superposition directement en face de la caméra. Nous avons utilisé les coordonnées-monde pour les panneaux de l’interface utilisateur et le texte. La seule particularité est qu’ils ont un script qui met en œuvre un comportement d’affichage qui maintient ces objets (game objects) face à l’utilisateur en permanence.

Ces bulles d’info pointent sur des régions du cerveau. Un simple ramp object du paquet standard prototype a été mis à l’échelle, aplati et positionné à 90 degrés près des panneaux de texte pour créer un effet de flèche. L’origine du game object contenant la flèche et le panneau de texte est placée à l’extrémité pointue ; cet objet est ensuite simplement déplacé vers la partie de cerveau correspondante avec un script.

decorative
Bulle de texte

Boutons

Nous avons trouvé une autre limitation avec le bouton d’interaction, qui est pourtant très facile à réaliser dans Unity. En fin de compte, nous avons dû gérer nos propres focus events pour changer l’état du bouton quand l’utilisateur le regarde. Microsoft fournit un script d’interaction Unity pour l’interface utilisateur ici ; il peut avoir son utilité si vous avez besoin de barres de défilement ou de curseurs dans votre application.

Ainsi, l’interface utilisateur pour les applications virtuelles nécessite une approche bien différente, et après avoir lu un peu à ce sujet, je crois qu’il reste encore de nombreuses bonnes pratiques à découvrir dans ce domaine. Designers UX, vous avez tout un nouveau terrain à conquérir !

Rendu

Ensuite, discutons brièvement de l’ajout de transparence au modèle. Le problème ici est que le mode de transparence du shader tout usage (standard shader) de Unity cause des artefacts étranges sur Hololens. Cela est provoqué par les objets du cerveau qui se chevauchent au niveau de la profondeur. Voici le script de changement de mode de la transparence du shader général que j’avais essayé qui s’affichait correctement sur le PC de bureau.

private void EnableFadeMode(Material material)
{
    material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
    material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
    material.SetInt("_ZWrite", 0);
    material.DisableKeyword("_ALPHATEST_ON");
    material.EnableKeyword("_ALPHABLEND_ON");
    material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
    material.renderQueue = 3000;
}

Nous avons fini par utiliser l’ancien shader de transparence de Unity que nous avons ajouté au package de l’application. Les réglages de Unity pour faire ça sont bien cachés. Vous devez aller à Edit -> Project Settings -> Graphics -> Always Included Shaders. Lorsque des parties du cerveau s’estompent, on passe dynamiquement chaque matériau de son shader initial au shader de transparence.

decorative
Shader tout usage

decorative
Ancien shader

Performance

La performance est l’autre chose avec laquelle nous avons lutté. Le modèle du cerveau que nous avons utilisé, qui peut être divisé en plusieurs parties, a un maillage très détaillé. Nous avons quelque peu atténué ce problème en effectuant une première passe de réduction automatique de maillage (automatic mesh reduction). Nous n’avions pas le temps de refaire entièrement la topologie des objets, de sorte que ça nous laisse quelques heurts lors du déplacement autour du modèle de cerveau. Ce n’est pas qu’Hololens soit trop mollasson, mais ses capacités n’atteignent pas le niveau des cartes graphiques de PC de bureau.

Commandes vocales

C’est une caractéristique de la démo qui a été aisée à mettre en œuvre; tout fonctionnait sans surprise. En utilisant le script fourni dans le “tutoriel 101”, il suffit d’écrire la version texte de la commande et d’ajouter un handler.

Outils Unity et Visual Studio

Voici quelques solutions de contournement pour les quelques erreurs que nous avons rencontré dans Visual Studio :

  1. Il fallait relancer périodiquement Visual Studio pour prévenir l’erreur de déploiement DEP0001.
  2. Erreur de l’outil SerializationWeaver. Assurez-vous que le nom de votre projet Unity ne contient pas d’espaces.

Aussi, avant de faire vos tests sur l’émulateur ou l’appareil HoloLens, assurez-vous de bien reproduire les configurations présentées dans le “tutoriel 100”. Certaines étapes sont omises dans le “tutoriel 101”. Ayant mal configuré un nouveau projet, nous avons été déçus de voir que notre application n’était pas lancée en mode plein écran.

Liens

Quelques liens d’intérêt :

Conclusion

J’espère que ces petits conseils vous aideront à outrepasser les quelques obstacles dans l’accès à cette technologie fascinante que Microsoft a mis à notre disposition.

Bon codage!