> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/opentrack/opentrack/llms.txt
> Use this file to discover all available pages before exploring further.

# Virtual Joystick

> Map head tracking to virtual joystick axes using vJoy driver

The Virtual Joystick protocol allows you to map head tracking movements to a virtual joystick device. This enables head tracking in games that support joystick input but don't have native head tracking support.

## How It Works

The protocol:

1. Connects to the vJoy virtual joystick driver
2. Maps your 6 head tracking axes (X, Y, Z, Pitch, Yaw, Roll) to 6 joystick axes
3. Scales values to fit joystick axis ranges
4. Updates the virtual joystick in real-time as you move your head

### Axis Mapping

OpenTrack maps tracking data to these HID joystick axes:

| Tracking Axis | Joystick Axis   | HID Usage      |
| ------------- | --------------- | -------------- |
| X Position    | X               | `HID_USAGE_X`  |
| Y Position    | Y               | `HID_USAGE_Y`  |
| Z Position    | Z               | `HID_USAGE_Z`  |
| Pitch         | RX (Rotation X) | `HID_USAGE_RX` |
| Yaw           | RY (Rotation Y) | `HID_USAGE_RY` |
| Roll          | RZ (Rotation Z) | `HID_USAGE_RZ` |

## Prerequisites

### vJoy Driver Installation

<Steps>
  <Step title="Download vJoy">
    Download the vJoy driver from:

    * **Official site**: [http://vjoystick.sourceforge.net/](http://vjoystick.sourceforge.net/)
    * **SourceForge**: [https://sourceforge.net/projects/vjoystick/](https://sourceforge.net/projects/vjoystick/)
  </Step>

  <Step title="Run installer">
    Run the vJoy installer and follow the setup wizard.

    **Important**: Install as administrator.
  </Step>

  <Step title="Configure vJoy device">
    After installation, run **Configure vJoy** from the Start menu:

    1. Select **Device 1**
    2. Ensure these axes are enabled:
       * X, Y, Z
       * RX, RY, RZ
    3. Click **Apply**
  </Step>

  <Step title="Verify installation">
    Check Windows Device Manager:

    * **Control Panel → Device Manager**
    * Look for "vJoy Device" under "Human Interface Devices"
  </Step>
</Steps>

<Warning>
  If vJoy is not installed or configured correctly, OpenTrack will display an error:

  * "vjoystick won't work without the driver installed."
  * "Virtual joystick already in use."
  * "Device missing. Add joystick #1."

  You must resolve these before the protocol will function.
</Warning>

## Setup Instructions

<Steps>
  <Step title="Install vJoy driver">
    Follow the prerequisites section above to install and configure vJoy.
  </Step>

  <Step title="Select Virtual Joystick protocol">
    In OpenTrack, go to the **Output** dropdown and select **"Joystick emulation -- vjoystick"**.
  </Step>

  <Step title="Start OpenTrack">
    Click **Start** in OpenTrack. The protocol will:

    * Connect to vJoy device #1
    * Query axis ranges
    * Begin sending joystick data
  </Step>

  <Step title="Configure game controls">
    In your game's control settings:

    1. Look for view control or camera options
    2. Bind view axes to the virtual joystick axes:
       * View left/right → Joystick RY (Yaw)
       * View up/down → Joystick RX (Pitch)
       * View roll → Joystick RZ (Roll)
       * View forward/back → Joystick Z
       * View left/right position → Joystick X
       * View up/down position → Joystick Y
    3. Adjust sensitivity and dead zones as needed
  </Step>

  <Step title="Test in game">
    Launch your game and verify head movements control the view through the virtual joystick.
  </Step>
</Steps>

## Configuration

### Axis Value Ranges

The protocol automatically scales tracking data to joystick axis ranges:

**Position axes (X, Y, Z):**

* Input range: ±50 cm
* Output: Scaled to joystick axis min/max

**Rotation axes (Pitch, Yaw, Roll):**

* Input range: ±180°
* Output: Scaled to joystick axis min/max

### Value Scaling Formula

```cpp theme={null}
int to_axis_value(double value, double minmax, long axis_min, long axis_max) {
    return clamp(
        (value + minmax) * axis_max / (2 * minmax) - axis_min,
        axis_min,
        axis_max
    );
}

// Position example (±50 cm range)
joystick_x = to_axis_value(headpose[X], 50.0, axis_min[0], axis_max[0]);

// Rotation example (±180° range)  
joystick_rx = to_axis_value(headpose[Pitch], 180.0, axis_min[3], axis_max[3]);
```

## Use Cases

### Games Without Native Head Tracking

Many games support joystick input but not head tracking. Examples:

* Racing games (camera movement)
* Flight arcade games
* Mech games (torso twist)
* First-person games (view control)

### View Control Schemes

**Cockpit games:**

```
Yaw → Look left/right
Pitch → Look up/down
Roll → Lean head
X → Lean body left/right
Y → Lean body up/down  
Z → Lean body forward/back
```

**Third-person games:**

```
Yaw → Rotate camera
Pitch → Camera height
Z → Camera distance
```

### Hybrid Input

Combine virtual joystick with physical controls:

* Use mouse/gamepad for aiming
* Use head tracking for view/camera
* Map only needed axes to avoid conflicts

## Troubleshooting

### "vjoystick won't work without the driver installed"

**Cause**: vJoy driver not installed.

**Solution**:

1. Download vJoy from sourceforge.net/projects/vjoystick
2. Run installer as administrator
3. Restart OpenTrack

### "Virtual joystick already in use"

**Cause**: Another application has acquired vJoy device #1.

**Solution**:

1. Close other applications that might use vJoy
2. Check Task Manager for vjoy-related processes
3. Restart computer if needed
4. Ensure OpenTrack starts before other joystick applications

### "Device missing. Add joystick #1"

**Cause**: vJoy device #1 not configured.

**Solution**:

1. Run "Configure vJoy" from Start menu
2. Ensure Device 1 exists and is enabled
3. Enable axes: X, Y, Z, RX, RY, RZ
4. Click Apply
5. Restart OpenTrack

### Game Doesn't Detect Joystick

**Symptoms**: vJoy works in OpenTrack but game doesn't see it.

**Solution**:

1. **Test in Windows**: Control Panel → Devices → Game Controllers
   * vJoy Device should appear
   * Right-click → Game controller settings → Properties
   * Move your head and verify axes move
2. **Restart game**: Some games only detect joysticks at startup
3. **Check game settings**: Ensure joystick input is enabled
4. **Update game**: Some older games don't support modern HID devices

### Wrong Axis Mapping

**Symptoms**: Moving head left/right rotates camera up/down.

**Solution**:

1. Check game control bindings
2. Different games map RX/RY/RZ differently
3. Try swapping axis assignments in game settings
4. Use OpenTrack axis mapping to reassign before sending to joystick

### Axis Moves But View Doesn't Center

**Cause**: Game expects spring-centered joystick.

**Solution**:

* In OpenTrack mapping, enable "Center" for position axes
* Adjust dead zone in game settings
* Some games aren't suitable for head tracking via joystick

### Jittery or Jumpy Movement

**Cause**: Insufficient smoothing or low update rate.

**Solution**:

1. Increase filter smoothing in OpenTrack
2. Adjust game joystick sensitivity
3. Enable joystick dead zones in game
4. Check input device tracking quality

## Advanced Configuration

### Partial Axis Usage

You don't need to use all 6 axes. Common configurations:

**Rotation only (3DOF):**

* Map only Pitch, Yaw, Roll
* Leave position axes at center
* Good for games with fixed camera position

**Position only:**

* Map only X, Y, Z
* Use for body lean in racing games
* Keep rotation centered

### vJoy Multi-Device

If you need multiple virtual joysticks:

1. Configure additional vJoy devices (Device 2, 3, etc.)
2. OpenTrack uses Device 1 only
3. Use other devices for different applications
4. Avoid device conflicts

### Game-Specific Profiles

Create OpenTrack profiles for different games:

1. Save profile with game name
2. Configure axis mappings per game
3. Set appropriate ranges and curves
4. Use profile shortcuts for quick switching

## Technical Details

### vJoy API Functions

```cpp theme={null}
// Driver check
vJoyEnabled()              // Check if driver installed
GetVJDStatus(device_id)    // Check device status

// Axis configuration  
GetVJDAxisExist()          // Check if axis exists
GetVJDAxisMin()            // Get axis minimum value
GetVJDAxisMax()            // Get axis maximum value

// Control
AcquireVJD(device_id)      // Acquire exclusive control
RelinquishVJD(device_id)   // Release control

// Data transmission
SetAxis(value, device_id, axis_id)  // Set axis value
```

### Device Status Codes

| Status          | Description    | Action                  |
| --------------- | -------------- | ----------------------- |
| `VJD_STAT_OWN`  | Already owned  | Bug - should not happen |
| `VJD_STAT_FREE` | Available      | Normal - acquire device |
| `VJD_STAT_BUSY` | In use         | Close other app         |
| `VJD_STAT_MISS` | Not configured | Run Configure vJoy      |
| `VJD_STAT_UNKN` | Unknown error  | Reinstall driver        |

### Axis ID Constants

```cpp theme={null}
HID_USAGE_X  = 0x30  // Position X
HID_USAGE_Y  = 0x31  // Position Y
HID_USAGE_Z  = 0x32  // Position Z
HID_USAGE_RX = 0x33  // Rotation X (Pitch)
HID_USAGE_RY = 0x34  // Rotation Y (Yaw)
HID_USAGE_RZ = 0x35  // Rotation Z (Roll)
```

### Update Rate

The protocol updates the virtual joystick at the same rate as OpenTrack's main loop:

* Typically 50-60 Hz depending on input device
* No artificial rate limiting
* Games poll joystick at their own rate

<Note>
  The Virtual Joystick protocol is most useful for games without native head tracking support. For games with FreeTrack support, use the FreeTrack protocol directly for better performance and lower latency.
</Note>

## Alternatives

For games that support other input methods:

* **FreeTrack support**: Use FreeTrack protocol (better performance)
* **Mouse emulation**: Use MouseLook or FreePIE scripts
* **UDP output**: Send data to custom game mods
* **OSC protocol**: Control games via Open Sound Control
