Model Targets Workflow

3.0 Workflows and Pseudocode

We describe the general usage of the API.

3.1 Init and Destroy ObjectTracker

To use model targets, initialize the ObjectTracker

TrackerManager& trackerManager = TrackerManager::getInstance(); 
ObjectTracker* objectTracker = static_cast<ObjectTracker*>trackerManager.initTracker(
    Vuforia::ObjectTracker::getClassType());

To destroy the ObjectTracker:

TrackerManager& trackerManager = TrackerManager::getInstance(); 
trackerManager.deinitTracker(Vuforia::ObjectTracker::getClassType()); 

3.2 Create and Configure the Model Dataset

A CAD Model Dataset is created from the Object Tracker. A CAD Model Dataset can be loaded from the created instance of a Dataset object:

DataSet* datasetCAD = objectTracker->createDataSet(); 
if (DataSet::exists("KTM.xml", Vuforia::STORAGE_ABSOLUTE)) 
    datasetCAD->load("KTM.xml", Vuforia::STORAGE_ABSOLUTE);

Loaded Dataset needs to be activated to be usable by the tracker (before starting the tracker and after load):

objectTracker->activateDataSet(datasetCAD);

Loaded Dataset needs to be deactivated after using the tracker (after stopping the tracker):

objectTracker->deactivateDataSet(datasetCAD);

Finally, the dataset needs to be destroyed after usage (after stopping the tracker and deactivating the dataset):

objectTracker->destroyDataSet(datasetCAD); 

3.3 Use the Guide View

Access the guide view from the Dataset:

ModelTarget* modelTarget = nullptr;
for (int i = 0; i < dataSetCAD->getNumTrackables(); ++i) 
{ 
    Trackable* trackable = dataSetCAD->getTrackable(i); 
    if (trackable->isOfType(ModelTarget::getClassType())) 
    {  
        modelTarget = static_cast<ModelTarget*>(trackable); 
        break; 
    } 
} 

Rendering the guide view using a textured rectangle overlay (from your render loop):

// Initialization code 
if (modelTarget && modelTarget->getGuideView(0) && modelTarget->getGuideView(0)->getImage())
{
    textureId = MyApp::createTexture(const_cast<Vuforia::Image*>(modelTarget->getGuideView(0)->getImage()));
}

MyApp::renderVideoBackground();

// Only display the guide when you don’t have tracking 
// scale your guide view with the video background rendering
if (state.getNumTrackableResults() == 0)
{    
    float guideViewAspectRatio = (float)modelTarget->getGuideView(0)->getImage()->getWidth() / 
        modelTarget->getGuideView(0)->getImage()->getHeight();
    float cameraAspectRatio = (float)viewport.data[2] / viewport.data[3];

    float planeDistance = 0.01f;
    float fieldOfView = Vuforia::CameraDevice::getInstance().getCameraCalibration().getFieldOfViewRads().data[1];
    float nearPlaneHeight = 2.0f * planeDistance * tanf(fieldOfView * 0.5f);
    float nearPlaneWidth = nearPlaneHeight * cameraAspectRatio;

    float planeWidth;
    float planeHeight;

    int guideViewSign = (0.0f < (guideViewAspectRatio - 1.0f)) - ((guideViewAspectRatio - 1.0f) < 0.0f);
    int cameraSign = (0.0f < (cameraAspectRatio - 1.0f)) - ((cameraAspectRatio - 1.0f) < 0.0f);

    if (guideViewSign == cameraSign)
    {
        // Scale the guide view to fit the horizontal fov while preserving the aspect ratio of the image.
        planeWidth = nearPlaneWidth;
        planeHeight = planeWidth / guideViewAspectRatio;
    }
    else if(cameraAspectRatio < 1.0f) // guideview landscape, camera portrait
    {
        // scale so that the long side of the camera (height) is the same length as guideview width
        planeWidth = nearPlaneHeight;
        planeHeight = planeWidth / guideViewAspectRatio;
    }
    else // guideview portrait, camera landscape
    {
        // scale so that the long side of the camera (width) is the same length as guideview height
        planeHeight = nearPlaneWidth;
        planeWidth = planeHeight * guideViewAspectRatio;
    }

    Vuforia::Vec2F scale = Vuforia::Vec2F(2.0f * planeWidth / nearPlaneWidth, -2.0f * planeHeight / nearPlaneHeight);

    // render the guide view image using an orthographic projection
    MyApp::renderRectangleTextured(scale, color, textureId);
}

3.4 Start and Stop the Model Tracker

Start the Model Tracker:

objectTracker->start();

Stop the Model Tracker:

objectTracker->stop();

3.5 Parse Model Target Result

void render() 
{
    const Vuforia::State state = Vuforia::TrackerManager::getInstance().getStateUpdater().updateState();

    // Find the CAD-defined object pose from the state.
    if (trackableResult->isOfType(ModelTargetResult::getClassType()))
    {
        const Vuforia::ModelTargetResult* otResult = static_cast<const Vuforia::ModelTargetResult*>(trackableResult); 
        const Vuforia::ModelTarget& ot = otResult->getTrackable(); 

        Vuforia::Matrix44F modelViewMatrix = Vuforia::Tool::convertPose2GLMatrix(trackableResult->getPose()); 

        // render with the pose, the coordinate system needds to be know to place augmentation 

        // Get the size of the CAD Model 
        Vuforia::Vec3F targetScale = Vec3F(ot.getSize().data[0], ot.getSize().data[1], ot.getSize().data[2]); 

        MyApp::renderBoxWireframe(modelViewMatrix, targetScale, colorRed); 
    }
}

3.6 Use Extended Tracking with Model Dataset

Query extended tracking support at run-time (that should be done after the tracker has started):

objectTrackerStarted = objectTracker->start(); 

// check if ET is supported 
for (int i = 0; i < dataSetCAD->getNumTrackables(); ++i)
{
    // on start ET is always on 
    if (dataSetCAD->getTrackable(i)->isExtendedTrackingStarted()) 
    {
        printf("Extended Tracking is activated for trackable %i", i); 
    }
    else
    {
        printf("Extended Tracking is not activated/available for trackable %i", i); 
    } 
} 

Please note that the status of ET support won’t change after the tracker has started, so no need to query that frequently in your update loop.

4.0 Public API Changes

The ModelTarget class extends the standard ObjectTarget with methods related to querying the bounding box and associated guide views.

/// A target for tracking rigid three-dimensional bodies.
class VUFORIA_API ModelTarget : public ObjectTarget
{
public:

    /// Returns the Trackable class' type
    static Type getClassType();

    /// Returns the system-wide unique id of the target.
    /**
    *  The target id uniquely identifies an ObjectTarget across multiple
    *  Vuforia Engine sessions. The system wide unique id may be generated off-line.
    *  This is opposed to the function getId() which is a dynamically
    *  generated id and which uniquely identifies a Trackable within one run
    *  of Vuforia Engine only.
    */
    virtual const char* getUniqueTargetId() const = 0;

    /// Returns the size (width, height, depth) of the target (in 3D scene units).
    virtual Vec3F getSize() const = 0;

    /// Set the size (width, height, depth) of the target (in 3D scene units).
    /**
    *  The dataset this target belongs to should not be active when calling
    *  this function, otherwise it will fail.
    *  We expect the scale factor to be uniform, and if the given size
    *  corresponds to non-uniform scaling based on the original size,
    *  we return false.
    *  Returns true if the size was set successfully, false otherwise.
    */
    virtual bool setSize(const Vec3F& size) = 0;

    /// Gets the bounding box of the target (in 3D scene units)
    /**
     * If the bounding box has been queried and setSize is called, getBoundingBox()
     * needs to be called again to have the correct size.
     */
    virtual const Obb3D& getBoundingBox() const = 0;

    /// Returns the number of guide views
    /**
    * guide views are the entry points that the application can use to snap to the trackables
    */
    virtual int getNumGuideViews() const = 0;

    /// Returns a pointer to a GuideView object
    /**
    * The pointer to the guide view is not owned by the caller of this function.
    * The application can use the information stored in GuideView to provide visual
    * feedback to use user about how to position the camera in order to snap to a
    * specific object
    */
    virtual GuideView * getGuideView(int idx) = 0;
}; 

The GuideView class provides access to the 2D guide view images and the associated pose and camera intrinsics. It also alows overriding the detection pose for scenarios where the pose is to be changed dynamically at runtime.

/// A guide view used to initialize snapping of ModelTargets
/**
 * The Guide View provides visual guide information that
 * that can be used to bootstrap a ModelTarget.
 */
class VUFORIA_API GuideView : private NonCopyable
{
public:
    /// Returns the intrinsics parameters of the camera associated to this view
    virtual const CameraCalibration& getIntrinsics() const = 0;

    /// Returns the extrinsics parameters of the camera associated to this view. 
    // Please note that the pose is defined in the Camera Coordinate System, and not the opposite.
    virtual const Matrix34F& getPose() const = 0;

    /// Alters the pose of the given guide view. This consequently will set the returned guide image to null,
    /// since it will not be re-rendered
    virtual void setPose(const Matrix34F& pose) = 0;

    /// Returns the image associated to this view
    virtual const Image* getImage() const = 0;

    virtual ~GuideView() {}
};
 

‹‹ Previous – 2.0; API Overview