Vorzeichenbehaftete Distanzfunktion (SDF)
Mit Signierten Distanzfeldern (SDFs) lassen sich einfache 3D-Geometrien (wie Kugeln, Quader, Kapseln und Ebenen) mithilfe einer Distanzfunktion anstelle von Netzmodellen beschreiben. In unserem Haptik-Stack wird ein SDF zu einem Kraftfeld, das Sie einer Gerätesitzung zuweisen können: Wenn sich der Cursor der Form nähert (oder in sie eintritt), erzeugt das System eine Normalkraft, deren Stärke von Entfernung, Reichweite und Beschleunigung abhängt.
Diese Seite dokumentiert die durch den Patch hinzugefügten bzw. aktualisierten öffentlichen API-Schnittstellen: die Nutzdaten des SDF-Haptik-Effekts, unterstützte Formen, Parameter sowie Beispiele für Anfragen und Antworten zum Erstellen, Aktualisieren, Auflisten und Löschen von SDF-Effekten.
Konzeptionelles Modell
Ein SDF-Effekt ist:
- A Form (z. B.
sphere,box,capsule,plane) - Eine Transformation (Position, Drehung und Skalierung des Effekts im Raum)
- A Parameterobjekt (
params) zur Konfiguration der ausgewählten Form (Radien, Endpunkte, Ausdehnung, Normalen usw.) - Steuerung der Kraft:
force_scale— Gesamtamplitudenmultiplikatorrange— Dicke des „aktiven Bandes“ außerhalb der Oberfläche, wo die Kräfte gegen Null abfallenease+reverse_easing— wie die Kraft mit der Entfernung ansteigt
- Einstellungen für die Komposition:
symmetry— wie das Verhältnis zwischen Innen und Außen behandelt wirdblend— wie sich mehrere SDF-Effekte miteinander verbinden
Sie können pro Gerät mehrere SDF-Effekte erstellen; jeder Effekt hat eine eindeutige id.
SDF-Effekt
{
"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"
}
Feldreferenz
| Feld | Typ | Erforderlich | Bedeutung |
|---|---|---|---|
id | String | ✅ | Eindeutige Kennung für diesen Effekt innerhalb eines Geräts. |
transform | Objekt | ✅ | Position des Effekts im Welt- bzw. Geräteraum. |
shape | String | ✅ | Die zu bewertende SDF-Primitive. |
params | Objekt | ✅ | Formspezifische Parameter (siehe unten). |
force_scale | Zahl | ⛔ | Multipliziert die endgültige Kraftgröße. Standard: 1.0. |
range | Zahl | ⛔ | Entfernung außerhalb der Fläche (in Metern), in der der Effekt aktiv ist. Standard: 1.0. |
ease | String | ⛔ | Angewandte Abflachungskurve [0..range]. Standard: linear. |
reverse_easing | Boolesche Variable | ⛔ | Falls wahr, wird die Richtung der Beschleunigung umgekehrt. Standard: false. |
symmetry | String | ⛔ | Wie „inside/outside“ behandelt wird (siehe unten). Standard: single. |
blend | String | ⛔ | Wie sich mehrere SDF-Effekte miteinander verbinden. Standard: additive. |
Formen und Parameter
Alle Formen werden über eine einzige params Objekt. Sie können nur die Felder, die Sie benötigen für die ausgewählte Form.
params Objekt
{
"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]
}
Tipp: Die Werte werden im Effekt lokaler Raum (nach dem Auftragen
transform).
Unterstützte Formen (aktuell)
Derzeit werden nur die folgenden SDF-Primitive unterstützt (mathematische Hintergründe finden Sie in der SDF-Galerie von IQ ):
| Form | shape Wert | Verwendete Parameter |
|---|---|---|
| Sphäre | sphere | r |
| Kasten | box | b (Halbformate) |
| Abgerundete Schachtel | rounded_box | b (Halbformate), r (Kurvenradius) |
| Kapsel (Segment) | capsule | a, b, r |
| Kapsel (vertikal) | capsule_vertical | h, r |
| Abgedeckter Zylinder (Segment) | capped_cylinder | a, b, r |
| Zylinder mit Deckel (vertikal) | capped_cylinder_vertical | h, r |
| Flugzeug | plane | n, h |
Hinweise zu den Konventionen
- Vektoren sind Arrays:
a,b,nsind 3D ([x,y,z]). - Kasten Verwendungszwecke
bals Halbbereiche (z. B.b=[0.1,0.2,0.1]). - Flugzeug Verwendungszwecke
nals das Normale undhals Versatz entlang der Normalen. - Vertikal Verwendung von Varianten
hals halbe Höhe (Kapsel/Zylinder, zentriert am Ursprung entlang der lokalen Y-Achse).
Symmetrie
symmetry legt fest, wie sich das Feld in Bezug auf die Oberfläche verhält:
single— Standardverhalten. Die Unterscheidung zwischen „innen“ und „außen“ bleibt erhalten.mirror— Nutzt den absoluten Abstand zur Oberfläche und wechselt die Richtung, wenn sich das Objekt „hinter“ der Oberfläche befindet, wodurch ein gespiegeltes Verhalten entsteht.align— Verwendet den absoluten Abstand, ohne die Richtung umzukehren (nützlich für Effekte, bei denen „immer in dieselbe Richtung geschoben“ wird).
Abschwächung und Bandbreite
Die Kraftstärke nimmt mit zunehmender Entfernung von der Oberfläche zu:
- An der Oberfläche (Abstand =
0): maximale Stärke (vorbehaltlich einer Abschwächung) - Aus der Ferne =
range: Die Stärke wird zu0(inaktiv)
ease legt die Form der Abklingkurve fest. reverse_easing kehrt die Kurve um.
Befehle
"set_sdf": Lokalisierte SDF-Effekte erstellen/aktualisieren (Array von Elementen)"remove_sdf": Effekte nach ID entfernen (Array von IDs)
SDF-Effekt festlegen / aktualisieren
{
"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
}
}
]
}
}
]
}
Einen SDF-Effekt entfernen
{
"inverse3": [{
"device_id": "049D",
"commands": {
"remove_sdf": ["boundary_049D"]
}
}]
}
- Jede ID im Array wird entfernt, sofern vorhanden.
- Das Entfernen einer nicht vorhandenen ID wird als No-Op behandelt (der Aufruf ist sicher).
REST-API
Die SDF-Endpunkte folgen denselben Konventionen für das Routing nach Sitzung und Gerät wie der Rest der Haptik-API.
- Ein Gerät kann über viele SDF-Effekte verfügen.
- Jeder Effekt wird durch seine
id.- Sie können Effekte einzeln oder gesammelt pro Gerät verwalten.
Routen
-
HOLEN
/{device_type}/{device_id}/sdf?session_id=<sid>→ Gerätebereich (Liste der SDFs)/{device_type}/{device_id}/sdf/{hfx_id}?session_id=<sid>→ einzelne SDF/{device_type}/*/sdf?session_id=<sid>→ Sitzungsbereich (alle Geräte)/{device_type}/*/sdf(neinsession_id) → alle Sitzungen
-
BEITRAG
/{device_type}/{device_id}/sdf/{hfx_id}?session_id=<sid>Text:sdf_hfx(einen anlegen/aktualisieren)/{device_type}/{device_id}/sdf?session_id=<sid>Text:device_sdf_dto(viele Einträge für das Gerät ersetzen oder bei Nichtvorhandensein einfügen)
-
LÖSCHEN
/{device_type}/{device_id}/sdf?session_id=<sid>oder.../sdf/{hfx_id}?session_id=<sid>session_id=*unterstützt für „Alle löschen“.
Handler validieren device_type (inverse3 (nur), durchsetzen session_id/device_id Anwesenheit und Rückkehr 404 wegen fehlender Sitzung/Gerät/Effekt.
Wichtige Verhaltensmerkmale
- GET-Routing umfasst: alle → Sitzung → Gerät → Einzelwirkung, abhängig von Pfad/Parametern.
- POST erzwingt Pfad/Inhalt
idGewährleistet Konsistenz bei Schreibvorgängen mit einfacher Wirkung und setzt SDFs auf Geräteebene beim Posten einer Liste. - DELETE ist idempotent und gibt eine Standard-OK-Antwort zurück, auch wenn nichts gelöscht wurde
Beispiele
Eine Kugel, in die man hineindrücken kann
{
"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"
}
Abgerundte Schachtel mit „weichen Wänden“
{
"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"
}
Segmentkapsel „Schiene“
{
"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"
}
Ebene „unsichtbare Grenze“
{
"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"
}