Controller

Provides the controller interface.

Controller List

Configure

setupConfig returns the Controller device configured data before its connected. It provides the driver information to DeviceService. Check ControllerDevice.Config.

@Override
public Config setupConfig() {
    Config configure = new Config();
    configure.trackingSystemName = "Controller Device";
    return configure;
}

Configure List

  • See Configure in VRDevice to learn more about device configuration.
  • Import the following WVR package to use the button name:
import com.htc.vr.sdk.WVR;
  • Use the following function to set up the button in the setupConfig() function:
private long ButtonMaskFromId( int id ) { return 1<< id; }

Touchpad

If the physical controller has a touchpad, set up that the touchpad on the controller is supported.

@Override
public Config setupConfig() {
    Config configure = new Config();

    // Setup "touchpad supported" for controller device
    int support = 0;
    support |= ButtonMaskFromId(WVR.InputId_Alias1_Touchpad);
    configure.supportedButton = support;

    support = 0;
    support |= ButtonMaskFromId(WVR.InputId_Alias1_Touchpad);
    configure.supportedAnalog = support;
    configure.analogType = new HashMap<Integer, Integer>();
    // Setup virtual D-Pad mechanism
    configure.analogType.put(WVR.InputId_Alias1_Touchpad, WVR.AnalogType_2D);

    support = configure.supportedButton;
    support |= ButtonMaskFromId(WVR.InputId_Alias1_Touchpad);
    configure.supportedTouch = support;

    return configure;
}
  • See Swipe Motions on Touchpad in Tracked Device for more information.

Thumbstick

If the physical controller has a thumbstick, set up that the thumbstick is supported.

@Override
public Config setupConfig() {
    Config configure = new Config();

    // Setup "thumbstick supported" for controller device
    int support = 0;
    support |= ButtonMaskFromId(WVR.InputId_Alias1_Thumbstick);
    configure.supportedButton = support;

    support = 0;
    support |= ButtonMaskFromId(WVR.InputId_Alias1_Thumbstick);
    configure.supportedAnalog = support;
    configure.analogType = new HashMap<Integer, Integer>();
    // Setup virtual D-Pad mechanism
    configure.analogType.put(WVR.InputId_Alias1_Thumbstick, WVR.AnalogType_2D);

    support = configure.supportedButton;
    support |= ButtonMaskFromId(WVR.InputId_Alias1_Thumbstick);
    configure.supportedTouch = support;

    return configure;
}
  • Only VR APP 3.2.0 or later supports thumbsticks. To use a thumbstick on an older version of VR APP , set up that touchpad and thumbstick are supported and supportVirDpadSwipeInputId. See Swipe Motions on Touchpad in Tracked Device for more information.

Virtual/Physical D-pad

If the physical controller has a physical D-pad, use the following code in method setupConfig() to set up that the “D-pad is supported” on the controller and disable the default “virtual D-pad” mechanism on the touchpad by the configure value “disableVirtualDpad”. However, if an implementation for the virtual D-pad or swipe motions exists, disable the virtual D-pad mechanism. Also, the virtual D-pad button events (i.e. touched, pressed, unpressed and untouched) must be sent by the implementation when a virtual D-pad button is pressed.

@Override
public Config setupConfig() {
    Config configure = new Config();

    int support = 0;
    // Set up "physical D-pad button supported" for controller device
    support |= ButtonMaskFromId(WVR.InputId_Alias1_DPad_Left);
    support |= ButtonMaskFromId(WVR.InputId_Alias1_DPad_Up);
    support |= ButtonMaskFromId(WVR.InputId_Alias1_DPad_Right);
    support |= ButtonMaskFromId(WVR.InputId_Alias1_DPad_Down);
    configure.supportedButton = support;

    // Disable default virtual D-pad button mechanism
    configure.disableVirtualDpad = true;

    return configure;
}
  • See Virtual D-Pad Button on Touchpad in Tracked Device for more information.

Trigger

The trigger is a button with an analog function.

If the physical controller has a trigger, set up that the trigger is supported.

@Override
public Config setupConfig() {
    Config configure = new Config();

    int support = 0;
    // Set up "trigger button supported" for controller device
    support |= ButtonMaskFromId(WVR.InputId_Alias1_Trigger);
    configure.supportedButton = support;

    support = 0;
    support |= ButtonMaskFromId(WVR.InputId_Alias1_Trigger);
    configure.supportedAnalog = support;
    configure.analogType = new HashMap<Integer, Integer>();
    // Setup virtual D-Pad mechanism
    configure.analogType.put(WVR.InputId_Alias1_Trigger, WVR.AnalogType_1D);

    return configure;
}

Render Model Name

renderModelName is the defined render model asset filename. If the renderModelName value is invalid, the default render model will be used.

@Override
public Config setupConfig() {
    Config configure = new Config();
    configure.renderModelName = "";
    return configure;
}

See controller model zip format for more information.

Controller Pose Mode

The configurations of controller pose mode (see also sample below) are used to set up the controller ray angle/position for three different controller pose modes (based on physical mechanism of controller):

  1. Trigger mode: The controller ray (in VR content) is parallel to the trigger button of controller. (eg, for gun usage)
  2. Panel mode: The controller ray (in VR content) is parallel to the panel of controller. (eg, for normal usage)
  3. Handle mode: The controller ray (in VR content) is parallel to the handle of controller. (eg, for sword usage)
_images/ControllerPoseMode.png

Note

  1. The angle of default controller pose SHOULD align with one of controller pose modes (eg. Panel mode), and its quaternion offset configuration should be set up quaternion_wxyz(1.0, 0.0, 0.0, 0.0) to be the benchmark for the adjustment of the other two configurations of controller pose modes.
  2. The translation offset configuration of aligned mode could be set up other value based on physical mechanism of controller.
  • Sample: Assume that the angle of default controller pose aligns with panel mode (quaternion offset is identity). Then, Follow the physical mechanism of controller (like the diagram as belows) to set up the configurations of controller pose mode (There is no translation offset in three modes in this sample).
_images/ControllerModeConfigSample.png
import com.htc.vr.sdk.Euler;
import com.htc.vr.sdk.Geometry;
import com.htc.vr.sdk.PoseOffset;
import com.htc.vr.sdk.Quaternion;
import com.htc.vr.sdk.Vector;
import com.htc.vr.sdk.WvrMatrix4f;
import java.lang.Math;

class SampleControllerDevice extends com.htc.vr.sdk.pluginkit.ControllerDevice {

    @Override
    public Config setupConfig() {
        Config configure = new Config();

        // Set up controller pose mode offset - Trigger
        WvrMatrix4f mat = new WvrMatrix4f();
        Euler euler = new Euler();
        euler.yaw = 0.0f;
        /* Based on physical mechanism of controller, increase pitch 30 degrees
           to become Trigger mode. */
        euler.pitch = Math.toRadians(30.0f); // +30 degrees
        euler.roll = 0.0f;
        mat = Geometry.EulerToMatrix(euler);
        Quaternion quat = new Quaternion();
        quat = Geometry.MatrixToQuat(mat);
        configure.poseTriggerModeOffset = new PoseOffset();
        configure.poseTriggerModeOffset.translation = new Vector();
        configure.poseTriggerModeOffset.translation.x = 0.0f;
        configure.poseTriggerModeOffset.translation.y = 0.0f;
        configure.poseTriggerModeOffset.translation.z = 0.0f;
        configure.poseTriggerModeOffset.quaternion = new Quaternion();
        configure.poseTriggerModeOffset.quaternion.w = quat.w;
        configure.poseTriggerModeOffset.quaternion.x = quat.x;
        configure.poseTriggerModeOffset.quaternion.y = quat.y;
        configure.poseTriggerModeOffset.quaternion.z = quat.z;

        // Set up controller pose mode offset - Panel
        configure.posePanelModeOffset = new PoseOffset();
        configure.posePanelModeOffset.translation = new Vector();
        configure.posePanelModeOffset.translation.x = 0.0f;
        configure.posePanelModeOffset.translation.y = 0.0f;
        configure.posePanelModeOffset.translation.z = 0.0f;
        /* The angle of controller pose aligns with panel mode, so set up configuration:
           quaternion_wxyz(1.0, 0.0, 0.0, 0.0) as the benchmark. */
        configure.posePanelModeOffset.quaternion = new Quaternion();
        configure.posePanelModeOffset.quaternion.w = 1.0f;
        configure.posePanelModeOffset.quaternion.x = 0.0f;
        configure.posePanelModeOffset.quaternion.y = 0.0f;
        configure.posePanelModeOffset.quaternion.z = 0.0f;

        // Set up controller pose mode offset - Hanle
        euler.yaw = 0.0f;
        /* Based on physical mechanism of controller, decrease pitch 17 degrees
           to become Hanle mode. */
        euler.pitch = Math.toRadians(-17.0f); // -17 degrees
        euler.roll = 0.0f;
        mat = Geometry.EulerToMatrix(euler);
        quat = Geometry.MatrixToQuat(mat);
        configure.poseHandleModeOffset = new PoseOffset();
        configure.poseHandleModeOffset.translation = new Vector();
        configure.poseHandleModeOffset.translation.x = 0.0f;
        configure.poseHandleModeOffset.translation.y = 0.0f;
        configure.poseHandleModeOffset.translation.z = 0.0f;
        configure.poseHandleModeOffset.quaternion = new Quaternion();
        configure.poseHandleModeOffset.quaternion.w = quat.w;
        configure.poseHandleModeOffset.quaternion.x = quat.x;
        configure.poseHandleModeOffset.quaternion.y = quat.y;
        configure.poseHandleModeOffset.quaternion.z = quat.z;

        return configure;
    }
}

Vibration

triggerVibrator is called by the VR app to trigger the vibration.

@Override
   public boolean triggerVibrator(int axis, long durationus, int intensity) {
       Debug.Log("get triggerVibrator Notification");
   }

Note

  • The unit of vibration duration is microseconds .
  • If necessary for to convert duration from microseconds to milliseconds, duration will divided by 1000. Please note that, when duration < 1000, after divided will be 0.

Role

ControllerRoleListener is a listener which is triggered by VRServer when the metadata of the controller role has been changed. There are two functions that developers have to override.

  • onControllerRoleChange() is triggered when the controller role has been changed. Use getControllerRole() to query the current controller role.
  • onDominantHandChange() is triggered when the dominant hand has been changed. Use isDominantHand() to verify the controller is the dominant hand.
ControllerRoleListener listener = new ControllerRoleListener() {
    @Override
    public void onControllerRoleChange() {
        Log.i(TAG, "onControllerRoleChange, role: " + getControllerRole());
        role = getControllerRole();
    }

    @Override
    public void onDominantHandChange() {
        Log.i(TAG, "onDominantHandChange, is dominant hand: " + ((isDominantHand()) ? "yes" : "no"));
    }
}

setControllerRoleListener registers a ControllerRoleListener that monitors if the controller role is changed by VRServer.

setControllerRoleListener(new ControllerListener() {
        @Override
        public void onControllerRoleChange() {
            Log.i(TAG, "onControllerRoleChange, role: " + getControllerRole());
            role = getControllerRole();
        }

        @Override
        public void onDominantHandChange() {
            Log.i(TAG, "onDominantHandChange, is dominant hand: " + ((isDominantHand) ? "yes" : "no"));
        }
    });

getControllerRole gets the current controller role. The returned value is either WVR.ControllerRole.LeftHand or WVR.ControllerRole.RightHand.

int role = getControllerRole();
Log.i(TAG, "controller role is " + ((role == WVR.ControllerRole.RightHand) ? "right hand" : "left hand"));

isDominantHand is the function that checks if the controller is the dominant hand. The returned value is boolean, true means the controller is the dominant hand.

if (isDominantHand()) {
    Log.i(TAG, "this controller is dominant hand");
}