Navigation
Le module Navigation permet à un curseur Inverse3 de déplacer l'espace de travail de l'application — ce que l'on appelle parfois « locomotion à contrôle de vitesse » ou « dérive à la manette de jeu ». Plutôt que de heurter une paroi rigide à la limite de l'espace de travail physique, le curseur pénètre dans une enveloppe souple où sa distance par rapport à un centre virtuel est associée à une vitesse qui fait glisser l'ensemble de l'espace de travail. Plus le curseur est poussé loin, plus la scène défile vite.
Le principal mode de navigation(et actuellement le seul) est la navigation par bulle. La forme de la bulle est définie à l'aide d'une primitive SDF — voir «Qu'est-ce qu'un SDF ? » pour en savoir plus sur ce concept.
Navigation par bulle — concept
Une bulle virtuelle est centrée sur un point précis dans l'espace de montage du dispositif. Le curseur se déplace au sein de trois zones concentriques :
┌──────────────────────────────────────────┐
│ WALL ZONE │ cursor beyond outer shell
│ ┌────────────────────────────────────┐ │
│ │ VELOCITY ZONE │ │ soft shell → scene moves
│ │ ┌──────────────────────────────┐ │ │
│ │ │ DEAD ZONE (inside) │ │ │ no scene movement
│ │ │ │ │ │
│ │ │ ● centre │ │ │
│ │ │ │ │ │
│ │ └──────────────────────────────┘ │ │
│ │ bubble surface │ │
│ └────────────────────────────────────┘ │
│ outer boundary │
└──────────────────────────────────────────┘
| Zone | Position du curseur | Comportement |
|---|---|---|
| Zone morte | À l'intérieur de la bulle | Pas de navigation. Amortissement léger. Vous pouvez manipuler la scène comme bon vous semble. |
| Zone de vitesse | Entre la surface et la limite extérieure | La courbe distance → vitesse déplace l'espace de travail dans la direction du curseur. |
| Zone de paroi | Au-delà de la frontière extérieure | Un ressort rigide repousse le curseur vers l'intérieur, ce qui limite la vitesse de déplacement. |
Une force haptique de type ressort-amortisseur s'exerce dans les trois zones : vous percevez la surface, la coque de la dérive et la paroi extérieure.
Guide de démarrage rapide — activer la navigation par bulles
La navigation est une configuration persistante, envoyée en une seule fois : elle reste active jusqu'à ce que vous la désactiviez explicitement, que vous redémarriez le service ou que vous vous déconnectiez.
Démarrer (version minimale — bulle par défaut dans une boîte arrondie)
- WebSocket
- HTTP
{
"inverse3": [
{
"device_id": "04C3",
"configure": {
"navigation": { "mode": "bubble" }
}
}
]
}
curl -X POST "http://localhost:10001/inverse3/04C3/config/navigation?session=:0" \
-H "Content-Type: application/json" \
-d '{"mode": "bubble"}'
Arrêter
- WebSocket
- HTTP
{
"inverse3": [
{
"device_id": "04C3",
"configure": {
"navigation": { "mode": "disabled" }
}
}
]
}
curl -X DELETE "http://localhost:10001/inverse3/04C3/config/navigation?session=:0"
Autres routes HTTP
| Méthode | Chemin | Rôle |
|---|---|---|
GET | /{type}/{id}/config/navigation?session=<expr> | Configuration actuelle de la navigation et état |
POST | /{type}/{id}/config/navigation?session=<expr> | Lancer ou actualiser la navigation |
DELETE | /{type}/{id}/config/navigation?session=<expr> | Arrêter la navigation |
Catalogue des formes de bulles
La zone morte de la bulle est définie par une forme à fonction de distance signée (SDF). Différentes formes procurent des sensations de navigation variées : une boîte arrondie (valeur par défaut) pour une zone de repos rectangulaire confortable, une sphère pour une dérive isotrope, un ellipsoïde pour privilégier certains axes, une capsule pour les couloirs.
Boîte arrondie (par défaut)
La zone morte par défaut est un volume plat, légèrement plus haut que profond, configuré pour offrir un confort d'utilisation optimal aussi bien sur Inverse3 que sur MInverse :
{
"shape": {
"primitive": "rounded_box",
"parameters": { "b": { "x": 0.05, "y": 0.02, "z": 0.03 }, "r": 0.01 }
}
}
Sphère — dérive isotrope
{
"shape": {
"primitive": "sphere",
"parameters": { "r": 0.05 }
}
}
Ellipsoïde — plus grand dans les axes X et Z que dans l'axe Y
À utiliser lorsque la dérive horizontale doit être plus souple que la dérive verticale :
{
"shape": {
"primitive": "ellipsoid",
"parameters": { "a": { "x": 0.06, "y": 0.03, "z": 0.06 } }
}
}
Capsule — couloir allongé
Deux points d'extrémité a/b ainsi qu'un rayon r :
{
"shape": {
"primitive": "capsule",
"parameters": {
"a": { "x": 0.0, "y": -0.03, "z": 0.0 },
"b": { "x": 0.0, "y": 0.03, "z": 0.0 },
"r": 0.04
}
}
}
Exemple complet avec dimensionnement personnalisé et impression de mouvement :
{
"inverse3": [
{
"device_id": "04C3",
"configure": {
"navigation": {
"mode": "bubble",
"bubble": {
"shape": {
"primitive": "ellipsoid",
"parameters": { "a": { "x": 0.06, "y": 0.03, "z": 0.06 } }
},
"velocity_zone_width": 0.025,
"max_velocity": 1.0,
"velocity_ease": "quadratic_in"
}
}
}
}
]
}
Courbe de vitesse
La distance de la zone de vitesse est transformée par une courbe d'accélération (easing) avant d'être convertie en vitesse dans l'espace de travail. Choisissez l'accélération qui correspond à la manière dont vous souhaitez que la scène s'accélère lorsque l'utilisateur appuie davantage sur la coque.
velocity_ease | Sensation | Quand l'utiliser |
|---|---|---|
linear | Pente constante | Prévisible, bon choix par défaut |
quadratic_in | Départ lent, accélération plus rapide | Précis près de la surface, long trajet rapide |
cubic_in | Départ très lent | Très précis, ils prennent de la vitesse sur les longs trajets |
sine_out | Départ rapide et fluide, plateau près de l'extérieur | Réactif, atteint son plafond en douceur |
quadratic_out | Rapide au démarrage, confortable sur les longs trajets | Une petite accélération rapide, une conduite confortable |
{ "velocity_ease": "quadratic_in", "max_velocity": 1.5 }
Comportement du centre
Le centre de la bulle est défini à l'aide d'un objet imbriqué center comportant quatre
champs — position, relative, follow, speed — qui remplace l'ancienne
disposition à plat composée de center, center_enabled, center_mode et center_drift_speed.
{
"center": {
"position": { "x": 0.0, "y": 0.0, "z": 0.0 },
"relative": true,
"follow": false,
"speed": 0.02
}
}
Ancrage du centre
position et relative déterminent la position initiale du centre lors de l'activation :
relative | Sémantique de position |
|---|---|
true (par défaut) | position est un décalage par rapport au curseur — le centre initial est cursor + position. Avec la valeur par défaut (0, 0, 0), la bulle apparaît exactement sur le curseur. |
false | position est un point absolu dans l'espace de l'application — il est converti en espace de montage à l'entrée, puis reconverti en espace de l'application à la sortie, de sorte que les valeurs après un aller-retour correspondent. |
Déplacement ultérieur du centre
follow et speed contrôlent le comportement à chaque cycle une fois que la bulle est active :
follow | speed | Comportement | Équivalent précédent |
|---|---|---|---|
false (par défaut) | ignoré | Le centre reste à sa position initiale — centre fixe. | center_mode: "fixed" |
true | > 0 | Le centre se déplace vers le curseur à la vitesse speed (m/s) tant que le curseur se trouve à l'intérieur. | center_mode: "auto_follow" (avec center_drift_speed) |
true | 0.0 | Le centre se positionne sur le curseur à chaque cycle — effet de téléportation. | center_mode: "track_cursor" |
Le comportement par défaut du centre est désormais fixe (follow = false). Les versions antérieures
utilisaient le curseur par défaut (auto_follow). Définissez center.follow = true
pour rétablir l'ancien comportement de dérive, puis réglez center.speed pour correspondre à l'ancienne valeur
de center_drift_speed.
Lorsque follow = true et dès que le curseur dépasse la limite extérieure, le centre
suit le curseur quelle que soit la valeur de speed, afin de maintenir la bulle autour de lui et
d'empêcher le curseur de s'échapper.
Réaction en cas de collision
La bulle réagit aux forces externes exercées sur le curseur qui dépassent collision_detection.force_threshold :
- La zone de vitesse s'élargit temporairement (jusqu'à
collision_detection.inflate_ratiofoisvelocity_zone_width) afin de donner à l'utilisateur davantage de marge de manœuvre pour contourner l'obstacle. - Lorsque
collision_detection.enabledvauttrue(par défaut), le centre de la bulle refuse de dériver dans la direction de la force de collision, ce qui empêche l'utilisateur de faire glisser l'espace de travail contre un mur rigide.
La détection des collisions utilise l'hystérésis pour éviter le scintillement autour du seuil :
une fois qu'une collision est active, elle reste active jusqu'à ce que |ext_force| descende sous le
produit collision_detection.force_threshold × collision_detection.exit_ratio.
Réduire exit_ratio pour élargir la plage d'hystérésis (collisions plus persistantes) ; réglez
la valeur à 1.0 pour désactiver l'hystérésis et n'utiliser qu'un seul seuil.
{
"collision_detection": {
"enabled": true,
"force_threshold": 0.5,
"inflate_ratio": 2.0,
"exit_ratio": 0.7
}
}
Référence des paramètres
Les plus souvent modifiés
| Paramètre | Valeur par défaut | Description |
|---|---|---|
shape | {rounded_box, r=0.01, b=(0.05,0.02,0.03)} | Forme SDF définissant la zone morte |
velocity_zone_width | 0.03 m | Épaisseur de la coque de contrôle en vitesse |
max_velocity | 0.5 m/s | Vitesse maximale de navigation |
velocity_ease | "quadratic_in" | Courbe de transition entre la distance et la vitesse |
center.follow | false | Indique si le centre suit le curseur |
center.speed | 0.02 m/s | Vitesse de dérive lorsque follow = true |
Liste complète des paramètres
| Champ | Type | Valeur par défaut | Description |
|---|---|---|---|
center.position | vec3 | (0, 0, 0) | Centre initial — décalage par rapport au curseur lorsque relative = true, point absolu de l'espace de l'application lorsque false |
center.relative | bool | true | true : position correspond à un décalage par rapport au curseur. false : point absolu de l'espace de l'application, converti en espace de montage à la frontière |
center.follow | bool | false | false : le centre reste dans sa position initiale. true : le centre suit le curseur |
center.speed | float | 0.02 | Vitesse de dérive (m/s) lorsque follow = true ; 0.0 centrer le curseur à chaque cycle |
shape | forme | {rounded_box, r=0.01, b=(0.05,0.02,0.03)} | Forme SDF de la zone morte |
velocity_zone_width | float | 0.03 | Épaisseur de la coque de contrôle en vitesse (m) |
max_velocity | float | 0.5 | Vitesse maximale de navigation (m/s) |
velocity_ease | chaîne de caractères | "quadratic_in" | Passage de la distance à la vitesse |
reset_velocity_on_entry | bool | true | Réinitialise la vitesse cumulée lorsque le curseur revient dans la zone de vitesse |
bump_width | float | 0.005 | Bosse tactile en surface (m) |
bump_stiffness | float | 200.0 | Constante de rigidité du ressort de la bosse à la surface |
spring_inner | float | 0.0 | Ressort au centre de la bulle |
spring_surface | float | 10.0 | Remonte à la surface |
spring_outer | float | 15.0 | Ressort à la frontière extérieure |
wall_stiffness | float | 700.0 | Rigidité du ressort de mur rigide au-delà de la limite extérieure |
damping_inner | float | 0.1 | Amortissement au centre |
damping_surface | float | 4.0 | Amortissement par surface |
damping_outer | float | 7.0 | Amortissement à la frontière extérieure |
rotation_enabled | bool | false | Applique la rotation de l'espace de travail à la direction de navigation |
scale_enabled | bool | false | Applique l'échelle de l'espace de travail à la vitesse de navigation |
collision_detection.enabled | bool | true | Bloque la circulation dans le sens de la collision |
collision_detection.force_threshold | float | 1.0 | Intensité de la force externe nécessaire pour provoquer une collision (N) |
collision_detection.inflate_ratio | float | 2.0 | Multiplicateur de la largeur de la zone de vitesse lors d'une collision (doit être ≥ 1,0) |
collision_detection.exit_ratio | float | 0.7 | Taux d'hystérésis — reste en collision tant que |ext_force| < force_threshold × exit_ratio. Plage (0, 1] ; 1.0 désactive l'hystérésis |
Deux groupes de fonctionnalités ne figurent pas dans le schéma JSON 3.5, leurs implémentations étant en cours de refonte pour la version 3.6 :
- Limites de l'avatar : les champs
avatar_boundary_enabled,avatar_boundaryetavatar_boundary_hysteresis. - Délimitation de l'espace de travail : les champs
workspace_bounded,workspace_transition_speedetworkspace_transition_ease.
Le code du tick se compile et s'exécute toujours avec les valeurs par défaut, mais les clients ne peuvent ni lire ni modifier ces champs via HTTP ou WebSocket. Dans la version 3.6, le contour de l'avatar réapparaîtra sous la forme d'un bounds de premier niveau, au même niveau que l'objet « bulle », avec une transformation de position complète ; la délimitation de l'espace de travail sera rétablie une fois l'analyse de la gigue du centre terminée.
Règles de validation
velocity_zone_width > 00 ≤ bump_width < velocity_zone_widthmax_velocity > 0bump_stiffness ≥ 0spring_inner ≥ 0etspring_inner ≤ spring_surface ≤ spring_outerwall_stiffness ≥ 0damping_inner ≥ 0etdamping_inner ≤ damping_surface ≤ damping_outercollision_detection.force_threshold > 0collision_detection.inflate_ratio ≥ 1.0collision_detection.exit_ratiodans(0, 1]center.speed ≥ 0
Un POST ou configure.navigation avec des paramètres non valides est rejeté et un événement invalid-value n'est pas émis ; la configuration précédente reste active.
Événements
| Nom de l'événement | Déclenché lorsque |
|---|---|
navigation-started | La navigation est activée sur un appareil |
navigation-updated | La configuration de navigation est mise à jour alors qu'elle est déjà active |
navigation-stopped | La navigation est désactivée (désactivation explicite, DELETE ou la fin de votre session) |
invalid-value | Une configuration de navigation est rejetée lors de la validation |
Limites connues
- Délimitation de l'espace de travail et frontières de l'avatar masquées dans la version 3.5: ces deux groupes de fonctionnalités ne figurent pas dans le schéma JSON, car ils sont en cours de refonte pour la version 3.6. Voir la note ci-dessus, sous « Référence des paramètres ».
- Mise à l'échelle non uniforme + rotation : lorsque
rotation_enabledetscale_enabledLorsqu'ils sont tous deux activés, la direction de la vitesse est légèrement imprécise, car la rotation n'est pas appliquée aux axes de mise à l'échelle. - Mise à l'échelle de la taille par appareil: les tailles des bulles (rayon, largeur de zone) ne sont pas mises à l'échelle en fonction du facteur d'échelle physique de l'appareil ; MInverse et Inverse3 utilisent les mêmes tailles absolues, qui peuvent donc sembler différentes sur chaque site.