AR Design
UBC EML collab with UBC SALA - visualizing IoT data in AR
SpatialUnderstandingCursor.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 UnityEngine;
5 using System;
6 using HoloToolkit.Unity;
7 using UnityEngine.UI;
8 using UnityEngine.EventSystems;
9 using System.Collections.Generic;
10 using Button = UnityEngine.UI.Button;
11 
12 namespace HoloToolkit.Examples.SpatialUnderstandingFeatureOverview
13 {
15  {
16  // Consts
17  public const float RayCastLength = 10.0f;
18 
19  // Config
20  public TextMesh CursorText;
21  public LayerMask UILayerMask;
22 
23  // Privates
24  private SpatialUnderstandingDll.Imports.RaycastResult rayCastResult;
25 
26  // Functions
27  protected override RaycastResult CalculateRayIntersect()
28  {
29  RaycastResult result = base.CalculateRayIntersect();
30 
31  // Now use the understanding code
32  if (SpatialUnderstanding.Instance.AllowSpatialUnderstanding &&
34  {
35  Vector3 rayPos = CameraCache.Main.transform.position;
36  Vector3 rayVec = CameraCache.Main.transform.forward * RayCastLength;
37  IntPtr raycastResultPtr = SpatialUnderstanding.Instance.UnderstandingDLL.GetStaticRaycastResultPtr();
39  rayPos.x, rayPos.y, rayPos.z,
40  rayVec.x, rayVec.y, rayVec.z,
41  raycastResultPtr);
42  rayCastResult = SpatialUnderstanding.Instance.UnderstandingDLL.GetStaticRaycastResult();
43 
44  float rayCastResultDist = Vector3.Distance(rayPos, rayCastResult.IntersectPoint);
45  float resultDist = Vector3.Distance(rayPos, result.Position);
46 
47  // Override
48  if (rayCastResult.SurfaceType != SpatialUnderstandingDll.Imports.RaycastResult.SurfaceTypes.Invalid &&
49  rayCastResultDist < resultDist)
50  {
51  result.Hit = true;
52  result.Position = rayCastResult.IntersectPoint;
53  result.Normal = rayCastResult.IntersectNormal;
54 
55  return result;
56  }
57  }
58 
59  return result;
60  }
61 
62  public bool RayCastUI(out Vector3 hitPos, out Vector3 hitNormal, out Button hitButton)
63  {
64  // Defaults
65  hitPos = Vector3.zero;
66  hitNormal = Vector3.zero;
67  hitButton = null;
68 
69  // Do the raycast
70  RaycastHit hitInfo;
71  Vector3 uiRayCastOrigin = CameraCache.Main.transform.position;
72  Vector3 uiRayCastDirection = CameraCache.Main.transform.forward;
73  if (Physics.Raycast(uiRayCastOrigin, uiRayCastDirection, out hitInfo, RayCastLength, UILayerMask))
74  {
75  Canvas canvas = hitInfo.collider.gameObject.GetComponent<Canvas>();
76  if (canvas != null)
77  {
78  GraphicRaycaster canvasRaycaster = canvas.gameObject.GetComponent<GraphicRaycaster>();
79  if (canvasRaycaster != null)
80  {
81  // Cast only against this canvas
82  PointerEventData pData = new PointerEventData(EventSystem.current);
83 
84  pData.position = new Vector2(Screen.width * 0.5f, Screen.height * 0.5f);
85  pData.delta = Vector2.zero;
86  pData.scrollDelta = Vector2.zero;
87 
88  List<UnityEngine.EventSystems.RaycastResult> canvasHits = new List<UnityEngine.EventSystems.RaycastResult>();
89  canvasRaycaster.Raycast(pData, canvasHits);
90  for (int i = 0; i < canvasHits.Count; ++i)
91  {
92  Button button = canvasHits[i].gameObject.GetComponent<Button>();
93  if (button != null)
94  {
95  hitPos = uiRayCastOrigin + uiRayCastDirection * canvasHits[i].distance;
96  hitNormal = canvasHits[i].gameObject.transform.forward;
97  hitButton = button;
98  return true;
99  }
100  }
101 
102  // No buttons, but hit canvas object
103  hitPos = hitInfo.point;
104  hitNormal = hitInfo.normal;
105  return true;
106  }
107  }
108  }
109  return false;
110  }
111 
112  protected override void LateUpdate()
113  {
114  // Base
115  base.LateUpdate();
116 
117  // Basic checks
118  if ((SpatialUnderstanding.Instance == null) ||
122  {
123  CursorText.gameObject.SetActive(false);
124  return;
125  }
126  if (!SpatialUnderstanding.Instance.AllowSpatialUnderstanding)
127  {
128  return;
129  }
130 
131  // Report the results
132  if ((rayCastResult != null) &&
133  (rayCastResult.SurfaceType != SpatialUnderstandingDll.Imports.RaycastResult.SurfaceTypes.Invalid))
134  {
135  CursorText.gameObject.SetActive(true);
136  CursorText.text = rayCastResult.SurfaceType.ToString();
137 
138  CursorText.transform.rotation = Quaternion.LookRotation(CameraCache.Main.transform.forward, Vector3.up);
139  CursorText.transform.position = transform.position + CameraCache.Main.transform.right * 0.05f;
140  }
141  else
142  {
143  CursorText.gameObject.SetActive(false);
144  }
145 
146  // If we're looking at the UI, fade the text
147  Vector3 hitPos, hitNormal;
148  Button hitButton;
149  float textAlpha = RayCastUI(out hitPos, out hitNormal, out hitButton) ? 0.15f : 1.0f;
150  CursorText.color = new Color(1.0f, 1.0f, 1.0f, textAlpha);
151  }
152  }
153 }
Encapsulates the primary DLL functions, including marshalling helper functions. The DLL functions are...
bool RayCastUI(out Vector3 hitPos, out Vector3 hitNormal, out Button hitButton)
The purpose of this class is to provide a cached reference to the main camera. Calling Camera...
Definition: CameraCache.cs:12
static T Instance
Returns the Singleton instance of the classes type. If no instance is found, then we search for an in...
Definition: Singleton.cs:26
static Camera Main
Returns a cached reference to the main camera and uses Camera.main if it hasn&#39;t been cached yet...
Definition: CameraCache.cs:20
static int PlayspaceRaycast([In] float rayPos_X, [In] float rayPos_Y, [In] float rayPos_Z, [In] float rayVec_X, [In] float rayVec_Y, [In] float rayVec_Z, [In] IntPtr result)
Perform a raycast against the internal world representation of the understanding DLL. This will not be valid until after scanning is finalized.
The SpatialUnderstanding class controls the state and flow of the scanning process used in the unders...