/Assets/HoloToolkit/SpatialUnderstanding/Scripts/SpatialUnderstanding.cs

https://gitlab.com/jarvis-uofu/HoloPhysics_prototype · C# · 256 lines · 169 code · 22 blank · 65 comment · 28 complexity · b8a88b7374c3d9b9177e8fae5808efd4 MD5 · raw file

  1. // Copyright (c) Microsoft Corporation. All rights reserved.
  2. // Licensed under the MIT License. See LICENSE in the project root for license information.
  3. using UnityEngine;
  4. using System.Collections;
  5. using HoloToolkit.Unity;
  6. using System.Collections.Generic;
  7. using System.Runtime.InteropServices;
  8. using System;
  9. namespace HoloToolkit.Unity
  10. {
  11. /// <summary>
  12. /// The SpatialUnderstanding class controls the state and flow of the
  13. /// scanning process used in the understanding module.
  14. /// </summary>
  15. [RequireComponent(typeof(SpatialUnderstandingSourceMesh))]
  16. [RequireComponent(typeof(SpatialUnderstandingCustomMesh))]
  17. public class SpatialUnderstanding : Singleton<SpatialUnderstanding>
  18. {
  19. // Consts
  20. public const float ScanSearchDistance = 8.0f;
  21. // Enums
  22. public enum ScanStates
  23. {
  24. None,
  25. ReadyToScan,
  26. Scanning,
  27. Finishing,
  28. Done
  29. }
  30. // Config
  31. [Tooltip("If set to false, scanning will only begin after RequestBeginScanning is called")]
  32. public bool AutoBeginScanning = true;
  33. [Tooltip("Update period used during the scanning process (typically faster than after scanning is completed)")]
  34. public float UpdatePeriod_DuringScanning = 1.0f;
  35. [Tooltip("Update period used after the scanning process is completed")]
  36. public float UpdatePeriod_AfterScanning = 4.0f;
  37. // Properties
  38. /// <summary>
  39. /// Switch used by the entire SpatialUnderstanding module to activate processing.
  40. /// </summary>
  41. public bool AllowSpatialUnderstanding
  42. {
  43. get
  44. {
  45. #if UNITY_METRO && !UNITY_EDITOR
  46. return true;
  47. #else
  48. return false;
  49. #endif
  50. }
  51. }
  52. /// <summary>
  53. /// Reference to the SpatialUnderstandingDLL class (wraps the understanding dll functions).
  54. /// </summary>
  55. public SpatialUnderstandingDll UnderstandingDLL { get; private set; }
  56. /// <summary>
  57. /// Reference to the SpatialUnderstandingSourceMesh behavior (input mesh data for the understanding module).
  58. /// </summary>
  59. public SpatialUnderstandingSourceMesh UnderstandingSourceMesh { get; private set; }
  60. /// <summary>
  61. /// Reference to the UnderstandingCustomMesh behavior (output mesh data from the understanding module).
  62. /// </summary>
  63. public SpatialUnderstandingCustomMesh UnderstandingCustomMesh { get; private set; }
  64. /// <summary>
  65. /// Indicates the current state of the scan process
  66. /// </summary>
  67. public ScanStates ScanState
  68. {
  69. get
  70. {
  71. return scanState;
  72. }
  73. private set
  74. {
  75. scanState = value;
  76. if (ScanStateChanged != null)
  77. {
  78. ScanStateChanged();
  79. }
  80. // Update scan period, based on state
  81. SpatialMappingManager.Instance.GetComponent<SpatialMappingObserver>().TimeBetweenUpdates = (scanState == ScanStates.Done) ? UpdatePeriod_AfterScanning : UpdatePeriod_DuringScanning;
  82. }
  83. }
  84. /// <summary>
  85. /// Indicates the the scanning statistics are still being processed.
  86. /// Request finish should not be called when this is true.
  87. /// </summary>
  88. public bool ScanStatsReportStillWorking
  89. {
  90. get
  91. {
  92. if (AllowSpatialUnderstanding)
  93. {
  94. SpatialUnderstandingDll.Imports.PlayspaceStats stats = UnderstandingDLL.GetStaticPlayspaceStats();
  95. return (stats.IsWorkingOnStats != 0);
  96. }
  97. return false;
  98. }
  99. }
  100. // Events
  101. /// <summary>
  102. /// Event indicating that the scan state has changed
  103. /// </summary>
  104. public event Action ScanStateChanged;
  105. // Privates
  106. private ScanStates scanState;
  107. private float timeSinceLastUpdate = 0.0f;
  108. // Functions
  109. private void Awake()
  110. {
  111. // Cache references to required component
  112. UnderstandingDLL = new SpatialUnderstandingDll();
  113. UnderstandingSourceMesh = GetComponent<SpatialUnderstandingSourceMesh>();
  114. UnderstandingCustomMesh = GetComponent<SpatialUnderstandingCustomMesh>();
  115. }
  116. private void Start()
  117. {
  118. // Initialize the DLL
  119. if (AllowSpatialUnderstanding)
  120. {
  121. SpatialUnderstandingDll.Imports.SpatialUnderstanding_Init();
  122. }
  123. }
  124. private void Update()
  125. {
  126. if (!AllowSpatialUnderstanding)
  127. {
  128. return;
  129. }
  130. // Only update every few frames, and only if we aren't pulling in a mesh
  131. // already.
  132. timeSinceLastUpdate += Time.deltaTime;
  133. if ((!UnderstandingCustomMesh.IsImportActive) &&
  134. (Time.frameCount % 3 == 0))
  135. {
  136. // Real-Time scan
  137. Update_Scan(timeSinceLastUpdate);
  138. timeSinceLastUpdate = 0;
  139. }
  140. }
  141. private void OnDestroy()
  142. {
  143. // Term the DLL
  144. if (AllowSpatialUnderstanding)
  145. {
  146. SpatialUnderstandingDll.Imports.SpatialUnderstanding_Term();
  147. }
  148. }
  149. /// <summary>
  150. /// Call to request that scanning should begin. If AutoBeginScanning
  151. /// is false, this function should be used to initiate the scanning process.
  152. /// </summary>
  153. public void RequestBeginScanning()
  154. {
  155. if (ScanState == ScanStates.None)
  156. {
  157. ScanState = ScanStates.ReadyToScan;
  158. }
  159. }
  160. /// <summary>
  161. /// Call to request that the scanning progress be finishing. The application must do
  162. /// this to finalize the playspace. The scan state will not progress pass
  163. /// Scanning until this is called. The spatial understanding queries will not function
  164. /// until the playspace is finalized.
  165. /// </summary>
  166. public void RequestFinishScan()
  167. {
  168. if (AllowSpatialUnderstanding)
  169. {
  170. SpatialUnderstandingDll.Imports.GeneratePlayspace_RequestFinish();
  171. ScanState = ScanStates.Finishing;
  172. }
  173. }
  174. /// <summary>
  175. /// Update the scan progress. This function will initialize the scan, update it,
  176. /// and issue a final mesh import, when the scan is complete.
  177. /// </summary>
  178. /// <param name="deltaTime">The amount of time that has passed since the last update (typically Time.deltaTime)</param>
  179. private void Update_Scan(float deltaTime)
  180. {
  181. // If we auto-start scanning, do it now
  182. if (AutoBeginScanning &&
  183. (ScanState == ScanStates.None))
  184. {
  185. RequestBeginScanning();
  186. }
  187. // Update the scan
  188. bool scanDone = false;
  189. if (((ScanState == ScanStates.ReadyToScan) ||
  190. (ScanState == ScanStates.Scanning) ||
  191. (ScanState == ScanStates.Finishing)) &&
  192. (AllowSpatialUnderstanding))
  193. {
  194. // Camera
  195. Vector3 camPos = Camera.main.transform.position;
  196. Vector3 camFwd = Camera.main.transform.forward;
  197. Vector3 camUp = Camera.main.transform.up;
  198. // If not yet initialized, do that now
  199. if (ScanState == ScanStates.ReadyToScan)
  200. {
  201. SpatialUnderstandingDll.Imports.GeneratePlayspace_InitScan(
  202. camPos.x, camPos.y, camPos.z,
  203. camFwd.x, camFwd.y, camFwd.z,
  204. camUp.x, camUp.y, camUp.z,
  205. ScanSearchDistance, ScanSearchDistance);
  206. ScanState = ScanStates.Scanning;
  207. }
  208. // Update
  209. int meshCount;
  210. IntPtr meshList;
  211. if (UnderstandingSourceMesh.GetInputMeshList(out meshCount, out meshList))
  212. {
  213. scanDone = SpatialUnderstandingDll.Imports.GeneratePlayspace_UpdateScan(
  214. meshCount, meshList,
  215. camPos.x, camPos.y, camPos.z,
  216. camFwd.x, camFwd.y, camFwd.z,
  217. camUp.x, camUp.y, camUp.z,
  218. deltaTime) == 1;
  219. }
  220. }
  221. // If it's done, finish up
  222. if ((ScanState == ScanStates.Finishing) &&
  223. (scanDone) &&
  224. (!UnderstandingCustomMesh.IsImportActive) &&
  225. (UnderstandingCustomMesh != null))
  226. {
  227. // Final mesh import
  228. StartCoroutine(UnderstandingCustomMesh.Import_UnderstandingMesh());
  229. // Mark it
  230. ScanState = ScanStates.Done;
  231. }
  232. }
  233. }
  234. }