내비게이션
내비게이션 모듈을 사용하면 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 │
└──────────────────────────────────────────┘
| 영역 | 커서 위치 | 동작 |
|---|---|---|
| 데드 존 | 거품 내부 | 내비게이션이 없습니다. 약간의 댐핑이 적용됩니다. 장면을 자유롭게 조작할 수 있습니다. |
| 속도 범위 | 표면과 외곽 경계 사이 | 거리 → 속도 곡선에 따라 커서가 가리키는 방향으로 작업 공간이 이동합니다. |
| 벽 영역 | 외곽 경계 너머 | 강한 스프링이 커서를 안쪽으로 밀어내며, 탐색 속도가 최고치에 도달합니다. |
세 영역 전체에 스프링-댐퍼 햅틱 힘이적용되어, 표면, 드리프트 쉘, 외곽 벽을 느낄 수 있습니다.
빠른 시작 — 버블 내비게이션 활성화
내비게이션은 지속형 일회성 설정입니다. 한 번 전송되면 명시적으로 중지하거나, 서비스를 다시 시작하거나, 세션을 닫을 때까지 활성 상태를 유지합니다.
시작 (최소 구성 — 기본 둥근 사각형 버블)
- 웹소켓
- 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"}'
중지
- 웹소켓
- 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 분/초 | 최대 내비게이션 속도 |
velocity_ease | "quadratic_in" | 거리 → 속도 이징 곡선 |
center.follow | false | 중심이 커서를 추적하는지 여부 |
center.speed | 0.02 분/초 | 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 | 모양 | {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 | 문자열 | "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는 동일한 절대 크기를 사용하므로, 기기에 따라 다르게 느껴질 수 있습니다.