Compare commits
	
		
			3 Commits
		
	
	
		
			41ce4980d8
			...
			developmen
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 092897c88d | |||
| dbdc045229 | |||
| d1c8949b16 | 
							
								
								
									
										40
									
								
								CHANGELOG.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								CHANGELOG.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| # Changelog | ||||
| All notable changes to this project will be documented in this file. | ||||
|  | ||||
| The format is based on **Keep a Changelog** and this project adheres to **Semantic Versioning**. | ||||
|  | ||||
| ## [Unreleased] | ||||
| ### Added | ||||
| - OBJ/GLB exporters with Draco compression (planned) | ||||
| - Furniture placement UX (snapping gizmos, align to wall) (planned) | ||||
| - Semantic plane helpers (wall/floor/ceiling) (planned) | ||||
| - RoomPlan native bridge behind `ROOMPLAN_ENABLED` (planned) | ||||
| - Lightship object detection behind `LIGHTSHIP_ENABLED` (planned) | ||||
|  | ||||
| ### Changed | ||||
| - TBD | ||||
|  | ||||
| ### Fixed | ||||
| - TBD | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## [0.1.0] - 2025-08-21 | ||||
| ### Added | ||||
| - iOS‑first project scaffolding (Unity 6.0 LTS, URP) with AR Foundation 6.x & ARKit XR Plugin 6.x. | ||||
| - Modular folder layout under `Assets/_Project/` and `.asmdef` per module. | ||||
| - `ScanScene` baseline: AR Session, XR Origin, AR managers (Plane/Raycast/Mesh). | ||||
| - `RoomScanner` to combine AR mesh chunks into a single mesh + collider. | ||||
| - `MeasureTool` for A→B distance in real meters. | ||||
| - API layer: `IFurnitureApi` + `HttpFurnitureApi` + `ApiConfig` ScriptableObject. | ||||
| - README with iOS build steps, contribution guidelines draft. | ||||
| - Git config: `.gitignore`, LFS patterns recommended, SmartMerge guidance. | ||||
|  | ||||
| ### Changed | ||||
| - N/A | ||||
|  | ||||
| ### Fixed | ||||
| - N/A | ||||
|  | ||||
| [Unreleased]: https://example.com/compare/v0.1.0...HEAD | ||||
| [0.1.0]: https://example.com/releases/tag/v0.1.0 | ||||
							
								
								
									
										128
									
								
								CONTRIBUTING.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								CONTRIBUTING.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,128 @@ | ||||
| # Contributing Guide | ||||
|  | ||||
| Thanks for helping build **AR Room Scanner & Furnishing (iOS‑first, Unity 6.0 LTS)**. This doc explains how to set up your environment, propose changes, and keep the project healthy and fast. | ||||
|  | ||||
| ## Table of Contents | ||||
| - [Project Setup](#project-setup) | ||||
| - [Branching Model](#branching-model) | ||||
| - [Commit Messages](#commit-messages) | ||||
| - [Pull Request Checklist](#pull-request-checklist) | ||||
| - [Coding Standards (C#)](#coding-standards-c) | ||||
| - [Unity Guidelines](#unity-guidelines) | ||||
| - [Scenes & Prefabs Rules](#scenes--prefabs-rules) | ||||
| - [Feature Flags](#feature-flags) | ||||
| - [API Config & Secrets](#api-config--secrets) | ||||
| - [Testing](#testing) | ||||
| - [Performance Budget](#performance-budget) | ||||
| - [Git LFS & Large Files](#git-lfs--large-files) | ||||
| - [Releases](#releases) | ||||
| - [Code Review](#code-review) | ||||
| - [Smart Merge](#smart-merge) | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## Project Setup | ||||
| - **Unity**: 6.0 LTS (URP template). | ||||
| - **Platform**: iOS (Metal only). Switch platform before importing heavy assets. | ||||
| - **Packages**: AR Foundation 6.x, ARKit XR Plugin 6.x, (optional) XR Interaction Toolkit 3.x. | ||||
| - **Folder layout** is under `Assets/_Project/...` with `.asmdef` per root module. | ||||
| - Keep `Settings/` (URP and project assets) and `Packages/` committed. | ||||
| - Enable **Visible Meta Files** and **Force Text Serialization**. | ||||
|  | ||||
| ## Branching Model | ||||
| - `main`: protected; always releasable. | ||||
| - Use short‑lived branches: `feature/<topic>`, `fix/<topic>`, `chore/<topic>`. | ||||
| - Rebase or squash merge to keep history clean. | ||||
| - Tag releases with SemVer (e.g., `v0.1.0`). | ||||
|  | ||||
| ## Commit Messages | ||||
| We use **Conventional Commits**: | ||||
| ``` | ||||
| feat: add room mesh exporter (OBJ) | ||||
| fix: avoid collider spike when updating sharedMesh | ||||
| docs: update iOS build steps | ||||
| refactor: split placement into service + controller | ||||
| perf: decimate combined mesh when >3M tris | ||||
| test: add domain unit tests | ||||
| build: bump ARKit XR Plugin to 6.2.x | ||||
| ci: cache Library on CI | ||||
| revert: revert placement snapping change | ||||
| ``` | ||||
| Scope is optional (e.g., `feat(placement): ...`). | ||||
|  | ||||
| ## Pull Request Checklist | ||||
| - [ ] Builds in Unity Editor and exports to **Xcode**. | ||||
| - [ ] Tested on **real iOS device** (LiDAR when feature needs it). | ||||
| - [ ] Scene follows **hierarchy rules** (see below). | ||||
| - [ ] **No per‑frame allocations** in hot paths; profiled once on device. | ||||
| - [ ] `.asmdef` references minimal and correct; no upward dependencies. | ||||
| - [ ] Updated **README/CHANGELOG** if user‑facing behavior changed. | ||||
| - [ ] Added/updated **tests** (Domain: unit; ARRuntime/App: playmode/manual checklist). | ||||
| - [ ] **No secrets** or hardcoded URLs; use `ApiConfig` ScriptableObject. | ||||
| - [ ] Large binaries are tracked by **LFS**; unnecessary assets removed. | ||||
|  | ||||
| ## Coding Standards (C#) | ||||
| - Namespaces by module: `App.*`, `ARRuntime.*`, `Domain.*`, `Infra.*`. | ||||
| - Prefer `readonly` fields, `record` for immutable DTOs, `TryGetComponent` over `FindObjectOfType`. | ||||
| - Avoid `new` allocations in `Update`; reuse buffers/lists (`.Clear()`). | ||||
| - Use `async/await` for API; timeouts & cancellation tokens where sensible. | ||||
| - No logic in `MonoBehaviour` constructors; use `Awake/OnEnable/Start`. | ||||
| - Guard nulls; avoid exceptions for control flow. | ||||
|  | ||||
| ## Unity Guidelines | ||||
| - One **Main Camera** under **XR Origin**. | ||||
| - `ARMeshManager` **must be a child of XR Origin**. | ||||
| - Keep **AR managers** grouped under a child GO (e.g., `AR Managers`). | ||||
| - Update **MeshCollider.sharedMesh** only when the combined mesh changes. | ||||
| - Place assets under `Assets/_Project/Art/...`; avoid dumping in root. | ||||
| - Use **prefabs** for placeable furniture; include colliders at authoring time. | ||||
|  | ||||
| ## Scenes & Prefabs Rules | ||||
| - Scene names live in `Assets/_Project/App/Scenes/`. | ||||
| - Do not reference Sample assets. Delete `SampleScene` once the project boots. | ||||
| - Minimal global singletons. Prefer scene‑local controllers in `App/Controllers`. | ||||
| - Prefabs: no missing scripts; default layer unless a dedicated layer is needed. | ||||
|  | ||||
| ## Feature Flags | ||||
| - Compile‑time defines: | ||||
|   - `LIGHTSHIP_ENABLED` → compiles `Detectors.Lightship/` only when set. | ||||
|   - `ROOMPLAN_ENABLED` → future native bridge for RoomPlan. | ||||
| - Runtime toggles: ScriptableObject `ProjectFeatures` (in `Infra/Settings/`). | ||||
|  | ||||
| ## API Config & Secrets | ||||
| - `Infra/Settings/ApiConfig` contains the base URL and timeouts per env. | ||||
| - **Do not commit secrets** or production keys. | ||||
| - For iOS, additional entitlements (e.g., iCloud) should be added in Xcode per‑target, not committed if secret‑bearing. | ||||
|  | ||||
| ## Testing | ||||
| - **Domain**: unit tests (EditMode). | ||||
| - **ARRuntime/App**: PlayMode tests + manual device checklist. | ||||
| - Provide a short test plan for PRs affecting scanning/placement. | ||||
|  | ||||
| ## Performance Budget | ||||
| - IL2CPP, ARM64, **Metal only**. | ||||
| - URP: SRP Batcher ON, MSAA 2x, mobile shadows. | ||||
| - Mesh combine every **1–2 s**; consider decimation > 3M tris. | ||||
| - Avoid large textures where not needed; prefer 2K for preview. | ||||
|  | ||||
| ## Git LFS & Large Files | ||||
| - Track large assets: `*.glb, *.gltf, *.obj, *.fbx, *.psd, *.exr, *.hdr, *.tga, *.tif`. | ||||
| - Keep big room exports outside `Assets/` in a top‑level `Scans/` folder (LFS‑tracked) to reduce Unity import cost. | ||||
| - Use **LFS locking** for shared binary assets when editing (`git lfs lock` / `unlock`). | ||||
|  | ||||
| ## Releases | ||||
| - Bump version using **SemVer** and update **CHANGELOG.md** (Keep a Changelog format). | ||||
| - Tag the commit (`vX.Y.Z`) and create a GitHub Release with notes and device compatibility. | ||||
| - Attach build artifacts as needed; Xcode projects are generated from Unity. | ||||
|  | ||||
| ## Code Review | ||||
| - At least **1 approval** (or 2 for risky changes). | ||||
| - Reviewers check: compile/run on device, profiler snapshot, GC allocs, scene hierarchy, asmdef deps, docs updated. | ||||
|  | ||||
| ## Smart Merge | ||||
| Enable Unity SmartMerge globally: | ||||
| ``` | ||||
| git config --global merge.unityyamlmerge.name "Unity SmartMerge (YAML)" | ||||
| git config --global merge.unityyamlmerge.driver "<UnityPath>/Tools/UnityYAMLMerge merge -p %O %A %B %P" | ||||
| ``` | ||||
| Ensure **Visible Meta Files** and **Force Text** are set in Unity. | ||||
							
								
								
									
										374
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										374
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,374 @@ | ||||
| # AR Room Scanner & Furnishing — **iOS-first (Unity 6.0 LTS)** | ||||
|  | ||||
| Clean, modular Unity **6.0 LTS** project focused on **iOS (ARKit)** for: | ||||
| 1) **Scanning** a real room on-device (LiDAR Scene Reconstruction when available)   | ||||
| 2) **Measuring** in real-world meters   | ||||
| 3) **Placing furniture** with collisions and snapping   | ||||
| 4) Optional **Object Detection** (kept behind a compile flag)   | ||||
| 5) Optional **RoomPlan** integration path (native bridge) for semantic room models | ||||
|  | ||||
| This repo is designed to be stable today and easy to evolve (upgrade to 6.1/6.2 later). | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## Table of Contents | ||||
| - [Why iOS](#why-ios) | ||||
| - [Folder Layout](#folder-layout) | ||||
| - [Assembly Definitions & Dependencies](#assembly-definitions--dependencies) | ||||
| - [Packages & Versions](#packages--versions) | ||||
| - [Device Support Matrix](#device-support-matrix) | ||||
| - [Getting Started](#getting-started) | ||||
| - [iOS Build & Xcode Setup](#ios-build--xcode-setup) | ||||
| - [Scenes & Flow](#scenes--flow) | ||||
| - [Core Modules](#core-modules) | ||||
| - [API Integration](#api-integration) | ||||
| - [Configuration & Environments](#configuration--environments) | ||||
| - [Version Control (Git, LFS, SmartMerge)](#version-control-git-lfs-smartmerge) | ||||
| - [Performance Guidelines (iOS/Metal)](#performance-guidelines-iosmetal) | ||||
| - [RoomPlan (future path)](#roomplan-future-path) | ||||
| - [Troubleshooting](#troubleshooting) | ||||
| - [Roadmap](#roadmap) | ||||
| - [License](#license) | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## Why iOS | ||||
| - **Best on-device scanning** via **ARKit Scene Reconstruction** on **LiDAR** devices (dense mesh, stable scale).   | ||||
| - **Consistent tracking & depth** across supported iPhones/iPads.   | ||||
| - Future option: **RoomPlan** (iOS 16+, LiDAR) to produce **semantic, parametric** rooms (walls/doors/windows) with accurate dimensions. | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## Folder Layout | ||||
|  | ||||
| ``` | ||||
| Assets/ | ||||
|   _Project/ | ||||
|     App/                        # app flow & UI | ||||
|       Controllers/ | ||||
|       Scenes/ | ||||
|         Bootstrap.unity | ||||
|         ScanScene.unity | ||||
|         FurnishScene.unity | ||||
|       UI/ | ||||
|     ARRuntime/                  # AR runtime features (platform-agnostic via AR Foundation) | ||||
|       Scanning/                 # mesh collection, colliders, export hooks | ||||
|       Measurement/              # AB ruler, heights, helpers | ||||
|       Placement/                # raycasts, snapping, overlap checks, physics | ||||
|     Art/                        # in-Unity assets | ||||
|       Logos/ | ||||
|       Materials/ | ||||
|       Models/ | ||||
|       Prefabs/ | ||||
|       Shaders/ | ||||
|       Textures/ | ||||
|     Domain/                     # pure business/domain (no Unity deps) | ||||
|       Models/ | ||||
|       Services/ | ||||
|     Infra/                      # outside world (API, storage, settings) | ||||
|       Api/                      # IFurnitureApi + HttpFurnitureApi + DTOs | ||||
|       Persistence/              # OBJ/GLB export, JSON metadata | ||||
|       Settings/                 # ScriptableObjects (ApiConfig, ProjectFeatures) | ||||
|       Detectors/ | ||||
|         Null/                   # default no-op detector | ||||
|         Lightship/              # stub; compiled only with LIGHTSHIP_ENABLED | ||||
|     Tests/                      # EditMode/PlayMode tests | ||||
|   Settings/                     # URP & project assets (keep!) | ||||
|   XR/                           # added by packages | ||||
| ``` | ||||
|  | ||||
| **Keep `Settings/`** (URP pipeline assets & editor links).   | ||||
| A separate top-level `Scans/` folder (outside `Assets/`) is recommended for large exports to avoid re-import churn. | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## Assembly Definitions & Dependencies | ||||
|  | ||||
| Create one `.asmdef` per root module: | ||||
|  | ||||
| - `Domain` (no references)   | ||||
| - `Infra` → references `Domain`   | ||||
| - `ARRuntime` → references `Domain`   | ||||
| - `App` → references `ARRuntime`, `Infra`, `Domain`   | ||||
| - `Detectors.Lightship` → references `Infra`, `Domain` with **define constraint** `LIGHTSHIP_ENABLED`   | ||||
| - `Tests` → references as needed | ||||
|  | ||||
| **Dependency direction**   | ||||
| `App → (ARRuntime, Infra, Domain)`   | ||||
| `ARRuntime → Domain`   | ||||
| `Infra → Domain`   | ||||
| `Domain` depends on nothing | ||||
|  | ||||
| This keeps compile times low and prevents “upward” coupling. | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## Packages & Versions | ||||
| - **Unity**: 6.0 LTS (URP template) | ||||
| - **AR Foundation**: 6.x   | ||||
| - **ARKit XR Plugin**: 6.x   | ||||
| - (Optional) XR Interaction Toolkit 3.x   | ||||
| - TextMesh Pro (built-in) | ||||
|  | ||||
| > Pin package versions in `Packages/manifest.json` once the project compiles cleanly. | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## Device Support Matrix | ||||
|  | ||||
| | Capability | Requirement | Notes | | ||||
| |---|---|---| | ||||
| | ARKit basic tracking | iPhone 8+ / iOS 13+ (practical: iOS 15+) | Non-LiDAR devices won’t produce dense meshes. | | ||||
| | **Scene Reconstruction (meshing)** | **LiDAR** devices (e.g., iPhone 12 Pro+, 13 Pro+, 14 Pro/Pro Max, 15 Pro/Pro Max; iPad Pro 2020+) | AR Foundation exposes meshes via `ARMeshManager`. | | ||||
| | Environment Depth / People Occlusion | Device-dependent | Used for occlusion realism; works best on LiDAR. | | ||||
| | **RoomPlan** (future) | iOS 16+, **LiDAR** | Generates semantic room model via native SDK. | | ||||
|  | ||||
| We gracefully **fall back**: if no LiDAR mesh is available, we still support plane detection + measurements. | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## Getting Started | ||||
|  | ||||
| 1) **Switch to iOS**   | ||||
|    `File → Build Settings → iOS → Switch Platform`. | ||||
|  | ||||
| 2) **Install packages** (Window → Package Manager)   | ||||
|    - AR Foundation 6.x   | ||||
|    - ARKit XR Plugin 6.x   | ||||
|    - (Optional) XR Interaction Toolkit 3.x | ||||
|  | ||||
| 3) **Project Settings (iOS)**   | ||||
|    - **Player → iOS**   | ||||
|      - Scripting Backend: **IL2CPP**   | ||||
|      - Target Architectures: **ARM64**   | ||||
|      - Graphics APIs: **Metal** (only)   | ||||
|      - Minimum iOS Version: **15+** recommended (RoomPlan needs 16+)   | ||||
|      - Camera Usage Description (Info.plist): e.g., _“AR scanning requires camera access.”_   | ||||
|      - Photo Library Add Usage Description (if you export files to Photos)   | ||||
|      - Motion Usage Description (only if you use CoreMotion; otherwise omit) | ||||
|    - **XR Plug-in Management → iOS**   | ||||
|      - Enable **ARKit**   | ||||
|      - In ARKit settings, enable **Environment Depth** (and People Occlusion if needed) | ||||
|    - **URP**   | ||||
|      - SRP Batcher: **ON**   | ||||
|      - MSAA: **2x**   | ||||
|      - Mobile-friendly shadows | ||||
|  | ||||
| 4) **Scenes**   | ||||
|    - Create `Bootstrap.unity`, `ScanScene.unity`, `FurnishScene.unity` under `Assets/_Project/App/Scenes/`. | ||||
|  | ||||
| 5) **First run**   | ||||
|    - Add `Bootstrap` and `ScanScene` to Build Settings (Bootstrap first).   | ||||
|    - Build to Xcode, set signing, run on device. | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## iOS Build & Xcode Setup | ||||
|  | ||||
| 1) **Build in Unity** → generates an Xcode project.   | ||||
| 2) **Xcode**   | ||||
|    - Select your **Team** & Provisioning profile   | ||||
|    - Ensure **Camera** privacy string is present (Unity will add based on Player Settings)   | ||||
|    - In “Signing & Capabilities”, you typically **don’t** need extra entitlements for ARKit beyond camera; add **Files (iCloud)** only if you export to Files app.   | ||||
| 3) **Run on device** (USB).   | ||||
| 4) If you see a black camera feed: check Privacy strings, ensure real device (not Simulator), and that `Requires ARKit` is set (Unity: Player → iOS → “Requires ARKit”). | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## Scenes & Flow | ||||
|  | ||||
| ### Scene Descriptions (TL;DR) | ||||
|  | ||||
| - **Bootstrap.unity** — Minimal entry scene. Initializes global settings (URP assets, `ProjectFeatures`, `ApiConfig`), handles one-time bootstrapping, and programmatically loads `ScanScene`. No AR logic or heavy UI here. | ||||
| - **ScanScene.unity** — Scanning & measuring. Contains AR Session, XR Origin, AR Plane/Raycast/Mesh Managers, and the camera with AR Camera Manager + AR Occlusion. Merges AR mesh chunks into a single mesh (RoomScanner), enables A→B measurements in meters (MeasureTool), and can optionally export the room mesh. | ||||
| - **FurnishScene.unity** — Furniture placement. Fetches items from the backend via `IFurnitureApi`, performs raycasts to floor/walls with snapping, runs overlap/collision checks before placement, uses occlusion for realism, and hosts the move/rotate/align UX. | ||||
|  | ||||
|  | ||||
| ### `Bootstrap.unity` | ||||
| Minimal loader that switches to the first “real” scene: | ||||
|  | ||||
| ```csharp | ||||
| using UnityEngine; | ||||
| using UnityEngine.SceneManagement; | ||||
|  | ||||
| public class Bootstrap : MonoBehaviour | ||||
| { | ||||
|     [SerializeField] string firstScene = "ScanScene"; | ||||
|     void Start() => SceneManager.LoadScene(firstScene, LoadSceneMode.Single); | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ### `ScanScene.unity` (first milestone) | ||||
| **Hierarchy (suggested)** | ||||
|  | ||||
| ``` | ||||
| AR Session | ||||
| XR Origin | ||||
|   └─ Camera Offset | ||||
|      └─ Main Camera (tag: MainCamera) | ||||
| AR Managers (child of XR Origin) | ||||
|   ├─ AR Plane Manager | ||||
|   ├─ AR Raycast Manager | ||||
|   └─ AR Mesh Manager          # must be under XR Origin in ARF 6 | ||||
| RoomMesh (MeshFilter + MeshRenderer + MeshCollider) | ||||
| RoomScanner (script)          # combines AR chunks into RoomMesh | ||||
| MeasureLine (LineRenderer) | ||||
| MeasureTool (script)          # tap A→B distances in meters | ||||
| ``` | ||||
|  | ||||
| On the **Main Camera** (child of XR Origin): add **AR Camera Manager** and **AR Occlusion Manager**. | ||||
|  | ||||
| ### `FurnishScene.unity` (next milestone) | ||||
| - Placement raycasts and snapping to **floor/walls**   | ||||
| - Overlap checks / colliders to prevent interpenetration   | ||||
| - Occlusion enabled for realism | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## Core Modules | ||||
|  | ||||
| ### `ARRuntime/Scanning` — RoomScanner | ||||
| - Polls `ARMeshManager.meshes` and **combines** all chunks into a single mesh every N seconds.   | ||||
| - Assigns that mesh to `RoomMesh`’s `MeshFilter` and `MeshCollider`.   | ||||
| - The combined mesh is in **meters** (Unity units = meters), so measuring is straightforward. | ||||
|  | ||||
| ### `ARRuntime/Measurement` — MeasureTool | ||||
| - Touch once = point A, touch again = point B.   | ||||
| - Draws a line (`LineRenderer`) and shows **meters** to 2 decimals.   | ||||
| - Uses `Physics.Raycast` against the combined collider or against detected planes. | ||||
|  | ||||
| ### `ARRuntime/Placement` | ||||
| - Raycast from screen to floor/wall planes or to the combined mesh.   | ||||
| - Snap by projecting onto a plane’s normal.   | ||||
| - Prevent collisions with `Physics.OverlapBox/Sphere` before placing. | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## API Integration | ||||
|  | ||||
| Interface-first, so the app logic doesn’t depend on a concrete client: | ||||
|  | ||||
| ```csharp | ||||
| // Infra/Api/IFurnitureApi.cs | ||||
| public interface IFurnitureApi | ||||
| { | ||||
|     Task<IReadOnlyList<Furniture>> GetVariantsAsync(IEnumerable<string> ids); | ||||
|     Task<IReadOnlyList<Furniture>> SearchAsync(string query, int page = 1, int pageSize = 20); | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ```csharp | ||||
| // Infra/Api/HttpFurnitureApi.cs | ||||
| public sealed class HttpFurnitureApi : IFurnitureApi | ||||
| { | ||||
|     private readonly HttpClient _http; | ||||
|     private readonly ApiConfig _cfg; | ||||
|  | ||||
|     public HttpFurnitureApi(HttpClient http, ApiConfig cfg) { _http = http; _cfg = cfg; } | ||||
|  | ||||
|     public async Task<IReadOnlyList<Furniture>> GetVariantsAsync(IEnumerable<string> ids) | ||||
|     { | ||||
|         var url = $"{_cfg.BaseUrl}/api/v1/FurnitureVariant/GetByIds"; | ||||
|         using var resp = await _http.PostAsJsonAsync(url, ids); | ||||
|         resp.EnsureSuccessStatusCode(); | ||||
|         return await resp.Content.ReadFromJsonAsync<List<Furniture>>() ?? new(); | ||||
|     } | ||||
|  | ||||
|     public async Task<IReadOnlyList<Furniture>> SearchAsync(string query, int page = 1, int pageSize = 20) | ||||
|     { | ||||
|         var url = $"{_cfg.BaseUrl}/api/v1/FurnitureVariant/Search?query={Uri.EscapeDataString(query)}&page={page}&pageSize={pageSize}"; | ||||
|         return await _http.GetFromJsonAsync<List<Furniture>>(url) ?? new(); | ||||
|     } | ||||
| } | ||||
| ``` | ||||
|  | ||||
| **Config**: `Infra/Settings/ApiConfig` (ScriptableObject) with `BaseUrl`, timeouts, and environment selectors (DEV/QA/PROD). | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## Configuration & Environments | ||||
|  | ||||
| Create a `ProjectFeatures` ScriptableObject (in `Infra/Settings/`) with toggles: | ||||
| - `useMeshing` (on by default) | ||||
| - `useOcclusion` (environment/people) | ||||
| - `useObjectDetection` (off; Lightship behind `LIGHTSHIP_ENABLED`) | ||||
| - `enableExports` (to write OBJ/GLB to app storage) | ||||
|  | ||||
| This lets QA test different combinations without code changes. | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## Version Control (Git, LFS, SmartMerge) | ||||
|  | ||||
| - Keep **text/YAML** in Git (scenes, prefabs, materials, `.meta`, `ProjectSettings/`, `Packages/`).   | ||||
| - Track **large binaries** (GLB/OBJ/FBX/PSDs/EXR/8K textures) with **Git LFS**.   | ||||
| - Enable **Unity Smart Merge** for clean scene/prefab merges. | ||||
|  | ||||
| (We also recommend a top-level `Scans/` folder, LFS-tracked, for big room exports.) | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## Performance Guidelines (iOS/Metal) | ||||
|  | ||||
| - **Metal only**, IL2CPP, ARM64.   | ||||
| - URP: **SRP Batcher ON**, **MSAA 2×**, mobile shadows.   | ||||
| - Avoid per-frame allocations; reuse buffers.   | ||||
| - Combine mesh at **intervals** (1–2 s) rather than every frame.   | ||||
| - Update `MeshCollider.sharedMesh` **only when merged mesh changes** to avoid spikes.   | ||||
| - Consider decimation for very large meshes if triangle count exceeds target thresholds. | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## RoomPlan (future path) | ||||
|  | ||||
| If you need clean, semantic floorplans and furniture categories: | ||||
| - Implement a **native iOS plugin** (Swift/Obj-C) that runs RoomPlan (iOS 16+, LiDAR).   | ||||
| - Export **USDZ/USDA/OBJ/GLTF** or RoomPlan **JSON**; import into Unity via `Infra/Persistence`.   | ||||
| - Provide an adapter `IRoomImporter` so `App` can switch between **Scene Reconstruction mesh** and **RoomPlan semantic model** at runtime/build time. | ||||
|  | ||||
| Keep all RoomPlan code behind a **`ROOMPLAN_ENABLED`** define if you prefer the same pattern as Lightship. | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## Troubleshooting | ||||
|  | ||||
| - **Popup: “An ARMeshManager must be a child of an XROrigin.”**   | ||||
|   Move `ARMeshManager` under **XR Origin** (not on the same GO). | ||||
|  | ||||
| - **Black camera feed**   | ||||
|   Real device only (no Simulator), **Camera** usage string present, `Requires ARKit` ticked, provisioning OK. | ||||
|  | ||||
| - **No mesh appears**   | ||||
|   Device may not have LiDAR; fall back to planes & depth. Ensure ARKit Scene Reconstruction is supported on the test device. | ||||
|  | ||||
| - **Raycast doesn’t hit**   | ||||
|   Ensure `RoomMesh` has a **MeshCollider** and that you merged at least once. Check layers. | ||||
|  | ||||
| - **Build fails in Xcode**   | ||||
|   Clear Derived Data, check signing, ensure Metal is the only graphics API. | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## Roadmap | ||||
|  | ||||
| - ✅ iOS-first scanning (Scene Reconstruction), measuring, placement skeleton   | ||||
| - ⏳ Exporters (OBJ/GLB + Draco), thumbnails, metadata (`units`, `bbox`, triangle count)   | ||||
| - ⏳ Furniture placement UX (snapping gizmos, grid, rotation/align to wall)   | ||||
| - ⏳ Semantic planes (wall/floor/ceiling) classification helpers   | ||||
| - ⏳ RoomPlan native bridge (optional feature flag)   | ||||
| - ⏳ Lightship detection re-enable (compile flag)   | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## License | ||||
| TBD — choose a license that suits your distribution model (MIT/Apache-2.0/Proprietary). | ||||
|  | ||||
| --- | ||||
|  | ||||
| ### Quick Start (TL;DR) | ||||
| 1. Open in Unity **6.0 LTS**, switch to **iOS**.   | ||||
| 2. Install **AR Foundation 6.x** + **ARKit XR Plugin 6.x**.   | ||||
| 3. Player: **IL2CPP / ARM64 / Metal**, iOS 15+, Camera privacy string.   | ||||
| 4. XR Plug-in Management: **ARKit ON**, enable Environment Depth.   | ||||
| 5. Open **ScanScene** → Run on a **LiDAR** device → tap two points to measure in meters.   | ||||
| 6. Move to **FurnishScene** for placement once scanning feels good. | ||||
		Reference in New Issue
	
	Block a user