Navigation
Das Modul Navigation ermöglicht es einem Inverse3-Cursor, den Arbeitsbereich der Anwendung zu verschieben – manchmal als Rate-Control-Locomotion oder „gamepadartiges Driften“ bezeichnet. Anstatt dass der Cursor am Rand des physischen Arbeitsbereichs auf eine harte Wand trifft, gelangt er in eine weiche Hülle, in der sein Abstand zu einem virtuellen Mittelpunkt auf eine Geschwindigkeit abgebildet wird, mit der sich der gesamte Arbeitsbereich verschiebt. Je weiter der Cursor gedrückt wird, desto schneller scrollt die Szene.
Das primäre (und derzeit einzige) Verhalten ist Bubble-Navigation. Die Form der Blase wird mithilfe eines SDF-Primitivs definiert – siehe Was ist ein SDF? für das Konzept.
Bubble-Navigation – Konzept
Eine virtuelle Blase ist um einen Mittelpunkt im Montageraum des Geräts verankert. Der Cursor erfährt 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 | Cursor-Position | Verhalten |
|---|---|---|
| Totzone | Innerhalb der Blase | Keine Navigation. Leichte Dämpfung. Sie können die Szene frei manipulieren. |
| Geschwindigkeitszone | Zwischen Oberfläche und äußerer Grenze | Abstand → Geschwindigkeitskurve verschiebt den Arbeitsbereich in Richtung des Cursors. |
| Wandzone | Jenseits der äußeren Grenze | Eine harte Feder drückt den Cursor zurück in die Blase, und die Navigationsgeschwindigkeit wird begrenzt. |
In allen drei Zonen wirkt eine haptische Feder-Dämpfer-Kraft – Sie spüren die Oberfläche, die Driftschale und die äußere Wand.
Schnellstart – Bubble-Navigation aktivieren
Die Navigation ist eine dauerhafte Einmal-Konfiguration – senden Sie sie einmal, und sie bleibt aktiv, bis Sie sie ausdrücklich beenden, den Dienst neu starten oder die Sitzung schließen.
Start (minimal – Standard-Blase mit abgerundetem Quader)
- 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"}'
Beenden
- 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 + Zustand |
POST | /{type}/{id}/config/navigation?session=<expr> | Navigation starten oder aktualisieren |
DELETE | /{type}/{id}/config/navigation?session=<expr> | Navigation beenden |
Katalog der Blasenformen
Die Totzone der Blase wird durch eine Form mit Vorzeichen-Abstandsfunktion (Signed Distance Function, SDF) beschrieben. Unterschiedliche Formen ergeben unterschiedliche Navigationsgefühle – ein abgerundeter Quader (der Standard) für eine komfortable rechteckige Ruhezone, eine Kugel für isotropes Driften, ein Ellipsoid, um bestimmte Achsen zu bevorzugen, und eine Kapsel für Korridore.
Abgerundeter Quader (Standard)
Die Standard-Totzone ist ein flaches Volumen, das etwas höher als tief ist – abgestimmt, damit sie sich sowohl mit Inverse3 als auch mit MInverse angenehm anfühlt:
{
"shape": {
"primitive": "rounded_box",
"parameters": { "b": { "x": 0.05, "y": 0.02, "z": 0.03 }, "r": 0.01 }
}
}
Kugel – isotropes Driften
{
"shape": {
"primitive": "sphere",
"parameters": { "r": 0.05 }
}
}
Ellipsoid – in X/Z breiter als in Y
Verwenden Sie diese Form, wenn sich das horizontale Driften lockerer anfühlen soll als das vertikale:
{
"shape": {
"primitive": "ellipsoid",
"parameters": { "a": { "x": 0.06, "y": 0.03, "z": 0.06 } }
}
}
Kapsel – länglicher Korridor
Zwei Endpunkte a/b sowie 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 benutzerdefinierter Größe 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 in der Geschwindigkeitszone wird vor der Umwandlung in eine Arbeitsbereich-Geschwindigkeit durch eine Easing-Kurve geführt. Wählen Sie das Easing, das dazu passt, wie die Szene beschleunigen soll, wenn der Benutzer weiter in die Hülle drückt.
velocity_ease | Gefühl | Wann verwenden |
|---|---|---|
linear | Konstanter Anstieg | Vorhersehbar, guter Standard |
quadratic_in | Langsamer Start, dann schnellerer Vorschub | Präzise nahe der Oberfläche, schnell bei langen Wegen |
cubic_in | Sehr langsamer Start | Sehr präzise, lange Wege mit steigender Rampe |
sine_out | Sanfter, schneller Start, flacht nahe der Außenkante ab | Reaktionsschnell, begrenzt sanft |
quadratic_out | Schnell beim Eintritt, komfortabel auf langen Distanzen | Schnelles Antippen, komfortables Gleiten |
{ "velocity_ease": "quadratic_in", "max_velocity": 1.5 }
Verhalten des Mittelpunkts
Der Mittelpunkt der Blase wird über ein verschachteltes center-Objekt mit vier Feldern konfiguriert – position, relative, follow, speed –; es ersetzt das ältere flache Layout aus center, center_enabled, center_mode und center_drift_speed.
{
"center": {
"position": { "x": 0.0, "y": 0.0, "z": 0.0 },
"relative": true,
"follow": false,
"speed": 0.02
}
}
Wo der Mittelpunkt verankert wird
position und relative steuern die anfängliche Lage des Mittelpunkts bei der Aktivierung:
relative | Bedeutung von position |
|---|---|
true (Standard) | position ist ein Versatz zum Cursor – der anfängliche Mittelpunkt ist cursor + position. Bei dem Standardwert (0, 0, 0) erscheint die Blase genau auf dem Cursor. |
false | position ist ein absoluter Punkt im Anwendungsraum – er wird beim Eingang in den Montageraum umgerechnet und beim Ausgang wieder in den Anwendungsraum zurückgerechnet, sodass die Werte bei der Hin- und Rückrechnung übereinstimmen. |
Wie sich der Mittelpunkt danach bewegt
follow und speed steuern das Verhalten pro Takt, sobald die Blase aktiv ist:
follow | speed | Verhalten | Bisheriges Äquivalent |
|---|---|---|---|
false (Standard) | ignoriert | Der Mittelpunkt bleibt an der Stelle, an der er initialisiert wurde – fester Mittelpunkt. | center_mode: "fixed" |
true | > 0 | Der Mittelpunkt driftet mit speed m/s in Richtung des Cursors, solange sich dieser innerhalb befindet. | center_mode: "auto_follow" (mit center_drift_speed) |
true | 0.0 | Der Mittelpunkt springt bei jedem Takt auf den Cursor – Teleportgefühl. | center_mode: "track_cursor" |
Das Standardverhalten des Mittelpunkts ist jetzt fest (follow = false). Frühere Versionen ließen den Mittelpunkt standardmäßig in Richtung des Cursors driften (auto_follow). Setzen Sie center.follow = true, um das alte Driftverhalten wiederherzustellen, und passen Sie center.speed an den alten Wert von center_drift_speed an.
Wenn follow = true gilt und der Cursor über die äußere Grenze hinausdrückt, folgt der Mittelpunkt dem Cursor unabhängig von speed, damit die Blase ihn weiterhin umschließt und der Cursor nicht entweichen kann.
Kollisionsverhalten
Die Blase reagiert auf äußere Cursorkräfte, die collision_detection.force_threshold überschreiten:
- Die Geschwindigkeitszone weitet sich vorübergehend aus (bis zum
collision_detection.inflate_ratio-Fachen vonvelocity_zone_width), damit Sie mehr Raum zum Manövrieren um das Hindernis herum haben. - Wenn
collision_detection.enabledauftruesteht (der Standardwert), driftet der Mittelpunkt der Blase nicht in Richtung der Kollisionskraft, sodass Sie den Arbeitsbereich nicht in eine harte Wand ziehen können.
Die Kollisionserkennung verwendet Hysterese, um ein Flackern um den Schwellenwert herum zu vermeiden: Sobald eine Kollision aktiv ist, bleibt sie aktiv, bis |ext_force| unter das Produkt aus collision_detection.force_threshold × collision_detection.exit_ratio fällt. Senken Sie exit_ratio, um das Hysteresband zu verbreitern (haftendere Kollisionen); setzen Sie den Wert auf 1.0, um die Hysterese zu deaktivieren und nur einen einzigen Schwellenwert zu verwenden.
{
"collision_detection": {
"enabled": true,
"force_threshold": 0.5,
"inflate_ratio": 2.0,
"exit_ratio": 0.7
}
}
Parameterreferenz
Am häufigsten angepasst
| 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 Steuerungshülle |
max_velocity | 0.5 m/s | Maximale Navigationsgeschwindigkeit |
velocity_ease | "quadratic_in" | Easing-Kurve von Abstand zu Geschwindigkeit |
center.follow | false | Ob der Mittelpunkt 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) | Anfänglicher Mittelpunkt — Cursor-Versatz bei relative = true, absoluter Punkt im App-Raum bei false |
center.relative | bool | true | true: position ist ein Versatz zum Cursor. false: absoluter Punkt im App-Raum, der an der Grenze in den Mount-Raum umgerechnet wird |
center.follow | bool | false | false: Der Mittelpunkt bleibt an seiner initialisierten Position fixiert. true: Der Mittelpunkt folgt dem Cursor |
center.speed | float | 0.02 | Driftgeschwindigkeit (m/s) bei follow = true; 0.0 springt bei jedem Tick auf den Cursor |
shape | shape | {rounded_box, r=0.01, b=(0.05,0.02,0.03)} | SDF-Form der Totzone |
velocity_zone_width | float | 0.03 | Breite der Schale zur Geschwindigkeitsregelung (m) |
max_velocity | float | 0.5 | Maximale Navigationsgeschwindigkeit (m/s) |
velocity_ease | string | "quadratic_in" | Easing von Abstand zu Geschwindigkeit |
reset_velocity_on_entry | bool | true | Akkumulierte Geschwindigkeit auf null zurücksetzen, wenn der Cursor die Geschwindigkeitszone erneut betritt |
bump_width | float | 0.005 | Taktile Erhebung an der Oberfläche (m) |
bump_stiffness | float | 200.0 | Federkonstante der Oberflächen-Erhebung |
spring_inner | float | 0.0 | Feder am Mittelpunkt der Blase |
spring_surface | float | 10.0 | Feder an der Oberfläche |
spring_outer | float | 15.0 | Feder an der äußeren Grenze |
wall_stiffness | float | 700.0 | Feder der harten Wand jenseits der äußeren Grenze |
damping_inner | float | 0.1 | Dämpfung am Mittelpunkt |
damping_surface | float | 4.0 | Dämpfung an der Oberfläche |
damping_outer | float | 7.0 | Dämpfung an der äußeren Grenze |
rotation_enabled | bool | false | Rotation des Arbeitsraums auf die Navigationsrichtung anwenden |
scale_enabled | bool | false | Skalierung des Arbeitsraums auf die Navigationsgeschwindigkeit anwenden |
collision_detection.enabled | bool | true | Navigation in Kollisionsrichtung blockieren |
collision_detection.force_threshold | float | 1.0 | Betrag der externen Kraft, ab der eine Kollision eintritt (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 | Hysterese-Verhältnis — im Kollisionszustand bleiben, bis |ext_force| < force_threshold × exit_ratio gilt. Bereich (0, 1]; 1.0 deaktiviert die Hysterese |
Zwei Funktionsgruppen sind im Schema JSON der Version 3.5 nicht enthalten, während ihre Implementierungen für 3.6 überarbeitet werden:
- Klemmung an der Avatar-Grenze: die Felder
avatar_boundary_enabled,avatar_boundaryundavatar_boundary_hysteresis. - Begrenzung des Arbeitsraums: die Felder
workspace_bounded,workspace_transition_speedundworkspace_transition_ease.
Der Tick-Code wird weiterhin mit Standardwerten kompiliert und ausgeführt, aber Clients können diese Felder weder über HTTP noch über WebSocket lesen noch schreiben. In 3.6 kehrt die Avatar-Grenze als gleichrangiges, oberstes Element bounds neben dem Blasenobjekt zurück, mit einer vollständigen Platzierungstransformation; die Begrenzung des Arbeitsraums kehrt zurück, sobald die Untersuchung des Zitterns des Mittelpunkts 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
Ein POST oder configure.navigation mit ungültigen Parametern wird abgelehnt, und ein
invalid-value-Ereignis wird ausgelöst; die vorherige Konfiguration bleibt aktiv.
Ereignisse
| Ereignisname | Ausgelöst, wenn |
|---|---|
navigation-started | Navigation wird auf einem Gerät aktiviert |
navigation-updated | Navigationskonfiguration wird aktualisiert, während sie bereits aktiv ist |
navigation-stopped | Navigation wird beendet (explizite Deaktivierung, DELETE oder Sitzungsende) |
invalid-value | Eine Navigationskonfiguration wird durch die Validierung abgelehnt |
Bekannte Einschränkungen
- Begrenzung des Arbeitsraums und Avatar-Grenzen in 3.5 ausgeblendet: beide Funktionsgruppen fehlen im Schema JSON, während sie für 3.6 überarbeitet werden. Siehe den Hinweis oben unter Parameterreferenz.
- Ungleichmäßige Skalierung + Rotation: wenn
rotation_enabledundscale_enabledbeide aktiviert sind, ist die Geschwindigkeitsrichtung leicht ungenau — die Rotation wird nicht auf die Skalierungsachsen angewendet. - Größenskalierung pro Gerät: Blasengrößen (Radius, Zonenbreite) werden nicht mit dem physischen Skalierungsfaktor des Geräts skaliert — MInverse und Inverse3 verwenden dieselben absoluten Größen, die sich auf den einzelnen Geräten unterschiedlich anfühlen können.