Newer
Older
HoloAnatomy / Assets / HoloToolkit / SpatialUnderstanding / Scripts / SpatialUnderstanding.cs
SURFACEBOOK2\jackwynne on 25 May 2018 9 KB v1
  1. // Copyright (c) Microsoft Corporation. All rights reserved.
  2. // Licensed under the MIT License. See LICENSE in the project root for license information.
  3.  
  4. using System;
  5. using UnityEngine;
  6. using HoloToolkit.Unity.SpatialMapping;
  7.  
  8. namespace HoloToolkit.Unity
  9. {
  10. /// <summary>
  11. /// The SpatialUnderstanding class controls the state and flow of the
  12. /// scanning process used in the understanding module.
  13. /// </summary>
  14. [RequireComponent(typeof(SpatialUnderstandingSourceMesh))]
  15. [RequireComponent(typeof(SpatialUnderstandingCustomMesh))]
  16. public class SpatialUnderstanding : Singleton<SpatialUnderstanding>
  17. {
  18. // Consts
  19. public const float ScanSearchDistance = 8.0f;
  20.  
  21. // Enums
  22. public enum ScanStates
  23. {
  24. None,
  25. ReadyToScan,
  26. Scanning,
  27. Finishing,
  28. Done
  29. }
  30.  
  31. // Config
  32. [Tooltip("If set to false, scanning will only begin after RequestBeginScanning is called")]
  33. public bool AutoBeginScanning = true;
  34. [Tooltip("Update period used during the scanning process (typically faster than after scanning is completed)")]
  35. public float UpdatePeriod_DuringScanning = 1.0f;
  36. [Tooltip("Update period used after the scanning process is completed")]
  37. public float UpdatePeriod_AfterScanning = 4.0f;
  38.  
  39. // Properties
  40. /// <summary>
  41. /// Switch used by the entire SpatialUnderstanding module to activate processing.
  42. /// </summary>
  43. public bool AllowSpatialUnderstanding
  44. {
  45. get
  46. {
  47. return true;
  48. }
  49. }
  50.  
  51. /// <summary>
  52. /// Reference to the SpatialUnderstandingDLL class (wraps the understanding DLL functions).
  53. /// </summary>
  54. public SpatialUnderstandingDll UnderstandingDLL { get; private set; }
  55. /// <summary>
  56. /// Reference to the SpatialUnderstandingSourceMesh behavior (input mesh data for the understanding module).
  57. /// </summary>
  58. public SpatialUnderstandingSourceMesh UnderstandingSourceMesh { get; private set; }
  59. /// <summary>
  60. /// Reference to the UnderstandingCustomMesh behavior (output mesh data from the understanding module).
  61. /// </summary>
  62. public SpatialUnderstandingCustomMesh UnderstandingCustomMesh { get; private set; }
  63. /// <summary>
  64. /// Indicates the current state of the scan process
  65. /// </summary>
  66. public ScanStates ScanState
  67. {
  68. get
  69. {
  70. return scanState;
  71. }
  72. private set
  73. {
  74. scanState = value;
  75. if (ScanStateChanged != null)
  76. {
  77. ScanStateChanged();
  78. }
  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 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.  
  101. public delegate void OnScanDoneDelegate();
  102.  
  103. // Events
  104. /// <summary>
  105. /// Event indicating that the scan is done
  106. /// </summary>
  107. public event OnScanDoneDelegate OnScanDone;
  108.  
  109. /// <summary>
  110. /// Event indicating that the scan state has changed
  111. /// </summary>
  112. public event Action ScanStateChanged;
  113.  
  114. // Privates
  115. private ScanStates scanState;
  116.  
  117. private float timeSinceLastUpdate = 0.0f;
  118.  
  119. // Functions
  120. protected override void Awake()
  121. {
  122. base.Awake();
  123.  
  124. // Cache references to required component
  125. UnderstandingDLL = new SpatialUnderstandingDll();
  126. UnderstandingSourceMesh = GetComponent<SpatialUnderstandingSourceMesh>();
  127. UnderstandingCustomMesh = GetComponent<SpatialUnderstandingCustomMesh>();
  128. }
  129.  
  130. private void Start()
  131. {
  132. // Initialize the DLL
  133. if (AllowSpatialUnderstanding)
  134. {
  135. SpatialUnderstandingDll.Imports.SpatialUnderstanding_Init();
  136. }
  137. }
  138.  
  139. private void Update()
  140. {
  141. if (!AllowSpatialUnderstanding)
  142. {
  143. return;
  144. }
  145.  
  146. // Only update every few frames, and only if we aren't pulling in a mesh
  147. // already.
  148. timeSinceLastUpdate += Time.deltaTime;
  149. if ((!UnderstandingCustomMesh.IsImportActive) &&
  150. (Time.frameCount % 3 == 0))
  151. {
  152. // Real-Time scan
  153. Update_Scan(timeSinceLastUpdate);
  154. timeSinceLastUpdate = 0;
  155. }
  156. }
  157.  
  158. protected override void OnDestroy()
  159. {
  160. // Term the DLL
  161. if (AllowSpatialUnderstanding)
  162. {
  163. SpatialUnderstandingDll.Imports.SpatialUnderstanding_Term();
  164. }
  165.  
  166. base.OnDestroy();
  167. }
  168.  
  169. /// <summary>
  170. /// Call to request that scanning should begin. If AutoBeginScanning
  171. /// is false, this function should be used to initiate the scanning process.
  172. /// </summary>
  173. public void RequestBeginScanning()
  174. {
  175. if (ScanState == ScanStates.None)
  176. {
  177. ScanState = ScanStates.ReadyToScan;
  178. }
  179. }
  180.  
  181. /// <summary>
  182. /// Call to request that the scanning progress be finishing. The application must do
  183. /// this to finalize the playspace. The scan state will not progress pass
  184. /// Scanning until this is called. The spatial understanding queries will not function
  185. /// until the playspace is finalized.
  186. /// </summary>
  187. public void RequestFinishScan()
  188. {
  189. if (AllowSpatialUnderstanding)
  190. {
  191. SpatialUnderstandingDll.Imports.GeneratePlayspace_RequestFinish();
  192. ScanState = ScanStates.Finishing;
  193. }
  194. }
  195.  
  196. /// <summary>
  197. /// Update the scan progress. This function will initialize the scan, update it,
  198. /// and issue a final mesh import, when the scan is complete.
  199. /// </summary>
  200. /// <param name="deltaTime">The amount of time that has passed since the last update (typically Time.deltaTime)</param>
  201. private void Update_Scan(float deltaTime)
  202. {
  203. // If we auto-start scanning, do it now
  204. if (AutoBeginScanning &&
  205. (ScanState == ScanStates.None))
  206. {
  207. RequestBeginScanning();
  208. }
  209.  
  210. // Update the scan
  211. bool scanDone = false;
  212. if (((ScanState == ScanStates.ReadyToScan) ||
  213. (ScanState == ScanStates.Scanning) ||
  214. (ScanState == ScanStates.Finishing)) &&
  215. (AllowSpatialUnderstanding))
  216. {
  217. // Camera
  218. Transform cameraTransform = CameraCache.Main.transform;
  219. Vector3 camPos = cameraTransform.position;
  220. Vector3 camFwd = cameraTransform.forward;
  221. Vector3 camUp = cameraTransform.up;
  222.  
  223. // If not yet initialized, do that now
  224. if (ScanState == ScanStates.ReadyToScan)
  225. {
  226. SpatialUnderstandingDll.Imports.GeneratePlayspace_InitScan(
  227. camPos.x, camPos.y, camPos.z,
  228. camFwd.x, camFwd.y, camFwd.z,
  229. camUp.x, camUp.y, camUp.z,
  230. ScanSearchDistance, ScanSearchDistance);
  231. ScanState = ScanStates.Scanning;
  232. }
  233.  
  234. // Update
  235. int meshCount;
  236. IntPtr meshList;
  237. if (UnderstandingSourceMesh.GetInputMeshList(out meshCount, out meshList))
  238. {
  239. var stopWatch = System.Diagnostics.Stopwatch.StartNew();
  240.  
  241. scanDone = SpatialUnderstandingDll.Imports.GeneratePlayspace_UpdateScan(
  242. meshCount, meshList,
  243. camPos.x, camPos.y, camPos.z,
  244. camFwd.x, camFwd.y, camFwd.z,
  245. camUp.x, camUp.y, camUp.z,
  246. deltaTime) == 1;
  247.  
  248. stopWatch.Stop();
  249.  
  250. if (stopWatch.Elapsed.TotalMilliseconds > (1000.0 / 30.0))
  251. {
  252. Debug.LogWarningFormat("SpatialUnderstandingDll.Imports.GeneratePlayspace_UpdateScan took {0,9:N2} ms", stopWatch.Elapsed.TotalMilliseconds);
  253. }
  254. }
  255. }
  256.  
  257. // If it's done, finish up
  258. if ((ScanState == ScanStates.Finishing) &&
  259. (scanDone) &&
  260. (!UnderstandingCustomMesh.IsImportActive) &&
  261. (UnderstandingCustomMesh != null))
  262. {
  263. // Final mesh import
  264. StartCoroutine(UnderstandingCustomMesh.Import_UnderstandingMesh());
  265.  
  266. // Mark it
  267. ScanState = ScanStates.Done;
  268. if (OnScanDone != null) OnScanDone.Invoke();
  269. }
  270. }
  271. }
  272. }