Compare commits
	
		
			5 Commits
		
	
	
		
			d569729c3c
			...
			developmen
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 092897c88d | |||
| dbdc045229 | |||
| d1c8949b16 | |||
| 41ce4980d8 | |||
| d64d200f8d | 
							
								
								
									
										37
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										37
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
								
							| @@ -1,3 +1,40 @@ | |||||||
|  | # Unity YAML (escenas, prefabs, materiales, anims, metas) -> usar SmartMerge | ||||||
|  | *.unity  merge=unityyamlmerge | ||||||
|  | *.prefab merge=unityyamlmerge | ||||||
|  | *.mat    merge=unityyamlmerge | ||||||
|  | *.anim   merge=unityyamlmerge | ||||||
|  | *.controller merge=unityyamlmerge | ||||||
|  | *.meta   merge=unityyamlmerge | ||||||
|  | # Forzar tratamiento de texto y EOL | ||||||
|  | * text=auto eol=lf | ||||||
| *.jpg filter=lfs diff=lfs merge=lfs -text | *.jpg filter=lfs diff=lfs merge=lfs -text | ||||||
| *.fbx filter=lfs diff=lfs merge=lfs -text | *.fbx filter=lfs diff=lfs merge=lfs -text | ||||||
| *.png filter=lfs diff=lfs merge=lfs -text | *.png filter=lfs diff=lfs merge=lfs -text | ||||||
|  | *.blend filter=lfs diff=lfs merge=lfs -text | ||||||
|  | *.obj filter=lfs diff=lfs merge=lfs -text | ||||||
|  | *.gltf filter=lfs diff=lfs merge=lfs -text | ||||||
|  | *.glb filter=lfs diff=lfs merge=lfs -text | ||||||
|  | *.jpeg filter=lfs diff=lfs merge=lfs -text | ||||||
|  | *.tga filter=lfs diff=lfs merge=lfs -text | ||||||
|  | *.tif filter=lfs diff=lfs merge=lfs -text | ||||||
|  | *.tiff filter=lfs diff=lfs merge=lfs -text | ||||||
|  | *.psd filter=lfs diff=lfs merge=lfs -text | ||||||
|  | *.exr filter=lfs diff=lfs merge=lfs -text | ||||||
|  | *.hdr filter=lfs diff=lfs merge=lfs -text | ||||||
|  | *.mov filter=lfs diff=lfs merge=lfs -text | ||||||
|  | *.wav filter=lfs diff=lfs merge=lfs -text | ||||||
|  | *.mp3 filter=lfs diff=lfs merge=lfs -text | ||||||
|  | *.ogg filter=lfs diff=lfs merge=lfs -text | ||||||
|  | *.aac filter=lfs diff=lfs merge=lfs -text | ||||||
|  | *.mp4 filter=lfs diff=lfs merge=lfs -text | ||||||
|  | *.zip filter=lfs diff=lfs merge=lfs -text | ||||||
|  | *.dll filter=lfs diff=lfs merge=lfs -text | ||||||
|  | *.so filter=lfs diff=lfs merge=lfs -text | ||||||
|  | *.a filter=lfs diff=lfs merge=lfs -text | ||||||
|  | Scans/** filter=lfs diff=lfs merge=lfs -text | ||||||
|  | *.usdz filter=lfs diff=lfs merge=lfs -text | ||||||
|  | *.mtl filter=lfs diff=lfs merge=lfs -text | ||||||
|  | *.ply filter=lfs diff=lfs merge=lfs -text | ||||||
|  | *.usd filter=lfs diff=lfs merge=lfs -text | ||||||
|  | *.7z filter=lfs diff=lfs merge=lfs -text | ||||||
|  | *.rar filter=lfs diff=lfs merge=lfs -text | ||||||
|   | |||||||
| @@ -38,12 +38,12 @@ RenderSettings: | |||||||
|   m_ReflectionIntensity: 1 |   m_ReflectionIntensity: 1 | ||||||
|   m_CustomReflection: {fileID: 0} |   m_CustomReflection: {fileID: 0} | ||||||
|   m_Sun: {fileID: 0} |   m_Sun: {fileID: 0} | ||||||
|   m_IndirectSpecularColor: {r: 0.18028378, g: 0.22571412, b: 0.30692285, a: 1} |  | ||||||
|   m_UseRadianceAmbientProbe: 0 |   m_UseRadianceAmbientProbe: 0 | ||||||
| --- !u!157 &3 | --- !u!157 &3 | ||||||
| LightmapSettings: | LightmapSettings: | ||||||
|   m_ObjectHideFlags: 0 |   m_ObjectHideFlags: 0 | ||||||
|   serializedVersion: 12 |   serializedVersion: 13 | ||||||
|  |   m_BakeOnSceneLoad: 0 | ||||||
|   m_GISettings: |   m_GISettings: | ||||||
|     serializedVersion: 2 |     serializedVersion: 2 | ||||||
|     m_BounceScale: 1 |     m_BounceScale: 1 | ||||||
| @@ -133,7 +133,7 @@ GameObject: | |||||||
|   - component: {fileID: 330585547} |   - component: {fileID: 330585547} | ||||||
|   m_Layer: 0 |   m_Layer: 0 | ||||||
|   m_Name: Main Camera |   m_Name: Main Camera | ||||||
|   m_TagString: MainCamera |   m_TagString: Untagged | ||||||
|   m_Icon: {fileID: 0} |   m_Icon: {fileID: 0} | ||||||
|   m_NavMeshLayer: 0 |   m_NavMeshLayer: 0 | ||||||
|   m_StaticEditorFlags: 0 |   m_StaticEditorFlags: 0 | ||||||
| @@ -250,12 +250,12 @@ MonoBehaviour: | |||||||
|   m_RequiresColorTexture: 0 |   m_RequiresColorTexture: 0 | ||||||
|   m_Version: 2 |   m_Version: 2 | ||||||
|   m_TaaSettings: |   m_TaaSettings: | ||||||
|     quality: 3 |     m_Quality: 3 | ||||||
|     frameInfluence: 0.1 |     m_FrameInfluence: 0.1 | ||||||
|     jitterScale: 1 |     m_JitterScale: 1 | ||||||
|     mipBias: 0 |     m_MipBias: 0 | ||||||
|     varianceClampScale: 0.9 |     m_VarianceClampScale: 0.9 | ||||||
|     contrastAdaptiveSharpening: 0 |     m_ContrastAdaptiveSharpening: 0 | ||||||
| --- !u!1 &410087039 | --- !u!1 &410087039 | ||||||
| GameObject: | GameObject: | ||||||
|   m_ObjectHideFlags: 0 |   m_ObjectHideFlags: 0 | ||||||
| @@ -336,6 +336,9 @@ Light: | |||||||
|   m_ForceVisible: 0 |   m_ForceVisible: 0 | ||||||
|   m_ShadowRadius: 0 |   m_ShadowRadius: 0 | ||||||
|   m_ShadowAngle: 0 |   m_ShadowAngle: 0 | ||||||
|  |   m_LightUnit: 1 | ||||||
|  |   m_LuxAtDistance: 1 | ||||||
|  |   m_EnableSpotReflector: 1 | ||||||
| --- !u!4 &410087041 | --- !u!4 &410087041 | ||||||
| Transform: | Transform: | ||||||
|   m_ObjectHideFlags: 0 |   m_ObjectHideFlags: 0 | ||||||
|   | |||||||
| @@ -129,6 +129,7 @@ GameObject: | |||||||
|   m_Component: |   m_Component: | ||||||
|   - component: {fileID: 55455372} |   - component: {fileID: 55455372} | ||||||
|   - component: {fileID: 55455371} |   - component: {fileID: 55455371} | ||||||
|  |   - component: {fileID: 55455373} | ||||||
|   m_Layer: 0 |   m_Layer: 0 | ||||||
|   m_Name: Directional Light |   m_Name: Directional Light | ||||||
|   m_TagString: Untagged |   m_TagString: Untagged | ||||||
| @@ -216,7 +217,30 @@ Transform: | |||||||
|   m_Children: [] |   m_Children: [] | ||||||
|   m_Father: {fileID: 0} |   m_Father: {fileID: 0} | ||||||
|   m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} |   m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} | ||||||
| --- !u!1 &360989555 | --- !u!114 &55455373 | ||||||
|  | MonoBehaviour: | ||||||
|  |   m_ObjectHideFlags: 0 | ||||||
|  |   m_CorrespondingSourceObject: {fileID: 0} | ||||||
|  |   m_PrefabInstance: {fileID: 0} | ||||||
|  |   m_PrefabAsset: {fileID: 0} | ||||||
|  |   m_GameObject: {fileID: 55455370} | ||||||
|  |   m_Enabled: 1 | ||||||
|  |   m_EditorHideFlags: 0 | ||||||
|  |   m_Script: {fileID: 11500000, guid: 474bcb49853aa07438625e644c072ee6, type: 3} | ||||||
|  |   m_Name:  | ||||||
|  |   m_EditorClassIdentifier:  | ||||||
|  |   m_Version: 3 | ||||||
|  |   m_UsePipelineSettings: 1 | ||||||
|  |   m_AdditionalLightsShadowResolutionTier: 2 | ||||||
|  |   m_LightLayerMask: 1 | ||||||
|  |   m_RenderingLayers: 1 | ||||||
|  |   m_CustomShadowLayers: 0 | ||||||
|  |   m_ShadowLayerMask: 1 | ||||||
|  |   m_ShadowRenderingLayers: 1 | ||||||
|  |   m_LightCookieSize: {x: 1, y: 1} | ||||||
|  |   m_LightCookieOffset: {x: 0, y: 0} | ||||||
|  |   m_SoftShadowQuality: 0 | ||||||
|  | --- !u!1 &581552791 | ||||||
| GameObject: | GameObject: | ||||||
|   m_ObjectHideFlags: 0 |   m_ObjectHideFlags: 0 | ||||||
|   m_CorrespondingSourceObject: {fileID: 0} |   m_CorrespondingSourceObject: {fileID: 0} | ||||||
| @@ -224,9 +248,261 @@ GameObject: | |||||||
|   m_PrefabAsset: {fileID: 0} |   m_PrefabAsset: {fileID: 0} | ||||||
|   serializedVersion: 6 |   serializedVersion: 6 | ||||||
|   m_Component: |   m_Component: | ||||||
|   - component: {fileID: 360989558} |   - component: {fileID: 581552792} | ||||||
|   - component: {fileID: 360989557} |   m_Layer: 0 | ||||||
|   - component: {fileID: 360989556} |   m_Name: Camera Offset | ||||||
|  |   m_TagString: Untagged | ||||||
|  |   m_Icon: {fileID: 0} | ||||||
|  |   m_NavMeshLayer: 0 | ||||||
|  |   m_StaticEditorFlags: 0 | ||||||
|  |   m_IsActive: 1 | ||||||
|  | --- !u!4 &581552792 | ||||||
|  | Transform: | ||||||
|  |   m_ObjectHideFlags: 0 | ||||||
|  |   m_CorrespondingSourceObject: {fileID: 0} | ||||||
|  |   m_PrefabInstance: {fileID: 0} | ||||||
|  |   m_PrefabAsset: {fileID: 0} | ||||||
|  |   m_GameObject: {fileID: 581552791} | ||||||
|  |   serializedVersion: 2 | ||||||
|  |   m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} | ||||||
|  |   m_LocalPosition: {x: 0, y: 0, z: 0} | ||||||
|  |   m_LocalScale: {x: 1, y: 1, z: 1} | ||||||
|  |   m_ConstrainProportionsScale: 0 | ||||||
|  |   m_Children: | ||||||
|  |   - {fileID: 1781544890} | ||||||
|  |   m_Father: {fileID: 774907435} | ||||||
|  |   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} | ||||||
|  | --- !u!1 &607252634 | ||||||
|  | GameObject: | ||||||
|  |   m_ObjectHideFlags: 0 | ||||||
|  |   m_CorrespondingSourceObject: {fileID: 0} | ||||||
|  |   m_PrefabInstance: {fileID: 0} | ||||||
|  |   m_PrefabAsset: {fileID: 0} | ||||||
|  |   serializedVersion: 6 | ||||||
|  |   m_Component: | ||||||
|  |   - component: {fileID: 607252637} | ||||||
|  |   - component: {fileID: 607252636} | ||||||
|  |   - component: {fileID: 607252635} | ||||||
|  |   m_Layer: 0 | ||||||
|  |   m_Name: AR Session | ||||||
|  |   m_TagString: Untagged | ||||||
|  |   m_Icon: {fileID: 0} | ||||||
|  |   m_NavMeshLayer: 0 | ||||||
|  |   m_StaticEditorFlags: 0 | ||||||
|  |   m_IsActive: 1 | ||||||
|  | --- !u!114 &607252635 | ||||||
|  | MonoBehaviour: | ||||||
|  |   m_ObjectHideFlags: 0 | ||||||
|  |   m_CorrespondingSourceObject: {fileID: 0} | ||||||
|  |   m_PrefabInstance: {fileID: 0} | ||||||
|  |   m_PrefabAsset: {fileID: 0} | ||||||
|  |   m_GameObject: {fileID: 607252634} | ||||||
|  |   m_Enabled: 1 | ||||||
|  |   m_EditorHideFlags: 0 | ||||||
|  |   m_Script: {fileID: 11500000, guid: fa850fbd5b8aded44846f96e35f1a9f5, type: 3} | ||||||
|  |   m_Name:  | ||||||
|  |   m_EditorClassIdentifier:  | ||||||
|  | --- !u!114 &607252636 | ||||||
|  | MonoBehaviour: | ||||||
|  |   m_ObjectHideFlags: 0 | ||||||
|  |   m_CorrespondingSourceObject: {fileID: 0} | ||||||
|  |   m_PrefabInstance: {fileID: 0} | ||||||
|  |   m_PrefabAsset: {fileID: 0} | ||||||
|  |   m_GameObject: {fileID: 607252634} | ||||||
|  |   m_Enabled: 1 | ||||||
|  |   m_EditorHideFlags: 0 | ||||||
|  |   m_Script: {fileID: 11500000, guid: 3859a92a05d4f5d418cb6ca605290e74, type: 3} | ||||||
|  |   m_Name:  | ||||||
|  |   m_EditorClassIdentifier:  | ||||||
|  |   m_AttemptUpdate: 1 | ||||||
|  |   m_MatchFrameRate: 1 | ||||||
|  |   m_TrackingMode: 2 | ||||||
|  | --- !u!4 &607252637 | ||||||
|  | Transform: | ||||||
|  |   m_ObjectHideFlags: 0 | ||||||
|  |   m_CorrespondingSourceObject: {fileID: 0} | ||||||
|  |   m_PrefabInstance: {fileID: 0} | ||||||
|  |   m_PrefabAsset: {fileID: 0} | ||||||
|  |   m_GameObject: {fileID: 607252634} | ||||||
|  |   serializedVersion: 2 | ||||||
|  |   m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} | ||||||
|  |   m_LocalPosition: {x: 0, y: 0, z: 0} | ||||||
|  |   m_LocalScale: {x: 1, y: 1, z: 1} | ||||||
|  |   m_ConstrainProportionsScale: 0 | ||||||
|  |   m_Children: [] | ||||||
|  |   m_Father: {fileID: 0} | ||||||
|  |   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} | ||||||
|  | --- !u!1 &774907431 | ||||||
|  | GameObject: | ||||||
|  |   m_ObjectHideFlags: 0 | ||||||
|  |   m_CorrespondingSourceObject: {fileID: 0} | ||||||
|  |   m_PrefabInstance: {fileID: 0} | ||||||
|  |   m_PrefabAsset: {fileID: 0} | ||||||
|  |   serializedVersion: 6 | ||||||
|  |   m_Component: | ||||||
|  |   - component: {fileID: 774907435} | ||||||
|  |   - component: {fileID: 774907434} | ||||||
|  |   m_Layer: 0 | ||||||
|  |   m_Name: XR Origin | ||||||
|  |   m_TagString: Untagged | ||||||
|  |   m_Icon: {fileID: 0} | ||||||
|  |   m_NavMeshLayer: 0 | ||||||
|  |   m_StaticEditorFlags: 0 | ||||||
|  |   m_IsActive: 1 | ||||||
|  | --- !u!114 &774907434 | ||||||
|  | MonoBehaviour: | ||||||
|  |   m_ObjectHideFlags: 0 | ||||||
|  |   m_CorrespondingSourceObject: {fileID: 0} | ||||||
|  |   m_PrefabInstance: {fileID: 0} | ||||||
|  |   m_PrefabAsset: {fileID: 0} | ||||||
|  |   m_GameObject: {fileID: 774907431} | ||||||
|  |   m_Enabled: 1 | ||||||
|  |   m_EditorHideFlags: 0 | ||||||
|  |   m_Script: {fileID: 11500000, guid: e0cb9aa70a22847b5925ee5f067c10a9, type: 3} | ||||||
|  |   m_Name:  | ||||||
|  |   m_EditorClassIdentifier:  | ||||||
|  |   m_Camera: {fileID: 1781544897} | ||||||
|  |   m_OriginBaseGameObject: {fileID: 774907431} | ||||||
|  |   m_CameraFloorOffsetObject: {fileID: 581552791} | ||||||
|  |   m_RequestedTrackingOriginMode: 0 | ||||||
|  |   m_CameraYOffset: 1.1176 | ||||||
|  | --- !u!4 &774907435 | ||||||
|  | Transform: | ||||||
|  |   m_ObjectHideFlags: 0 | ||||||
|  |   m_CorrespondingSourceObject: {fileID: 0} | ||||||
|  |   m_PrefabInstance: {fileID: 0} | ||||||
|  |   m_PrefabAsset: {fileID: 0} | ||||||
|  |   m_GameObject: {fileID: 774907431} | ||||||
|  |   serializedVersion: 2 | ||||||
|  |   m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} | ||||||
|  |   m_LocalPosition: {x: 0, y: 0, z: 0} | ||||||
|  |   m_LocalScale: {x: 1, y: 1, z: 1} | ||||||
|  |   m_ConstrainProportionsScale: 0 | ||||||
|  |   m_Children: | ||||||
|  |   - {fileID: 825994263} | ||||||
|  |   - {fileID: 581552792} | ||||||
|  |   m_Father: {fileID: 0} | ||||||
|  |   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} | ||||||
|  | --- !u!1 &825994262 | ||||||
|  | GameObject: | ||||||
|  |   m_ObjectHideFlags: 0 | ||||||
|  |   m_CorrespondingSourceObject: {fileID: 0} | ||||||
|  |   m_PrefabInstance: {fileID: 0} | ||||||
|  |   m_PrefabAsset: {fileID: 0} | ||||||
|  |   serializedVersion: 6 | ||||||
|  |   m_Component: | ||||||
|  |   - component: {fileID: 825994263} | ||||||
|  |   - component: {fileID: 825994267} | ||||||
|  |   - component: {fileID: 825994266} | ||||||
|  |   - component: {fileID: 825994265} | ||||||
|  |   - component: {fileID: 825994264} | ||||||
|  |   m_Layer: 0 | ||||||
|  |   m_Name: AR Managers | ||||||
|  |   m_TagString: Untagged | ||||||
|  |   m_Icon: {fileID: 0} | ||||||
|  |   m_NavMeshLayer: 0 | ||||||
|  |   m_StaticEditorFlags: 0 | ||||||
|  |   m_IsActive: 1 | ||||||
|  | --- !u!4 &825994263 | ||||||
|  | Transform: | ||||||
|  |   m_ObjectHideFlags: 0 | ||||||
|  |   m_CorrespondingSourceObject: {fileID: 0} | ||||||
|  |   m_PrefabInstance: {fileID: 0} | ||||||
|  |   m_PrefabAsset: {fileID: 0} | ||||||
|  |   m_GameObject: {fileID: 825994262} | ||||||
|  |   serializedVersion: 2 | ||||||
|  |   m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} | ||||||
|  |   m_LocalPosition: {x: 0, y: 0, z: 0} | ||||||
|  |   m_LocalScale: {x: 10, y: 10, z: 10} | ||||||
|  |   m_ConstrainProportionsScale: 0 | ||||||
|  |   m_Children: [] | ||||||
|  |   m_Father: {fileID: 774907435} | ||||||
|  |   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} | ||||||
|  | --- !u!114 &825994264 | ||||||
|  | MonoBehaviour: | ||||||
|  |   m_ObjectHideFlags: 0 | ||||||
|  |   m_CorrespondingSourceObject: {fileID: 0} | ||||||
|  |   m_PrefabInstance: {fileID: 0} | ||||||
|  |   m_PrefabAsset: {fileID: 0} | ||||||
|  |   m_GameObject: {fileID: 825994262} | ||||||
|  |   m_Enabled: 1 | ||||||
|  |   m_EditorHideFlags: 0 | ||||||
|  |   m_Script: {fileID: 11500000, guid: 968053edfd89749c48f4ea5d444abf64, type: 3} | ||||||
|  |   m_Name:  | ||||||
|  |   m_EditorClassIdentifier:  | ||||||
|  |   m_MeshPrefab: {fileID: 0} | ||||||
|  |   m_Density: 0.5 | ||||||
|  |   m_Normals: 1 | ||||||
|  |   m_Tangents: 0 | ||||||
|  |   m_TextureCoordinates: 0 | ||||||
|  |   m_Colors: 0 | ||||||
|  |   m_ConcurrentQueueSize: 4 | ||||||
|  | --- !u!114 &825994265 | ||||||
|  | MonoBehaviour: | ||||||
|  |   m_ObjectHideFlags: 0 | ||||||
|  |   m_CorrespondingSourceObject: {fileID: 0} | ||||||
|  |   m_PrefabInstance: {fileID: 0} | ||||||
|  |   m_PrefabAsset: {fileID: 0} | ||||||
|  |   m_GameObject: {fileID: 825994262} | ||||||
|  |   m_Enabled: 1 | ||||||
|  |   m_EditorHideFlags: 0 | ||||||
|  |   m_Script: {fileID: 11500000, guid: fa17d122634046b4a8e23048891fafc5, type: 3} | ||||||
|  |   m_Name:  | ||||||
|  |   m_EditorClassIdentifier:  | ||||||
|  |   <trackablesChanged>k__BackingField: | ||||||
|  |     m_PersistentCalls: | ||||||
|  |       m_Calls: [] | ||||||
|  |   m_RaycastPrefab: {fileID: 0} | ||||||
|  | --- !u!114 &825994266 | ||||||
|  | MonoBehaviour: | ||||||
|  |   m_ObjectHideFlags: 0 | ||||||
|  |   m_CorrespondingSourceObject: {fileID: 0} | ||||||
|  |   m_PrefabInstance: {fileID: 0} | ||||||
|  |   m_PrefabAsset: {fileID: 0} | ||||||
|  |   m_GameObject: {fileID: 825994262} | ||||||
|  |   m_Enabled: 1 | ||||||
|  |   m_EditorHideFlags: 0 | ||||||
|  |   m_Script: {fileID: 11500000, guid: e1760703bbd54c04488a8d10600262ab, type: 3} | ||||||
|  |   m_Name:  | ||||||
|  |   m_EditorClassIdentifier:  | ||||||
|  |   <trackablesChanged>k__BackingField: | ||||||
|  |     m_PersistentCalls: | ||||||
|  |       m_Calls: [] | ||||||
|  |   m_PlanePrefab: {fileID: 0} | ||||||
|  |   m_DetectionMode: -1 | ||||||
|  | --- !u!114 &825994267 | ||||||
|  | MonoBehaviour: | ||||||
|  |   m_ObjectHideFlags: 0 | ||||||
|  |   m_CorrespondingSourceObject: {fileID: 0} | ||||||
|  |   m_PrefabInstance: {fileID: 0} | ||||||
|  |   m_PrefabAsset: {fileID: 0} | ||||||
|  |   m_GameObject: {fileID: 825994262} | ||||||
|  |   m_Enabled: 1 | ||||||
|  |   m_EditorHideFlags: 0 | ||||||
|  |   m_Script: {fileID: 11500000, guid: e0cb9aa70a22847b5925ee5f067c10a9, type: 3} | ||||||
|  |   m_Name:  | ||||||
|  |   m_EditorClassIdentifier:  | ||||||
|  |   m_Camera: {fileID: 0} | ||||||
|  |   m_OriginBaseGameObject: {fileID: 825994262} | ||||||
|  |   m_CameraFloorOffsetObject: {fileID: 0} | ||||||
|  |   m_RequestedTrackingOriginMode: 0 | ||||||
|  |   m_CameraYOffset: 1.1176 | ||||||
|  | --- !u!1 &1781544889 | ||||||
|  | GameObject: | ||||||
|  |   m_ObjectHideFlags: 0 | ||||||
|  |   m_CorrespondingSourceObject: {fileID: 0} | ||||||
|  |   m_PrefabInstance: {fileID: 0} | ||||||
|  |   m_PrefabAsset: {fileID: 0} | ||||||
|  |   serializedVersion: 6 | ||||||
|  |   m_Component: | ||||||
|  |   - component: {fileID: 1781544890} | ||||||
|  |   - component: {fileID: 1781544897} | ||||||
|  |   - component: {fileID: 1781544896} | ||||||
|  |   - component: {fileID: 1781544895} | ||||||
|  |   - component: {fileID: 1781544894} | ||||||
|  |   - component: {fileID: 1781544893} | ||||||
|  |   - component: {fileID: 1781544892} | ||||||
|  |   - component: {fileID: 1781544891} | ||||||
|   m_Layer: 0 |   m_Layer: 0 | ||||||
|   m_Name: Main Camera |   m_Name: Main Camera | ||||||
|   m_TagString: MainCamera |   m_TagString: MainCamera | ||||||
| @@ -234,25 +510,235 @@ GameObject: | |||||||
|   m_NavMeshLayer: 0 |   m_NavMeshLayer: 0 | ||||||
|   m_StaticEditorFlags: 0 |   m_StaticEditorFlags: 0 | ||||||
|   m_IsActive: 1 |   m_IsActive: 1 | ||||||
| --- !u!81 &360989556 | --- !u!4 &1781544890 | ||||||
|  | Transform: | ||||||
|  |   m_ObjectHideFlags: 0 | ||||||
|  |   m_CorrespondingSourceObject: {fileID: 0} | ||||||
|  |   m_PrefabInstance: {fileID: 0} | ||||||
|  |   m_PrefabAsset: {fileID: 0} | ||||||
|  |   m_GameObject: {fileID: 1781544889} | ||||||
|  |   serializedVersion: 2 | ||||||
|  |   m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} | ||||||
|  |   m_LocalPosition: {x: 0, y: 0, z: 0} | ||||||
|  |   m_LocalScale: {x: 1, y: 1, z: 1} | ||||||
|  |   m_ConstrainProportionsScale: 0 | ||||||
|  |   m_Children: [] | ||||||
|  |   m_Father: {fileID: 581552792} | ||||||
|  |   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} | ||||||
|  | --- !u!114 &1781544891 | ||||||
|  | MonoBehaviour: | ||||||
|  |   m_ObjectHideFlags: 0 | ||||||
|  |   m_CorrespondingSourceObject: {fileID: 0} | ||||||
|  |   m_PrefabInstance: {fileID: 0} | ||||||
|  |   m_PrefabAsset: {fileID: 0} | ||||||
|  |   m_GameObject: {fileID: 1781544889} | ||||||
|  |   m_Enabled: 1 | ||||||
|  |   m_EditorHideFlags: 0 | ||||||
|  |   m_Script: {fileID: 11500000, guid: b15f82cc229284894964d2d30806969d, type: 3} | ||||||
|  |   m_Name:  | ||||||
|  |   m_EditorClassIdentifier:  | ||||||
|  |   m_HumanSegmentationStencilMode: 0 | ||||||
|  |   m_HumanSegmentationDepthMode: 0 | ||||||
|  |   m_EnvironmentDepthMode: 1 | ||||||
|  |   m_EnvironmentDepthTemporalSmoothing: 1 | ||||||
|  |   m_OcclusionPreferenceMode: 0 | ||||||
|  | --- !u!114 &1781544892 | ||||||
|  | MonoBehaviour: | ||||||
|  |   m_ObjectHideFlags: 0 | ||||||
|  |   m_CorrespondingSourceObject: {fileID: 0} | ||||||
|  |   m_PrefabInstance: {fileID: 0} | ||||||
|  |   m_PrefabAsset: {fileID: 0} | ||||||
|  |   m_GameObject: {fileID: 1781544889} | ||||||
|  |   m_Enabled: 1 | ||||||
|  |   m_EditorHideFlags: 0 | ||||||
|  |   m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3} | ||||||
|  |   m_Name:  | ||||||
|  |   m_EditorClassIdentifier:  | ||||||
|  |   m_RenderShadows: 1 | ||||||
|  |   m_RequiresDepthTextureOption: 2 | ||||||
|  |   m_RequiresOpaqueTextureOption: 2 | ||||||
|  |   m_CameraType: 0 | ||||||
|  |   m_Cameras: [] | ||||||
|  |   m_RendererIndex: -1 | ||||||
|  |   m_VolumeLayerMask: | ||||||
|  |     serializedVersion: 2 | ||||||
|  |     m_Bits: 1 | ||||||
|  |   m_VolumeTrigger: {fileID: 0} | ||||||
|  |   m_VolumeFrameworkUpdateModeOption: 2 | ||||||
|  |   m_RenderPostProcessing: 0 | ||||||
|  |   m_Antialiasing: 0 | ||||||
|  |   m_AntialiasingQuality: 2 | ||||||
|  |   m_StopNaN: 0 | ||||||
|  |   m_Dithering: 0 | ||||||
|  |   m_ClearDepth: 1 | ||||||
|  |   m_AllowXRRendering: 1 | ||||||
|  |   m_AllowHDROutput: 1 | ||||||
|  |   m_UseScreenCoordOverride: 0 | ||||||
|  |   m_ScreenSizeOverride: {x: 0, y: 0, z: 0, w: 0} | ||||||
|  |   m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0} | ||||||
|  |   m_RequiresDepthTexture: 0 | ||||||
|  |   m_RequiresColorTexture: 0 | ||||||
|  |   m_Version: 2 | ||||||
|  |   m_TaaSettings: | ||||||
|  |     m_Quality: 3 | ||||||
|  |     m_FrameInfluence: 0.1 | ||||||
|  |     m_JitterScale: 1 | ||||||
|  |     m_MipBias: 0 | ||||||
|  |     m_VarianceClampScale: 0.9 | ||||||
|  |     m_ContrastAdaptiveSharpening: 0 | ||||||
|  | --- !u!114 &1781544893 | ||||||
|  | MonoBehaviour: | ||||||
|  |   m_ObjectHideFlags: 0 | ||||||
|  |   m_CorrespondingSourceObject: {fileID: 0} | ||||||
|  |   m_PrefabInstance: {fileID: 0} | ||||||
|  |   m_PrefabAsset: {fileID: 0} | ||||||
|  |   m_GameObject: {fileID: 1781544889} | ||||||
|  |   m_Enabled: 1 | ||||||
|  |   m_EditorHideFlags: 0 | ||||||
|  |   m_Script: {fileID: 11500000, guid: c2fadf230d1919748a9aa21d40f74619, type: 3} | ||||||
|  |   m_Name:  | ||||||
|  |   m_EditorClassIdentifier:  | ||||||
|  |   m_TrackingType: 0 | ||||||
|  |   m_UpdateType: 0 | ||||||
|  |   m_IgnoreTrackingState: 0 | ||||||
|  |   m_PositionInput: | ||||||
|  |     m_UseReference: 0 | ||||||
|  |     m_Action: | ||||||
|  |       m_Name: Position | ||||||
|  |       m_Type: 0 | ||||||
|  |       m_ExpectedControlType: Vector3 | ||||||
|  |       m_Id: 1d22341e-4dd7-44bf-8c99-2f3a85960318 | ||||||
|  |       m_Processors:  | ||||||
|  |       m_Interactions:  | ||||||
|  |       m_SingletonActionBindings: | ||||||
|  |       - m_Name:  | ||||||
|  |         m_Id: 12bf3a58-2acd-4a2b-8d62-744979ae84e5 | ||||||
|  |         m_Path: <XRHMD>/centerEyePosition | ||||||
|  |         m_Interactions:  | ||||||
|  |         m_Processors:  | ||||||
|  |         m_Groups:  | ||||||
|  |         m_Action: Position | ||||||
|  |         m_Flags: 0 | ||||||
|  |       - m_Name:  | ||||||
|  |         m_Id: a5495caa-b892-4db8-b2ef-dc080af8d77f | ||||||
|  |         m_Path: <HandheldARInputDevice>/devicePosition | ||||||
|  |         m_Interactions:  | ||||||
|  |         m_Processors:  | ||||||
|  |         m_Groups:  | ||||||
|  |         m_Action: Position | ||||||
|  |         m_Flags: 0 | ||||||
|  |       m_Flags: 0 | ||||||
|  |     m_Reference: {fileID: 0} | ||||||
|  |   m_RotationInput: | ||||||
|  |     m_UseReference: 0 | ||||||
|  |     m_Action: | ||||||
|  |       m_Name: Rotation | ||||||
|  |       m_Type: 0 | ||||||
|  |       m_ExpectedControlType: Quaternion | ||||||
|  |       m_Id: e9e9ac37-8193-4657-ae44-53991f390a47 | ||||||
|  |       m_Processors:  | ||||||
|  |       m_Interactions:  | ||||||
|  |       m_SingletonActionBindings: | ||||||
|  |       - m_Name:  | ||||||
|  |         m_Id: f37fe228-69c0-45d4-b523-5c69a0b1379c | ||||||
|  |         m_Path: <XRHMD>/centerEyeRotation | ||||||
|  |         m_Interactions:  | ||||||
|  |         m_Processors:  | ||||||
|  |         m_Groups:  | ||||||
|  |         m_Action: Rotation | ||||||
|  |         m_Flags: 0 | ||||||
|  |       - m_Name:  | ||||||
|  |         m_Id: dce2fb17-049e-4ce3-93d5-86736b049153 | ||||||
|  |         m_Path: <HandheldARInputDevice>/deviceRotation | ||||||
|  |         m_Interactions:  | ||||||
|  |         m_Processors:  | ||||||
|  |         m_Groups:  | ||||||
|  |         m_Action: Rotation | ||||||
|  |         m_Flags: 0 | ||||||
|  |       m_Flags: 0 | ||||||
|  |     m_Reference: {fileID: 0} | ||||||
|  |   m_TrackingStateInput: | ||||||
|  |     m_UseReference: 0 | ||||||
|  |     m_Action: | ||||||
|  |       m_Name: Tracking State | ||||||
|  |       m_Type: 0 | ||||||
|  |       m_ExpectedControlType: Integer | ||||||
|  |       m_Id: 8ef3e154-d314-48e3-961f-a379d469d435 | ||||||
|  |       m_Processors:  | ||||||
|  |       m_Interactions:  | ||||||
|  |       m_SingletonActionBindings: [] | ||||||
|  |       m_Flags: 0 | ||||||
|  |     m_Reference: {fileID: 0} | ||||||
|  |   m_PositionAction: | ||||||
|  |     m_Name:  | ||||||
|  |     m_Type: 0 | ||||||
|  |     m_ExpectedControlType:  | ||||||
|  |     m_Id: f61998f6-4054-4f9f-b80c-de37dae3d176 | ||||||
|  |     m_Processors:  | ||||||
|  |     m_Interactions:  | ||||||
|  |     m_SingletonActionBindings: [] | ||||||
|  |     m_Flags: 0 | ||||||
|  |   m_RotationAction: | ||||||
|  |     m_Name:  | ||||||
|  |     m_Type: 0 | ||||||
|  |     m_ExpectedControlType:  | ||||||
|  |     m_Id: 11600a54-9e03-48ce-aea1-5a4edddfba90 | ||||||
|  |     m_Processors:  | ||||||
|  |     m_Interactions:  | ||||||
|  |     m_SingletonActionBindings: [] | ||||||
|  |     m_Flags: 0 | ||||||
|  | --- !u!114 &1781544894 | ||||||
|  | MonoBehaviour: | ||||||
|  |   m_ObjectHideFlags: 0 | ||||||
|  |   m_CorrespondingSourceObject: {fileID: 0} | ||||||
|  |   m_PrefabInstance: {fileID: 0} | ||||||
|  |   m_PrefabAsset: {fileID: 0} | ||||||
|  |   m_GameObject: {fileID: 1781544889} | ||||||
|  |   m_Enabled: 1 | ||||||
|  |   m_EditorHideFlags: 0 | ||||||
|  |   m_Script: {fileID: 11500000, guid: 816b289ef451e094f9ae174fb4cf8db0, type: 3} | ||||||
|  |   m_Name:  | ||||||
|  |   m_EditorClassIdentifier:  | ||||||
|  |   m_UseCustomMaterial: 0 | ||||||
|  |   m_CustomMaterial: {fileID: 0} | ||||||
|  | --- !u!114 &1781544895 | ||||||
|  | MonoBehaviour: | ||||||
|  |   m_ObjectHideFlags: 0 | ||||||
|  |   m_CorrespondingSourceObject: {fileID: 0} | ||||||
|  |   m_PrefabInstance: {fileID: 0} | ||||||
|  |   m_PrefabAsset: {fileID: 0} | ||||||
|  |   m_GameObject: {fileID: 1781544889} | ||||||
|  |   m_Enabled: 1 | ||||||
|  |   m_EditorHideFlags: 0 | ||||||
|  |   m_Script: {fileID: 11500000, guid: 4966719baa26e4b0e8231a24d9bd491a, type: 3} | ||||||
|  |   m_Name:  | ||||||
|  |   m_EditorClassIdentifier:  | ||||||
|  |   m_FocusMode: -1 | ||||||
|  |   m_LightEstimationMode: -1 | ||||||
|  |   m_AutoFocus: 1 | ||||||
|  |   m_ImageStabilization: 0 | ||||||
|  |   m_LightEstimation: 0 | ||||||
|  |   m_FacingDirection: 1 | ||||||
|  |   m_RenderMode: 0 | ||||||
|  | --- !u!81 &1781544896 | ||||||
| AudioListener: | AudioListener: | ||||||
|   m_ObjectHideFlags: 0 |   m_ObjectHideFlags: 0 | ||||||
|   m_CorrespondingSourceObject: {fileID: 0} |   m_CorrespondingSourceObject: {fileID: 0} | ||||||
|   m_PrefabInstance: {fileID: 0} |   m_PrefabInstance: {fileID: 0} | ||||||
|   m_PrefabAsset: {fileID: 0} |   m_PrefabAsset: {fileID: 0} | ||||||
|   m_GameObject: {fileID: 360989555} |   m_GameObject: {fileID: 1781544889} | ||||||
|   m_Enabled: 1 |   m_Enabled: 1 | ||||||
| --- !u!20 &360989557 | --- !u!20 &1781544897 | ||||||
| Camera: | Camera: | ||||||
|   m_ObjectHideFlags: 0 |   m_ObjectHideFlags: 0 | ||||||
|   m_CorrespondingSourceObject: {fileID: 0} |   m_CorrespondingSourceObject: {fileID: 0} | ||||||
|   m_PrefabInstance: {fileID: 0} |   m_PrefabInstance: {fileID: 0} | ||||||
|   m_PrefabAsset: {fileID: 0} |   m_PrefabAsset: {fileID: 0} | ||||||
|   m_GameObject: {fileID: 360989555} |   m_GameObject: {fileID: 1781544889} | ||||||
|   m_Enabled: 1 |   m_Enabled: 1 | ||||||
|   serializedVersion: 2 |   serializedVersion: 2 | ||||||
|   m_ClearFlags: 1 |   m_ClearFlags: 2 | ||||||
|   m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} |   m_BackGroundColor: {r: 0, g: 0, b: 0, a: 1} | ||||||
|   m_projectionMatrixMode: 1 |   m_projectionMatrixMode: 1 | ||||||
|   m_GateFitMode: 2 |   m_GateFitMode: 2 | ||||||
|   m_FOVAxisMode: 0 |   m_FOVAxisMode: 0 | ||||||
| @@ -273,12 +759,12 @@ Camera: | |||||||
|     y: 0 |     y: 0 | ||||||
|     width: 1 |     width: 1 | ||||||
|     height: 1 |     height: 1 | ||||||
|   near clip plane: 0.3 |   near clip plane: 0.1 | ||||||
|   far clip plane: 1000 |   far clip plane: 20 | ||||||
|   field of view: 60 |   field of view: 60 | ||||||
|   orthographic: 0 |   orthographic: 0 | ||||||
|   orthographic size: 5 |   orthographic size: 5 | ||||||
|   m_Depth: -1 |   m_Depth: 0 | ||||||
|   m_CullingMask: |   m_CullingMask: | ||||||
|     serializedVersion: 2 |     serializedVersion: 2 | ||||||
|     m_Bits: 4294967295 |     m_Bits: 4294967295 | ||||||
| @@ -293,24 +779,10 @@ Camera: | |||||||
|   m_OcclusionCulling: 1 |   m_OcclusionCulling: 1 | ||||||
|   m_StereoConvergence: 10 |   m_StereoConvergence: 10 | ||||||
|   m_StereoSeparation: 0.022 |   m_StereoSeparation: 0.022 | ||||||
| --- !u!4 &360989558 |  | ||||||
| Transform: |  | ||||||
|   m_ObjectHideFlags: 0 |  | ||||||
|   m_CorrespondingSourceObject: {fileID: 0} |  | ||||||
|   m_PrefabInstance: {fileID: 0} |  | ||||||
|   m_PrefabAsset: {fileID: 0} |  | ||||||
|   m_GameObject: {fileID: 360989555} |  | ||||||
|   serializedVersion: 2 |  | ||||||
|   m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} |  | ||||||
|   m_LocalPosition: {x: 0, y: 1, z: -10} |  | ||||||
|   m_LocalScale: {x: 1, y: 1, z: 1} |  | ||||||
|   m_ConstrainProportionsScale: 0 |  | ||||||
|   m_Children: [] |  | ||||||
|   m_Father: {fileID: 0} |  | ||||||
|   m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} |  | ||||||
| --- !u!1660057539 &9223372036854775807 | --- !u!1660057539 &9223372036854775807 | ||||||
| SceneRoots: | SceneRoots: | ||||||
|   m_ObjectHideFlags: 0 |   m_ObjectHideFlags: 0 | ||||||
|   m_Roots: |   m_Roots: | ||||||
|   - {fileID: 360989558} |  | ||||||
|   - {fileID: 55455372} |   - {fileID: 55455372} | ||||||
|  |   - {fileID: 607252637} | ||||||
|  |   - {fileID: 774907435} | ||||||
|   | |||||||
							
								
								
									
										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. | ||||||
							
								
								
									
										121
									
								
								ProjectSettings/SceneTemplateSettings.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								ProjectSettings/SceneTemplateSettings.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,121 @@ | |||||||
|  | { | ||||||
|  |     "templatePinStates": [], | ||||||
|  |     "dependencyTypeInfos": [ | ||||||
|  |         { | ||||||
|  |             "userAdded": false, | ||||||
|  |             "type": "UnityEngine.AnimationClip", | ||||||
|  |             "defaultInstantiationMode": 0 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "userAdded": false, | ||||||
|  |             "type": "UnityEditor.Animations.AnimatorController", | ||||||
|  |             "defaultInstantiationMode": 0 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "userAdded": false, | ||||||
|  |             "type": "UnityEngine.AnimatorOverrideController", | ||||||
|  |             "defaultInstantiationMode": 0 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "userAdded": false, | ||||||
|  |             "type": "UnityEditor.Audio.AudioMixerController", | ||||||
|  |             "defaultInstantiationMode": 0 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "userAdded": false, | ||||||
|  |             "type": "UnityEngine.ComputeShader", | ||||||
|  |             "defaultInstantiationMode": 1 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "userAdded": false, | ||||||
|  |             "type": "UnityEngine.Cubemap", | ||||||
|  |             "defaultInstantiationMode": 0 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "userAdded": false, | ||||||
|  |             "type": "UnityEngine.GameObject", | ||||||
|  |             "defaultInstantiationMode": 0 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "userAdded": false, | ||||||
|  |             "type": "UnityEditor.LightingDataAsset", | ||||||
|  |             "defaultInstantiationMode": 0 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "userAdded": false, | ||||||
|  |             "type": "UnityEngine.LightingSettings", | ||||||
|  |             "defaultInstantiationMode": 0 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "userAdded": false, | ||||||
|  |             "type": "UnityEngine.Material", | ||||||
|  |             "defaultInstantiationMode": 0 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "userAdded": false, | ||||||
|  |             "type": "UnityEditor.MonoScript", | ||||||
|  |             "defaultInstantiationMode": 1 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "userAdded": false, | ||||||
|  |             "type": "UnityEngine.PhysicsMaterial", | ||||||
|  |             "defaultInstantiationMode": 0 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "userAdded": false, | ||||||
|  |             "type": "UnityEngine.PhysicsMaterial2D", | ||||||
|  |             "defaultInstantiationMode": 0 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "userAdded": false, | ||||||
|  |             "type": "UnityEngine.Rendering.PostProcessing.PostProcessProfile", | ||||||
|  |             "defaultInstantiationMode": 0 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "userAdded": false, | ||||||
|  |             "type": "UnityEngine.Rendering.PostProcessing.PostProcessResources", | ||||||
|  |             "defaultInstantiationMode": 0 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "userAdded": false, | ||||||
|  |             "type": "UnityEngine.Rendering.VolumeProfile", | ||||||
|  |             "defaultInstantiationMode": 0 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "userAdded": false, | ||||||
|  |             "type": "UnityEditor.SceneAsset", | ||||||
|  |             "defaultInstantiationMode": 1 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "userAdded": false, | ||||||
|  |             "type": "UnityEngine.Shader", | ||||||
|  |             "defaultInstantiationMode": 1 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "userAdded": false, | ||||||
|  |             "type": "UnityEngine.ShaderVariantCollection", | ||||||
|  |             "defaultInstantiationMode": 1 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "userAdded": false, | ||||||
|  |             "type": "UnityEngine.Texture", | ||||||
|  |             "defaultInstantiationMode": 0 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "userAdded": false, | ||||||
|  |             "type": "UnityEngine.Texture2D", | ||||||
|  |             "defaultInstantiationMode": 0 | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "userAdded": false, | ||||||
|  |             "type": "UnityEngine.Timeline.TimelineAsset", | ||||||
|  |             "defaultInstantiationMode": 0 | ||||||
|  |         } | ||||||
|  |     ], | ||||||
|  |     "defaultDependencyTypeInfo": { | ||||||
|  |         "userAdded": false, | ||||||
|  |         "type": "<default_scene_template_dependencies>", | ||||||
|  |         "defaultInstantiationMode": 1 | ||||||
|  |     }, | ||||||
|  |     "newSceneOverride": 0 | ||||||
|  | } | ||||||
| @@ -4,5 +4,4 @@ | |||||||
| VersionControlSettings: | VersionControlSettings: | ||||||
|   m_ObjectHideFlags: 0 |   m_ObjectHideFlags: 0 | ||||||
|   m_Mode: Visible Meta Files |   m_Mode: Visible Meta Files | ||||||
|   m_CollabEditorSettings: |   m_TrackPackagesOutsideProject: 0 | ||||||
|     inProgressEnabled: 1 |  | ||||||
|   | |||||||
							
								
								
									
										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