AR Design
UBC EML collab with UBC SALA - visualizing IoT data in AR
SpatialUnderstandingDll.cs
Go to the documentation of this 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 
4 using System;
5 using System.Collections.Generic;
6 using System.Runtime.InteropServices;
7 using UnityEngine;
8 
9 namespace HoloToolkit.Unity
10 {
19  {
24  public struct MeshData
25  {
26  public int MeshID;
27  public int LastUpdateID;
28  public Matrix4x4 Transform;
29  public Vector3[] Verts;
30  public Vector3[] Normals;
31  public Int32[] Indices;
32 
33  public MeshData(MeshFilter meshFilter)
34  {
35  MeshID = 0;
36  LastUpdateID = 0;
37 
38  Transform = meshFilter.transform.localToWorldMatrix;
39  Verts = meshFilter.sharedMesh.vertices;
40  Normals = meshFilter.sharedMesh.normals;
41  Indices = meshFilter.sharedMesh.triangles;
42  }
43 
44  public void CopyFrom(MeshFilter meshFilter, int meshID = 0, int lastUpdateID = 0)
45  {
46  MeshID = meshID;
47  LastUpdateID = lastUpdateID;
48 
49  if (meshFilter != null)
50  {
51  Transform = meshFilter.transform.localToWorldMatrix;
52 
53  // Note that we are assuming that Unity's getters for vertices/normals/triangles make
54  // copies of the array. As of unity 5.4 this assumption is correct.
55  Verts = meshFilter.sharedMesh.vertices;
56  Normals = meshFilter.sharedMesh.normals;
57  Indices = meshFilter.sharedMesh.triangles;
58  }
59  }
60  }
61 
62  // Privates
63  private Imports.MeshData[] reusedMeshesForMarshalling = null;
64  private List<GCHandle> reusedPinnedMemoryHandles = new List<GCHandle>();
65 
66  private Imports.RaycastResult reusedRaycastResult = new Imports.RaycastResult();
67  private IntPtr reusedRaycastResultPtr;
68 
69  private Imports.PlayspaceStats reusedPlayspaceStats = new Imports.PlayspaceStats();
70  private IntPtr reusedPlayspaceStatsPtr;
71 
72  private Imports.PlayspaceAlignment reusedPlayspaceAlignment = new Imports.PlayspaceAlignment();
73  private IntPtr reusedPlayspaceAlignmentPtr;
74 
76  private IntPtr reusedObjectPlacementResultPtr;
77 
83  public IntPtr PinObject(System.Object obj)
84  {
85  GCHandle h = GCHandle.Alloc(obj, GCHandleType.Pinned);
86  reusedPinnedMemoryHandles.Add(h);
87  return h.AddrOfPinnedObject();
88  }
89 
94  public IntPtr PinString(string str)
95  {
96  byte[] obj = System.Text.Encoding.ASCII.GetBytes(str);
97  GCHandle h = GCHandle.Alloc(obj, GCHandleType.Pinned);
98  reusedPinnedMemoryHandles.Add(h);
99  return h.AddrOfPinnedObject();
100  }
101 
105  public void UnpinAllObjects()
106  {
107  for (int i = 0; i < reusedPinnedMemoryHandles.Count; ++i)
108  {
109  reusedPinnedMemoryHandles[i].Free();
110  }
111  reusedPinnedMemoryHandles.Clear();
112  }
113 
120  public IntPtr PinMeshDataForMarshalling(List<MeshData> meshes)
121  {
122  // if we have a big enough array reuse it, otherwise create new
123  if (reusedMeshesForMarshalling == null || reusedMeshesForMarshalling.Length < meshes.Count)
124  {
125  reusedMeshesForMarshalling = new Imports.MeshData[meshes.Count];
126  }
127 
128  for (int i = 0; i < meshes.Count; ++i)
129  {
130  IntPtr pinnedVerts = (meshes[i].Verts != null) && (meshes[i].Verts.Length > 0) ? PinObject(meshes[i].Verts) : IntPtr.Zero;
131  IntPtr pinnedNormals = (meshes[i].Verts != null) && (meshes[i].Verts.Length > 0) ? PinObject(meshes[i].Normals) : IntPtr.Zero;
132  IntPtr pinnedIndices = (meshes[i].Indices != null) && (meshes[i].Indices.Length > 0) ? PinObject(meshes[i].Indices) : IntPtr.Zero;
133  reusedMeshesForMarshalling[i] = new Imports.MeshData()
134  {
135  meshID = meshes[i].MeshID,
136  lastUpdateID = meshes[i].LastUpdateID,
137  transform = meshes[i].Transform,
138  vertCount = (meshes[i].Verts != null) ? meshes[i].Verts.Length : 0,
139  indexCount = (meshes[i].Indices != null) ? meshes[i].Indices.Length : 0,
140  verts = pinnedVerts,
141  normals = pinnedNormals,
142  indices = pinnedIndices,
143  };
144  }
145 
146  return PinObject(reusedMeshesForMarshalling);
147  }
148 
154  {
155  if (reusedRaycastResultPtr == IntPtr.Zero)
156  {
157  GCHandle h = GCHandle.Alloc(reusedRaycastResult, GCHandleType.Pinned);
158  reusedRaycastResultPtr = h.AddrOfPinnedObject();
159  }
160  return reusedRaycastResultPtr;
161  }
167  {
168  return reusedRaycastResult;
169  }
170 
176  {
177  if (reusedPlayspaceStatsPtr == IntPtr.Zero)
178  {
179  GCHandle h = GCHandle.Alloc(reusedPlayspaceStats, GCHandleType.Pinned);
180  reusedPlayspaceStatsPtr = h.AddrOfPinnedObject();
181  }
182  return reusedPlayspaceStatsPtr;
183  }
189  {
190  return reusedPlayspaceStats;
191  }
192 
198  {
199  if (reusedPlayspaceAlignmentPtr == IntPtr.Zero)
200  {
201  GCHandle h = GCHandle.Alloc(reusedPlayspaceAlignment, GCHandleType.Pinned);
202  reusedPlayspaceAlignmentPtr = h.AddrOfPinnedObject();
203  }
204  return reusedPlayspaceAlignmentPtr;
205  }
211  {
212  return reusedPlayspaceAlignment;
213  }
214 
220  {
221  if (reusedObjectPlacementResultPtr == IntPtr.Zero)
222  {
223  GCHandle h = GCHandle.Alloc(reusedObjectPlacementResult, GCHandleType.Pinned);
224  reusedObjectPlacementResultPtr = h.AddrOfPinnedObject();
225  }
226  return reusedObjectPlacementResultPtr;
227  }
233  {
234  return reusedObjectPlacementResult;
235  }
236 
241  public T[] MarshalArrayFromIntPtr<T>(IntPtr outArray, int count)
242  {
243  T[] resultArray = new T[count];
244 
245  int structSize =
246 #if UNITY_EDITOR || !UNITY_WSA
247  Marshal.SizeOf(typeof(T));
248 #else
249  Marshal.SizeOf<T>();
250 #endif
251 
252  IntPtr current = outArray;
253 
254  try
255  {
256  for (int i = 0; i < count; i++)
257  {
258  resultArray[i] =
259 #if UNITY_EDITOR || !UNITY_WSA
260  (T)Marshal.PtrToStructure(current, typeof(T));
261 #else
262  Marshal.PtrToStructure<T>(current);
263 #endif
264 
265  current = (IntPtr)((long)current + structSize);
266  }
267  }
268  finally
269  {
270  Marshal.FreeCoTaskMem(outArray);
271  }
272 
273  return resultArray;
274  }
275 
276  public class Imports
277  {
281  [StructLayout(LayoutKind.Sequential, Pack = 1)]
282  public struct MeshData
283  {
284  public int meshID;
285  public int lastUpdateID;
286  public Matrix4x4 transform;
287  public Int32 vertCount;
288  public Int32 indexCount;
289  public IntPtr verts;
290  public IntPtr normals;
291  public IntPtr indices;
292  };
296  [StructLayout(LayoutKind.Sequential, Pack = 1)]
297  public class PlayspaceStats
298  {
299  public int IsWorkingOnStats; // 0 if still working on creating the stats
300 
301  public float HorizSurfaceArea; // In m2 : All horizontal faces UP between Ground – 0.15 and Ground + 1.f (include Ground and convenient horiz surface)
302  public float TotalSurfaceArea; // In m2 : All !
303  public float UpSurfaceArea; // In m2 : All horizontal faces UP (no constraint => including ground)
304  public float DownSurfaceArea; // In m2 : All horizontal faces DOWN (no constraint => including ceiling)
305  public float WallSurfaceArea; // In m2 : All Vertical faces (not only walls)
306  public float VirtualCeilingSurfaceArea; // In m2 : estimation of surface of virtual Ceiling.
307  public float VirtualWallSurfaceArea; // In m2 : estimation of surface of virtual Walls.
308 
309  public int NumFloor; // List of Area of each Floor surface (contains count)
310  public int NumCeiling; // List of Area of each Ceiling surface (contains count)
311  public int NumWall_XNeg; // List of Area of each Wall XNeg surface (contains count)
312  public int NumWall_XPos; // List of Area of each Wall XPos surface (contains count)
313  public int NumWall_ZNeg; // List of Area of each Wall ZNeg surface (contains count)
314  public int NumWall_ZPos; // List of Area of each Wall ZPos surface (contains count)
315  public int NumPlatform; // List of Area of each Horizontal not Floor surface (contains count)
316 
317  public int CellCount_IsPaintMode; // Number paint cells (could deduce surface of painted area) => 8cm x 8cm cell
318  public int CellCount_IsSeenQualtiy_None; // Number of not seen cells => 8cm x 8cm cell
319  public int CellCount_IsSeenQualtiy_Seen; // Number of seen cells => 8cm x 8cm cell
320  public int CellCount_IsSeenQualtiy_Good; // Number of seen cells good quality => 8cm x 8cm cell
321  };
325  [StructLayout(LayoutKind.Sequential, Pack = 1)]
326  public class PlayspaceAlignment
327  {
328  public Vector3 Center;
329  public Vector3 HalfDims;
330  public Vector3 BasisX;
331  public Vector3 BasisY;
332  public Vector3 BasisZ;
333  public float FloorYValue;
334  public float CeilingYValue;
335  };
339  [StructLayout(LayoutKind.Sequential, Pack = 1)]
340  public class RaycastResult
341  {
342  public enum SurfaceTypes
343  {
344  Invalid, // If no intersection
345  Other,
346  Floor,
347  FloorLike, // Not part of the floor topology, but close to the floor and looks like the floor
348  Platform, // Horizontal platform between the ground and the ceiling
349  Ceiling,
350  WallExternal,
351  WallLike, // Not part of the external wall surface
352  };
353  public SurfaceTypes SurfaceType;
354  float SurfaceArea; // Zero if unknown (not part of the topology analysis)
355  public Vector3 IntersectPoint;
356  public Vector3 IntersectNormal;
357  };
358 
359  // Functions
365  [DllImport("SpatialUnderstanding", CallingConvention = CallingConvention.Cdecl)]
366  public static extern int SpatialUnderstanding_Init();
370  [DllImport("SpatialUnderstanding", CallingConvention = CallingConvention.Cdecl)]
371  public static extern void SpatialUnderstanding_Term();
372 
387  [DllImport("SpatialUnderstanding", CallingConvention = CallingConvention.Cdecl)]
388  public static extern void GeneratePlayspace_InitScan(
389  [In] float camPos_X, [In] float camPos_Y, [In] float camPos_Z,
390  [In] float camFwd_X, [In] float camFwd_Y, [In] float camFwd_Z,
391  [In] float camUp_X, [In] float camUp_Y, [In] float camUp_Z,
392  [In] float searchDst, [In] float optimalSize);
393 
410  [DllImport("SpatialUnderstanding", CallingConvention = CallingConvention.Cdecl)]
411  public static extern int GeneratePlayspace_UpdateScan(
412  [In] int meshCount, [In] IntPtr meshes,
413  [In] float camPos_X, [In] float camPos_Y, [In] float camPos_Z,
414  [In] float camFwd_X, [In] float camFwd_Y, [In] float camFwd_Z,
415  [In] float camUp_X, [In] float camUp_Y, [In] float camUp_Z,
416  [In] float deltaTime);
417 
423  [DllImport("SpatialUnderstanding", CallingConvention = CallingConvention.Cdecl)]
424  public static extern void GeneratePlayspace_RequestFinish();
425 
435  [DllImport("SpatialUnderstanding", CallingConvention = CallingConvention.Cdecl)]
436  public static extern int GeneratePlayspace_ExtractMesh_Setup(
437  [Out] out int vertexCount,
438  [Out] out int indexCount);
439 
450  [DllImport("SpatialUnderstanding", CallingConvention = CallingConvention.Cdecl)]
451  public static extern int GeneratePlayspace_ExtractMesh_Extract(
452  [In] int bufferVertexCount,
453  [In] IntPtr verticesPos, // (vertexCount) DirectX::XMFLOAT3*
454  [In] IntPtr verticesNormal, // (vertexCount) DirectX::XMFLOAT3*
455  [In] int bufferIndexCount,
456  [In] IntPtr indices); // (indexCount) INT32*
457 
463  [DllImport("SpatialUnderstanding", CallingConvention = CallingConvention.Cdecl)]
464  public static extern int QueryPlayspaceStats(
465  [In] IntPtr playspaceStats); // PlayspaceStats
466 
472  [DllImport("SpatialUnderstanding", CallingConvention = CallingConvention.Cdecl)]
473  public static extern int QueryPlayspaceAlignment(
474  [In] IntPtr playspaceAlignment); // PlayspaceAlignment
475 
488  [DllImport("SpatialUnderstanding", CallingConvention = CallingConvention.Cdecl)]
489  public static extern int PlayspaceRaycast(
490  [In] float rayPos_X, [In] float rayPos_Y, [In] float rayPos_Z,
491  [In] float rayVec_X, [In] float rayVec_Y, [In] float rayVec_Z,
492  [In] IntPtr result); // RaycastResult
493  }
494  }
495 }
IntPtr PinObject(System.Object obj)
Pins the specified object so that the backing memory can not be relocated, adds the pinned memory han...
IntPtr PinMeshDataForMarshalling(List< MeshData > meshes)
Copies the supplied mesh data into the reusedMeshesForMarhsalling array. All managed arrays are pinne...
void UnpinAllObjects()
Unpins all of the memory previously pinned by calls to PinObject().
Encapsulates the primary DLL functions, including marshalling helper functions. The DLL functions are...
Object placement result. Defines an oriented bounding box result for the object placement query...
Imports.PlayspaceStats GetStaticPlayspaceStats()
Reusable playspace statistics. Can be used for inline playspace statistics calls. ...
SpatialUnderstandingDllObjectPlacement.ObjectPlacementResult GetStaticObjectPlacementResult()
Reusable object placement results. Can be used for inline object placement queries.
Representation of the mesh data to be passed to the understanding DLL. Used by SpatialUnderstandingSo...
Playspace alignment results. Reports internal alignment of room in Unity space and basic alignment of...
Imports.PlayspaceAlignment GetStaticPlayspaceAlignment()
Reusable playspace alignment. Can be used for inline playspace alignment query calls.
Encapsulates the object placement queries of the understanding DLL. These queries will not be valid u...
IntPtr PinString(string str)
Pins the string, converting to the format expected by the DLL. See PinObject for additional details...
IntPtr GetStaticRaycastResultPtr()
Reusable raycast result object pointer. Can be used for inline raycast calls.
IntPtr GetStaticObjectPlacementResultPtr()
Reusable object placement results pointer. Can be used for inline object placement queries...
Imports.RaycastResult GetStaticRaycastResult()
Reusable raycast result object. Can be used for inline raycast calls.
Playspace statistics for querying scanning progress
IntPtr GetStaticPlayspaceAlignmentPtr()
Reusable playspace alignment pointer. Can be used for inline playspace alignment query calls...
void CopyFrom(MeshFilter meshFilter, int meshID=0, int lastUpdateID=0)
IntPtr GetStaticPlayspaceStatsPtr()
Reusable playspace statistics pointer. Can be used for inline playspace statistics calls...