Project Setup
The following files need to be included in your project
File(s) | Purpose |
.h files from the include directory | C header files for the API |
One of the libraries from lib directory | The Tilt Five NDK support library |
Using the Glasses
Service Connection
Most of the operations performed with the glasses are not done directly by the client, but are performed by the Tilt Five™ service on behalf of the client.
The connection to the service is not guaranteed to always be available. Scenarios where the service is unavailable include:
- During client startup there can be a small delay before the connection is established.
- The service is not installed (e.g. User hasn't installed the Tilt Five™ drivers).
- The service may have crashed or been stopped by a user. As such, all queries should anticipate a response of T5_ERROR_NO_SERVICE and retry appropriately (assuming it's a transient condition).
A trivial example of handling this is shown below:
433 bool waiting =
false;
440 printf(
"Service version : %s\n", serviceVersion);
446 printf(
"Waiting for service...\n");
#define T5_MAX_STRING_PARAM_LEN
The maximum number of characters allowed for string values.
@ kT5_ParamSys_UTF8_Service_Version
Version of the service software - UTF8.
T5_EXPORT const char * t5GetResultMessage(T5_Result result)
#define T5_ERROR_NO_SERVICE
Service isn't connected.
T5_EXPORT T5_Result t5GetSystemUtf8Param(T5_Context context, T5_ParamSys param, char *buffer, size_t *bufferSize)
Get a system-wide UTF-8 encoded string parameter.
Threading
All calls are blocking, and their thread safety is documented on each call. Generally, calls are grouped into a number of groups. From each group only one function should should be called concurrently. Calls may be made to functions in different groups concurrently. Additionally, some calls require specific threads (such as graphics related functions like t5InitGlassesGraphicsContext() and t5SendFrameToGlasses()).
Operations
Depending on the level of access required to the API, there are one or more setup steps. Details are shown below with example code. Further details of the API are here documented in the Tilt Five™ Native Interface (C).
Create Context
404 .applicationVersion =
"1.0.0",
412 printf(
"Failed to create context\n");
uint32_t T5_Result
Represents an error code that may be returned by the Tilt Five™ API.
struct T5_ContextImpl * T5_Context
Opaque handle used with system-wide functions.
T5_EXPORT T5_Result t5CreateContext(T5_Context *context, const T5_ClientInfo *clientInfo, void *platformContext)
Create a context object.
Client provided information for use with t5CreateGlasses()
const char * applicationId
The application ID.
Release Context
The context should be released after it's finished with
T5_EXPORT void t5DestroyContext(T5_Context *context)
Destroy a context object.
System-wide Queries
System-wide queries require nothing more than a client to perform. Most of these operations are querying the service for common parameters such as the service version (t5GetSystemUtf8Param() and fixed physical parameters (t5GetGameboardSize()).
422 printf(
"Failed to get gameboard size\n");
424 printf(
"LE Gameboard size : %fm x %fm x %fm\n",
@ kT5_GameboardType_LE
An LE gameboard.
T5_EXPORT T5_Result t5GetGameboardSize(T5_Context context, T5_GameboardType gameboardType, T5_GameboardSize *gameboardSize)
Get the gameboard dimensions.
Physical dimensions of a gameboard.
float viewableExtentNegativeY
The distance in meters from the gameboard origin to the edge of the viewable area in the negative Y d...
float viewableExtentPositiveZ
The distance in meters above the gameboard origin that the viewable area extends in the positive Z di...
float viewableExtentPositiveY
The distance in meters from the gameboard origin to the edge of the viewable area in the positive Y d...
float viewableExtentNegativeX
The distance in meters from the gameboard origin to the edge of the viewable area in the negative X d...
float viewableExtentPositiveX
The distance in meters from the gameboard origin to the edge of the viewable area in the positive X d...
Enumerate Glasses
458 size_t bufferSize = GLASSES_BUFFER_SIZE;
459 char glassesListBuffer[GLASSES_BUFFER_SIZE];
462 size_t glassesCount = 0;
464 const char* buffPtr = glassesListBuffer;
468 size_t stringLength = strnlen(buffPtr, GLASSES_BUFFER_SIZE);
469 if (stringLength == 0) {
473 fprintf(stderr,
"Glasses : %s\n", buffPtr);
T5_EXPORT T5_Result t5ListGlasses(T5_Context context, char *buffer, size_t *bufferSize)
Enumerate all glasses.
At this point buffPtr
contains a glasses identifier suitable for Create Glasses 'creating/selecting glasses'.
481 buffPtr += stringLength;
482 if (buffPtr > (glassesListBuffer + GLASSES_BUFFER_SIZE)) {
483 printf(
"Warning: list may be missing null terminator");
488 printf(
"Listed glasses [%zu found]\n", glassesCount);
494 printf(
"Waiting for service...\n");
Create Glasses
Creating glasses handles requires a hardware identifier (id
below) for the glasses as well as some information about the client.
285 printf(
"Created glasses : '%s'\n",
id);
struct T5_GlassesImpl * T5_Glasses
Opaque handle used with glasses.
T5_EXPORT T5_Result t5CreateGlasses(T5_Context context, const char *id, T5_Glasses *glasses)
Create a glasses access object.
Non-exclusive Operations
Some glasses operations are available without acquiring exclusive access. These include operations to query stored parameters about glasses such as the IPD (t5GetGlassesFloatParam()) and user specified friendly name (t5GetGlassesUtf8Param()). Additionally, accessing the Wand Stream 'wand stream' does not require an exclusive connection.
225 printf(
"Watching for changes to settings... (forever)\n");
227 uint16_t
count = PARAM_BUFFER_SIZE;
236 for (
int i = 0; i <
count; i++) {
237 switch (paramBuffer[i]) {
242 printf(
"Error getting changed IPD for '%s' : %s\n",
248 printf(
"IPD changed for '%s' : %f\n",
id, value);
255 glassesHandle, paramBuffer[i], 0, buffer, &bufferSize);
257 printf(
"Error getting changed friendly name for '%s' : %s\n",
263 printf(
"Friendly name changed for '%s' : '%s'\n",
id, buffer);
constexpr iterator_traits< _InputIterator >::difference_type count(_InputIterator __first, _InputIterator __last, const _Tp &__value)
T5_ParamGlasses
Possible parameters that can be retrieved for glasses.
@ kT5_ParamGlasses_Float_IPD
Interpupillary distance - Float, millimeters
@ kT5_ParamGlasses_UTF8_FriendlyName
User-facing name of the glasses - UTF8.
T5_EXPORT T5_Result t5GetGlassesFloatParam(T5_Glasses glasses, T5_WandHandle wand, T5_ParamGlasses param, double *value)
Get a glasses floating point parameter.
T5_EXPORT T5_Result t5GetGlassesUtf8Param(T5_Glasses glasses, T5_WandHandle wand, T5_ParamGlasses param, char *buffer, size_t *bufferSize)
Get a glasses UTF-8 encoded string parameter.
T5_EXPORT T5_Result t5GetChangedGlassesParams(T5_Glasses glasses, T5_ParamGlasses *buffer, uint16_t *count)
Get a glasses-specific list of changed parameters.
Reserve for Exclusive
Other operations require exclusive access before a client can perform them. Only one client can have exclusive access to glasses at a time. Principally, obtaining the current pose (t5GetGlassesPose()) and sending frames for rendering (t5SendFrameToGlasses()) require exclusive access.
Essentially, this is a process of repeatedly calling t5ReserveGlasses() until the function returns success. This can succeed even if glasses are not fully available (for example due to rebooting). Once the glasses are marked exclusive, then it is time to ensure the glasses are ready for exclusive operations.
T5_EXPORT T5_Result t5ReserveGlasses(T5_Glasses glasses, const char *displayName)
Reserve glasses for exclusive operations by the client.
Ensure Ready for Exclusive
After a pair of glasses has been reserved, they need to be made fully ready for exclusive operations (e.g., getting the current glasses pose and sending frames) using t5EnsureGlassesReady()
. This may return an error that retry is needed if the glasses are not yet ready. Upon success, the glasses are ready for exclusive operations.
322 printf(
"Glasses ready : '%s'\n",
id);
#define T5_ERROR_TRY_AGAIN
Target is not currently available.
T5_EXPORT T5_Result t5EnsureGlassesReady(T5_Glasses glasses)
Ensure that reserved glasses are ready for exclusive operations.
Exclusive Operations
Once an exclusive connection has been established, you may perform exclusive operations such as t5GetGlassesPose() and t5SendFrameToGlasses().
176 printf(
"Getting some poses");
178 bool waiting =
false;
179 for (
int i = 0; i < 1000; i++) {
184 printf(
"\nWaiting...");
202 printf(
"\nGLASSES POSE : [%lu] (Board:%s) "
203 "[%6.4f, %6.4f, %6.4f] [%6.4f, %6.4f, %6.4f, %6.4f]",
@ kT5_GlassesPoseUsage_GlassesPresentation
The pose will be used to render images to be presented on the glasses.
T5_EXPORT T5_Result t5GetGlassesPose(T5_Glasses glasses, T5_GlassesPoseUsage usage, T5_GlassesPose *pose)
Get the latest pose of the glasses.
Glasses pose information to be retrieved with t5GetGlassesPose()
uint64_t timestampNanos
The timestamp of the pose.
T5_Vec3 posGLS_GBD
The position of the origin of the GLS (glasses) frame relative to the GBD (gameboard) frame.
T5_Quat rotToGLS_GBD
The rotation that transforms points in the GBD (gameboard) frame orientation to the GLS (glasses) fra...
T5_GameboardType gameboardType
The type of gameboard visible for this pose.
Release Exclusive Access
At any point after glasses have been reserved by a client, they can be released so that another client can reserve them instead without needing to destroy the whole glasses object or context. Use t5ReleaseGlasses() to restore availability to other clients.
T5_EXPORT T5_Result t5ReleaseGlasses(T5_Glasses glasses)
Wand Stream
Information about wand events is not delivered separately for each connected wand, but is instead multiplexed into a glasses global stream. Stream events are one of the following (T5_WandStreamEventType):
Event | Meaning |
Connect | Glasses have detected a wand has connected. |
Disconnect | Glasses have detected a wand disconnection. |
Desync | The wand stream has desynchronized, and the client may have missed one or more connection, disconnection or report packets. |
Report | A T5_WandReport is available detailing button, analog and positional data for a wand. |
Simplistically, accessing the wand stream is done by configuring the stream (t5ConfigureWandStreamForGlasses()) and then repeatedly polling the stream (t5ReadWandStreamForGlasses()).
112 for (
int i = 0; i < 100; i++) {
123 switch (event.
type) {
125 printf(
"WAND EVENT : CONNECT [%u]\n", event.
wandId);
129 printf(
"WAND EVENT : DISCONNECT [%u]\n", event.
wandId);
133 printf(
"WAND EVENT : DESYNC [%u]\n", event.
wandId);
137 printf(
"WAND EVENT : REPORT [%u] %fx%f\n",
@ kT5_WandStreamEventType_Connect
Wand connected.
@ kT5_WandStreamEventType_Disconnect
Wand disconnected.
@ kT5_WandStreamEventType_Report
Wand report (Pose, Buttons, Trigger, Stick, Battery)
@ kT5_WandStreamEventType_Desync
Stream has desynchronized.
#define T5_TIMEOUT
Timeout.
T5_EXPORT T5_Result t5ReadWandStreamForGlasses(T5_Glasses glasses, T5_WandStreamEvent *event, uint32_t timeoutMs)
Read from the wands event stream.
T5_EXPORT T5_Result t5ConfigureWandStreamForGlasses(T5_Glasses glasses, const T5_WandStreamConfig *config)
Configure the wand event stream.
T5_Vec2 stick
Stick (X/Y) - Analog, Range [-1.0 - 1.0], 0 = Centered, 1.0 = Top/Right.
Wand stream configuration.
bool enabled
Enable or disable the entire stream. True = enabled.
Represents an event from the wand stream.
T5_WandReport report
Report (Valid if type = kT5_WandStreamEventType_Report)
T5_WandStreamEventType type
Type of event.
T5_WandHandle wandId
Opaque identifier for the wand.