Navigation
Das Navigationsmodul ermöglicht es einem Inverse3 , den Arbeitsbereich der Anwendung zu verschieben – manchmal auch als „Rate-Control-Locomotion“ oder „gamepadähnliche Drift“ bezeichnet. Anstatt dass der Cursor am Rand des physischen Arbeitsbereichs auf eine harte Wand trifft, betritt er eine weiche Hülle, in der sein Abstand zu einem virtuellen Zentrum auf eine Geschwindigkeit abgebildet wird, die den gesamten Arbeitsbereich verschiebt. Je weiter der Cursor drückt, desto schneller scrollt die Szene.
Das primäre (und derzeit einzige) Verhalten ist die Bubble-Navigation. Die Blasenform wird mithilfe einer SDF-Primitive definiert – siehe „Was ist ein SDF?“ für eine Erläuterung des Konzepts.
Bubble-Navigation – Konzept
Eine virtuelle Blase wird um einen Mittelpunkt im Einbauraum des Geräts herum verankert. Der Cursor durchläuft drei konzentrische Zonen:
┌──────────────────────────────────────────┐
│ WALL ZONE │ cursor beyond outer shell
│ ┌────────────────────────────────────┐ │
│ │ VELOCITY ZONE │ │ soft shell → scene moves
│ │ ┌──────────────────────────────┐ │ │
│ │ │ DEAD ZONE (inside) │ │ │ no scene movement
│ │ │ │ │ │
│ │ │ ● centre │ │ │
│ │ │ │ │ │
│ │ └──────────────────────────────┘ │ │
│ │ bubble surface │ │
│ └────────────────────────────────────┘ │
│ outer boundary │
└──────────────────────────────────────────┘
| Zone | Cursorposition | Verhalten |
|---|---|---|
| Tote Zone | Innerhalb der Blase | Keine Navigation. Leichte Dämpfung. Du kannst die Szene frei manipulieren. |
| Geschwindigkeitszone | Zwischen der Oberfläche und der äußeren Grenze | Die Kurve „Weg → Geschwindigkeit“ verschiebt den Arbeitsbereich in Richtung des Cursors. |
| Wandbereich | Jenseits der äußeren Grenze | Eine starke Feder drückt den Cursor zurück, und die Navigationsgeschwindigkeit erreicht ihren Höchstwert. |
In allen drei Bereichen wird eine haptische Kraft durch Feder-Dämpfer-Mechanismen erzeugt – man spürt die Oberfläche, die Drift-Hülle und die Außenwand.
Schnellstart – Bubble-Navigation aktivieren
Die Navigation ist eine dauerhafte, einmalige Konfiguration – sobald sie einmal gesendet wurde, bleibt sie aktiv, bis Sie sie explizit beenden, den Dienst neu starten oder die Sitzung schließen.
Start (minimal – standardmäßige Blase mit abgerundeten Ecken)
- 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"}'
Stopp
- WebSocket
- HTTP
{
"inverse3": [
{
"device_id": "04C3",
"configure": {
"navigation": { "mode": "disabled" }
}
}
]
}
curl -X DELETE "http://localhost:10001/inverse3/04C3/config/navigation?session=:0"
Weitere HTTP-Routen
| Methode | Pfad | Zweck |
|---|---|---|
GET | /{type}/{id}/config/navigation?session=<expr> | Aktuelle Navigationskonfiguration + Status |
POST | /{type}/{id}/config/navigation?session=<expr> | Navigation starten oder aktualisieren |
DELETE | /{type}/{id}/config/navigation?session=<expr> | Navigation beenden |
Katalog für Blasenformen
Die tote Zone der Blase wird durch eine SDF-Form (Signed-Distance-Function) beschrieben. Verschiedene Formen sorgen für unterschiedliche Navigationserlebnisse – ein abgerundeter Quader (Standard) für eine angenehme rechteckige Ruhezone, eine Kugel für isotropes Driften, ein Ellipsoid zur Bevorzugung bestimmter Achsen, eine Kapsel für Korridore.
Abgerundetes Feld (Standard)
Die Standard-Dead-Zone ist ein flacher, in der Höhe etwas höher als in der Tiefe ausgeprägter Bereich – so abgestimmt, dass sie sich sowohl bei Inverse3 bei MInverse angenehm anfühlt:
{
"shape": {
"primitive": "rounded_box",
"parameters": { "b": { "x": 0.05, "y": 0.02, "z": 0.03 }, "r": 0.01 }
}
}
Kugel – isotrope Drift
{
"shape": {
"primitive": "sphere",
"parameters": { "r": 0.05 }
}
}
Ellipsoid – in X/Z-Richtung breiter als in Y-Richtung
Verwenden Sie diese Einstellung, wenn sich die horizontale Drift lockerer anfühlen soll als die vertikale:
{
"shape": {
"primitive": "ellipsoid",
"parameters": { "a": { "x": 0.06, "y": 0.03, "z": 0.06 } }
}
}
Kapsel – langgestreckter Korridor
Zwei Endpunkte a/b plus ein Radius 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
}
}
}
Vollständiges Beispiel mit individueller Größenanpassung und Bewegungsgefühl:
{
"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"
}
}
}
}
]
}
Geschwindigkeitskurve
Der Abstand zur Geschwindigkeitszone wird über eine Beschleunigungskurve abgebildet, bevor er in die Geschwindigkeit im Arbeitsbereich umgewandelt wird. Wählen Sie die Beschleunigungskurve, die dem gewünschten Beschleunigungsverlauf der Szene entspricht, wenn der Benutzer tiefer in die Hülle vordringt.
velocity_ease | Fühlen | Wann anzuwenden |
|---|---|---|
linear | Konstante Steigung | Vorhersehbar, gute Standardauswahl |
quadratic_in | Langsamer Start, schneller Endspurt | Präzise im Nahbereich, schnell bei großen Verfahrwegen |
cubic_in | Ein sehr langsamer Start | Sehr präzise, mit langem Hub |
sine_out | Sanfter, schneller Start, flacht im äußeren Bereich ab | Reaktionsschnell, mit sanften Großbuchstaben |
quadratic_out | Schnell beim Anfahren, komfortabel auf langen Strecken | Schnelles Beschleunigen, komfortables Cruisen |
{ "velocity_ease": "quadratic_in", "max_velocity": 1.5 }
Verhalten im Zentrum
Der Mittelpunkt der Blase wird durch eine verschachtelte center Objekt mit vier
Feldern — position, relative, follow, speed — als Ersatz für das ältere flache
Layout aus center, center_enabled, center_modeund center_drift_speed.
{
"center": {
"position": { "x": 0.0, "y": 0.0, "z": 0.0 },
"relative": true,
"follow": false,
"speed": 0.02
}
}
Wo das Zentrum verankert ist
position und relative die anfängliche Position des Mittelpunkts bei der Aktivierung festlegen:
relative | Semantik von position |
|---|---|
true (Standard) | position ist ein Versatz vom Cursor — der ursprüngliche Mittelpunkt ist cursor + position. Mit der Standardeinstellung (0, 0, 0), erscheint die Blase genau an der Stelle, an der sich der Cursor befindet. |
false | position ist ein absoluter Punkt im Anwendungsraum — Er wird beim Eingang in Mount-Speicherplatz umgewandelt und beim Ausgang wieder in Anwendungsspeicherplatz zurückgewandelt, sodass die Werte für den Hin- und Rückweg übereinstimmen. |
Wie sich das Zentrum danach verhält
follow und speed das Verhalten bei jedem Tick steuern, sobald die Blase aktiv ist:
follow | speed | Verhalten | Bisherige Entsprechung |
|---|---|---|---|
false (Standard) | ignoriert | Der Mittelpunkt bleibt dort, wo er ursprünglich festgelegt wurde – fester Mittelpunkt. | center_mode: "fixed" |
true | > 0 | Die Mitte verschiebt sich in Richtung des Cursors bei speed m/s, solange sich der Cursor darin befindet. | center_mode: "auto_follow" (mit center_drift_speed) |
true | 0.0 | Die Mitte springt bei jedem Ticken zum Cursor – wie beim Teleportieren. | center_mode: "track_cursor" |
Das Standardverhalten bei der Zentrierung ist nun korrigiert (follow = false). Frühere Versionen
bewegten sich standardmäßig in Richtung des Cursors (auto_follow). Einstellen center.follow = true
um das alte Drift-Verhalten wiederherzustellen und zu optimieren center.speed um dem alten Wert
von center_drift_speed.
Wenn follow = true und der Cursor die äußere Begrenzung überschreitet, folgt die Mitte
dem Cursor unabhängig davon, speed, um den Rahmen darum herum beizubehalten und
zu verhindern, dass der Cursor herausrutscht.
Reaktion bei einer Kollision
Die Blase reagiert auf äußere Cursorkräfte, die collision_detection.force_threshold:
- Die Geschwindigkeitszone vorübergehend bläst auf (bis zu
collision_detection.inflate_ratioMalvelocity_zone_width), um dem Benutzer mehr Spielraum beim Umfahren des Hindernisses zu geben. - Wenn
collision_detection.enabledisttrue(Standard), driftet der Mittelpunkt der Blase nicht in Richtung der Kollisionskraft, wodurch verhindert wird, dass der Benutzer den Arbeitsbereich gegen eine feste Wand zieht.
Anwendungen der Kollisionserkennung Hysterese Um ein Flackern im Bereich des Schwellenwerts zu vermeiden:
Sobald eine Kollision aktiv ist, bleibt sie aktiv, bis |ext_force| fällt unter das
Produkt collision_detection.force_threshold × collision_detection.exit_ratio.
Senken Sie die exit_ratio um das Hysterese-Band zu erweitern (stärkere Zusammenstöße); stelle
es auf 1.0 um die Hysterese zu deaktivieren und einen einzigen Schwellenwert zu verwenden.
{
"collision_detection": {
"enabled": true,
"force_threshold": 0.5,
"inflate_ratio": 2.0,
"exit_ratio": 0.7
}
}
Parameterübersicht
Am häufigsten gestimmt
| Parameter | Standard | Beschreibung |
|---|---|---|
shape | {rounded_box, r=0.01, b=(0.05,0.02,0.03)} | SDF-Form, die die Totzone definiert |
velocity_zone_width | 0.03 m | Dicke der Hülle zur Geschwindigkeitsregelung |
max_velocity | 0.5 m/s | Maximale Fahrgeschwindigkeit |
velocity_ease | "quadratic_in" | Entfernung → Geschwindigkeits-Easing-Kurve |
center.follow | false | Ob die Mitte dem Cursor folgt |
center.speed | 0.02 m/s | Driftrate, wenn follow = true |
Vollständige Parameterliste
| Feld | Typ | Standard | Beschreibung |
|---|---|---|---|
center.position | vec3 | (0, 0, 0) | Anfangsposition – Cursor-Versatz bei relative = true, absoluter Punkt im App-Raum, wenn false |
center.relative | bool | true | true: position ist ein Versatz vom Cursor. false: absoluter Punkt im App-Speicher, umgerechnet auf den Speicherplatz an der Grenze |
center.follow | bool | false | false: Die Mitte bleibt an ihrer Ausgangsposition. true: Die Mitte folgt dem Cursor |
center.speed | float | 0.02 | Driftgeschwindigkeit (m/s) bei follow = true; 0.0 rastet bei jedem Ticken am Cursor ein |
shape | Form | {rounded_box, r=0.01, b=(0.05,0.02,0.03)} | SDF-Form der Totzone |
velocity_zone_width | float | 0.03 | Breite der Durchflussregelungshülle (m) |
max_velocity | float | 0.5 | Maximale Fahrgeschwindigkeit (m/s) |
velocity_ease | String | "quadratic_in" | Entfernung → Geschwindigkeitsüberblendung |
reset_velocity_on_entry | bool | true | Die kumulierte Geschwindigkeit auf Null zurücksetzen, wenn der Cursor erneut in den Geschwindigkeitsbereich gelangt |
bump_width | float | 0.005 | Taktile Erhebung an der Oberfläche (m) |
bump_stiffness | float | 200.0 | Federkonstante der Oberflächenunebenheit |
spring_inner | float | 0.0 | Frühling im Bubble Centre |
spring_surface | float | 10.0 | Frühling an der Oberfläche |
spring_outer | float | 15.0 | Frühling an der Außengrenze |
wall_stiffness | float | 700.0 | Feder mit harter Wand hinter der Außengrenze |
damping_inner | float | 0.1 | Dämpfung in der Mitte |
damping_surface | float | 4.0 | Dämpfung an der Oberfläche |
damping_outer | float | 7.0 | Dämpfung an der Außengrenze |
rotation_enabled | bool | false | Wende die Drehung des Arbeitsbereichs auf die Navigationsrichtung an |
scale_enabled | bool | false | Wende den Arbeitsbereichsmaßstab auf die Navigationsgeschwindigkeit an |
collision_detection.enabled | bool | true | Navigation in Kollisionsrichtung blockieren |
collision_detection.force_threshold | float | 1.0 | Größe der äußeren Kraft, die bei einer Kollision wirkt (N) |
collision_detection.inflate_ratio | float | 2.0 | Multiplikator für die Breite der Geschwindigkeitszone während einer Kollision (muss ≥ 1,0 sein) |
collision_detection.exit_ratio | float | 0.7 | Hystereseverhältnis – Kollision so lange aufrechterhalten, bis |ext_force| < force_threshold × exit_ratio. Reichweite (0, 1]; 1.0 deaktiviert die Hysterese |
Zwei Merkmalsgruppen wurden aus dem JSON-Schema der Version 3.5 weggelassen, während ihre Implementierungen für Version 3.6 überarbeitet wurden:
- Avatar-Grenzen-Clamping: die Felder
avatar_boundary_enabled,avatar_boundaryundavatar_boundary_hysteresis. - Begrenzung des Arbeitsbereichs: die Felder
workspace_bounded,workspace_transition_speedundworkspace_transition_ease.
Der Tick-Code lässt sich mit den Standardeinstellungen weiterhin kompilieren und ausführen, aber Clients können diese Felder nicht
über HTTP oder WebSocket lesen oder schreiben. In Version 3.6 wird die Avatar-Grenze
wieder als Top-Level-Element bounds Ein Peer des Bubble-Objekts mit vollständiger Platzierungstransformation;
die Begrenzung des Arbeitsbereichs wird wiederhergestellt, sobald die Untersuchung des
Zentrums-Jitters abgeschlossen ist.
Validierungsregeln
velocity_zone_width > 00 ≤ bump_width < velocity_zone_widthmax_velocity > 0bump_stiffness ≥ 0spring_inner ≥ 0undspring_inner ≤ spring_surface ≤ spring_outerwall_stiffness ≥ 0damping_inner ≥ 0unddamping_inner ≤ damping_surface ≤ damping_outercollision_detection.force_threshold > 0collision_detection.inflate_ratio ≥ 1.0collision_detection.exit_ratioin(0, 1]center.speed ≥ 0
A POST oder configure.navigation mit ungültigen Parametern wird abgelehnt und eine
invalid-value Das Ereignis wird ausgelöst; die vorherige Konfiguration bleibt aktiv.
Veranstaltungen
| Name der Veranstaltung | Entlassen, als |
|---|---|
navigation-started | Die Navigation ist auf dem Gerät aktiviert |
navigation-updated | Die Navigationseinstellungen werden aktualisiert, während die Navigation bereits aktiv ist |
navigation-stopped | Die Navigation ist deaktiviert (explizite Deaktivierung, DELETEoder beim Schließen der Sitzung) |
invalid-value | Eine Navigationskonfiguration wird bei der Validierung abgelehnt |
Bekannte Einschränkungen
- Begrenzung des Arbeitsbereichs und Avatar-Grenzen in Version 3.5 ausgeblendet: Beide Merkmalsgruppen fehlen im JSON-Schema, während sie für Version 3.6 neu gestaltet wurden. Siehe den Hinweis oben unter „Parameter-Referenz“.
- Nicht einheitliche Skalierung + Drehung: wenn beide
rotation_enabledundscale_enabledsind aktiviert, ist die Geschwindigkeitsrichtung leicht ungenau – die Drehung wird nicht auf die Skalenachsen angewendet. - Größenskalierung pro Gerät: Die Blasengrößen (Radius, Zonenbreite) werden nicht anhand des physikalischen Skalierungsfaktors des Geräts skaliert – MInverse Inverse3 dieselben absoluten Größen, was auf den jeweiligen Geräten unterschiedlich wirken kann.