Please complete steps in the Setup section before building your application.

Before Start

There are some steps that is required before start the detection:

  1. Make sure to accquire camera permission before starting detection on Android.
  2. Call UseExternalTransform() function if needed.
  3. Call SetARCoreSession() function before starting detection if using ARCore.

Start Detection

Call StartGestureDetection() function to start hand detection. This function is non-blocking, detection will be started in a background thread.

Caller can set max raw detection fps limit within the GestureOption struct. Option is modified to return what mode is selected in current detection.

The return value of the function indicates if any error occured during the start.

Calling this function when detection is already started is an no-op. The return value is always GestureFailure::GestureFailureNone, option is modified to return current running mode.

Sample Usage
GestureOption option;
// Add your code here to modify option
// option.maxFPS = ...

// Start detection and check result
GestureFailure result = StartGestureDetection(&option);
if (result != GestureFailureNone) {
  std::cout << "Detection start failed with error: " << result << std::endl;
std::cout << "Detection started with mode: " << option.mode << std::endl;

Set HMD Transform

If you have called UseExternalTransform(true) before start, you need to call SetCameraTransform() function every frame to provide HMD transform.


It’s recommended to start calling SetCameraTransform() function before detection start. This can make sure the first detection frame is using correct HMD transform.

Getting Detection Result

After detection is started, call GetGestureResult() frequently to fetch hand result. We suggest to fetch results in higher frequency than detection speed based on platform and modes. Fetching results in same speed as rendering is recommended. The function returns an array of GestureResult and an optional frame index.

The result array is managed by Vive Hand Tracking SDK, the caller don’t need to malloc/free the pointer. The array is valid until next call to GetGestureResult() or StopGestureDetection().

The frame index is used as a hint to show if hand results are changed or not. The result array is guanranteed to be same if frame index is not changed. Therefore, heavy computation that depends only on hand result can be safely skipped in such cases.


The points are returned in Unity3D coordinate system, i.e. +x is right, +y is up, +z is forward, unit is meter. You may need to convert them to your coordinate system before use.

Sample Usage
const GestureResult* points = NULL;
int lastFrameIndex = -1;

// pseudo game loop
while (true) {
  int frameIndex = -1;
  int size = GetGestureResult(&points, &frameIndex);
  if (frameIndex < 0) {
    std::cout << "Gesture detection start failed with error: " << result << std::endl;
  } else if (frameIndex == lastFrameIndex)

  lastFrameIndex = frameIndex;
  // do stuffs with points
  for (int i = 0; i < size; i++)
    std::cout << "Hand " << i << " is " << points[i].isLeft ? "left" : "right" << " hand" << std::endl;

Stop Detection

Call StopGestureDetection() function to stop hand detection. This function is blocking, it returns after the detection is stopped. Calling this function when detection is not started is an no-op.