Tuto: Créer et utiliser un maillage de navigation avec Babylon.js

Il est très courant, lors de développement de jeux vidéo ou d'applications que l'on ait besoin de pouvoir déplacer un personnage d'un point à un autre. Les collisions physiques le permettent en gérant les interactions avec les obstacles mais cette méthode est largement trop coûteuse en ressources sur une grande scène. Cet article va vous permettre de trouver votre chemin dans le labyrinthe de BabylonJS !

Attention, cet article date de plus de 2 ans maintenant... Il est possible que les infos publiées ne soient plus correctes aujourd'hui...

1ère étape : Création du maillage de navigation (ou navigation mesh)

Le maillage de navigation est tout simplement la zone sur laquelle vous allez pouvoir vous déplacer. Si vous avez des notions de théorie des graphes, le maillage de navigation est considéré comme un graphe : les triangles sont des nœuds et les arrêtes voisines entre triangles sont des liaisons.

Pour créer ce maillage, il faut d'abord ouvrir notre scène avec Blender.

Maillage avec Blender

Note 1 : il n'est vraiment pas important de savoir maîtriser Blender pour générer ce maillage.
Note 2 : des dizaines d'importeurs existent pour les .obj et encore .json pour Blender.

Une fois Blender ouvert, il faut le mettre en mode "Game" avec une vue "Game Logic". Ces 2 informations sont dans la barre d'outils.

Vue Game Logic

Ce mode va nous permettre d'accéder aux paramètres de la création du maillage en bas à droite de l'écran en cliquant sur la petite icone "Type of active data to display and edit".

Game menu

Une série de paramètres apparaît permettant de configurer à notre guise le maillage, le mieux est de tester chacun des paramètres pour faire un maillage vraiment personnalisé mais je vais quand même décrire leur utilité :

Propriété

  • Cell size permet de définir la taille des triangles du maillage à créer. Ce paramètre va permettre de réduire la complexité du maillage, mais les espaces étroits de la scène ne vont pas être accessible.
  • Cell Height définit la hauteur du maillage de navigation. En général, il est préférable de le laisser au minimum pour prendre en compte tous les obstacles de la scène.
  • Height est la hauteur minimum à avoir. Typiquement, ce paramètre est intéressant lorsque la scène contient des tunnels ou des ponts.
  • Radius, ou rayon, est l'écart entre le bord et la zone praticable. Encore une fois, il faut faire attention aux zones étroites avec ce paramètre.
  • MaxSlope est la pente max que le personnage pourra monter et Max Climb est la hauteur max que le personnage pourra grimper.
  • Min Region et Merged R permettent d'éliminer des zones trop petites, par exemple le dessus d'un cube, qui sont des obstacles ou autres faces trop petites pour être considérées comme "walkable".
  • Vert Per Poly permet de définir la taille des cellules.

Il est obligatoire d'avoir un paramètre Verts Per Poly à 3 car les maillages utilisés dans Babylon.js sont constitués exclusivement de triangle.

Une fois tous ces paramètres initialisés, il ne nous reste plus qu'à cliquer sur le bouton "Build navigation mesh" et le tour est joué. En général, la génération de ce maillage n'est pas bonne du premier coup et il faut affiner ces paramètres. Pour les utilisateurs de Blender avancés, la modification du maillage en "edit mode" ne pose aucun problème, il faut juste éviter de créer des triangles dégénérés.

Maillage de navigation final

Il ne vous reste plus qu'à exporter la totalité du maillage dans le format souhaité.

Il est possible d'exporter en .babylon avec ce lien et toute l'explication du processus est expliquée ici.

2ème étape : Intégration dans Babylon.js

La 1ère étape n'a posé aucun problème, la 2ème est encore plus simple.

Il faut d'abord ajouter le package babylon-navigation-mesh à votre projet :

npm install babylon-navigation-mesh --save

Ou cloner ce répo Gihub.

git clone git@github.com:wanadev/babylon-navigation-mesh.git

Pour les utilisateurs de ThreeJS, ne vous inquiétez pas, PatrolJS permet de faire exactement la même chose avec le même algorithme.

Avec le fichier babylon créé, il nous faut importer la scène 3D avec la fonction BABYLON.SceneLoader.Append("cheminDuMaillage", "scene.babylon", scene, onLoaded);

Une fois le maillage chargé, nous pouvons créer le graphe associé au maillage

var navigation = new Navigation();
var scene = engine.scene;

// Fonction appliquée une fois que la scène est chargé
var onLoaded = function(mesh) {
     // Le maillage de navigation 
     var navmesh = scene.getMeshByName("Navmesh");
     // Création du graphe de navigation
     var zoneNodes = navigation.buildNodes(navmesh);
     // Application du graphe à notre objet de navigation
     navigation.setZoneData('scene', zoneNodes);
};

BuildNodes vas s'occuper de créer tout le graphe. Le graphe de navigation n'a besoin d'être généré qu'une seule fois, au chargement de la scène, et peut être réutilisé tout au long de l'expérience.

Si le maillage de navigation est modifié, il faudra regénéré ce graphe, sinon votre personnage se déplaceras comme l'ancien maillage le suggérait.

3ème étape : Se déplacer sur le maillage de navigation

On arrive à la partie la plus dynamique ! Tout ce dont on a besoin c'est de 2 points sur le maillage et le tour est joué.

On vas d'abord chercher la zone sur laquelle le personnage se trouve.

var zone = navigation.getGroup('scene', positionDuPersonnage);

puis on trouve le chemin à suivre en utilisant :

var chemin = navigation.findPath(positionDuPersonnage, destination, 'scene', zone);

Et hop, le tour est joué. On arrive facilement à créer une petite animation:

var path = navigation.findPath(positionDuPersonnage, destination, 'scene', zone);
if (path && path.length > 1) {
    var length = 0;
    var direction = [{  
        frame: 0,
        value: positionDuPersonnage
    }];
    for (var i = 0; i < path.length; i++) {
        length += BABYLON.Vector3.Distance(direction[i].value, path[i]);
        direction.push({
            frame: length,
            value: path[i]
        });
    }

    var move = new BABYLON.Animation("Move", "position", 3, BABYLON.Animation.ANIMATIONTYPE_VECTOR3, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT);
    move.setKeys(direction);
    personnage.push(move);

    scene.beginAnimation(minimoi, 0, length);
}

On peut obtenir ce genre de résultat.

Petit plus, une fonction intéressante que j'ai utilisé sur un projet est projectOnNavmesh. Cette fonction permet d'avoir rapidement la projection d'une position sur le maillage de navigation. Ainsi on peut faire un déplacement de la caméra, toujours posé sur le maillage de navigation, par exemple avec cette fonction en surchargeant _updatePosition de la camera :

freeCamera._updatePosition = function () {
    this.position.addInPlace(this.cameraDirection);
    newPosition = navigation.projectOnNavmesh(this.position, 'scene', navigation.getGroup('scene', this.position));
    this.position.copyFrom(newPosition);
};

Voila en ce qui concerne la navigation sur un maillage ! Si vous avez la moindre question sur la librairie, sur Blender ou encore sur BabylonJs, n'hésitez pas à poster un commentaire, on se feras un plaisir d'y répondre !

Tags de
l'article

mesh BabylonJS

Catégories de l'article

WebGL

Commentaires

Il n'y a actuellement aucun commentaire. Soyez le premier !

Articles liés