- The MENU toggle now works at any viewport width, not just small screens — desktop/tablet default to the panel open, phones default to closed, and crossing the 768px breakpoint resets to that side's default. The canvas already spans the full window behind the panel, so hiding it needs no resize. The empty-state "open a file" prompt re-centers when the panel is hidden. - Android's WebView renders the page in a separate process with its own memory ceiling, independent of the app's Java heap (android:largeHeap wouldn't help). A 1.35GB .pcd blew through it and crashed the renderer, taking the whole app down with no catchable JS exception — confirmed via a device tombstone: "Render process crash wasn't handled by all associated webviews, triggering application crash." openFile() now blocks anything over 300MB on Android (empirical: 233MB survived, 1.35GB didn't) with a clear in-app message instead of a silent kill. Desktop is unaffected — it has far more headroom. - Two-finger touch now free-rotates (any drag direction, not locked to one axis) while pinch still zooms (OrbitControls' DOLLY_ROTATE instead of the default DOLLY_PAN). Trades away two-finger panning, which double-click to recenter mostly substitutes for. Verified on a physical Galaxy Z Fold.
PCD Viewer — 네이티브 빌드 (macOS / Android)
FAST-LIVO2용 포인트 클라우드 뷰어(pcd_viewer.html, Three.js)를 Tauri 2로 감싼 macOS 앱.
빌드 없는 단일 HTML이 웹의 단일 소스이고, src-tauri/가 그걸 그대로 실어 네이티브 창으로 띄운다.
준비물
- Rust 툴체인 (
rustup권장,src-tauri/Cargo.toml의rust-version확인) - Xcode Command Line Tools (
xcode-select --install) cargo tauri(tauri-cli)는 필요 없음 — 아래는 rawcargo build만으로 진행하는 절차
빌드
git clone <this-repo> && cd duru_pcd_viewer
sh src-tauri/stage-web.sh # pcd_viewer.html + vendor/ 를 src-tauri/web/ 로 스테이징
cd src-tauri
cargo build --release # target/release/pcd-viewer (원시 실행 파일)
.app 번들(target/release/bundle/macos/PCD Viewer.app)이 이미 존재한다면(첫 빌드가 아니라면),
cargo build --release만으로는 그 안의 바이너리가 갱신되지 않는다 — cargo tauri build(번들러)가
만드는 별개 산출물이기 때문. 재빌드할 때마다 아래로 동기화한다.
cp target/release/pcd-viewer \
"target/release/bundle/macos/PCD Viewer.app/Contents/MacOS/pcd-viewer"
tauri-cli(cargo install tauri-cli --version "^2")가 있다면 cargo tauri build로
번들·서명까지 한 번에 처리할 수 있다(위 수동 동기화 불필요).
실행
open "target/release/bundle/macos/PCD Viewer.app"
.pcd 파일은 앱에 번들되어 있지 않다 — 창에 드래그해서 불러오는 구조가 의도된 설계다
(DEFAULT_URL이 404 나는 게 정상이며, 그때 드래그 안내로 자연스럽게 떨어진다).
코드를 고쳤다면
web/은 빌드 시점에 바이너리로 임베드되므로, pcd_viewer.html만 고쳐서는 네이티브 앱에 반영되지
않는다. 위 빌드 절차(stage-web.sh → cargo build --release → 바이너리 동기화)를 다시 밟아야 한다.
Android 빌드
같은 pcd_viewer.html을 Android WebView로 감싼다(React Native/Expo 대신 — WebView도 진짜
하드웨어 가속 WebGL을 쓰므로 렌더링 경로 자체는 동일하고, 코드베이스를 두 벌로 안 나눠도 된다).
src-tauri/gen/android/는 cargo tauri android init이 생성한 Android Studio 프로젝트다.
준비물
- Rust는 rustup으로 설치되어 있어야 함 — Homebrew의
rust패키지(고정 타깃 하나만 빌드)로는aarch64-linux-android같은 크로스 타깃을 추가할 수 없다.brew install rustup(또는 공식 설치 스크립트) 후:rustup target add aarch64-linux-android armv7-linux-androideabi \ i686-linux-android x86_64-linux-android - Android SDK + NDK (
sdkmanager로 platform-tools, platform, NDK 설치, 라이선스 동의까지) - JDK 17+ (Temurin 21 확인됨)
cargo install tauri-cli --version "^2" --locked
macOS에 Homebrew rust와 rustup이 공존하면 cargo/rustc가 PATH상 Homebrew 쪽으로 잡힐 수 있다
(데스크톱 빌드는 그대로 Homebrew rust를 쓰도록 건드리지 않았다) — Android 명령은 rustup 툴체인의
cargo를 명시적으로 가리켜서 실행한다:
export JAVA_HOME=/Library/Java/JavaVirtualMachines/temurin-21.jdk/Contents/Home
export ANDROID_HOME=~/Library/Android/sdk
export NDK_HOME=~/Library/Android/sdk/ndk/<설치된 버전>
export PATH="$HOME/.rustup/toolchains/stable-aarch64-apple-darwin/bin:$HOME/.cargo/bin:$PATH"
빌드
cd src-tauri
sh stage-web.sh
cargo tauri android build --debug --target aarch64 # 갤럭시 대부분은 arm64-v8a
산출물:
- APK:
gen/android/app/build/outputs/apk/universal/debug/app-universal-debug.apk - AAB:
gen/android/app/build/outputs/bundle/universalDebug/app-universal-debug.aab
기기에 설치
adb install "gen/android/app/build/outputs/apk/universal/debug/app-universal-debug.apk"
(갤럭시에서 설정 → 휴대전화 정보 → 빌드 번호 7번 탭으로 개발자 옵션 열고, USB 디버깅 켠 뒤
USB로 연결 — adb devices에 기기가 떠야 설치된다.) USB 없이는 APK 파일을 기기로 옮겨 직접
설치(출처를 알 수 없는 앱 허용 필요)해도 된다.
알아둘 점
usesCleartextTraffic이 디버그 빌드에선 자동으로 켜지지만 release 빌드에선 꺼진다 — rosbridge 주소가ws://(평문)라면 release APK에서 연결이 막힌다.wss://로 옮기거나gen/android/app/src/main/AndroidManifest.xml에서 명시적으로 허용해야 한다.- 아이콘은 기본 Tauri 플레이스홀더다.
cargo tauri icon <source.png>로 교체 가능. gen/android/는 커밋되어 있지만build/·.gradle/·생성된 Kotlin 소스·jniLibs/*.so는 중첩.gitignore로 제외된다 — 클론 후 첫 빌드에서 다시 만들어진다.
그 밖의 문서
PCD_Viewer_가이드.md— 사용법(측정/실시간 모니터링). 아직 vendoring·Tauri 반영 전 버전.ROS2_이관_체크리스트.md— ROS2 이관 체크리스트.