Augmented Reality Vuforia 7 Ground Plane Detection.

by matthewh8 in Circuits > Software

18548 Views, 8 Favorites, 0 Comments

Augmented Reality Vuforia 7 Ground Plane Detection.

VuforiaThumbnail.jpg
Screen Shot 2018-02-15 at 11.15.01 PM.png

Vuforia's augmented reality SDK for Unity 3D uses ARCore and ARKit to detect ground planes in AR. Today's tutorial will use their native integration in Unity to make an AR app for Android or IOS. We will have a car fall out of the sky onto the ground, and it's doors will open automatically when we get close. We will also go over doing video in AR. To follow along you will need Unity 3D installed on your computer (it's free). These instructions are for total beginners so we will go over everything in detail!

The best part about Vuforia's SLAM is the amount of IOS and Android devices that it supports. A full device list can be found here:

https://library.vuforia.com/articles/Solution/grou...

Start a New Project.

Screen Shot 2018-02-15 at 11.45.37 PM.png

Download Unity 3D from here if you don't already have it: https://unity3d.com/

Make sure to install support for Vuforia Augmented Reality and Android or IOS depending on which device you have.

Open up Unity and start a new Unity project, call it whatever you want.

First lets get out app set up to build out so we don't forget. So, save the scene and call it "main".

Go to file, build settings, and switch your build platform to Android or IOS. Navigate to the XR settings in player settings and check Vuforia Augmented Reality Supported.

If your on Android you won't have to do anything else, but on IOS go to other settings and make sure to put in something for your bundle identifier. Use the format "com.YourCompanyName.YourAppName."

Put in anything for the camera usage description and change the target minimum build version to at least 9.0.

Close out of that and now let's get everything else set up.

Let's Set Up Vuforia.

Screen Shot 2018-02-15 at 11.58.25 PM.png

Now let's get everything set up.

Go to gameobject in the top menu and click ARCamera. Now delete the main camera from your scene.

Select the ARCamera and on the right side in the inspector click on Open Vuforia Configuration. Click the datasets collection and uncheck everything because we aren't using any image targets here.

Click on device tracker and click track device pose. Change the tracking from rotational to positional.

Now go back to the game object tab and click Vuforia, Ground Plane, and Plane finder. This houses the scripts that find our ground plane.

The last thing we need is the ground plane stage, so go to game object again in the top menu, and click Vuforia, Ground Plane, and choose Ground Plane Stage. Now anything that we child to this will show up in AR.

Add a New Script.

Screen Shot 2018-02-16 at 12.11.18 AM.png
Screen Shot 2018-02-16 at 12.11.40 AM.png

The default behavior of this ground plane detection is to place a new object every time you press on the screen. What we want is to just reposition the object every time you press on the screen. So right click in your assets folder and create a new C# script. Call it "DeployStageOnce" and replace everything with this code:

using System;
using UnityEngine;
using Vuforia;
 
public class DeployStageOnce : MonoBehaviour {
     
    public GameObject AnchorStage;
    private PositionalDeviceTracker _deviceTracker;
    private GameObject _previousAnchor;
     
    public void Start ()
    {
        if (AnchorStage == null)
        {
            Debug.Log("AnchorStage must be specified");
            return;
        }
 
        AnchorStage.SetActive(false);
    }
 
    public void Awake()
    {
        VuforiaARController.Instance.RegisterVuforiaStartedCallback(OnVuforiaStarted);
    }
 
    public void OnDestroy()
    {
        VuforiaARController.Instance.UnregisterVuforiaStartedCallback(OnVuforiaStarted);
    }
 
    private void OnVuforiaStarted()
    {
        _deviceTracker = TrackerManager.Instance.GetTracker<PositionalDeviceTracker>();
    }
 
    public void OnInteractiveHitTest(HitTestResult result)
    {
        if (result == null || AnchorStage == null)
        {
            Debug.LogWarning("Hit test is invalid or AnchorStage not set");
            return;
        }
 
        var anchor = _deviceTracker.CreatePlaneAnchor(Guid.NewGuid().ToString(), result);
 
        if (anchor != null)
        {
            AnchorStage.transform.parent = anchor.transform;
            AnchorStage.transform.localPosition = Vector3.zero;
            AnchorStage.transform.localRotation = Quaternion.identity;
            AnchorStage.SetActive(true);
        }
 
        if (_previousAnchor != null)
        {
            Destroy(_previousAnchor);
        }
 
        _previousAnchor = anchor;
    }
}

In order to make sure this script gets used we need to call the OnInteractiveHitTest() function so go back to Unity and click the plane finder game object. Change the mode from Automatic to Interactive. Drag the script we just made onto the plane finder game object. Remove the ContentPositioningBehavior script. You will see a spot for a game object on the DeployStageOnce script, drag the plane finder into there, and find this script, choose the OnInteractiveHitTest function from the top of the list. Now our function will get called whenever the user clicks on the screen!

Let's Add the Car.

Screen Shot 2018-02-16 at 12.48.00 AM.png

Download this free car 3D model from here(Make sure to get the .obj version):

https://www.turbosquid.com/3d-models/max-exterior-...

Also, download this sound because we are gonna play it when the car hits the ground:

https://freesound.org/people/PaulMorek/sounds/1967...

Unzip both of those files and drag them into your assets folder.

Click on the car and look to the right, change Use Embedded Materials to Use External Materials(Legacy) from the drop down menu at the top. Now we will be able to change the color of all the materials on the car.

Drag the car onto your ground plane stage making it a child. Change the scale to .035 on the x, y, and z.

Now go through each of the cars child game objects and change their materials to whatever color you want.

Add a rigid body component to the car's root game object and also add a box collider, scale it so it covers the whole car. Also add a box collider to the ground plane stage and scale it so its a few times wider than the ground plane stage. This way we can drop the car out of the sky and it will hit the ground using Unity's built in physics engine.

Put the Car in the Sky.

Screen Shot 2018-02-16 at 1.08.42 AM.png

Add an audio source component to the car's root game object, drag the car crash sound into it's audio clip spot.

Now we need to make a script that will put the car into the air when the user presses on the screen and then plays the crash sound when the car hits the ground. So, right click in the assets folder and create a new C# script and call it "CarController."

Replace all the code there with this:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CarController : MonoBehaviour {

	private bool soundPlayed = false;

	// Update is called once per frame
	void Update () {
		if (!soundPlayed && transform.localPosition.y < .05f) {
			soundPlayed = true;
			StartCoroutine (DelayPlaySound ());
		}
	}

	public void MoveCar(){
		transform.localPosition += new Vector3 (0, 10, 0);
		transform.eulerAngles += new Vector3 (5, 20, 5);
		soundPlayed = false;
	}

	IEnumerator DelayPlaySound(){
		yield return new WaitForSeconds (.2f);
		GetComponent<AudioSource> ().Play ();
	}
}


Add the MoveCar function to the OnInteractiveHitTest event like in the picture above. Now it will get called when the user clicks on the screen.

Lambo Doors.

Screen Shot 2018-02-16 at 1.15.09 AM.png

So if you expand the car game object and find the doors, you will notice both doors are one single mesh. If we want to open the doors our only option is going to be Lambo doors that open vertically. To make this work we need to first change their pivot point.

Make an empty game object that is a child of the car. Drag the doors in and make them a child of this new game object. Move the parent game object to where the pivot point should be, by the door hinges. Now move the child doors back into place. Now when we rotate the doors parent, the pivot point is in the right place.

We are going to make a script that opens the doors when you get close to the car but before we do that we need a way to "trigger" the event. Add a box collider to your door parent game object and scale it so it goes a little ways over the car in both directions. Check "isTrigger". Now add a box collider to the main camera and scale it appropriately. Also check "isTrigger". Add a Rigid Body component to your camera and uncheck "useGravity". With your camera selected, change it's tag to "MainCamera" in the top of the inspector.

Add a new script called "LamboDoorBehavior" and add the code below. Drag the script onto your door's parent.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LamboDoorBehavior : MonoBehaviour {

	private float currAngle = 0;
	private float desiredAngle = 0;
	
	// Update is called once per frame
	void Update () {
		currAngle = Mathf.LerpAngle (currAngle, desiredAngle, Time.deltaTime * 3f);
		transform.localEulerAngles = new Vector3 (currAngle, 0, 0);
	}

	public void OpenDoors(){
		desiredAngle = 60f;
	}

	public void CloseDoors(){
		desiredAngle = 0;
	}

	void OnTriggerEnter(Collider col){
		if (col.CompareTag ("MainCamera")) {
			OpenDoors ();
		}
	}

	void OnTriggerExit(Collider col){
		if (col.CompareTag ("MainCamera")) {
			CloseDoors ();
		}
	}
}

This script will cause your doors to open slowly when you get close the them in AR by using the Lerp() function in unity which interpolates between two points (or in this case two angles).

Playing Video in AR.

Screen Shot 2018-02-16 at 1.30.44 AM.png
Screen Shot 2018-02-16 at 1.31.15 AM.png

The last thing we need to do is get video playing in AR.

Right click on any game object that is a child of your car and create a 3D object, Quad. This will make sure the quad is a child of your car. Position and resize this quad such that it fits inside the dash of your car and looks like it supposed to be there. This is what we are going to play the video on.

Add a video player component to your quad. Change the source to URL and find a hard link to an .MP4 file or drag a video file into your assets folder and then drag that clip into the empty slot. If you want to stream in a video from a URL, Instragram is a great source. Right click on any Instagram video in Google Chrome and click inspect. Find the div containing the video and copy the link from there (I have this method pictured above).

Make sure to check loop if you want it to play more than once. Add an audio source component to this game object and change the output source to audio source on the video player. Drag in your newly created audio source into that slot.

Finally we are done!

Put the App on Your Phone!

Screen Shot 2018-02-16 at 1.41.25 AM.png

If you are building for Android you can just go to file and hit build and run with your phone plugged in.

If you are building out to an iPhone or and iPad, make sure to download Xcode from the app store. Also, sign up for a free apple developer account from www.apple.developer.com. Go to file and hit build. Open up the file that was created from Xcode and plug in your phone. Choose your development team and hit the play button.

You may have to move the camera around a little bit but give it a second and tap the screen and you should see your car fall out of the sky onto the ground! Now you can walk inside and watch your video play in the dashboard!

Have fun and let me know if you have any questions in the comments!