Vuforia is a market leading AR platform with SDKs available for iOs, Android and Unity, and even comes integrated with the latter as of Unity version 2017.2. Vuforia offers different marker types, one of which being the VuMark marker type, which allow you to generate seemingly identical marker images that have a unique ID embedded in them. Using this embedded ID you can for example decide what sort of content to display on the VuMark as it is being recognized by the Vuforia tracking system (see the image below). This post explains how (assuming you are using string IDs).

The image above shows one of the VuMarks provided by Vuforia as part of their VuMark-Designer plugin. Note how all the 4 images look similar, but that on a closer look, only the ones in the left column are exact equals, as are the ones in the right column.

As we hold this image up in front of the camera, Vuforia is able to detect 4 instances of the same VuMark (also called a VuMark template), and read the IDs embedded in the images, ending up with 4 images and unique ID count of 2. In the image on the right, we can see how we can control what is being displayed on top of these markers based on their embedded IDs.

Note that this post is not about how to get Vuforia up and running within Unity, or on how to generate a VuMark. It assumes you are already familiar with the basic of AR, Vuforia, VuMarks and VuMark generation, if not see the resources linked below. Also it is not about whether VuMarks are the right choice for you, since VuMarks are more complicated to generate than simple image markers, make sure that VuMarks are right for your specific situation.

That said, let’s have a look at how we can control what is visible on a VuMark through its embedded (string) ID. Vuforia uses a very ingenious system when it comes to VuMarks of which the basic principle is this:

  1.  To use a VuMark, you first have to create a VuMark template using Adobe Illustrator and the plugin provided by Vuforia.
    It is called a template, because many ‘instances’ of the template can be generated, each with their own unique ID.
  2. After finishing the template, you import it into the target manager, specifying the type and length of your ID, so that you can create a downloadable unity package for your application (aka target ‘database’) AND generate instances of your template for download and print. Note however that the downloadable unity package contains enough info to recognize any pattern that can be encoded using your template, whether you actually generate, download and print it or not.
  3. After importing this unity package, you create a VuMark GameObject in your scene through the GameObject/Vuforia/VuMark menu, and navigating to the VuMarkBehaviour script on this object, select the correct database AND the VuMark template. Note that you cannot specify an ID or whatever for this instance, it will match all possible images that can be generated from your chosen template. Because you cannot specify an ID, you can also NOT have multiple copies of the same VuMark template in your scene, because Unity wouldn’t know which one to pick. Any duplicates will award you with some warnings in your console.
  4. Upon recognizing a VuMark in front of the camera, Unity/Vuforia will display any content that you attached to your marker in the editor on top of the marker image in your video feed, and as such it seems nothing is different yet from using a standard image marker for example. However…
  5. … when and only when Vuforia at runtime detects multiple instances of your VuMark template being held up in front of the camera, it will clone your VuMark gameobject with all its content and display the cloned content on the respective marker. Removing the marker image from the feed, will not remove the clones, it will merely deactivate them.

That is it for the basic process, but where and how do these aforementioned IDs come into play?
And how can we control what is displayed on an instance of a VuMark based on its ID?

As said the first thing that happens when you move a marker image in front of the camera is that Vuforia recognizes it and starts tracking it. Using event handlers we can register ourselves to be notified when this happens:


	private void Awake()
	{
		TrackerManager.Instance.
			GetStateManager().
			GetVuMarkManager().
			RegisterVuMarkBehaviourDetectedCallback(onVuMarkBehaviourFound);
	}

The second thing that happens is that Vuforia actually reads the ID encoded in the VuMark, wraps this in a so-called VuMarkTarget and assigns it to the VuMarkBehaviour in question. We can register for that event as well, however to make sure we do not register ourselves for these target-assigned-callbacks multiple times, we should keep a list of VuMarkBehaviour that were found previously:

List<VuMarkBehaviour> registeredBehaviours = new List<VuMarkBehaviour>();

private void onVuMarkBehaviourFound(VuMarkBehaviour pVuMarkBehaviour)
{
    //check if we have already registered for the target assigned callbacks
    if (registeredBehaviours.Contains(pVuMarkBehaviour))
    {
        log("Previously tracked VumarkBehaviour found (" + pVuMarkBehaviour.name+")");
    } else
    {
        log("Newly tracked VumarkBehaviour found (" + pVuMarkBehaviour.name + ")");
        log("Registering for VuMarkTargetAssignedCallbacks from " + pVuMarkBehaviour.name);
 
        //if we hadn't registered yet, we do so now
        registeredBehaviours.Add(pVuMarkBehaviour);
 
        pVuMarkBehaviour.RegisterVuMarkTargetAssignedCallback(
            () => vumarkTargetAssigned(pVuMarkBehaviour)
        );
    }
}

Last but not least, as this target-assigned-callback is being triggered, we now have a) a reference to the VuMarkBehaviour (and thus its GameObject) in question, and a reference to its assigned VuMarkTarget aka its ID. Using this information we can setup a system where we add multiple children to the VuMark in the editor, and selectively enable or disable them based on the ID that we received through the callback. The easiest approach here is to map the IDs to the names of the VuMark’s child game objects:

	/**
	 * Every time a vumarkTarget is assigned to a specific vuMarkBehaviour
	 * we can process it's children to make sure only the right ones are visible.
	 */
	private void vumarkTargetAssigned(VuMarkBehaviour pVuMarkBehaviour)
	{
		log("VuMarkTarget assigned to " + pVuMarkBehaviour.name + " with ID:"+pVuMarkBehaviour.VuMarkTarget.InstanceId.ToString());
	
		string myID = GetID(pVuMarkBehaviour.VuMarkTarget.InstanceId);

		log("Enabling object with ID:" + myID + " ....");

		foreach (Transform child in pVuMarkBehaviour.transform)
		{
			log("Matching gameObject " + child.name + " with ID " + myID + " SetActive (" + (myID == child.name) + ")");
			child.gameObject.SetActive(myID == child.name);
		}
	}

Note that Vuforia fills out any ID strings with string terminator characters if you do not provide enough info, so you might want to use some sort of getID method to sanitize the IDs:

public int IDLength = 2;

/**
 * Helper method to sanitize the returned ID's
 */
private string GetID (InstanceId pInstanceId)
{
	int inputLength = pInstanceId.StringValue.Length;
	int outputLength = Mathf.Min(IDLength, inputLength);
	string subString = pInstanceId.StringValue.Substring(0, outputLength);
	return subString;
}

And to turn the logging on/off we include our own conditional log method:

	[Conditional("VUMARKHANDLER_DEBUG")]
	private void log (string pInfo)
	{
		UnityEngine.Debug.Log("VUMARKHANDLER:"+pInfo);
	}

To use the script above, create an empty GameObject in your scene next to your VuMark, drag the VuMarkHandler script on it, and rename the GameObject appropriately (ILoveCoding? VuMarkHandler? IDSRules? :)) and inform the script of the length of your IDs (note: not the amount of IDs but the length. This also implies all your IDs should have the same length).

Alternatively for a more detailed example of how this works please download this sample project: VuMarkHandlerDemo (120 downloads) , and print these default markers from Vuforia.
Once downloaded and opened, don’t forget to fill in your App License Key in the VuforiaConfiguration.
Run the project, hold up the printed markers in front of the camera and see the script in action.

That’s it!

One final note before ending this post, let’s take a short moment to discuss some implications of not using unique IDs.

Imagine this scenario:

  • we hold up two identical images up in front of the camera, one Image A in our left hand and one Image A in our right hand.
  • as explained above Vuforia will clone your VuMark instance and display the marker’s content once for each instance in front of the camera, which of course is then also identical.
  • now let’s say, you are doing something with this content based on some (random?) condition, for example changing its state, the way an animation plays, the speed of an animation, the color of a model. So we get for example a blue model X on Image A in our left hand and a green model X on the other Image A in our right hand.
  • now you move the images out of the camera’s view frustum and then back in again. All Vuforia sees is two instances of the same template with the same ID again. There is nothing there to control that the blue model X ends up on Image A in your left hand again and green on the other, they could as well be swapped. That is only possible when you do use unique IDs. Of course this all makes sense and is very logical, but still it is something I think you should be aware of.
image_pdfimage_print
0 replies

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *