Skip to main content
Version : 3.5.x

Fonction de distance signée (SDF)

Les champs de distance signés (SDF) permettent de décrire une géométrie 3D simple (comme des sphères, des cubes, des capsules et des plans) à l'aide d'une fonction de distance plutôt qu'à l'aide de maillages. Dans notre pile haptique, un SDF devient un champ de force que l'on peut associer à une session de périphérique : lorsque le curseur s'approche (ou pénètre) dans la forme, le système génère une force normale dont l'intensité dépend de la distance, de la portée et de l'accélération.

Cette page présente l'interface API publique ajoutée ou mise à jour par le correctif : la charge utile de l'effet SDF Haptics, les formes prises en charge, les paramètres, ainsi que des exemples de requêtes et de réponses pour la création, la mise à jour, la liste et la suppression d'effets SDF.

Modèle conceptuel

Un effet SDF est :

  • A forme (par exemple, sphere, box, capsule, plane)
  • Une transformation (position, rotation et échelle de l'effet dans l'espace)
  • A objet paramètre (params) qui permet de configurer la forme sélectionnée (rayons, extrémités, dimensions, normales, etc.)
  • Commandes de force :
    • force_scale — coefficient multiplicateur global
    • range — épaisseur de la « bande active » à l'extérieur de la surface où les forces s'atténuent jusqu'à zéro
    • ease + reverse_easing — comment la force augmente en fonction de la distance
  • Commandes de composition :
    • symmetry — la manière dont la distinction entre l'intérieur et l'extérieur est abordée
    • blend — comment les effets multiples des SDF se combinent

Vous pouvez créer plusieurs effets SDF par appareil ; chaque effet possède un id.

Effet SDF

{
"id": "string",
"transform": {
/* transform object */
},
"shape": "sphere | box | rounded_box | capsule | capsule_vertical | capped_cylinder | capped_cylinder_vertical | plane",
"params": {
/* shape parameters */
},
"force_scale": 1.0,
"range": 1.0,
"ease": "linear",
"reverse_easing": false,
"symmetry": "single | mirror | align",
"blend": "additive"
}

Référence sur le terrain

Champ d'applicationTypeObligatoireSignification
idchaîne de caractèresIdentifiant unique de cet effet au sein d'un appareil.
transformobjetPosition de l'effet dans l'espace mondial/de l'appareil.
shapechaîne de caractèresLa primitive SDF à évaluer.
paramsobjetParamètres spécifiques à la forme (voir ci-dessous).
force_scalenombreMultiplie l'amplitude de la force finale. Valeur par défaut : 1.0.
rangenombreDistance en dehors de la surface (en mètres) où l'effet est actif. Par défaut : 1.0.
easechaîne de caractèresCourbe d'atténuation appliquée sur [0..range]. Par défaut : linear.
reverse_easingbooléenSi cette option est activée, elle inverse le sens de l'accélération. Par défaut : false.
symmetrychaîne de caractèresComment le paramètre « inside/outside » est géré (voir ci-dessous). Par défaut : single.
blendchaîne de caractèresComment les effets multiples des SDF se combinent. Par défaut : additive.

Formes et paramètres

Toutes les formes sont configurées via un seul params objet. Vous pouvez fournir uniquement les champs dont vous avez besoin pour la forme sélectionnée.

params objet

{
"r": 1.0,
"h": 0.0,
"a": [0.0, 0.0, 0.0],
"b": [0.0, 0.0, 0.0],
"n": [0.0, 1.0, 0.0]
}

Conseil : les valeurs sont interprétées dans l'effet espace local (après avoir appliqué transform).

Formes prises en charge (actuellement)

Seules les primitives SDF suivantes sont actuellement prises en charge (voir la galerie SDF d'IQ pour plus d'informations mathématiques) :

Formeshape valeurParamètres utilisés
Sphèrespherer
Boîteboxb (demi-feuilles)
Boîte arrondierounded_boxb (demi-feuilles), r (rayon de courbure)
Capsule (segment)capsulea, b, r
Capsule (verticale)capsule_verticalh, r
Cylindre à capuchon (segment)capped_cylindera, b, r
Cylindre à couvercle (vertical)capped_cylinder_verticalh, r
Avionplanen, h

Remarques sur les conventions

  • Vecteurs sont des tableaux : a, b, n sont en 3D ([x,y,z]).
  • Boîte utilisations b sous forme de demi-intervalles (par exemple, b=[0.1,0.2,0.1]).
  • Avion utilisations n comme la norme et h décalé le long de la normale.
  • Vertical utilisation des variantes h comme une demi-hauteur (capsule/cylindre centré sur l'origine le long de l'axe Y local).

Symétrie

symmetry détermine le comportement du champ par rapport à la surface :

  • single — Comportement par défaut. La distinction entre l'intérieur et l'extérieur est conservée.
  • mirror — Utilise la distance absolue par rapport à la surface et inverse la direction lorsqu'il se trouve « derrière » celle-ci, créant ainsi un effet de miroir.
  • align — Utilise la distance absolue sans inverser le sens (utile pour les effets du type « toujours pousser dans la même direction »).

Modulation et gamme

L'intensité de la force augmente avec la distance par rapport à la surface :

  • En surface (distance = 0) : amplitude maximale (sous réserve d'un assouplissement)
  • À distance = range: l'amplitude devient 0 (inactif)

ease définit la courbe de l'atténuation. reverse_easing inverse la courbe.


Commandes

  • "set_sdf": créer/mettre à jour des effets SDF localisés (tableau d'éléments)
  • "remove_sdf": supprimer les effets par ID (tableau d'ID)

Définir / Mettre à jour l'effet SDF

{
"inverse3": [
{
"device_id": "049D",
"commands": {
"set_sdf": [
{
"id": "boundary_049D",
"transform": {
"position": {
"x": 0,
"y": -0.05,
"z": -0.04
},
"rotation": {
"x": 0,
"y": 0,
"z": 0,
"w": 1
},
"scale": {
"x": 0.15,
"y": 0.1,
"z": 0.1
}
},
"shape": "sphere",
"force_scale": -2.0,
"range": 0.1,
"ease": "cubicInOut",
"reverse_easing": false,
"symmetry": "single",
"blend": "additive",
"params": {
"r": 1.0
}
}
]
}
}
]
}

Supprimer un effet SDF

{
"inverse3": [{
"device_id": "049D",
"commands": {
"remove_sdf": ["boundary_049D"]
}
}]
}
  • Chaque identifiant présent dans le tableau est supprimé.
  • La suppression d'un identifiant inexistant est considérée comme une opération sans effet (on peut l'appeler sans risque).

API REST

Les points de terminaison SDF respectent les mêmes conventions de routage par session/appareil que le reste de l'API haptique.

  • Un appareil peut comporter plusieurs effets SDF.
  • Chaque effet est identifié par son id.
  • Vous pouvez gérer les effets individuellement ou en bloc pour chaque appareil.

Itinéraires

  • OBTENIR

    • /{device_type}/{device_id}/sdf?session_id=<sid> → Portée de l'appareil (liste des SDF)
    • /{device_type}/{device_id}/sdf/{hfx_id}?session_id=<sid> → SDF simple
    • /{device_type}/*/sdf?session_id=<sid> → Portée de la session (tous les appareils)
    • /{device_type}/*/sdf (non session_id) → toutes les sessions
  • PUBLICATION

    • /{device_type}/{device_id}/sdf/{hfx_id}?session_id=<sid> corps : sdf_hfx (en créer/mettre à jour un)
    • /{device_type}/{device_id}/sdf?session_id=<sid> corps : device_sdf_dto (remplacer ou mettre à jour/ajouter plusieurs éléments pour l'appareil)
  • SUPPRIMER

    • /{device_type}/{device_id}/sdf?session_id=<sid> ou .../sdf/{hfx_id}?session_id=<sid>
    • session_id=* Prise en charge de la fonction « Tout effacer ».
info

Les gestionnaires vérifient device_type (inverse3 (uniquement), appliquer session_id/device_id présence et retour 404 en cas d'absence de session, d'appareil ou d'effet.

Points forts en matière de comportement

  • Le routage GET couvre : tout → session → périphérique → effet unique en fonction du chemin et des paramètres.
  • La méthode POST impose l'utilisation d'un chemin d'accès et d'un corps de requête id garantit la cohérence pour les écritures à effet unique et met à jour les SDF au niveau du périphérique lors de la publication d'une liste.
  • La commande DELETE est idempotente et renvoie une réponse standard indiquant que l'opération s'est bien déroulée, même si rien n'a été supprimé

Exemples

Une « bulle » sphérique sur laquelle on peut appuyer

{
"id": "bubble",
"transform": {
/* place it where you want */
},
"shape": "sphere",
"params": {
"r": 0.12
},
"force_scale": 1.0,
"range": 0.08,
"ease": "linear",
"reverse_easing": false,
"symmetry": "single",
"blend": "additive"
}

Boîte arrondie « à parois souples »

{
"id": "soft_wall",
"transform": {
/* oriented wall */
},
"shape": "rounded_box",
"params": {
"b": [
0.30,
0.02,
0.30
],
"r": 0.01
},
"force_scale": 0.9,
"range": 0.06,
"ease": "cubicInOut",
"reverse_easing": false,
"symmetry": "single",
"blend": "additive"
}

Segment de capsule « rail »

{
"id": "rail",
"transform": {
/* position/rotate rail */
},
"shape": "capsule",
"params": {
"a": [
-0.15,
0.0,
0.0
],
"b": [
0.15,
0.0,
0.0
],
"r": 0.015
},
"force_scale": 0.7,
"range": 0.05,
"ease": "quadraticOut",
"reverse_easing": false,
"symmetry": "mirror",
"blend": "additive"
}

Plan « limite invisible »

{
"id": "boundary",
"transform": {
/* place plane */
},
"shape": "plane",
"params": {
"n": [
1.0,
0.0,
0.0
],
"h": 0.0
},
"force_scale": 0.8,
"range": 0.10,
"ease": "linear",
"reverse_easing": false,
"symmetry": "single",
"blend": "additive"
}