Placement of the hologram

The user will be able to place the hologram in the real world. We expect they will use the prompt to circumscribe the tire. And then we can display the instruction graphics registered to the tire.

To place the hologram, the user will click on it using the select gesture while gazing at the Circle Prompt. Then, moving their head to gaze at a new location, the hologram will follow the gaze until another select is detected. That will be the new position of the hologram.

Placing objects in the real world uses HoloLens Spatial Mapping. The device is always scanning the environment, taking depth readings, and constructing a 3D mesh of all surfaces. To place the hologram in the space, the user will gaze at the desired location. We will cast a ray (draw a straight line) from the user's gaze and determine where it intersects with the Spatial Map mesh. This 3D point will be the location we move the hologram to.

There's a bit of math involved in accomplishing this, but Unity provides all the functions we need:

  1. Find the SpatialMapping prefab in Project Assets/Holotoolkit/SpatialMapping/Prefabs, and drag it to the Hierarchy.
  2. In your HowToChangeATire/Scripts folder, create a new C# script named TapToPlaceInstructions.
  3. In Hierarchy, select Circle Prompt.
  4. Drag the new script component to the Circle Prompt.
  5. Double-click the script to open it for editing.
Note that the HoloToolkit namespace is pending to be renamed to MixedRealityToolkit at the time of publishing this book. By the time you read this, you may need to use the updated namespace.

The full script is shown as follows. Enter the following code into your script:

File: TapToPlaceInstructions.cs 
using UnityEngine; 
using HoloToolkit.Unity.InputModule; 
using HoloToolkit.Unity.SpatialMapping; 
 
public class TapToPlaceInstructions : MonoBehaviour, IInputClickHandler { 
    public SpatialMappingManager spatialMapping; 
    public bool placing; 
 
    public void OnInputClicked(InputClickedEventData eventData) { 
        placing = !placing; 
 
        spatialMapping.DrawVisualMeshes = placing; 
    } 
 
    void Start() { 
        spatialMapping.DrawVisualMeshes = placing; 
    } 
 
    void Update() { 
        if (placing) { 
            Vector3 headPosition = Camera.main.transform.position; 
            Vector3 gazeDirection = Camera.main.transform.forward; 
            int layerMask = 1 << spatialMapping.PhysicsLayer; 
            RaycastHit hitInfo; 
            if (Physics.Raycast(headPosition, gazeDirection, out hitInfo, 30.0f, layerMask)) { 
                this.transform.parent.position = hitInfo.point; 
                Quaternion toQuat = Camera.main.transform.localRotation; 
                toQuat.x = 0; 
                toQuat.z = 0; 
                this.transform.parent.rotation = toQuat; 
            } 
        } 
    } 
} 

At the top of the script, we declare that we will be using the HoloToolkit (MixedRealityToolkit) Input Module and Spatial Mapping APIs.

The TapToPlaceInstructions class will implement an interface for IInputClickHandler, the event system for the Input Module. When the user does a select gesture while gazing at the current object (Circle Prompt), the OnInputClicked method will get called.

We declare two variables for the class. spatialMapping is a reference to the spatialMapping object in the scene, so we can turn the spatial map mesh visibility on and off. placing is a Boolean that keeps track of when we're in the middle of placing the object.

So, when the user clicks on the circle, OnInputClicked is called, and placing is enabled, then we turn on the meshes. When not placing, the meshes are turned off. Rather than writing if placing then DrawVisualMeshes = true else DrawVisualMeshes = false, we use a coding shortcut and simply use the placing Boolean value to set the DrawVisualMeshes value itself.

placing is a public variable, and it can be set in the Unity editor. If we choose to start the app with placing turned on (to force the user to begin placing the hologram first thing), we want to draw the meshes in Start() also.

While placing on each Update(), we cast a ray from the head position (camera position) in the gaze direction (camera forward vector) and see if and where it intersects the spatial mesh. We limit the ray cast to 30 meters.

How does Physics.Raycast know we're looking for a spatial mesh intersection and not anything else in the scene? If you go back to Unity and click the SpatialMapping object, you'll see its (default) Physics Layer is set to 31. The Raycast will only look for objects on layer 31 (the Raycast function requires a binary layer mask which we generate by binary-shifting the value 1 over 31 positions with the instruction 1 << 31).

If we get an intersection hit point, we set the Hologram's position to that point. (Hologram is the parent of Circle Prompt in Hierarchy.) We also rotate the hologram, like a billboard, so it's always facing you.

When the user selects again, the placing mode is disabled, and wherever the hologram was last positioned is where it stays.

  1. Save the script.
  2. Drag the SpatialMapping object from Hierarchy to the Spatial Mapping slot on the Tap To Place Instructions component.
  3. Check the Placing checkbox.

And try it in the HoloLens. When you're placing the circle, the spatial map mesh will be drawn. As you move your gaze, the hologram moves around your room, as follows:

When you click again, it is done, the mesh is hidden, and the instructions hologram is now in its new position.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.17.79.59