Aller au contenu principal

Navigation

Le module Navigation permet à un curseur Inverse3 de déplacer l'espace de travail de l'application — parfois appelé locomotion à contrôle de vitesse ou « dérive façon manette de jeu ». Plutôt que de heurter une paroi dure à la limite de l'espace de travail physique, le curseur entre dans une coque 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 comportement principal (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 le concept.


Navigation par bulle — concept​

Une bulle virtuelle est ancrée autour d'un point central dans l'espace de montage du dispositif. Le curseur évolue 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 │
└──────────────────────────────────────────┘
ZonePosition du curseurComportement
Zone morteÀ l'intérieur de la bulleAucune navigation. Léger amortissement. Vous pouvez manipuler la scène librement.
Zone de vitesseEntre la surface et la limite extérieureLa courbe distance → vitesse déplace l'espace de travail dans la direction du curseur.
Zone de paroiAu-delà de la limite extérieureUn ressort rigide repousse le curseur vers l'intérieur, et la vitesse de navigation est plafonnée.

Une force haptique de type ressort-amortisseur s'applique dans les trois zones — vous ressentez la surface, la coque de dérive et la paroi extérieure.


Démarrage rapide — activer la navigation par bulle​

La navigation est une configuration persistante, envoyée en une seule fois : elle reste active jusqu'à ce que vous l'arrêtiez explicitement, que vous redémarriez le service ou que vous fermiez la session.

Démarrer (minimal — bulle par défaut en boîte arrondie)​

{
"inverse3": [
{
"device_id": "04C3",
"configure": {
"navigation": { "mode": "bubble" }
}
}
]
}

Arrêter​

{
"inverse3": [
{
"device_id": "04C3",
"configure": {
"navigation": { "mode": "disabled" }
}
}
]
}

Autres routes HTTP​

MéthodeCheminRôle
GET/{type}/{id}/config/navigation?session=<expr>Configuration de navigation actuelle et état
POST/{type}/{id}/config/navigation?session=<expr>Démarrer ou mettre à jour la navigation
DELETE/{type}/{id}/config/navigation?session=<expr>Arrêter la navigation

Catalogue des formes de bulle​

La zone morte de la bulle est décrite par une forme à fonction de distance signée (SDF). Différentes formes donnent différentes sensations de navigation — une boîte arrondie (la valeur par défaut) pour une zone de repos rectangulaire confortable, une sphère pour une dérive isotrope, un ellipsoïde pour favoriser 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, réglé pour être agréable à utiliser sur Inverse3 comme 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 large en X/Z qu'en 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 sensation 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 de l'espace de travail. Choisissez l'accélération qui correspond à la façon dont vous souhaitez que la scène accélère lorsque l'utilisateur pousse davantage dans la coque.

velocity_easeSensationQuand l'utiliser
linearRampe constantePrévisible, bon choix par défaut
quadratic_inDépart lent, poussée plus rapidePrécis près de la surface, long trajet rapide
cubic_inDépart très lentTrès précis, les longs trajets montent en vitesse
sine_outDépart rapide et fluide, plateau près de l'extérieurRéactif, plafonne en douceur
quadratic_outRapide à l'entrée, confortable sur longue distancePetite impulsion rapide, croisière confortable
{ "velocity_ease": "quadratic_in", "max_velocity": 1.5 }

Comportement du centre​

Le centre de la bulle se configure au moyen 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 contrôlent l'emplacement initial du centre lors de l'activation :

relativeSé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.
falseposition est un point absolu dans l'espace de l'application — il est converti en espace de montage à l'entrée et 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 la bulle active :

followspeedComportementÉquivalent précédent
false (par défaut)ignoréLe centre reste à sa position initiale — centre fixe.center_mode: "fixed"
true> 0Le centre dérive 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)
true0.0Le centre se cale sur le curseur à chaque cycle — effet de téléportation.center_mode: "track_cursor"
Valeur par défaut modifiée dans la version 3.5

Le comportement par défaut du centre est désormais fixe (follow = false). Les versions antérieures dérivaient vers le curseur par défaut (auto_follow). Définissez center.follow = true pour rétablir l'ancien comportement de dérive, et ajustez center.speed pour correspondre à l'ancienne valeur de center_drift_speed.

Lorsque follow = true et que le curseur dépasse la frontière extérieure, le centre suit le curseur quelle que soit la valeur de speed, afin de garder la bulle autour de lui et d'empêcher le curseur de s'échapper.


Réponse aux collisions​

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_ratio fois velocity_zone_width) afin de donner à l'utilisateur plus de marge de manœuvre pour contourner l'obstacle.
  • Lorsque collision_detection.enabled vaut true (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 d'entraîner l'espace de travail contre un mur rigide.

La détection de collision utilise l'hystérésis pour éviter le scintillement autour du seuil : une fois une collision active, elle reste active jusqu'à ce que |ext_force| descende sous le produit collision_detection.force_threshold × collision_detection.exit_ratio. Diminuez 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 ajustés​

ParamètreValeur par défautDescription
shape{rounded_box, r=0.01, b=(0.05,0.02,0.03)}Forme SDF définissant la zone morte
velocity_zone_width0.03 mÉpaisseur de la coque de contrôle en vitesse
max_velocity0.5 m/sVitesse maximale de navigation
velocity_ease"quadratic_in"Courbe de transition de la distance vers la vitesse
center.followfalseIndique si le centre suit le curseur
center.speed0.02 m/sVitesse de dérive lorsque follow = true

Liste complète des paramètres​

ChampTypeValeur par défautDescription
center.positionvec3(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.relativebooltruetrue : position est 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.followboolfalsefalse : le centre reste fixé à sa position initiale. true : le centre suit le curseur
center.speedfloat0.02Vitesse de dérive (m/s) lorsque follow = true ; 0.0 cale le centre sur le curseur à chaque cycle
shapeshape{rounded_box, r=0.01, b=(0.05,0.02,0.03)}Forme SDF de la zone morte
velocity_zone_widthfloat0.03Épaisseur de la coque de contrôle en vitesse (m)
max_velocityfloat0.5Vitesse maximale de navigation (m/s)
velocity_easestring"quadratic_in"Transition de la distance vers la vitesse
reset_velocity_on_entrybooltrueRemet à zéro la vitesse accumulée lorsque le curseur rentre à nouveau dans la zone de vitesse
bump_widthfloat0.005Bosse tactile à la surface (m)
bump_stiffnessfloat200.0Constante de raideur du ressort de la bosse à la surface
spring_innerfloat0.0Ressort au centre de la bulle
spring_surfacefloat10.0Ressort à la surface
spring_outerfloat15.0Ressort à la frontière extérieure
wall_stiffnessfloat700.0Raideur du ressort de mur rigide au-delà de la frontière extérieure
damping_innerfloat0.1Amortissement au centre
damping_surfacefloat4.0Amortissement à la surface
damping_outerfloat7.0Amortissement à la frontière extérieure
rotation_enabledboolfalseApplique la rotation de l'espace de travail à la direction de navigation
scale_enabledboolfalseApplique l'échelle de l'espace de travail à la vitesse de navigation
collision_detection.enabledbooltrueBloque la navigation dans la direction de la collision
collision_detection.force_thresholdfloat1.0Intensité de la force externe nécessaire pour entrer en collision (N)
collision_detection.inflate_ratiofloat2.0Multiplicateur de la largeur de la zone de vitesse pendant une collision (doit être ≥ 1.0)
collision_detection.exit_ratiofloat0.7Ratio 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
Champs masqués dans la 3.5

Deux groupes de fonctionnalités sont omis du schéma JSON 3.5 pendant que leurs implémentations sont remaniées pour la 3.6 :

  • Bornage de la frontière de l'avatar : les champs avatar_boundary_enabled, avatar_boundary et avatar_boundary_hysteresis.
  • Délimitation de l'espace de travail : les champs workspace_bounded, workspace_transition_speed et workspace_transition_ease.

Le code du tick compile et s'exécute toujours avec les valeurs par défaut, mais les clients ne peuvent ni lire ni écrire ces champs via HTTP ou WebSocket. Dans la 3.6, la frontière de l'avatar reviendra sous la forme d'un bounds de premier niveau, au même niveau que l'objet bulle, avec une transformation de placement complète ; la délimitation de l'espace de travail reviendra une fois l'analyse de la gigue du centre terminée.

Règles de validation​

  • velocity_zone_width > 0
  • 0 ≤ bump_width < velocity_zone_width
  • max_velocity > 0
  • bump_stiffness ≥ 0
  • spring_inner ≥ 0 et spring_inner ≤ spring_surface ≤ spring_outer
  • wall_stiffness ≥ 0
  • damping_inner ≥ 0 et damping_inner ≤ damping_surface ≤ damping_outer
  • collision_detection.force_threshold > 0
  • collision_detection.inflate_ratio ≥ 1.0
  • collision_detection.exit_ratio dans (0, 1]
  • center.speed ≥ 0

Un POST ou configure.navigation avec des paramètres invalides est rejeté et un événement invalid-value est émis ; la configuration précédente reste active.


Événements​

Nom de l'événementDéclenché lorsque
navigation-startedLa navigation est activée sur un appareil
navigation-updatedLa configuration de navigation est mise à jour alors qu'elle est déjà active
navigation-stoppedLa navigation est arrêtée (désactivation explicite, DELETE ou fermeture de session)
invalid-valueUne configuration de navigation est rejetée par la validation

Limites connues​

  • Délimitation de l'espace de travail et frontières de l'avatar masquées dans la 3.5 : les deux groupes de fonctionnalités sont absents du schéma JSON pendant qu'ils sont remaniés pour la 3.6. Voir la note ci-dessus, sous Référence des paramètres.
  • Mise à l'échelle non uniforme + rotation : lorsque rotation_enabled et scale_enabled sont tous deux activés, la direction de la vitesse est légèrement inexacte, 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 par le facteur d'échelle physique de l'appareil ; MInverse et Inverse3 utilisent les mêmes tailles absolues, qui peuvent donc sembler différentes sur chacun.