diff --git a/.idea/.idea.hse-ar-scanner/.idea/indexLayout.xml b/.idea/.idea.hse-ar-scanner/.idea/indexLayout.xml index 4ab2dbead55c0f061d587baee8d0da1cfb2173fb..31fefb2377ad9093fd1d9c0cf8e93c0321883312 100644 --- a/.idea/.idea.hse-ar-scanner/.idea/indexLayout.xml +++ b/.idea/.idea.hse-ar-scanner/.idea/indexLayout.xml @@ -1,31 +1,31 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project version="4"> - <component name="ContentModelUserStore"> - <attachedFolders /> - <explicitIncludes> - <Path>Library/PackageCache/com.unity.collab-proxy@1.2.16</Path> - <Path>Library/PackageCache/com.unity.ext.nunit@1.0.6</Path> - <Path>Library/PackageCache/com.unity.ide.rider@1.1.4</Path> - <Path>Library/PackageCache/com.unity.ide.vscode@1.2.3</Path> - <Path>Library/PackageCache/com.unity.multiplayer-hlapi@1.0.8</Path> - <Path>Library/PackageCache/com.unity.subsystemregistration@1.0.6</Path> - <Path>Library/PackageCache/com.unity.test-framework@1.1.22</Path> - <Path>Library/PackageCache/com.unity.textmeshpro@2.0.1</Path> - <Path>Library/PackageCache/com.unity.timeline@1.2.18</Path> - <Path>Library/PackageCache/com.unity.xr.legacyinputhelpers@2.1.7</Path> - <Path>Library/PackageCache/com.unity.xr.management@3.2.17</Path> - <Path>Library/PackageCache/nuget.mono-cecil@0.1.6-preview</Path> - <Path>Packages</Path> - <Path>ProjectSettings</Path> - </explicitIncludes> - <explicitExcludes> - <Path>.git</Path> - <Path>.idea</Path> - <Path>Builds</Path> - <Path>Library</Path> - <Path>Logs</Path> - <Path>Temp</Path> - <Path>obj</Path> - </explicitExcludes> - </component> +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="ContentModelUserStore"> + <attachedFolders /> + <explicitIncludes> + <Path>Library/PackageCache/com.unity.collab-proxy@1.2.16</Path> + <Path>Library/PackageCache/com.unity.ext.nunit@1.0.6</Path> + <Path>Library/PackageCache/com.unity.ide.rider@1.1.4</Path> + <Path>Library/PackageCache/com.unity.ide.vscode@1.2.3</Path> + <Path>Library/PackageCache/com.unity.multiplayer-hlapi@1.0.8</Path> + <Path>Library/PackageCache/com.unity.subsystemregistration@1.0.6</Path> + <Path>Library/PackageCache/com.unity.test-framework@1.1.22</Path> + <Path>Library/PackageCache/com.unity.textmeshpro@2.0.1</Path> + <Path>Library/PackageCache/com.unity.timeline@1.2.18</Path> + <Path>Library/PackageCache/com.unity.xr.legacyinputhelpers@2.1.7</Path> + <Path>Library/PackageCache/com.unity.xr.management@3.2.17</Path> + <Path>Library/PackageCache/nuget.mono-cecil@0.1.6-preview</Path> + <Path>Packages</Path> + <Path>ProjectSettings</Path> + </explicitIncludes> + <explicitExcludes> + <Path>.git</Path> + <Path>.idea</Path> + <Path>Builds</Path> + <Path>Library</Path> + <Path>Logs</Path> + <Path>Temp</Path> + <Path>obj</Path> + </explicitExcludes> + </component> </project> \ No newline at end of file diff --git a/Assets/FpsCounter.cs b/Assets/FpsCounter.cs new file mode 100644 index 0000000000000000000000000000000000000000..1eb1f7f835d3b970c12131c7ab451b11bf32e22b --- /dev/null +++ b/Assets/FpsCounter.cs @@ -0,0 +1,30 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; + +public class FpsCounter : MonoBehaviour +{ + float deltaTime = 0.0f; + + void Update() + { + deltaTime += (Time.unscaledDeltaTime - deltaTime) * 0.1f; + } + + void OnGUI() + { + int w = Screen.width, h = Screen.height; + + GUIStyle style = new GUIStyle(); + + Rect rect = new Rect(0, 0, w, h * 2 / 100); + style.alignment = TextAnchor.UpperLeft; + style.fontSize = h * 2 / 100; + style.normal.textColor = new Color (0.0f, 0.0f, 0.5f, 1.0f); + float msec = deltaTime * 1000.0f; + float fps = 1.0f / deltaTime; + string text = string.Format("{0:0.0} ms ({1:0.} fps)", msec, fps); + GUI.Label(rect, text, style); + } +} \ No newline at end of file diff --git a/Assets/FpsCounter.cs.meta b/Assets/FpsCounter.cs.meta new file mode 100644 index 0000000000000000000000000000000000000000..1eaabefb694f2ffa28ff11fbcda983aac184ebde --- /dev/null +++ b/Assets/FpsCounter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 905a87ab2b3c59f4abeebb4b006fe010 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/Materials/Pc.mat b/Assets/Resources/Materials/Pc.mat index e1f848ea5c05e7b25067bf2238e01eccf94f0a67..bc997af5a69fec5caece0b97b0ef827f159609cc 100644 --- a/Assets/Resources/Materials/Pc.mat +++ b/Assets/Resources/Materials/Pc.mat @@ -8,21 +8,21 @@ Material: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_Name: Pc - m_Shader: {fileID: 210, guid: 0000000000000000f000000000000000, type: 0} - m_ShaderKeywords: _ALPHABLEND_ON _COLORADDSUBDIFF_ON _NORMALMAP + m_Shader: {fileID: 211, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: _ALPHATEST_ON _COLORCOLOR_ON m_LightmapFlags: 0 m_EnableInstancingVariants: 0 m_DoubleSidedGI: 0 - m_CustomRenderQueue: 3000 + m_CustomRenderQueue: 2450 stringTagMap: - RenderType: Transparent + RenderType: TransparentCutout disabledShaderPasses: - ALWAYS m_SavedProperties: serializedVersion: 3 m_TexEnvs: - _BumpMap: - m_Texture: {fileID: 2800000, guid: 6b07f0d5b24b9b1468ca57a02e7f96d5, type: 3} + m_Texture: {fileID: 0} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} - _DetailAlbedoMap: @@ -42,7 +42,7 @@ Material: m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} - _MainTex: - m_Texture: {fileID: 10912, guid: 0000000000000000f000000000000000, type: 0} + m_Texture: {fileID: 10300, guid: 0000000000000000f000000000000000, type: 0} m_Scale: {x: 1, y: 1} m_Offset: {x: 0, y: 0} - _MetallicGlossMap: @@ -63,7 +63,7 @@ Material: - _CameraFadingEnabled: 0 - _CameraFarFadeDistance: 2 - _CameraNearFadeDistance: 1 - - _ColorMode: 1 + - _ColorMode: 4 - _Cull: 2 - _Cutoff: 0.677 - _DetailNormalMapScale: 1 @@ -71,15 +71,15 @@ Material: - _DistortionEnabled: 0 - _DistortionStrength: -171.02 - _DistortionStrengthScaled: -17.102001 - - _DstBlend: 10 + - _DstBlend: 0 - _EmissionEnabled: 0 - _FlipbookMode: 0 - _GlossMapScale: 1 - _Glossiness: 0.2 - _GlossyReflections: 1 - - _LightingEnabled: 1 + - _LightingEnabled: 0 - _Metallic: 0 - - _Mode: 2 + - _Mode: 1 - _OcclusionStrength: 1 - _Parallax: 0.02 - _SmoothnessTextureChannel: 0 @@ -87,12 +87,12 @@ Material: - _SoftParticlesFarFadeDistance: 1 - _SoftParticlesNearFadeDistance: 0 - _SpecularHighlights: 1 - - _SrcBlend: 5 + - _SrcBlend: 1 - _UVSec: 0 - - _ZWrite: 0 + - _ZWrite: 1 m_Colors: - _CameraFadeParams: {r: 0, g: Infinity, b: 0, a: 0} - - _Color: {r: 0.865, g: 0.865, b: 0.865, a: 1} + - _Color: {r: 0.9433962, g: 0.9433962, b: 0.9433962, a: 1} - _ColorAddSubDiff: {r: 1, g: 0, b: 0, a: 0} - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} - _SoftParticleFadeParams: {r: 0, g: 0, b: 0, a: 0} diff --git a/Assets/Resources/Prefabs/PointCloudParticles.prefab b/Assets/Resources/Prefabs/PointCloudParticles.prefab index f8ae460033e43e9a4bf24dac1cce15968b2be8e8..392cf149c347bfe54d66468bb01a4b1ac3ccbb62 100644 --- a/Assets/Resources/Prefabs/PointCloudParticles.prefab +++ b/Assets/Resources/Prefabs/PointCloudParticles.prefab @@ -4748,7 +4748,7 @@ ParticleSystemRenderer: m_EnableGPUInstancing: 1 m_ApplyActiveColorSpace: 1 m_AllowRoll: 1 - m_VertexStreams: 0001030402 + m_VertexStreams: 000304 m_Mesh: {fileID: 0} m_Mesh1: {fileID: 0} m_Mesh2: {fileID: 0} diff --git a/Assets/Resources/Scenes/RawARCorePointCloudRetriever.unity b/Assets/Resources/Scenes/RawARCorePointCloudRetriever.unity index e0631693a160b60ee806c6f12792b19e7710764b..d76c82a9e66324ec04690406fa04e556e1ad9954 100644 --- a/Assets/Resources/Scenes/RawARCorePointCloudRetriever.unity +++ b/Assets/Resources/Scenes/RawARCorePointCloudRetriever.unity @@ -388,12 +388,11 @@ MonoBehaviour: m_EditorClassIdentifier: pointCloud: {fileID: 1157256428} maxSqrDistance: 25 - minConfidence: 0.6875 + minConfidence: 0.6885 continueCollectingPoints: 0 progressBar: {fileID: 553464322} progressText: {fileID: 665878184} defaultColor: {r: 0.97462785, g: 1, b: 0.27058828, a: 1} - weldColor: {r: 0.3529412, g: 0.9372549, b: 0.44705883, a: 1} Buttons: - {fileID: 1191312876} - {fileID: 1458103011} @@ -401,6 +400,7 @@ MonoBehaviour: RenderDistance: 5 MaxRenderDistance: 6 RenderSlider: {fileID: 1891182249} + weldDistance: 0.025 --- !u!4 &125579805 Transform: m_ObjectHideFlags: 0 @@ -409,7 +409,7 @@ Transform: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 125579803} m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0.90831095, y: -3.264731, z: 14.116892} + m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_Children: - {fileID: 1706220893} @@ -1068,6 +1068,49 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 519045787} m_CullTransparentMesh: 0 +--- !u!1 &522305924 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 522305926} + - component: {fileID: 522305925} + m_Layer: 0 + m_Name: Fps + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &522305925 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 522305924} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 905a87ab2b3c59f4abeebb4b006fe010, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!4 &522305926 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 522305924} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0.17662245, y: -3.132567, z: -5.5776186} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 12 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &553464321 GameObject: m_ObjectHideFlags: 0 @@ -2819,6 +2862,11 @@ PrefabInstance: propertyPath: playOnAwake value: 0 objectReference: {fileID: 0} + - target: {fileID: 1859515531890607645, guid: 9b64b381f7cb3be4a9f2dcf1483252b5, + type: 3} + propertyPath: ringBufferMode + value: 1 + objectReference: {fileID: 0} - target: {fileID: 1859515531890607645, guid: 9b64b381f7cb3be4a9f2dcf1483252b5, type: 3} propertyPath: TrailModule.mode @@ -2827,7 +2875,7 @@ PrefabInstance: - target: {fileID: 1859515531890607645, guid: 9b64b381f7cb3be4a9f2dcf1483252b5, type: 3} propertyPath: moveWithTransform - value: 1 + value: 0 objectReference: {fileID: 0} - target: {fileID: 1859515531890607645, guid: 9b64b381f7cb3be4a9f2dcf1483252b5, type: 3} @@ -2844,10 +2892,15 @@ PrefabInstance: propertyPath: SizeModule.curve.scalar value: 2 objectReference: {fileID: 0} + - target: {fileID: 1859515531890607645, guid: 9b64b381f7cb3be4a9f2dcf1483252b5, + type: 3} + propertyPath: InitialModule.maxNumParticles + value: 300000 + objectReference: {fileID: 0} - target: {fileID: 1859515531890607645, guid: 9b64b381f7cb3be4a9f2dcf1483252b5, type: 3} propertyPath: InitialModule.startSize.scalar - value: 0.01875 + value: 0.02 objectReference: {fileID: 0} - target: {fileID: 1859515531890607645, guid: 9b64b381f7cb3be4a9f2dcf1483252b5, type: 3} @@ -2857,7 +2910,7 @@ PrefabInstance: - target: {fileID: 1859515531890607645, guid: 9b64b381f7cb3be4a9f2dcf1483252b5, type: 3} propertyPath: InitialModule.startLifetime.scalar - value: 3600 + value: 1800 objectReference: {fileID: 0} - target: {fileID: 1859515531890607645, guid: 9b64b381f7cb3be4a9f2dcf1483252b5, type: 3} @@ -2957,17 +3010,22 @@ PrefabInstance: - target: {fileID: 1859515531890607646, guid: 9b64b381f7cb3be4a9f2dcf1483252b5, type: 3} propertyPath: m_RenderMode - value: 4 + value: 0 objectReference: {fileID: 0} - target: {fileID: 1859515531890607646, guid: 9b64b381f7cb3be4a9f2dcf1483252b5, type: 3} propertyPath: m_CastShadows value: 0 objectReference: {fileID: 0} + - target: {fileID: 1859515531890607646, guid: 9b64b381f7cb3be4a9f2dcf1483252b5, + type: 3} + propertyPath: m_MaskInteraction + value: 0 + objectReference: {fileID: 0} - target: {fileID: 1859515531890607646, guid: 9b64b381f7cb3be4a9f2dcf1483252b5, type: 3} propertyPath: m_RenderAlignment - value: 2 + value: 0 objectReference: {fileID: 0} - target: {fileID: 1859515531890607646, guid: 9b64b381f7cb3be4a9f2dcf1483252b5, type: 3} @@ -2983,21 +3041,21 @@ PrefabInstance: type: 3} propertyPath: m_Materials.Array.data[0] value: - objectReference: {fileID: 2100000, guid: 21228ec852575b74ea71fcaff5bf72cf, type: 2} + objectReference: {fileID: 2100000, guid: 43243cadedf4c2d4ea2e9fce4c5c6593, type: 2} - target: {fileID: 1859515531890607646, guid: 9b64b381f7cb3be4a9f2dcf1483252b5, type: 3} propertyPath: m_VertexStreams.Array.size - value: 5 + value: 3 objectReference: {fileID: 0} - target: {fileID: 1859515531890607646, guid: 9b64b381f7cb3be4a9f2dcf1483252b5, type: 3} propertyPath: m_VertexStreams.Array.data[1] - value: 1 + value: 3 objectReference: {fileID: 0} - target: {fileID: 1859515531890607646, guid: 9b64b381f7cb3be4a9f2dcf1483252b5, type: 3} propertyPath: m_VertexStreams.Array.data[2] - value: 3 + value: 4 objectReference: {fileID: 0} - target: {fileID: 1859515531890607646, guid: 9b64b381f7cb3be4a9f2dcf1483252b5, type: 3} @@ -3007,7 +3065,7 @@ PrefabInstance: - target: {fileID: 1859515531890607646, guid: 9b64b381f7cb3be4a9f2dcf1483252b5, type: 3} propertyPath: m_VertexStreams.Array.data[4] - value: 9 + value: 2 objectReference: {fileID: 0} - target: {fileID: 1859515531890607647, guid: 9b64b381f7cb3be4a9f2dcf1483252b5, type: 3} diff --git a/Assets/Resources/Scripts/MyPointCloudVisualizer.cs b/Assets/Resources/Scripts/MyPointCloudVisualizer.cs index bf80d34d4fb9bec06f31ff962701537b08dd5302..c456cd62f35cda613a2d2e7ce522ff6e842052f7 100644 --- a/Assets/Resources/Scripts/MyPointCloudVisualizer.cs +++ b/Assets/Resources/Scripts/MyPointCloudVisualizer.cs @@ -1,386 +1,457 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using DataStructures.ViliWonka.KDTree; -using GoogleARCore; -using UnityEngine; -using UnityEngine.UI; -using Random = UnityEngine.Random; - -public class MyPointCloudVisualizer : MonoBehaviour -{ - public ParticleSystem pointCloud; - [Space(10)] public float maxSqrDistance = 25f; - private float maxDistance; - - public float minConfidence = 0.625f; - // public float minConfidence = 0.55f; - // public float softConfidence = 0.65f; - - private Transform currentCamTransform; - - private ParticleSystem.EmitParams emitParams; - private ParticleSystem.EmitParams emitParamsWelded; - - private List<Vector3> points; - - public List<Vector3> Points => points; - private KDTree _kdTree = new KDTree(); - private KDQuery _query = new KDQuery(); - - private int minPointsCount = 4600; - private float minBoundingBoxVolume = 90f; - - private Vector3 minPoint; - private Vector3 maxPoint; - - public bool continueCollectingPoints = false; - - - [Space(10)] public RectTransform progressBar; - private float defaultProgressBarScale; - public Text progressText; - - [Space(10)] public Color defaultColor = new Color32(249, 255, 69, 255); - public Color weldColor = new Color32(90, 239, 114, 255); - - [Space(10)] public List<Button> Buttons; - - private bool lastConditiondsState = false; - private float notificationDelay = 4; - private float lastNotificationTime = 0f; - public bool CanFinish = true; - public float RenderDistance = 5f; - public float MaxRenderDistance = 6f; - public Slider RenderSlider; - - // Start is called before the first frame update - void Start() - { - points = new List<Vector3>(); - emitParams = new ParticleSystem.EmitParams(); - emitParams.startColor = defaultColor; - - emitParamsWelded = new ParticleSystem.EmitParams(); - emitParamsWelded.startColor = weldColor; - emitParamsWelded.startSize = 0.015f; - - defaultProgressBarScale = progressBar.localScale.x; - //defaultColor = new Color32(emitParams.startColor.r, emitParams.startColor.g, emitParams.startColor.b, emitParams.startColor.a); - - minPoint = Vector3.positiveInfinity; - maxPoint = Vector3.negativeInfinity; - - maxDistance = Mathf.Sqrt(maxSqrDistance); - - foreach (var button in Buttons) - { - button.interactable = false; - } - - lastNotificationTime = Time.time; - currentCamTransform = Camera.main.transform; - - RenderSlider.minValue = 0.5f; - RenderSlider.maxValue = MaxRenderDistance; - RenderSlider.value = RenderDistance; - - - StartCoroutine(DelayedStart()); - } - - public void UpdateRenderDistance(float newVal) - { - RenderDistance = newVal; - } - - private IEnumerator DelayedStart(float delay = 0.05f) - { - continueCollectingPoints = false; - yield return new WaitForSeconds(delay); - continueCollectingPoints = true; - StartCoroutine(WeldRoutine()); - } - - // Update is called once per frame - void Update() - { - if (!continueCollectingPoints) - return; - if (Frame.PointCloud.IsUpdatedThisFrame) - { - for (int i = 0; i < Frame.PointCloud.PointCount; i++) - { - var point = Frame.PointCloud.GetPointAsStruct(i); - if (point.Confidence < minConfidence) continue; - // if (point.Confidence < softConfidence && Random.Range(0f, 1f) < 0.25f) continue; - - var distance = (currentCamTransform.position - point.Position).sqrMagnitude; - if (distance > maxSqrDistance) continue; - - emitParams.position = point.Position; - pointCloud.Emit(emitParams, 1); - points.Add(point.Position); - if (!(Random.Range(0f, 1f) < 0.2f)) continue; - if (point.Position.x < minPoint.x) - minPoint.x = point.Position.x; - if (point.Position.y < minPoint.y) - minPoint.y = point.Position.y; - if (point.Position.z < minPoint.z) - minPoint.z = point.Position.z; - - if (point.Position.x > maxPoint.x) - maxPoint.x = point.Position.x; - if (point.Position.y > maxPoint.y) - maxPoint.y = point.Position.y; - if (point.Position.z > maxPoint.z) - maxPoint.z = point.Position.z; - } - } - - var currentConditionsState = CheckFinishConditionsSatisfied(); - // сохранение и отправка - if (currentConditionsState) - { - if (currentConditionsState != lastConditiondsState) - { - var curTime = Time.time; - if (curTime - lastNotificationTime > notificationDelay) - { - lastNotificationTime = curTime; - NotificationManager.instance.CreateNotification( - "Собрано достаточно точек - можно продолжать сканирование или отправить их на сервер"); - } - } - - foreach (var button in Buttons) - { - button.interactable = true; - } - } - else - { - foreach (var button in Buttons) - { - button.interactable = false; - } - } - - lastConditiondsState = currentConditionsState; - - UpdateUI(); - } - - private bool CheckFinishConditionsSatisfied() - { - return CanFinish && CheckBoundingBox() && points.Count >= minPointsCount; - } - - private float CalculateCurrentBoundingBoxVolume() - { -// print($"{minPoint}, {maxPoint}"); - var diag = maxPoint - minPoint; - return Mathf.Abs(diag.x * diag.y * diag.z); - } - - private bool CheckBoundingBox() - { - return CalculateCurrentBoundingBoxVolume() >= minBoundingBoxVolume; - } - - private IEnumerator WeldRoutine(float maxRadius = 0.01125f, float uniformPart = 0.4f, int maxSamples = 400, int maxSamplesPerFrame = 150) - { - var extendedMaxSamplesPerFrame = maxSamplesPerFrame * 2; - var counter = 0; - List<int> nearestPointsInd = new List<int>(); - List<int> results = new List<int>(); - List<int> samples = new List<int>(); - var weldMask = new List<bool>(points.Count); - while (true) - { - if (!gameObject.activeInHierarchy || - points.Count == 0 || - uniformPart <= 0f) - yield return null; - - _kdTree.Build(points, 32); - nearestPointsInd.Clear(); - _query.Radius(_kdTree, currentCamTransform.position, maxDistance + 0.1f, nearestPointsInd); - - samples.Clear(); - - var numSamples = (int) (nearestPointsInd.Count * uniformPart) + 1; - numSamples = Math.Min(numSamples, maxSamples); - var probNum = numSamples; - - for (var i = 0; i < nearestPointsInd.Count; i++) - { - var probability = probNum * 1.0f / nearestPointsInd.Count; - if (Random.Range(0f, 1f) < probability) - { - probNum -= 1; - samples.Add(nearestPointsInd[i]); - } - - if (samples.Count > numSamples * 1.2f) - break; - } - yield return null; - - weldMask.Clear(); - for (int i = 0; i < points.Count; i++) - { - counter++; - weldMask.Add(false); - if (counter > extendedMaxSamplesPerFrame) - { - yield return null; - counter = 0; - } - } - - - results.Clear(); - foreach (var sampleInd in samples) - { - counter++; - var point = points[sampleInd]; - _query.Radius(_kdTree, point, maxRadius*0.9f, results); - // yield return null; - if (results.Count > 1) // 1 is point itself; 2 is neighbour - weldMask[sampleInd] = true; - results.Clear(); - if (counter > maxSamplesPerFrame) - { - yield return null; - counter = 0; - } - } - - - for (int i = weldMask.Count - 1; i > -1; i--) - { - counter++; - // print($"i:{i}, mask_len:{weldMask.Count}"); - if (weldMask[i]) - { - points.RemoveAt(i); - } - if (counter > maxSamplesPerFrame) - { - yield return null; - counter = 0; - } - } - results.Clear(); - _kdTree.Build(points); - _query.Radius(_kdTree, currentCamTransform.position, RenderDistance, results); - - pointCloud.Clear(); - foreach (var pointInd in results) - { - if (Random.Range(0.0f, 1.0f) < 0.75) - { - continue; - } - counter++; - emitParamsWelded.position = points[pointInd]; - pointCloud.Emit(emitParamsWelded, 1); - if (counter > extendedMaxSamplesPerFrame) - { - yield return null; - counter = 0; - } - } - results.Clear(); - yield return null; - } - } - - private void WeldPoints(float maxRadius = 0.015f, float uniformPart = 0.45f, int maxSamples = 1200) - { - if (points.Count == 0 || - uniformPart <= 0f) - { - return; - } - - var oldCount = points.Count; - _kdTree.Build(points); - - - List<int> nearestPointsInd = new List<int>(); - _query.Radius(_kdTree, currentCamTransform.position, maxDistance + 0.1f, nearestPointsInd); - - - List<int> results = new List<int>(); - List<int> samples = new List<int>(); - var numSamples = (int) (nearestPointsInd.Count * uniformPart) + 1; - numSamples = Math.Min(numSamples, maxSamples); - var probNum = numSamples; - for (var i = 0; i < nearestPointsInd.Count; i++) - { - var probability = probNum * 1.0f / nearestPointsInd.Count; - if (Random.Range(0f, 1f) < probability) - { - probNum -= 1; - samples.Add(nearestPointsInd[i]); - } - - if (samples.Count > numSamples * 1.2f) - break; - } - - print(samples.Count); - - var weldMask = new List<bool>(points.Count); - for (int i = 0; i < points.Count; i++) - weldMask.Add(false); - - foreach (var sampleInd in samples) - { - var point = points[sampleInd]; - _query.Radius(_kdTree, point, maxRadius*0.9f, results); - if (results.Count > 1) // 1 is point itself; 2 is neighbour - weldMask[sampleInd] = true; - results.Clear(); - } - - - pointCloud.Clear(); - for (int i = points.Count - 1; i > -1; i--) - { - if (weldMask[i]) - { - points.RemoveAt(i); - } - } - results.Clear(); - _kdTree.Build(points); - _query.Radius(_kdTree, currentCamTransform.position, maxDistance, results); - foreach (var pointInd in results) - { - emitParamsWelded.position = points[pointInd]; - pointCloud.Emit(emitParamsWelded, 1); - } - - // NotificationManager.instance.CreateNotification($"Удалено {points.Count - oldCount} похожих точек\n" + - // $"Отображено {results.Count}/{points.Count}", 2f); - } - - - private void UpdateUI() - { - var pointsRatio = Mathf.Clamp01(1f * points.Count / minPointsCount); - var bbVol = CalculateCurrentBoundingBoxVolume(); - var volumeRatio = Mathf.Clamp01(bbVol / minBoundingBoxVolume); - - var ratio = (pointsRatio + volumeRatio) / 2f; - - progressBar.localScale = new Vector3(ratio, 1f, 1f); - progressText.text = - $"{points.Count}/{minPointsCount} points | {Math.Round(bbVol, 1)}/{minBoundingBoxVolume} m3"; - } +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using DataStructures.ViliWonka.KDTree; +using GoogleARCore; +using UnityEngine; +using UnityEngine.UI; +using Random = UnityEngine.Random; + +public class MyPointCloudVisualizer : MonoBehaviour +{ + public ParticleSystem pointCloud; + [Space(10)] public float maxSqrDistance = 25f; + private float maxDistance; + + public float minConfidence = 0.625f; + // public float minConfidence = 0.55f; + // public float softConfidence = 0.65f; + + private Transform currentCamTransform; + + private ParticleSystem.EmitParams emitParams; + + private KDTree globalPoints = new KDTree(); + private KDTree localPoints = new KDTree(); + private KDQuery interQuery = new KDQuery(); + + private List<Vector3> pointsToAdd; + + //private List<Vector3> points; + + public List<Vector3> Points => new List<Vector3>(globalPoints.Points); + + private int minPointsCount = 4600; + private float minBoundingBoxVolume = 90f; + + private Vector3 minPoint; + private Vector3 maxPoint; + private Vector3 oldPos; + + public bool continueCollectingPoints = false; + + + [Space(10)] public RectTransform progressBar; + public Text progressText; + + [Space(10)] public Color defaultColor = new Color32(249, 255, 69, 255); + + [Space(10)] public List<Button> Buttons; + + private bool lastConditiondsState = false; + private float notificationDelay = 4; + private float lastNotificationTime = 0f; + public bool CanFinish = true; + public float RenderDistance = 5f; + public float MaxRenderDistance = 6f; + public Slider RenderSlider; + public float weldDistance = 0.015f; + + // Start is called before the first frame update + void Start() + { + pointsToAdd = new List<Vector3>(); + emitParams = new ParticleSystem.EmitParams(); + emitParams.startColor = defaultColor; + + minPoint = Vector3.positiveInfinity; + maxPoint = Vector3.negativeInfinity; + + maxDistance = Mathf.Sqrt(maxSqrDistance); + + foreach (var button in Buttons) + { + button.interactable = false; + } + + lastNotificationTime = Time.time; + currentCamTransform = Camera.main.transform; + + RenderSlider.minValue = 0.5f; + RenderSlider.maxValue = MaxRenderDistance; + RenderSlider.value = RenderDistance; + oldPos = currentCamTransform.position; + + StartCoroutine(DelayedStart()); + } + + public void UpdateRenderDistance(float newVal) + { + RenderDistance = newVal; + } + + private IEnumerator DelayedStart(float delay = 0.05f) + { + continueCollectingPoints = false; + yield return new WaitForSeconds(delay); + continueCollectingPoints = true; + } + + void Rerender() + { + pointCloud.Clear(); + + foreach (var point in localPoints.Points) + { + emitParams.position = point; + pointCloud.Emit(emitParams, 1); + } + oldPos = currentCamTransform.position; + } + + void RotatePoints() + { + var newPoints = new List<Vector3>(globalPoints.Points); + newPoints.AddRange(pointsToAdd); + + globalPoints.Build(newPoints); + CreateLocalKD(); + foreach (var point in pointsToAdd) + { + if (!(Random.Range(0f, 1f) < 0.4f)) continue; + if (point.x < minPoint.x) + minPoint.x = point.x; + if (point.y < minPoint.y) + minPoint.y = point.y; + if (point.z < minPoint.z) + minPoint.z = point.z; + + if (point.x > maxPoint.x) + maxPoint.x = point.x; + if (point.y > maxPoint.y) + maxPoint.y = point.y; + if (point.z > maxPoint.z) + maxPoint.z = point.z; + } + + pointsToAdd.Clear(); + } + + void CreateLocalKD() + { + if (globalPoints.Count == 0) + { + localPoints.Build(new List<Vector3>()); + return; + } + List<int> nearestPointsInd = new List<int>(); + interQuery.Radius(globalPoints, currentCamTransform.position, maxDistance + 0.1f, nearestPointsInd); + var localPointsList = new List<Vector3>(); + foreach (var pInd in nearestPointsInd) + { + localPointsList.Add(globalPoints.Points[pInd]); + } + + localPoints.Build(localPointsList); + } + + // Update is called once per frame + void Update() + { + if (!continueCollectingPoints) + return; + + + if (Frame.PointCloud.IsUpdatedThisFrame) + { + if (pointsToAdd.Count > 400) + { + RotatePoints(); + } + else if (Random.Range(0f, 1f) < 0.0115f || (oldPos - currentCamTransform.position).sqrMagnitude > 1) + { + CreateLocalKD(); + Rerender(); + } + + List<int> queryResults = new List<int>(); + for (int i = 0; i < Frame.PointCloud.PointCount; i++) + { + queryResults.Clear(); + + var point = Frame.PointCloud.GetPointAsStruct(i); + if (point.Confidence < minConfidence) continue; + // if (point.Confidence < softConfidence && Random.Range(0f, 1f) < 0.25f) continue; + + var distance = (currentCamTransform.position - point.Position).sqrMagnitude; + if (distance > maxSqrDistance) continue; + + // compare against localkd + if (localPoints.Count > 0) + { + interQuery.Radius(localPoints, point.Position, weldDistance, queryResults); + if (queryResults.Count > 0) + { + continue; + } + } + + //add to pointsToAdd + + + if (Random.Range(0f, 1f) < 0.35f) + { + emitParams.position = point; + pointCloud.Emit(emitParams, 1); + } + + pointsToAdd.Add(point.Position); + } + } + + var currentConditionsState = CheckFinishConditionsSatisfied(); + // сохранение и отправка + if (currentConditionsState) + { + if (currentConditionsState != lastConditiondsState) + { + var curTime = Time.time; + if (curTime - lastNotificationTime > notificationDelay) + { + lastNotificationTime = curTime; + NotificationManager.instance.CreateNotification( + "Собрано достаточно точек - можно продолжать сканирование или отправить их на сервер"); + } + } + + foreach (var button in Buttons) + { + button.interactable = true; + } + } + else + { + foreach (var button in Buttons) + { + button.interactable = false; + } + } + + lastConditiondsState = currentConditionsState; + + UpdateUI(); + } + + private bool CheckFinishConditionsSatisfied() + { + return CanFinish && CheckBoundingBox() && globalPoints.Count >= minPointsCount; + } + + private float CalculateCurrentBoundingBoxVolume() + { +// print($"{minPoint}, {maxPoint}"); + var diag = maxPoint - minPoint; + return Mathf.Abs(diag.x * diag.y * diag.z); + } + + private bool CheckBoundingBox() + { + return CalculateCurrentBoundingBoxVolume() >= minBoundingBoxVolume; + } + + // private IEnumerator WeldRoutine(float maxRadius = 0.01125f, float uniformPart = 0.4f, int maxSamples = 400, int maxSamplesPerFrame = 150) + // { + // var extendedMaxSamplesPerFrame = maxSamplesPerFrame * 2; + // var counter = 0; + // List<int> nearestPointsInd = new List<int>(); + // List<int> results = new List<int>(); + // List<int> samples = new List<int>(); + // var weldMask = new List<bool>(points.Count); + // while (true) + // { + // if (!gameObject.activeInHierarchy || + // points.Count == 0 || + // uniformPart <= 0f) + // yield return null; + // + // _kdTree.Build(points, 32); + // nearestPointsInd.Clear(); + // _query.Radius(_kdTree, currentCamTransform.position, maxDistance + 0.1f, nearestPointsInd); + // + // samples.Clear(); + // + // var numSamples = (int) (nearestPointsInd.Count * uniformPart) + 1; + // numSamples = Math.Min(numSamples, maxSamples); + // var probNum = numSamples; + // + // for (var i = 0; i < nearestPointsInd.Count; i++) + // { + // var probability = probNum * 1.0f / nearestPointsInd.Count; + // if (Random.Range(0f, 1f) < probability) + // { + // probNum -= 1; + // samples.Add(nearestPointsInd[i]); + // } + // + // if (samples.Count > numSamples * 1.2f) + // break; + // } + // yield return null; + // + // weldMask.Clear(); + // for (int i = 0; i < points.Count; i++) + // { + // counter++; + // weldMask.Add(false); + // if (counter > extendedMaxSamplesPerFrame) + // { + // yield return null; + // counter = 0; + // } + // } + // + // + // results.Clear(); + // foreach (var sampleInd in samples) + // { + // counter++; + // var point = points[sampleInd]; + // _query.Radius(_kdTree, point, maxRadius*0.9f, results); + // // yield return null; + // if (results.Count > 1) // 1 is point itself; 2 is neighbour + // weldMask[sampleInd] = true; + // results.Clear(); + // if (counter > maxSamplesPerFrame) + // { + // yield return null; + // counter = 0; + // } + // } + // + // + // for (int i = weldMask.Count - 1; i > -1; i--) + // { + // counter++; + // // print($"i:{i}, mask_len:{weldMask.Count}"); + // if (weldMask[i]) + // { + // points.RemoveAt(i); + // } + // if (counter > maxSamplesPerFrame) + // { + // yield return null; + // counter = 0; + // } + // } + // results.Clear(); + // _kdTree.Build(points); + // _query.Radius(_kdTree, currentCamTransform.position, RenderDistance, results); + // + // pointCloud.Clear(); + // foreach (var pointInd in results) + // { + // if (Random.Range(0.0f, 1.0f) < 0.75) + // { + // continue; + // } + // counter++; + // emitParamsWelded.position = points[pointInd]; + // pointCloud.Emit(emitParamsWelded, 1); + // if (counter > extendedMaxSamplesPerFrame) + // { + // yield return null; + // counter = 0; + // } + // } + // results.Clear(); + // yield return null; + // } + // } + // + // private void WeldPoints(float maxRadius = 0.015f, float uniformPart = 0.45f, int maxSamples = 1200) + // { + // if (points.Count == 0 || + // uniformPart <= 0f) + // { + // return; + // } + // + // var oldCount = points.Count; + // _kdTree.Build(points); + // + // + // List<int> nearestPointsInd = new List<int>(); + // _query.Radius(_kdTree, currentCamTransform.position, maxDistance + 0.1f, nearestPointsInd); + // + // + // List<int> results = new List<int>(); + // List<int> samples = new List<int>(); + // var numSamples = (int) (nearestPointsInd.Count * uniformPart) + 1; + // numSamples = Math.Min(numSamples, maxSamples); + // var probNum = numSamples; + // for (var i = 0; i < nearestPointsInd.Count; i++) + // { + // var probability = probNum * 1.0f / nearestPointsInd.Count; + // if (Random.Range(0f, 1f) < probability) + // { + // probNum -= 1; + // samples.Add(nearestPointsInd[i]); + // } + // + // if (samples.Count > numSamples * 1.2f) + // break; + // } + // + // print(samples.Count); + // + // var weldMask = new List<bool>(points.Count); + // for (int i = 0; i < points.Count; i++) + // weldMask.Add(false); + // + // foreach (var sampleInd in samples) + // { + // var point = points[sampleInd]; + // _query.Radius(_kdTree, point, maxRadius*0.9f, results); + // if (results.Count > 1) // 1 is point itself; 2 is neighbour + // weldMask[sampleInd] = true; + // results.Clear(); + // } + // + // + // pointCloud.Clear(); + // for (int i = points.Count - 1; i > -1; i--) + // { + // if (weldMask[i]) + // { + // points.RemoveAt(i); + // } + // } + // results.Clear(); + // _kdTree.Build(points); + // _query.Radius(_kdTree, currentCamTransform.position, maxDistance, results); + // foreach (var pointInd in results) + // { + // emitParamsWelded.position = points[pointInd]; + // pointCloud.Emit(emitParamsWelded, 1); + // } + // + // // NotificationManager.instance.CreateNotification($"Удалено {points.Count - oldCount} похожих точек\n" + + // // $"Отображено {results.Count}/{points.Count}", 2f); + // } + // + + private void UpdateUI() + { + var pointsRatio = Mathf.Clamp01(1f * globalPoints.Count / minPointsCount); + var bbVol = CalculateCurrentBoundingBoxVolume(); + var volumeRatio = Mathf.Clamp01(bbVol / minBoundingBoxVolume); + + var ratio = (pointsRatio + volumeRatio) / 2f; + + progressBar.localScale = new Vector3(ratio, 1f, 1f); + progressText.text = + $"{globalPoints.Count}/{minPointsCount} points | {Math.Round(bbVol, 1)}/{minBoundingBoxVolume} m3"; + } } \ No newline at end of file diff --git a/Assets/Resources/Scripts/PointCloudSender.cs b/Assets/Resources/Scripts/PointCloudSender.cs index 6b4c3835165e13bd6c2c7ce32116aeb9c92f818c..c3434e620525e86040b58acf02476316306ef5e5 100644 --- a/Assets/Resources/Scripts/PointCloudSender.cs +++ b/Assets/Resources/Scripts/PointCloudSender.cs @@ -1,200 +1,200 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using UnityEngine; -using UnityEngine.Networking; -using UnityEngine.UI; - -public class PointCloudSender : MonoBehaviour -{ - public InputField host; - public GameObject RemoteMarker; - - private PointCloudSaver _pointCloudSaver; - private MyPointCloudVisualizer _pointCloudVisualizer; - - void Start() - { - _pointCloudSaver = GetComponent<PointCloudSaver>(); - _pointCloudVisualizer = GetComponent<MyPointCloudVisualizer>(); - NotificationManager.instance.CreateNotification("Система работает", 5f); - } - - private string GetUrl(string sendType) - { - var hostAddr = host.text; - var url = hostAddr + "/" + sendType; - return url; - } - - private string SaveCurrentPointCloud() - { - var points = _pointCloudVisualizer.Points; - var filename = _pointCloudSaver.SavePointCloud(points); - NotificationManager.instance.CreateNotification("Облако точек сохранено"); - return filename; - } - - public void SendAsMap() - { - var filename = SaveCurrentPointCloud(); - SendAsMap(filename); - } - - public void SendAsMap(string filename) - { - StartCoroutine(SendAsMapRoutine(filename)); - } - - private IEnumerator Note() - { - yield return new WaitForSeconds(15f); - NotificationManager.instance.CreateNotification( - "Обработка может занять длительное время, пожалуйста, подождите"); - while (true) - { - yield return new WaitForSeconds(15f); - NotificationManager.instance.CreateNotification( - "Сервер всё еще обрабатывает ваш запрос, пожалуйста, подождите"); - } - } - - private IEnumerator SendAsMapRoutine(string filename) - { - var url = GetUrl("addmap"); - List<IMultipartFormSection> formData = new List<IMultipartFormSection>(); - - - var bytePointCloud = File.ReadAllBytes(filename); - formData.Add(new MultipartFormFileSection( - "pointCloud", bytePointCloud, "MapPointCloud.xyz", "text/plain")); - - List<Vector3> armarkers = new List<Vector3>(); - foreach (var markerTransform in ARMarker.instances) - { - var pos = markerTransform.position; - armarkers.Add(pos); - } - - if (armarkers.Count > 0) - { - var markersFile = _pointCloudSaver.SavePointCloud(armarkers, "ar_markers.txt"); - var byteMarkers = File.ReadAllBytes(markersFile); - formData.Add(new MultipartFormFileSection( - "markers", byteMarkers, "Markers.xyz", "text/plain")); - } - - - UnityWebRequest www = UnityWebRequest.Post(url, formData); - var routine = StartCoroutine(Note()); - foreach (var button in _pointCloudVisualizer.Buttons) - { - button.interactable = false; - } - _pointCloudVisualizer.CanFinish = false; - - NotificationManager.instance.CreateNotification("Сервер начал думать над вашим запросом"); - yield return www.SendWebRequest(); - StopCoroutine(routine); - foreach (var button in _pointCloudVisualizer.Buttons) - { - button.interactable = true; - } - _pointCloudVisualizer.CanFinish = true; - - if (www.isNetworkError) - { - NotificationManager.instance.CreateNotification("Сервер недоступен, проверьте соединение"); - } - else if (www.isHttpError) - { - Debug.Log(www.error); - NotificationManager.instance.CreateNotification("Ошибка сервера, не удалось создать карту"); - } - else - { - NotificationManager.instance.CreateNotification("Карта создана успешно"); - } - } - - public void SendAsAlign() - { - var filename = SaveCurrentPointCloud(); - SendAsAlign(filename); - } - - public void SendAsAlign(string filename) - { - StartCoroutine(SendAsAlignRoutine(filename)); - } - - private IEnumerator SendAsAlignRoutine(string filename) - { - var url = GetUrl("align"); - List<IMultipartFormSection> formData = new List<IMultipartFormSection>(); - formData.Add(new MultipartFormDataSection("targetMap=1")); - - var bytePointCloud = File.ReadAllBytes(filename); - formData.Add(new MultipartFormFileSection( - "pointCloud", bytePointCloud, "MapPointCloud.xyz", "text/plain")); - - UnityWebRequest www = UnityWebRequest.Post(url, formData); - var routine = StartCoroutine(Note()); - foreach (var button in _pointCloudVisualizer.Buttons) - { - button.interactable = false; - } - _pointCloudVisualizer.CanFinish = false; - - NotificationManager.instance.CreateNotification("Сервер начал думать над вашим запросом"); - yield return www.SendWebRequest(); - StopCoroutine(routine); - foreach (var button in _pointCloudVisualizer.Buttons) - { - button.interactable = true; - } - _pointCloudVisualizer.CanFinish = true; - - if (www.isNetworkError) - { - NotificationManager.instance.CreateNotification("Сервер недоступен, проверьте соединение"); - yield break; - } - - if (www.isHttpError) - { - Debug.Log(www.error); - NotificationManager.instance.CreateNotification("Ошибка сервера, не удалось локализоваться"); - yield break; - } - - //x y z\nx y z... - var resp = www.downloadHandler.text.Split('\n'); - foreach (var strVec in resp) - { - var splitted = strVec.Split(' '); - var pos = new Vector3( - float.Parse(splitted[0], CultureInfo.InvariantCulture), - float.Parse(splitted[1], CultureInfo.InvariantCulture), - float.Parse(splitted[2], CultureInfo.InvariantCulture)); - Instantiate(RemoteMarker, pos, Quaternion.identity); - } - - NotificationManager.instance.CreateNotification("Локализация прошла успешно"); - - // var translationFl = new float[3]; - // for (var i = 0; i < translationStr.Count; i++) - // { - // var coord = float.Parse(translationStr); - // translationFl[i] = coord; - // } - // - // var rotationFl = new float[4]; - // foreach (var coordStr in translationStr) - // { - // rotationFl[i] = float.Parse(coordStr); - // } - } +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using UnityEngine; +using UnityEngine.Networking; +using UnityEngine.UI; + +public class PointCloudSender : MonoBehaviour +{ + public InputField host; + public GameObject RemoteMarker; + + private PointCloudSaver _pointCloudSaver; + private MyPointCloudVisualizer _pointCloudVisualizer; + + void Start() + { + _pointCloudSaver = GetComponent<PointCloudSaver>(); + _pointCloudVisualizer = GetComponent<MyPointCloudVisualizer>(); + NotificationManager.instance.CreateNotification("Система работает", 5f); + } + + private string GetUrl(string sendType) + { + var hostAddr = host.text; + var url = hostAddr + "/" + sendType; + return url; + } + + private string SaveCurrentPointCloud() + { + var points = _pointCloudVisualizer.Points; + var filename = _pointCloudSaver.SavePointCloud(points); + NotificationManager.instance.CreateNotification("Облако точек сохранено"); + return filename; + } + + public void SendAsMap() + { + var filename = SaveCurrentPointCloud(); + SendAsMap(filename); + } + + public void SendAsMap(string filename) + { + StartCoroutine(SendAsMapRoutine(filename)); + } + + private IEnumerator Note() + { + yield return new WaitForSeconds(15f); + NotificationManager.instance.CreateNotification( + "Обработка может занять длительное время, пожалуйста, подождите"); + while (true) + { + yield return new WaitForSeconds(15f); + NotificationManager.instance.CreateNotification( + "Сервер всё еще обрабатывает ваш запрос, пожалуйста, подождите"); + } + } + + private IEnumerator SendAsMapRoutine(string filename) + { + var url = GetUrl("addmap"); + List<IMultipartFormSection> formData = new List<IMultipartFormSection>(); + + + var bytePointCloud = File.ReadAllBytes(filename); + formData.Add(new MultipartFormFileSection( + "pointCloud", bytePointCloud, "MapPointCloud.xyz", "text/plain")); + + List<Vector3> armarkers = new List<Vector3>(); + foreach (var markerTransform in ARMarker.instances) + { + var pos = markerTransform.position; + armarkers.Add(pos); + } + + if (armarkers.Count > 0) + { + var markersFile = _pointCloudSaver.SavePointCloud(armarkers, "ar_markers.txt"); + var byteMarkers = File.ReadAllBytes(markersFile); + formData.Add(new MultipartFormFileSection( + "markers", byteMarkers, "Markers.xyz", "text/plain")); + } + + + UnityWebRequest www = UnityWebRequest.Post(url, formData); + var routine = StartCoroutine(Note()); + foreach (var button in _pointCloudVisualizer.Buttons) + { + button.interactable = false; + } + _pointCloudVisualizer.CanFinish = false; + + NotificationManager.instance.CreateNotification("Сервер начал думать над вашим запросом"); + yield return www.SendWebRequest(); + StopCoroutine(routine); + foreach (var button in _pointCloudVisualizer.Buttons) + { + button.interactable = true; + } + _pointCloudVisualizer.CanFinish = true; + + if (www.isNetworkError) + { + NotificationManager.instance.CreateNotification("Сервер недоступен, проверьте соединение"); + } + else if (www.isHttpError) + { + Debug.Log(www.error); + NotificationManager.instance.CreateNotification("Ошибка сервера, не удалось создать карту"); + } + else + { + NotificationManager.instance.CreateNotification("Карта создана успешно"); + } + } + + public void SendAsAlign() + { + var filename = SaveCurrentPointCloud(); + SendAsAlign(filename); + } + + public void SendAsAlign(string filename) + { + StartCoroutine(SendAsAlignRoutine(filename)); + } + + private IEnumerator SendAsAlignRoutine(string filename) + { + var url = GetUrl("align"); + List<IMultipartFormSection> formData = new List<IMultipartFormSection>(); + formData.Add(new MultipartFormDataSection("targetMap=1")); + + var bytePointCloud = File.ReadAllBytes(filename); + formData.Add(new MultipartFormFileSection( + "pointCloud", bytePointCloud, "MapPointCloud.xyz", "text/plain")); + + UnityWebRequest www = UnityWebRequest.Post(url, formData); + var routine = StartCoroutine(Note()); + foreach (var button in _pointCloudVisualizer.Buttons) + { + button.interactable = false; + } + _pointCloudVisualizer.CanFinish = false; + + NotificationManager.instance.CreateNotification("Сервер начал думать над вашим запросом"); + yield return www.SendWebRequest(); + StopCoroutine(routine); + foreach (var button in _pointCloudVisualizer.Buttons) + { + button.interactable = true; + } + _pointCloudVisualizer.CanFinish = true; + + if (www.isNetworkError) + { + NotificationManager.instance.CreateNotification("Сервер недоступен, проверьте соединение"); + yield break; + } + + if (www.isHttpError) + { + Debug.Log(www.error); + NotificationManager.instance.CreateNotification("Ошибка сервера, не удалось локализоваться"); + yield break; + } + + //x y z\nx y z... + var resp = www.downloadHandler.text.Split('\n'); + foreach (var strVec in resp) + { + var splitted = strVec.Split(' '); + var pos = new Vector3( + float.Parse(splitted[0], CultureInfo.InvariantCulture), + float.Parse(splitted[1], CultureInfo.InvariantCulture), + float.Parse(splitted[2], CultureInfo.InvariantCulture)); + Instantiate(RemoteMarker, pos, Quaternion.identity); + } + + NotificationManager.instance.CreateNotification("Локализация прошла успешно"); + + // var translationFl = new float[3]; + // for (var i = 0; i < translationStr.Count; i++) + // { + // var coord = float.Parse(translationStr); + // translationFl[i] = coord; + // } + // + // var rotationFl = new float[4]; + // foreach (var coordStr in translationStr) + // { + // rotationFl[i] = float.Parse(coordStr); + // } + } } \ No newline at end of file