Skip to content

Commit a8dbe6d

Browse files
committed
qtm: to avoid confusion, eye tracking -> head tracking
1 parent e09a49a commit a8dbe6d

File tree

2 files changed

+35
-31
lines changed

2 files changed

+35
-31
lines changed

libctru/include/3ds/services/qtm.h

Lines changed: 32 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,20 @@
33
* @brief QTM services.
44
*
55
* QTM is responsible for the following:
6-
* - tracking and predicting the position of the user's eyes. This is done by using the inner
7-
* camera sampling at 320x240px at 30 FPS, and by using the gyroscope to predict the position
8-
* of the eyes between two camera samples (effectively doubling the tracking rate).
9-
* The API reporting eye tracking data is actually *console-agnostic*. This concept is most
6+
* - tracking and predicting the position of the user's head and eye position (head tracking).
7+
* This is done by using the inner camera sampling at 320x240px at 30 FPS, and by using
8+
* the gyroscope to predict the position of the eyes between two camera samples (effectively
9+
* doubling the tracking rate).
10+
* The API reporting head tracking data is actually *console-agnostic*. This concept is most
1011
* likely covered by patent US9098112B2
11-
* - automatically managing the IR LED emitter used for eye tracking in low-light conditions
12+
* - automatically managing the IR LED emitter used for head tracking in low-light conditions
1213
* - managing the state of the parallax barrier by controlling the positions of the barrier's
1314
* mask (opaque/transparent state by repeating pattern of 12 units, plus polarity). This is
1415
* done via a TI TCA6416A I2C->Parallel expander (highlighted in yellow in this teardown photo:
1516
* https://guide-images.cdn.ifixit.com/igi/IKlW6WTZKKmapYkt.full, with the expected 12 traces
16-
* being clearly visible near the ribbon cable slot)
17-
* - updating the barrier position according to eye tracking data relative to an optimal setting
17+
* being clearly visible near the ribbon cable slot); the parallax barrier polarity and pattern
18+
* is dithered by software approximately every frame.
19+
* - updating the barrier position according to head tracking data relative to an optimal setting
1820
* stored in calibration data: this is what Nintendo calls "Super Stable 3D" (SS3D); not done
1921
* when in 2D mode
2022
*
@@ -52,7 +54,7 @@
5254
* to blacklist or console being N2DSXL), `qtm:u` users should check Result return values, and `qtm:s`
5355
* users can call \ref QTMS_SetQtmStatus to check the actual availability status.
5456
*
55-
* Considering that the eye tracking data reporting API is hardware-agnostic, it is advisable to
57+
* Considering that the head tracking data reporting API is hardware-agnostic, it is advisable to
5658
* hardcode neither camera aspect ratio (even if it is 4/3 on real hardware) and resolution nor
5759
* field-of-view angle.
5860
*
@@ -138,18 +140,18 @@ typedef enum QtmEyeSide {
138140
QTM_EYE_NUM, ///< Number of eyes.
139141
} QtmEyeSide;
140142

141-
/// QTM raw eye tracking data
143+
/// QTM raw head tracking data
142144
typedef struct QtmRawTrackingData {
143145
/**
144146
* @brief Eye position detected or predicted, equals (confidenceLevel > 0).
145147
* If false, QTM will attempt to make a guess based on gyro data.
146148
* If the console isn't moving either, then QTM will assume the user's eyes are progressively
147149
* moving back to face the screen.
148150
*/
149-
bool eyesTracked; ///< Eye position detected or predicted, equals (confidenceLevel > 0).
151+
bool headTracked; ///< Eye position detected or predicted, equals (confidenceLevel > 0).
150152
u8 _padding[3]; ///< Padding.
151-
u32 singletonQtmPtr; ///< Pointer to eye-tracking singleton pointer, in QTM's .bss, located in N3DS extra memory.
152-
float confidenceLevel; ///< Eye tracking confidence level (0 to 1).
153+
u32 singletonQtmPtr; ///< Pointer to head-tracking singleton pointer, in QTM's .bss, located in N3DS extra memory.
154+
float confidenceLevel; ///< Head tracking confidence level (0 to 1).
153155

154156
/**
155157
* @brief Raw predicted or detected eye coordinates. Each eye is represented as one point.
@@ -166,16 +168,16 @@ typedef struct QtmRawTrackingData {
166168
s64 samplingTick; ///< Time point the current measurements were made.
167169
} QtmRawTrackingData;
168170

169-
/// QTM processed eye tracking data, suitable for 3D programming
171+
/// QTM processed head tracking data, suitable for 3D programming
170172
typedef struct QtmTrackingData {
171-
bool eyesTracked; ///< Eye position detected or tracked with some confidence, equals (confidenceLevel > 0). Even if false, QTM may make a guess
173+
bool headTracked; ///< Eye position detected or tracked with some confidence, equals (confidenceLevel > 0). Even if false, QTM may make a guess
172174
bool faceDetected; ///< Whether or not the entirety of the user's face has been detected with good confidence.
173175
bool eyesDetected; ///< Whether or not the user's eyes have actually been detected with full confidence.
174176
u8 _unused; ///< Unused.
175177
bool clamped; ///< Whether or not the normalized eye coordinates have been clamped after accounting for lens distortion.
176178
u8 _padding[3]; ///< Padding.
177179

178-
float confidenceLevel; ///< Eye tracking confidence level (0 to 1).
180+
float confidenceLevel; ///< Head tracking confidence level (0 to 1).
179181

180182
/**
181183
* @brief Normalized eye coordinates, for each eye, after accounting for lens distortion, centered around camera.
@@ -204,7 +206,7 @@ typedef struct QtmTrackingData {
204206
/// QTM service name enum, excluding `qtm:c`
205207
typedef enum QtmServiceName {
206208
/**
207-
* @brief `qtm:u`: has eye-tracking commands and IR LED control commands, but for some
209+
* @brief `qtm:u`: has head-tracking commands and IR LED control commands, but for some
208210
* reason cannot fetch ambiant lux data from the camera's luminosity sensor.
209211
*/
210212
QTM_SERVICE_USER = 0,
@@ -256,7 +258,7 @@ bool qtmIsInitialized(void);
256258
Handle *qtmGetSessionHandle(void);
257259

258260
/**
259-
* @brief Gets the current raw eye tracking data, with an optional prediction made for predictionTimePointOrZero = t+dt,
261+
* @brief Gets the current raw head tracking data, with an optional prediction made for predictionTimePointOrZero = t+dt,
260262
* or for the current time point (QTM makes predictions based on gyro data since inner camera runs at 30 FPS).
261263
*
262264
* @param[out] outData Where to write the raw tracking data to. Cleared to all-zero on failure (instead of being left uninitialized).
@@ -269,7 +271,7 @@ Handle *qtmGetSessionHandle(void);
269271
Result QTMU_GetRawTrackingDataEx(QtmRawTrackingData *outData, s64 predictionTimePointOrZero);
270272

271273
/**
272-
* @brief Gets the current raw eye tracking data.
274+
* @brief Gets the current raw head tracking data.
273275
*
274276
* @param[out] outData Where to write the raw tracking data to. Cleared to all-zero on failure (instead of being left uninitialized).
275277
* @return `0xC8A18008` if camera is in use by user, or `0xC8A183EF` if QTM is unavailable (in particular, QTM is always
@@ -282,7 +284,7 @@ static inline Result QTMU_GetRawTrackingData(QtmRawTrackingData *outData)
282284
}
283285

284286
/**
285-
* @brief Gets the current normalized eye tracking data, made suitable for 3D programming with an optional prediction made
287+
* @brief Gets the current normalized head tracking data, made suitable for 3D programming with an optional prediction made
286288
* for predictionTimePointOrZero = t+dt, or for the current time point (QTM makes predictions based on gyro data since
287289
* inner camera runs at 30 FPS).
288290
*
@@ -296,7 +298,7 @@ static inline Result QTMU_GetRawTrackingData(QtmRawTrackingData *outData)
296298
Result QTMU_GetTrackingDataEx(QtmTrackingData *outData, s64 predictionTimePointOrZero);
297299

298300
/**
299-
* @brief Gets the current normalized eye tracking data, made suitable for 3D programming.
301+
* @brief Gets the current normalized head tracking data, made suitable for 3D programming.
300302
*
301303
* @param[out] outData Where to write the raw tracking data to. Cleared to all-zero on failure (instead of being left uninitialized).
302304
* @return `0xC8A18008` if camera is in use by user, or `0xC8A183EF` if QTM is unavailable (in particular, QTM is always
@@ -309,45 +311,45 @@ static inline Result QTMU_GetTrackingData(QtmTrackingData *outData)
309311
}
310312

311313
/**
312-
* @brief Computes an approximation of the horizontal angular field of view of the camera based on eye tracking data.
314+
* @brief Computes an approximation of the horizontal angular field of view of the camera based on head tracking data.
313315
*
314-
* @param data Eye tracking data, obtained from \ref QTMU_GetTrackingData or \ref QTMU_GetTrackingDataEx.
316+
* @param data Head tracking data, obtained from \ref QTMU_GetTrackingData or \ref QTMU_GetTrackingDataEx.
315317
* @return Horizontal angular field of view in radians. Corresponds to 64.9 degrees on real hardware.
316318
*/
317319
float qtmComputeFovX(const QtmTrackingData *data);
318320

319321
/**
320-
* @brief Computes an approximation of the vertical angular field of view of the camera based on eye tracking data.
322+
* @brief Computes an approximation of the vertical angular field of view of the camera based on head tracking data.
321323
*
322-
* @param data Eye tracking data, obtained from \ref QTMU_GetTrackingData or \ref QTMU_GetTrackingDataEx.
324+
* @param data Head tracking data, obtained from \ref QTMU_GetTrackingData or \ref QTMU_GetTrackingDataEx.
323325
* @return Vertical angular field of view in radians. Corresponds to 51.0 degrees on real hardware.
324326
*/
325327
float qtmComputeFovY(const QtmTrackingData *data);
326328

327329
/**
328-
* @brief Computes a rough approximation of the inverse of the aspect ration of the camera based on eye tracking data.
330+
* @brief Computes a rough approximation of the inverse of the aspect ration of the camera based on head tracking data.
329331
*
330-
* @param data Eye tracking data, obtained from \ref QTMU_GetTrackingData or \ref QTMU_GetTrackingDataEx.
332+
* @param data Head tracking data, obtained from \ref QTMU_GetTrackingData or \ref QTMU_GetTrackingDataEx.
331333
* @return Rough approximation of the inverse of the aspect ratio of the camera. Aspect ratio is exactly 0.75 on real hardware.
332334
*/
333335
float qtmComputeInverseAspectRatio(const QtmTrackingData *data);
334336

335337
/**
336-
* @brief Computes the user's head tilt angle, that is, the angle between the line through both eyes and the camera's
338+
* @brief Computes the user's head tilt angle, that is, the angle between the line through both head and the camera's
337339
* horizontal axis in camera space.
338340
*
339-
* @param data Eye tracking data, obtained from \ref QTMU_GetTrackingData or \ref QTMU_GetTrackingDataEx.
341+
* @param data Head tracking data, obtained from \ref QTMU_GetTrackingData or \ref QTMU_GetTrackingDataEx.
340342
* @return Horizontal head angle relative to camera, in radians.
341343
*/
342344
float qtmComputeHeadTiltAngle(const QtmTrackingData *data);
343345

344346
/**
345347
* @brief Estimates the distance between the user's eyes and the camera, based on
346-
* eye tracking data. This may be a little bit inaccurate, as this assumes
348+
* head tracking data. This may be a little bit inaccurate, as this assumes
347349
* interocular distance of 62mm (like all 3DS software does), and that both
348350
* eyes are at the same distance from the screen.
349351
*
350-
* @param data Eye tracking data, obtained from \ref QTMU_GetTrackingData or \ref QTMU_GetTrackingDataEx.
352+
* @param data Head tracking data, obtained from \ref QTMU_GetTrackingData or \ref QTMU_GetTrackingDataEx.
351353
* @return Eye-to-camera distance in millimeters.
352354
*/
353355
float qtmEstimateEyeToCameraDistance(const QtmTrackingData *data);

libctru/include/3ds/services/qtmc.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ Result QTMC_StopHardwareCheck(void);
5151
*
5252
* QTM's expander management thread repeatedly writes (on every loop iteration) the current mask pattern
5353
* plus polarity bit, whether it is normally set or overridden by `qtm:c`, then on the following set,
54-
* negates both (it writes pattern ^ 0x1FFF). This is done at all times, even it 2D mode.
54+
* negates both (it writes pattern ^ 0x1FFF). This is done at all times, even it 2D mode. This software-
55+
* controlled dithering seems to at every sampling interval, about 60 times per second (I couldn't
56+
* formally verify this timing).
5557
*
5658
* The register being written to are regId 0x02 and 0x03 (output ports).
5759
* TI TCA6416A I2C->Parallel expander is located on bus I2C1 (PA 0x10161000) device ID 0x40.

0 commit comments

Comments
 (0)