Working with VuMarks

Unity

The Vuforia VuMark Sample project provides a pre-configured VuMark scene that you can use as a reference and starting point for your own VuMark apps. This document will show you how to author content using VuMarks in the sample, how to customize event handling for the detection and tracking of VuMarks, and how to read and respond to data encoded in a VuMark.

Vuforia Image

Importing the sample

The VuMark sample is in the VuforiaSamples sample app or in the Unity Asset Store. Import the VuforiaSamples.unitypackage into a new Unity project.

Enable "Vuforia Augmented Reality" in the Unity "XR Settings" panel in Player Settings/

Adding a License Key

Here is a table that summarizes the dependencies between the VuMark feature and the Vuforia license type:

Vuforia License Type

VuMark Target Manager Capabilities

Vumark SDK Capabilities

Development, Classic & Cloud
  • One (1) VuMark target per downloaded database
  • Ability to generate 100 VuMark instances per target
Load and activate one (1) VuMark database per app
Pro & Enterprise
  • Unlimited VuMark targets per downloaded database
  • Ability to generate 100+ VuMark instances per target
Load and activate more than one (1) VuMark database per app

For additional details about the capabilities of each Vuforia license type, please refer to our pricing page.

Note that one of the behaviors of attempting to load and activate more than one (1) VuMark database using a Development, Classic or Cloud license is that only one database will be enabled. The database enabled depends upon the order in which they are activated.

Build Settings

To build the sample, add all of the scenes in the /SamplesScenes folder to Scenes In Build in the File > Build Settings dialog. Select Android, iOS or Universal Windows Platform as the build Platform.

Selecting Build for either Universal Windows Platform or iOS will generate a native project archive for those platforms. You will then need to build an executable from those tools.

Vuforia Image

Building and executing the sample

  1. Set your platform build target for either IOS, Android or Universal Windows Platformin File > Build Settings.
  2. Add your scene(s) to Scenes in Build.
  3. Define a unique Bundle ID in Player Settings > Other Settings.
  4. Define a unique Product Name to serve as the name of the app when installed on a device.
  5. Select Build to generate an executable or Build & Run to both generate an executable and deploy it to a connected device.
    There is no need to change any of the default Player Settings to support VuMarks. You can customize the presentation of your app on the device by adding icons and splash images in Player Settings and setting the app's device orientation.
    Note: Be sure to set your build target for x86 in Visual Studio 2015 when targeting the Windows Store platform.


To package your app for all UWP devices, See: https://msdn.microsoft.com/en-us/library/hh454036.aspx

Scene Elements and their Configuration

Vuforia Image

The sample's scene Hierarchy demonstrates how to set-up a Vuforia VuMark scene in Unity.

VuMarkUI

The VuMarkUI object contains the UI elements that are populated with the instance ID information that is decoded from the VuMark when it is recognized. See the VuMarkHandler.cs script to understand how this data is retrieved and written to these UI fields.

ARCamera

The ARCamera GameObject represents both the device camera and scene camera.

VuMark

The VuMark GameObject encapsulates the VuMarkBehavior and VuMark Trackable Event Handler. These are the primary script components that you will use to customize an app that uses VuMarks.

Database: defines the dataset to use for this project

VuMark: defines which VuMark template to use from the Database

Width: width of the VuMark template

Height: height of the VuMark template

Preserve Child Size: retains content scale when its parent VuMark is rescaled

Enable Extended Tracking: activates the extended tracking feature to support content registration when the VuMark is not in view.

You can also activate extended tracking programmatically by calling StartExtendedTracking() on the VuMarkTemplate for a given VuMarkBehaviour. See: Enabling Extended Tracking below.

Vuforia Image

Significant Scripts for Customization

Default Trackable Event Handler

The VuMark Trackable Event Handler component is responsible for handling callbacks to the VuMark Behaviour arising from changes in the state of the VuMark Trackable, such as when it has been detected and is then being tracked.
This script is used to enable and disable rendering and collision detection on digital content that is a child of the VuMark.
Extend this script s OnTrackingFound() and OnTrackingLost() methods to implement custom event handling for your app.

VuMarkEvent Handler

The VuMark Handler implements the ITrackableEventHandler interface to respond to callbacks in the same way that the DefaultTrackableEventHandler does. This event handler is responsible for querying the InstanceId of the VuMark that has been found and to pass its data to the sample UI.

Using PlayMode

Vuforia supports rapid application development in Unity using a webcam. You can activate Vuforia PlayMode by pressing the Play button at the top of the Unity Editor.

See: Vuforia Play Mode for Unity

Enabling Extended Tracking

Extended tracking enables you to maintain tracking for a scene even when the VuMark isn t in the camera view. This enables you to place content further away from the VuMark, See: Extended Tracking

You can enable extended tracking at build time by selecting it on the VuMark Behaviour component, or at runtime by by calling StartExtendedTracking() on the VuMarkTemplate for a given VuMarkBehaviour.

Example:

VuMarkBehaviour vmb = tb as VuMarkBehaviour;
vmb.VuMarkTemplate.StartExtendedTracking();

Printing VuMarks

You can obtain printable instances of your VuMark from either the Target Manager, or by using the VuMark Generation API.

See:
Generating A VuMark Instance in the Target Manager
Using the VuMark Generation API


Visual Studio 2015

This article will guide you through the steps for setting up the Vuforia UWP SDK and VuMarks sample in Visual Studio 2015.

Installing the SDK and Sample

Unpack the Vuforia UWP SDK at a suitable location in your development environment

Go to the samples directory in the SDK root folder

User-added image

Unpack the VuMark sample into the /samples folder

User-added image

Double click the *.sln file in the VuMark sample folder to load the sample project in Visual Studio 2015

Running the sample

Obtain a license key from developer.vuforia.com and add it to your project, See: How To Create a License Key
Add this key to the the InitAR() method in AppSession.cpp

  void AppSession::InitAR()
   {
    const char *licenseKey = "add your key here";
    Vuforia::setInitParameters(licenseKey);    
    auto initVuforiaTask = InitVuforiaAsync();
    auto initTrackersTask = initVuforiaTask.then([this](int result) {    
        if (result < 0) {
            ThrowInitError(result);
        }        
        if (!m_appControl->DoInitTrackers()) {
            throw ref new Platform::Exception(E_FAIL, "Failed to init Trackers.");
        }
    });

    auto loadTrackersDataTask = initTrackersTask.then([this]() {
        if (!m_appControl->DoLoadTrackersData()) {
            throw ref new Platform::Exception(E_FAIL, "Failed to Load Tracker Data.");
        }
        m_vuforiaInitialized = true;
        m_appControl->OnInitARDone();
    });

You can now build and run the sample.

Note: If Visual Studio does not recognize the include path for the sample project, you ll need to add it via the Properties dialog for the VuMark project by right clicking the project name in the project inspector. Add the Vuforia folder to the include path.

User-added image


Be sure to set your build target for x86, be aware that 64bit builds are not supported.

User-added image

To package your app for all UWP devices, See: https://msdn.microsoft.com/en-us/library/hh454036.aspx

User-added image

Modifying the Sample

Obtaining the Trackable State

The State object contains references to all current TrackableResults. You can obtain if from the Vuforia Renderer instance, as shown in the Render() method in VuforiaRenderer.cpp.

 

    // Renders one frame using the vertex and pixel shaders.
    void VuMarkRenderer::Render()
    {
        // Vuforia initialization and data loading is asynchronous.
        // Only starts rendering after Vuforia init/loading is complete.
        if (!m_rendererInitialized || !m_vuforiaStarted)
        {
            return;
        }
    
        // Get the state from Vuforia and mark the beginning of a rendering section
        Vuforia::DXRenderData dxRenderData(m_deviceResources->GetD3DDevice());
        const Vuforia::State state = Vuforia::TrackerManager::getInstance().getStateUpdater().updateState();
    
        Vuforia::Renderer &vuforiaRenderer = Vuforia::Renderer::getInstance();
        vuforiaRenderer.begin(state, &dxRenderData);
    
        RenderScene(vuforiaRenderer, state);
    
        RenderReticle();
    
        vuforiaRenderer.end();
    }

Querying Trackable Results

Once you have the State object, you can query the state of each TrackableResult to access its pose, determine its type, and obtain a reference to its associated Trackable instance.

The TrackableResult will enable you to retrieve the VuMark s instance ID.

    for (int tIdx = 0; tIdx < state.getNumTrackableResults(); tIdx++)
    {
        // Get the trackable:
        const Vuforia::TrackableResult *result = state.getTrackableResult(tIdx);
        const Vuforia::Trackable &trackable = result->getTrackable();
        const char* trackableName = trackable.getName();
    
        if (result->isOfType(Vuforia::VuMarkTargetResult::getClassType()))
        {
            gotVuMark = true;
    
            const Vuforia::VuMarkTargetResult* vmResult = (const Vuforia::VuMarkTargetResult*)result;
            const Vuforia::VuMarkTarget &vmTarget = vmResult->getTrackable();
    
            // This boolean teels if the current VuMark is the 'main' one,
            // i.e either the closest one to the camera center or the only one
            bool isMainVumark = (indexVuMarkToDisplay < 0) || (indexVuMarkToDisplay == tIdx);
    
            const Vuforia::VuMarkTemplate& vmTemplate = vmTarget.getTemplate();
            const Vuforia::InstanceId & vmId = vmTarget.getInstanceId();
            const Vuforia::Image & vmImage = vmTarget.getInstanceImage();
    
            if (isMainVumark)
            {
                char vmId_cstr[VUMARK_ID_MAX_LENGTH + 1];
                ConvertInstanceIdToString(vmId, vmId_cstr);
    
                char vmType_cstr[16];
                GetInstanceType(vmId, vmType_cstr);
    
                // if the vumark has changed, we hide the card
                // and reset the animation
                if (strcmp(vmId_cstr, currVuMarkId.c_str()) != 0)
                {
                    BlinkVumark(true);
    
                    // Hide the VuMark Card
                    if (m_uiDispatcher != nullptr)
                    {
                        m_uiDispatcher->RunAsync(
                            Windows::UI::Core::CoreDispatcherPriority::Normal,
                            ref new Windows::UI::Core::DispatchedHandler([this]()
                        {
                            m_vuMarkView->HideVuMarkCard();
                        }));
                    }
                }
    
                Platform::String^ vmIdStr = SampleCommon::SampleUtil::ToPlatformString(vmId_cstr);
                Platform::String^ vmTypeStr = SampleCommon::SampleUtil::ToPlatformString(vmType_cstr);

Rendering Content

The pose obtained from this result can then be used to render content onto the VuMark in the camera view.

    // build Bitmap from Vuforia::Image and pass it here
    int vmImgWid = vmImage.getWidth();
    int vmImgHgt = vmImage.getHeight();
    m_vuMarkView->UpdateVuMarkInstance(
        vmIdStr, vmTypeStr, vmImgWid, vmImgHgt,
        (byte*)vmImage.getPixels()
    );
}

    // Set up the modelview matrix
    auto poseGL = Vuforia::Tool::convertPose2GLMatrix(result->getPose());
    XMFLOAT4X4 poseDX;
    memcpy(poseDX.m, poseGL.data, sizeof(float) * 16);
    XMStoreFloat4x4(&poseDX, XMMatrixTranspose(XMLoadFloat4x4(&poseDX)));
    XMMATRIX xmPose = XMLoadFloat4x4(&poseDX);
    
    float opacity = isMainVumark ? BlinkVumark(false) : 1.0f;
    float vmOrigX = -vmTemplate.getOrigin().data[0];
    float vmOrigY = -vmTemplate.getOrigin().data[1];
    float vmWidth = vmTarget.getSize().data[0];
    float vmHeight = vmTarget.getSize().data[1];
    if (!m_augmentationTexture->IsInitialized()) {
        m_augmentationTexture->Init();
    }
    
    // Combine the device pose (view matrix) with the model matrix
    xmPose = DirectX::XMMatrixMultiply(XMLoadFloat4x4(&devicePoseMatrixDX), XMLoadFloat4x4(&poseDX));
    
    RenderVuMark(vmOrigX, vmOrigY, vmWidth, vmHeight, xmPose, xmProjection, m_augmentationTexture,     opacity);
    }
}

Camera Device Mode: Setting enables your to prioritize render quality vs frame rate for your app. Selecting MODE_DEFAULT will typically prioritize rendering except on devices with lower performance characteristics.

Max Simultaneous Tracked Images: this value defines the maximum number of targets that can be tracked simultaneously.

World Center Mode: defines which object in the scene will serve as the origin ( 0,0,0 ) of the scene s world space. When SPECIFIC_TARGET is chosen the World Center field is presented, enabling you to select which target is used as the scene origin.