내비게이션
내비게이션 모듈을 사용하면 Inverse3 커서로 애플리케이션의 작업 공간(workspace)을 이동할 수 있습니다. 이를 rate-control locomotion 또는 "gamepad-like drift"라고도 합니다. 커서가 물리적 작업 공간의 가장자리에서 단단한 벽에 부딪히는 대신, 가상 중심으로부터의 거리가 작업 공간 전체를 이동시키는 속도로 매핑되는 소프트 셸(soft shell) 영역에 진입합니다. 커서를 더 멀리 밀수록 장면이 더 빠르게 스크롤됩니다.
기본(현재 유일한) 동작은 버블 내비게이션입니다. 버블의 형태는 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> | 내비게이션 중지 |
버블 형태 목록
버블의 데드 존은 부호 있는 거리 함수(signed-distance-function, SDF) 형태로 정의됩니다. 형태에 따라 내비게이션 느낌이 달라집니다. 편안한 직사각형 휴지 영역에는 둥근 사각형(기본값)을, 등방성 드리프트에는 구(sphere)를, 특정 축을 우선하도록 하려면 타원체(ellipsoid)를, 통로에는 캡슐(capsule)을 사용합니다.
둥근 사각형 (기본값)
기본 데드 존은 깊이보다 약간 높은, 다소 납작한 볼륨이며, 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"
}
}
}
}
]
}
속도 곡선
속도 영역 거리는 이징(easing) 곡선을 통해 매핑된 후 작업 공간 속도로 변환됩니다. 사용자가 셸 안쪽으로 더 깊이 밀 때 장면이 어떻게 가속되기를 원하는지에 맞는 이징을 선택하십시오.
velocity_ease | 느낌 | 사용 시기 |
|---|---|---|
linear | 일정한 증가 | 예측 가능하고 무난한 기본값 |
quadratic_in | 느린 시작, 빠른 밀기 | 표면 근처에서는 정밀하고, 장거리 이동이 빠름 |
cubic_in | 매우 느린 시작 | 매우 정밀하며, 장거리 이동 시 점진적으로 가속 |
sine_out | 부드럽고 빠른 시작, 외곽 근처에서 완만해짐 | 반응이 빠르며, 완만하게 상한이 걸림 |
quadratic_out | 진입 시 빠르고, 장거리에서 편안함 | 빠른 미세 조정, 편안한 순항 |
{ "velocity_ease": "quadratic_in", "max_velocity": 1.5 }
중심 동작
버블의 중심은 네 개의 필드(position, relative, follow, speed)로 구성된 중첩 center 객체를 통해 설정합니다. 이는 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 | 속도 제어(rate-control) 셸의 두께 |
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일 때의 드리프트 속도(m/s). 0.0이면 매 틱마다 커서에 즉시 맞춰집니다 |
shape | shape | {rounded_box, r=0.01, b=(0.05,0.02,0.03)} | 데드존 SDF 형상 |
velocity_zone_width | float | 0.03 | 속도 제어 셸의 폭(m) |
max_velocity | float | 0.5 | 최대 내비게이션 속도(m/s) |
velocity_ease | string | "quadratic_in" | 거리 → 속도 이징 |
reset_velocity_on_entry | bool | true | 커서가 속도 영역에 다시 진입하면 누적 속도를 0으로 초기화합니다 |
bump_width | float | 0.005 | 표면의 촉각 범프(m) |
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 | 충돌에 진입하기 위한 외력 크기(N) |
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.6을 위해 구현이 재구성되는 동안 3.5 JSON 스키마에서 제외됩니다:
- 아바타 경계 클램핑:
avatar_boundary_enabled,avatar_boundary,avatar_boundary_hysteresis필드. - 워크스페이스 바운딩:
workspace_bounded,workspace_transition_speed,workspace_transition_ease필드.
틱 코드는 여전히 기본값으로 컴파일되고 실행되지만, 클라이언트는 HTTP 또는 WebSocket를 통해 해당 필드를 읽거나 쓸 수 없습니다. 3.6에서는 아바타 경계가 버블 객체와 동급의 최상위 bounds 항목으로 다시 제공되며, 전체 배치 변환(placement transform)을 갖습니다. 워크스페이스 바운딩은 중심 지터(centre-jitter) 조사가 완료되면 다시 제공될 예정입니다.
검증 규칙
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에서 숨겨진 워크스페이스 바운딩 및 아바타 경계: 두 기능 그룹은 3.6을 위해 재구성되는 동안 JSON 스키마에서 빠져 있습니다. 매개변수 참조 항목 아래의 위 참고 사항을 확인하십시오.
- 비균일 스케일 + 회전:
rotation_enabled와scale_enabled가 모두 켜져 있으면 속도 방향이 약간 부정확해집니다. 회전은 스케일 축에 적용되지 않습니다. - 기기별 크기 스케일링: 버블 크기(반지름, 영역 폭)는 기기의 물리적 스케일 계수로 조정되지 않습니다. MInverse와 Inverse3는 동일한 절대 크기를 사용하므로, 기기마다 다르게 느껴질 수 있습니다.