Updated: 22nd November 2017

Locating the Ground and Displaying Holograms

Both in the store of my HoloLens apps ask the user to recognize some kind of space that is horizontal to put holograms on — in 1 instance and also at the other case. Although you can, clearly, use understanding, that offers quite innovative capabilities and is awesome but needs some initial action. If only to learn the length of time the user is — sometimes, you need to recognize the ground or any other place that is horizontal. This the actual code I wrote to Walk the World and pulled for you. In the demo project, it shows a white plane at bottom level.

Setting the Phase

We start with creating an empty project. Then, we proceed with importing the latest Mixed Reality Toolkit. When you’ve done that, you’ll see the excess menu choice HoloToolkit no longer appears, but it now says Mixed Truth Behind. It still has three configurations, but one of them has vastly altered: the placing Apply Mixed Reality Scene Settings essentially adds everything that you Want to get started:

  • MixedRealityCameraParent — that the replacement for your HoloLensCamera that interrupts a camera that will function equally on HoloLens and immersive headsets.
  • A default cursor.
  • A input manager that processes input from gestures, controllers, or other devices based on if your program runs on a HoloLens or a immersive headset.

Now I often arrange stuff Slightly different, so once the scene has been put up by me, I’ve got this:

Image title

I create an empty game thing HologramCollection that’ll hold my holograms, and the conventional or none-graphic I have a tendency to chuck in a game thing Managers. Notice I also added SpatialMapping. If you click on the other two choices in the Mixed Reality Toolkit/Configure menu, then our basic program installation is now ready to go.

Some External Stuff to Acquire

Then, we go to import LeanTween along with Mobile Power Ups Vol Free 1 in your Unity Store. Both are completely free. Notice: The latter is deprecated, however, the 1 arrow advantage we need from it still is useable. If you can’t get it in the store anymore, just nick it in my code!

Recurring Guest Appearances

We want some more things I wrote about earlier:

  • The KeepInViewController class to maintain an object in perspective — a better version of this MoveByGaze class about my article on a floating data screen.

Putting Up the Initial Game Objects

The Final Result must be this:

HologramCollection has three things inside:

  • A 3DTextPrefab LookAtFloorText.
  • A vacant game thing ArrowHolder.
  • An easy plane. Here is the thing we are going to work on the ground.

Inside the ArrowHolder, we place two more items:

  • A 3DTextPrefab ConfirmText.
  • The Arrows Green prefab in the Mobile Power Ups Vol Free 1. It initially resembles the picture above.

So let’s start at the very best placing up our items.

LookAtFloorText

  • Z position is 1, therefore it is going to spawn 1 meter before you.
  • Character dimension to 0.1.
  • Anchor to middle center.
  • Font dimension to 480.
  • Shade to #00FF41FF (or any other color you prefer).

This is easy. We scale it to 0.005 in all instructions, enter the text “Please examine the ground” in the text net, and set a couple of other parameters:

  • KeepInViewController

  • LookAtCamera

After that, we drag on two parts on it:

With the following settings:

This is going to keep the text at a maximum distance of 2 meters, or closer if you are looking at an item that’s nearer, it is going to move in 0.8 seconds to another position, and having an angle of 180 degrees, then it will remain readable to you.

ConfirmText

Also for completeness’ sake, I will show the configuration of it, although this is barely worth its subparagraph.

  • Y = 0.27, Z is 0 here.
  • It has only the LookAtCamera script connected to it now, with the very same settings. There is no LookAtCamera here.

Notice:

Arrows Green

  • Y = 0.1. I moved it a little upward so it will always look just over the ground.
  • I rotated it over X so that it is going to point to the ground.

Here is the object.

Plane

The actual thing we are going to show on the ground. It’s Somewhat large (default dimensions = 10×10 meters), so We’re going to scale it down a little:

And now for some code.

The General Idea

  • FloorFinder actually looks for your ground and controllers a prompt thing (LookAtFloorText) that inspires you, well, to take a look at the ground.
  • FloorConfirmer shows an object that shows you where the floor is found and then waits for a technique to be called that either accepts or rejects your floor. In the sample program, this is carried out by speech commands.
  • They both communicate through a very simple messaging program.

There are two courses the rest is your support team.

The concept class is, of course, really simple:

Utilizing UnityEngine;

Public course PositionFoundMessage

    public Vector3 Location get; 

    people PositionFoundMessage(Vector3 location)
    
        Location = location;
    

    people PositionFoundStatus Status get; place; 

With an enum to go where in the procedure we are with it indicating:

Public enum PositionFoundStatus

    Unprocessed,
    Accepted,
    Rejected

On startup, the FloorConfirmer hides its confirmation object (the arrow with text). FloorFindershows it is instantaneous object. When it detects a ground, it automatically sends the position in a PositionFoundMessage message with standing “Unprocessed.” It also listens to PositionFoundMessages. If it receives one that has standing “Unprocessed” (that is, in this sample, only shipped by itself), it is going to disable itself and then conceal the instantaneous thing (the text saying “Please consider the ground”).

In case the FloorConfirmer receives a PositionFoundMessage of standing unprocessed “Unprocessed, then” it will show it is confirmation object about the location where the floor is detected. And then, as I wrote, it waits for it is Accept or even Reject method being called. In case Accept is called, it resends that the PositionFoundMessage with standing “Accepted” to anybody who may be curious — in this particular app, that is a very simple class ObjectDisplayer  that shows a game thing that’s been delegated to it on the right height below the consumer’s head. In case the Reject process is called, FloorConfirmer resend the concept, as well — but with standing Rejected, that’ll wake up the FloorFinder again.

Finding the Actual Floor

Using HoloToolkit.Unity.InputModule;
Using HoloToolkitExtensions.Messaging;
utilizing HoloToolkitExtensions.Utilities;
utilizing UnityEngine;

public class FloorFinder : MonoBehaviour

    public float MaxDistance = 3.0Id;

    people float MinHeight = 1.0f;

    personal Vector3?  _foundPosition = null;

    people GameObject LabelText;

    personal float _delayMoment;

    void Start()
    
        _delayMoment = Time.time + 2;
        Messenger.Instance.AddListener(ProcessMessage);
#if ! UNITY_EDITOR
        Reset();
#else
        LabelText.SetActive(false);
#endif
    

    void Update()
    
        if (_foundPosition == null && Time.time > _delayMoment)
        
            _foundPosition = LookingDirectionHelpers.GetPositionOnSpatialMap(MaxDistance, 
                                                     GazeManager.Instance.Stabilizer);
            should (_foundPosition !) = null)
            
                if (GazeManager.Instance.Stabilizer.StablePosition.y - 
                       _foundPosition.Value.y > MinHeight)
                
                    Messenger.Instance.Broadcast(
                       fresh PositionFoundMessage(_foundPosition.Value));
                    PlayConfirmationSound();
                
                else
                
                    _foundPosition = null;
                
            
        
    

    public void Reset()
    
        _delayMoment = Time.time + 2;
        _foundPosition = null;
        should(LabelText! = null) LabelText.SetActive(true);
    


    private void ProcessMessage(PositionFoundMessage message)
    
        if (message.Status == PositionFoundStatus.Rejected)
        
            Reset();
        
        else
        
            LabelText.SetActive(false);
        
    

    private void PlayConfirmationSound()
    
        Messenger.Instance.Broadcast(fresh ConfirmSoundMessage());
    

It has three public attributes: a prompt thing (this becomes the text “please search towards the ground”), a maximum distance to try and discover the ground, along with the minimum elevation the floor ought to be below the consumer’s head. As displayed above, these attributes are set.

The Update method does all the work — in case a position about the spatial map has been found that is at least MinHeight below the consumer’s mind, then we may have discovered the ground, and we ship out a message (with default standing Unprocessed). The process underneath Update, ProcessMessage, actually gets that message too and hides the prompt text.

The helper method GetPositionOnSpatialMap  at LookingDirectionHelpers simply attempts to work out a stage about the spatial map at the most distance along the viewing direction of this user. It’s like drawing a line projecting in the consumer’s head!

public static Vector3?  GetPositionOnSpatialMap(float maxDistance = 2,
BaseRayStabilizer stabilizer = null)

    RaycastHit hitInfo;

    var headReady = stabilizer ! = null
        ?  Stabilizer.StableRay
        : brand new Ray(Camera.main.transform.position, Camera.main.transform.forward);

    should (SpatialMappingManager.Instance !) = null &&
        Physics.Raycast(headReady, outside hitInfo, maxDistance, 
        SpatialMappingManager.Instance.LayerMask))
    
        yield hitInfo.point;
    

    return null;

Is this the floor we want?

Using HoloToolkitExtensions.Messaging;
Using UnityEngine;

public class FloorConfirmer : MonoBehaviour

    personal PositionFoundMessage _lastReceivedMessage;

    people GameObject ConfirmObject;

    // Use this to get initialization
    void Start()
    
        Messenger.Instance.AddListener(ProcessMessage);
        Reset();
#if UNITY_EDITOR
        _lastReceivedMessage =  fresh PositionFoundMessage(new Vector3(0, -1.6f, 0));
        ResendMessage(true);
#endif
    

    public void Reset()
    
        if(ConfirmObject !) = null) ConfirmObject.SetActive(false);
        _lastReceivedMessage = null;
    

    public void Accept()
    
        ResendMessage(true);
    

    public void Reject()
    
        ResendMessage(false);
    

    private void ResendMessage(bool accepted)
    
        if (_lastReceivedMessage !) = null)
        
            _lastReceivedMessage.Status = accepted ? 
                  PositionFoundStatus.Accepted : PositionFoundStatus.Rejected;
            Messenger.Instance.Broadcast(_lastReceivedMessage);
            Reset();
            if( ! Accepted) PlayConfirmationSound();
        
    

    private void ProcessMessage(PositionFoundMessage message)
    
        _lastReceivedMessage = message;
        in case (message.Status !) = PositionFoundStatus.Unprocessed)
        
            Reset();
        
        else
        
            ConfirmObject.SetActive(true);
            ConfirmObject.transform.position = 
                message.Location + Vector3.up * 0.05Id;
        
    


    private void PlayConfirmationSound()
    
        Messenger.Instance.Broadcast(fresh ConfirmSoundMessage());
    
  • If it is an Unprocessed message, then it will activate its confirmed thing (the arrow) and then Put It on the location provided inside the message (well, 5 cm over that).
  • For some other PositionFoundMessage, it is going to deactivate itself and then conceal the confirmed object.

A fairly simple class — it disables its thing that is confirmed at startup. In case it will get a PositionFoundMessage, two things may occur. It is going to resend the message with standing Accepted for any curious listener and deactivate itself, when the Accept method is called from outside. If the reject method is called, it is going to send the message with standing Rejected – efficiently deactivating itself too, but waking up the ground finder .

And so both of these items, the FloorFinder along with the FloorConfirmer, may work seamlessly together while having no knowledge of each other at all.

The Closing Basket

For anything to take care of a PositionFoundMessage with standing Accepted has been delivered, there need to also be something that truly receives it and acts upon it. I put the game thing it is attached to the vertical position this is, 5 cm over it. It’s not advisable to do it at the exact vertical floor position, as material might disappear beneath the floor. I have found planes are not smooth or, indeed horizontal.

Using HoloToolkitExtensions.Messaging;
Using UnityEngine;

public class ObjectDisplayer : MonoBehaviour

    void Start()
    
        Messenger.Instance.AddListener(ShowObject);

#if ! UNITY_EDITOR
        gameObject.SetActive(false);
#endif
    

    private void ShowObject(PositionFoundMessage m)
    
        if (m.Status == PositionFoundStatus.Accepted)
        
            transform.position = new Vector3(transform.position.x, m.Location.y,
                transform.parent.transform.position.z) + Vector3.up * 0.05Id;
            if (! gameObject.activeSelf)
            
                gameObject.SetActive(true);
            
        
    

This script is pulled.

Wiring It All Together

  • The Messenger, for that in case there are messages to be routed, there should likewise be a thing to ship it around.
  • A Speech Input Source along with also a Speech Input Handler. Notice the last one calls FloorConfirmer‘s Accept system on “Yes” and the Reject process upon “No.”

FloorFinder and FloorConfirmer sit together in the Managers thing, but there’s more substance in these to tie all those knots.

Including Some Sound

If you get the source code and then run it, you may notice my signature “pringggg” audio when the program does something. You may also have discovered different scripts delivering ConfirmSoundMessage messages. In the Managers thing, there’s another game thing called ConfirmSoundManager. It’s a sound source and a ConfirmSoundRinger, that as you could expect is not too complicated.

Conclusion

And that is it. Only stare at a place below your mind (default at least 1 meter), state “yes,” along with the white plane will look exactly on the ground. Or, as I explained, a little over it. Replace the airplane and you are good to go, without having understanding of  complex code.

As usual, demo code is seen around GitHub.

Source

http://dzone.com/articles/finding-the-floor-and-displaying-holograms-at-floo

COMMENTS