导航
导航模块可让 Inverse3 光标移动应用的工作区——这有时被称为 速率控制式移动 或“类游戏手柄漂移”。 光标不会在物理工作区的边缘撞上硬墙,而是进入一个软壳层:光标与虚拟中心的距离会被映射为速度,从而带动整个工作区滑动。光标推得越远,场景滚动得越快。
目前主要(也是唯一)的行为是气泡导航。气泡形状通过 SDF 图元 定义——相关概念请参见 什么是 SDF?。
气泡导航——概念
虚拟气泡锚定在设备安装空间中的一个中心点周围。光标会经历三个同心区域:
┌──────────────────────────────────────────┐
│ WALL ZONE │ cursor beyond outer shell
│ ┌────────────────────────────────────┐ │
│ │ VELOCITY ZONE │ │ soft shell → scene moves
│ │ ┌──────────────────────────────┐ │ │
│ │ │ DEAD ZONE (inside) │ │ │ no scene movement
│ │ │ │ │ │
│ │ │ ● centre │ │ │
│ │ │ │ │ │
│ │ └──────────────────────────────┘ │ │
│ │ bubble surface │ │
│ └────────────────────────────────────┘ │
│ outer boundary │
└──────────────────────────────────────────┘
| 区域 | 光标位置 | 行为 |
|---|---|---|
| 死区 | 气泡内部 | 不进行导航。轻度阻尼。您可以自由操控场景。 |
| 速度区 | 气泡表面与外边界之间 | 距离→速度曲线使工作区沿光标方向移动。 |
| 墙区 | 超出外边界 | 硬弹簧将光标推回内部,导航速度随之达到饱和。 |
三个区域均施加弹簧-阻尼触觉力——您可以感受到表面、漂移壳层以及外墙。
快速开始——启用气泡导航
导航是一种持久的单次配置——只需发送一次,它便会保持激活状态,直到您显式停止导航、重启服务或关闭会话。
启动(最简配置——默认圆角盒气泡)
- 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"}'
停止
- WebSocket
- HTTP
{
"inverse3": [
{
"device_id": "04C3",
"configure": {
"navigation": { "mode": "disabled" }
}
}
]
}
curl -X DELETE "http://localhost:10001/inverse3/04C3/config/navigation?session=:0"
其他 HTTP 路由
| 方法 | 路径 | 用途 |
|---|---|---|
GET | /{type}/{id}/config/navigation?session=<expr> | 当前导航配置与状态 |
POST | /{type}/{id}/config/navigation?session=<expr> | 启动或更新导航 |
DELETE | /{type}/{id}/config/navigation?session=<expr> | 停止导航 |
气泡形状目录
气泡的死区由有符号距离函数(SDF)形状描述。不同形状带来不同的导航手感:圆角盒(默认)适用于舒适的矩形静止区,球体适用于各向同性漂移,椭球体用于偏向某些轴向,胶囊体则适用于走廊类场景。
圆角盒(默认)
默认死区是一个扁平的体积,其高度略大于深度——经过调校,可在 Inverse3 与 MInverse 上都带来舒适的手感:
{
"shape": {
"primitive": "rounded_box",
"parameters": { "b": { "x": 0.05, "y": 0.02, "z": 0.03 }, "r": 0.01 }
}
}
球体——各向同性漂移
{
"shape": {
"primitive": "sphere",
"parameters": { "r": 0.05 }
}
}
椭球体——X/Z 方向比 Y 方向更宽
当水平漂移的手感应比垂直方向更松弛时使用:
{
"shape": {
"primitive": "ellipsoid",
"parameters": { "a": { "x": 0.06, "y": 0.03, "z": 0.06 } }
}
}
胶囊体——细长走廊
由两个端点 a/b 与半径 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
}
}
}
包含自定义尺寸与运动手感的完整示例:
{
"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"
}
}
}
}
]
}
速度曲线
速度区的距离会先经过缓动曲线映射,再转换为工作区速度。请选择与您期望的加速方式相匹配的缓动函数——即用户继续向壳层深处推动时,场景应如何加速。
velocity_ease | 手感 | 适用场景 |
|---|---|---|
linear | 恒定斜率 | 可预测,推荐作为默认值 |
quadratic_in | 起步慢,推动越深越快 | 贴近表面时精确,长距离移动快 |
cubic_in | 起步非常慢 | 非常精确,长距离时逐步加速 |
sine_out | 起步平滑快速,接近外边界时趋于平稳 | 响应灵敏,速度平缓封顶 |
quadratic_out | 进入时快,长距离手感舒适 | 快速轻推,舒适巡航 |
{ "velocity_ease": "quadratic_in", "max_velocity": 1.5 }
中心行为
气泡的中心通过嵌套的 center 对象进行配置,该对象包含四个字段——position、relative、follow、speed——取代了由 center、center_enabled、center_mode 和 center_drift_speed 组成的旧版扁平布局。
{
"center": {
"position": { "x": 0.0, "y": 0.0, "z": 0.0 },
"relative": true,
"follow": false,
"speed": 0.02
}
}
中心的锚定位置
position 与 relative 控制激活时的初始中心位置:
relative | position 的含义 |
|---|---|
true(默认) | position 是相对于光标的偏移量——初始中心为 cursor + position。使用默认值 (0, 0, 0) 时,气泡恰好生成于光标位置。 |
false | position 是应用空间中的绝对点——入站时转换为安装空间,出站时再转换回应用空间,因此往返数值保持一致。 |
之后中心如何移动
follow 与 speed 控制气泡激活后,每个更新周期的行为:
follow | speed | 行为 | 旧版等效配置 |
|---|---|---|---|
false(默认) | 忽略 | 中心保持初始化时的位置——固定中心。 | center_mode: "fixed" |
true | > 0 | 光标位于气泡内时,中心以 speed m/s 的速度向光标漂移。 | center_mode: "auto_follow"(配合 center_drift_speed) |
true | 0.0 | 中心在每个更新周期直接贴合光标——瞬移手感。 | center_mode: "track_cursor" |
中心的默认行为现已改为固定(follow = false)。早期版本默认会向光标漂移(auto_follow)。如需恢复旧的漂移行为,请设置 center.follow = true,并将 center.speed 调整为与旧的 center_drift_speed 值一致。
当 follow = true 且光标推过外边界时,无论 speed 为何值,中心都会跟随光标,使气泡始终环绕光标,防止光标逃逸。
碰撞响应
当外部光标力超过 collision_detection.force_threshold 时,气泡会做出响应:
- 速度区会临时膨胀(最多可达
velocity_zone_width的collision_detection.inflate_ratio倍),以便用户绕过障碍物时有更多操作空间。 - 当
collision_detection.enabled为true(默认值)时,气泡中心会拒绝沿碰撞力的方向漂移,防止用户把工作区拖入硬墙。
碰撞检测采用滞回机制,以避免在阈值附近出现抖动:碰撞一旦激活,就会保持激活状态,直到 |ext_force| 降至 collision_detection.force_threshold × collision_detection.exit_ratio 的乘积以下。降低 exit_ratio 可加宽滞回区间(使碰撞更具粘滞性);将其设为 1.0 则可禁用滞回,仅使用单一阈值。
{
"collision_detection": {
"enabled": true,
"force_threshold": 0.5,
"inflate_ratio": 2.0,
"exit_ratio": 0.7
}
}
参数参考
最常调整的参数
| 参数 | 默认值 | 说明 |
|---|---|---|
shape | {rounded_box, r=0.01, b=(0.05,0.02,0.03)} | 定义死区的 SDF 形状 |
velocity_zone_width | 0.03 m | 速率控制壳层的厚度 |
max_velocity | 0.5 m/s | 最大导航速度 |
velocity_ease | "quadratic_in" | 距离→速度的缓动曲线 |
center.follow | false | 中心是否跟随光标 |
center.speed | 0.02 m/s | follow = true 时的漂移速率 |
完整参数列表
| 字段 | 类型 | 默认值 | 描述 |
|---|---|---|---|
center.position | vec3 | (0, 0, 0) | 初始中心点——relative = true 时为相对光标的偏移量,false 时为绝对的应用空间坐标点 |
center.relative | bool | true | true:position 为相对光标的偏移量。false:绝对的应用空间坐标点,在边界处转换为安装空间坐标 |
center.follow | bool | false | false:中心点保持在其初始化位置。true:中心点跟随光标 |
center.speed | float | 0.02 | follow = true 时的漂移速度(米/秒);0.0 表示每个周期直接吸附到光标 |
shape | shape | {rounded_box, r=0.01, b=(0.05,0.02,0.03)} | 死区 SDF 形状 |
velocity_zone_width | float | 0.03 | 速率控制外壳的宽度(米) |
max_velocity | float | 0.5 | 最大导航速度(米/秒) |
velocity_ease | string | "quadratic_in" | 距离到速度的缓动函数 |
reset_velocity_on_entry | bool | true | 光标重新进入速度区域时,将累积速度归零 |
bump_width | float | 0.005 | 表面处的触觉凸起宽度(米) |
bump_stiffness | float | 200.0 | 表面凸起的弹簧常数 |
spring_inner | float | 0.0 | 气泡中心处的弹簧 |
spring_surface | float | 10.0 | 表面处的弹簧 |
spring_outer | float | 15.0 | 外边界处的弹簧 |
wall_stiffness | float | 700.0 | 超出外边界后的硬壁弹簧 |
damping_inner | float | 0.1 | 中心处的阻尼 |
damping_surface | float | 4.0 | 表面处的阻尼 |
damping_outer | float | 7.0 | 外边界处的阻尼 |
rotation_enabled | bool | false | 将工作空间旋转应用于导航方向 |
scale_enabled | bool | false | 将工作空间缩放应用于导航速度 |
collision_detection.enabled | bool | true | 阻止沿碰撞方向的导航 |
collision_detection.force_threshold | float | 1.0 | 进入碰撞所需的外力大小(牛) |
collision_detection.inflate_ratio | float | 2.0 | 碰撞期间速度区域宽度的放大倍数(必须 ≥ 1.0) |
collision_detection.exit_ratio | float | 0.7 | 滞后比率——保持碰撞状态,直到 |ext_force| < force_threshold × exit_ratio。取值范围 (0, 1];1.0 表示禁用滞后 |
以下两组功能在 3.5 版 JSON 模式中被省略,而其实现正在为 3.6 版重新设计:
- Avatar 边界钳位:字段
avatar_boundary_enabled、avatar_boundary和avatar_boundary_hysteresis。 - 工作空间边界约束:字段
workspace_bounded、workspace_transition_speed和workspace_transition_ease。
tick 代码仍会以默认值编译并运行,但客户端无法通过 HTTP 或 WebSocket 读取或写入这些字段。在 3.6 版中,Avatar 边界将作为与气泡对象同级的顶层 bounds 字段重新加入,并附带完整的放置变换;工作空间边界约束将在中心抖动问题排查完成后重新加入。
校验规则
velocity_zone_width > 00 ≤ bump_width < velocity_zone_widthmax_velocity > 0bump_stiffness ≥ 0spring_inner ≥ 0且spring_inner ≤ spring_surface ≤ spring_outerwall_stiffness ≥ 0damping_inner ≥ 0且damping_inner ≤ damping_surface ≤ damping_outercollision_detection.force_threshold > 0collision_detection.inflate_ratio ≥ 1.0collision_detection.exit_ratio取值在(0, 1]范围内center.speed ≥ 0
使用无效参数的 POST 或 configure.navigation 请求会被拒绝,并触发 invalid-value 事件;先前的配置保持生效。
事件
| 事件名称 | 触发时机 |
|---|---|
navigation-started | 设备上的导航被激活 |
navigation-updated | 导航已处于激活状态时,其配置被更新 |
navigation-stopped | 导航被停止(显式禁用、DELETE 请求或会话关闭) |
invalid-value | 导航配置未通过校验而被拒绝 |
已知限制
- 3.5 中隐藏的工作空间边界与 Avatar 边界:这两组功能在 JSON 模式中均不存在,因为它们正在为 3.6 版重新设计。请参阅上文 参数参考 中的说明。
- 非均匀缩放 + 旋转:当
rotation_enabled与scale_enabled同时开启时,速度方向会略有偏差——旋转未应用于缩放轴。 - 按设备的尺寸缩放:气泡尺寸(半径、区域宽度)不会按设备的物理缩放系数进行缩放——MInverse 和 Inverse3 使用相同的绝对尺寸,因此两者的手感可能不同。