-
Notifications
You must be signed in to change notification settings - Fork 0
Using the Razer Hydra Controller Input Events
The new Torque 3D Razer Hydra input device provides a number of input events that may be used with Torque 3D's action map system. There are a number of different ways to use the Razer Hydra input device, which are set up using global TorqueScript variables.
When binding a TorqueScript function to a Razer Hydra input event using Torque 3D's action map system, the device name to use is razerhydra
. As only one Razer Hydra may be used on a computer at a time, there is no need to append a device instance number to the end of the device name. The following is an example of setting up a proper action map binding:
moveMap.bind( razerhydra, rh_trigger1, gamepadFire );
The $RazerHydra::ProcessWhenDocked
global TorqueScript variable determines if input events are generated by the Razer Hydra when a controller is docked. A controller is considered docked when it is placed in the Razer Hydra base station. When $RazerHydra::ProcessWhenDocked
is false
(the default) then no events will be generated by the controller. When this global variable is set to true
then all input events will continue to be generated by a docked controller. Please note that a controller's position and rotation values may be warped when it is placed near or on the base station.
The Razer Hydra provides a full compliment of gamepad buttons and sticks spread across two hand held controllers. Torque 3D provides complete access to all of these input events which behave as you would expect from a Xbox 360 compatible gamepad. The following action map input events are available:
Left Controller
-
rh_thumbx0
- thumb stick x-axis motion in the range of -1.0 to 1.0 -
rh_thumby0
- thumb stick y-axis motion in the range of -1.0 to 1.0 -
rh_trigger0
- trigger motion (sometimes referred to as z-axis motion) in the range of 0.0 to 1.0 -
rh_shoulder0
- shoulder (or bumper) button -
rh_thumb0
- thumb stick used as a button -
rh_start0
- start button -
rh_1button0
- 1 button -
rh_2button0
- 2 button -
rh_3button0
- 3 button -
rh_4button0
- 4 button
Right Controller
-
rh_thumbx1
- thumb stick x-axis motion in the range of -1.0 to 1.0 -
rh_thumby1
- thumb stick y-axis motion in the range of -1.0 to 1.0 -
rh_trigger1
- trigger motion (sometimes referred to as z-axis motion) in the range of 0.0 to 1.0 -
rh_shoulder1
- shoulder (or bumper) button -
rh_thumb1
- thumb stick used as a button -
rh_start1
- start button -
rh_1button1
- 1 button -
rh_2button1
- 2 button -
rh_3button1
- 3 button -
rh_4button1
- 4 button
As with a standard gamepad, each of the thumb stick motions (and even the trigger although it is not usually used this way) are of the AXIS type. This means that additional modifiers may be placed on their inputs, such as defining a dead zone. For example, here is how you could set up the right controller's thumb stick to be used to rotate the player with a slight dead zone around the stick's neutral position:
moveMap.bind( razerhydra, rh_thumbx1, "D", "-0.23 0.23", gamepadYaw );
moveMap.bind( razerhydra, rh_thumby1, "D", "-0.23 0.23", gamepadPitch );
The unique feature of the Razer Hydra is being able to detect each the left and right controller's absolute position and rotation in space. When it comes to generating position input events, there are two options available. The first option is to receive each x, y and z axis update as separate events given as rh_posx
, rh_posy
and rh_posz
. You activate this option by setting the global TorqueScript variable $RazerHydra::SeparatePositionEvents
to true
, which is the default setting. This is similar to how a thumb stick generates separate events for both the x and y axis.
The second option is to receive only a single position event rh_pos
that includes each axis as a separate parameter. You activate this mode by setting the global TorqueScript variable $RazerHydra::CombinedPositionEvents
to true
. The primary advantage of this mode is you generally produce much less input events for Torque 3D to process.
The following action map input events are available (all positions are in millimeters and all rotations are in angled axis format):
Left Controller
-
rh_posx0
- absolute x axis position -
rh_posy0
- absolute y axis position -
rh_posz0
- absolute z axis position -
rh_pos0
- absolute position provided as 3 parameters -
rh_rot0
- absolute rotation
Right Controller
-
rh_posx1
- absolute x axis position -
rh_posy1
- absolute y axis position -
rh_posz1
- absolute z axis position -
rh_pos1
- absolute position provided as 3 parameters -
rh_rot1
- absolute rotation
You bind Razer Hydra position and rotation events to an action map just like any other input event. Here is an example of making use of the position (the single event version) and rotation events generated by the right controller (place it in scripts/client/default.bind.cs
):
function RHPos1(%x, %y, %z)
{
// Output the absolute position of the right controller to the console:
echo("Right controller position in millimeters:" SPC %x SPC %y SPC %z);
}
function RHRot1(%x, %y, %z, %a)
{
// Output the absolute rotation of the right controller to the console:
echo("Right controller rotation as angled axis:" SPC %x SPC %y SPC %z SPC %a);
// Convert into a world space forward vector
%pos = "0 0 0";
%rot = %x SPC %y SPC %z SPC %a;
%transform = MatrixCreate( %pos, %rot );
%forward = MatrixMulVector( %transform, "0 1 0" );
echo("Right controller world forward vector:" SPC %forward.x SPC %forward.y SPC %forward.z);
}
$RazerHydra::SeparatePositionEvents = false;
$RazerHydra::CombinedPositionEvents= true;
moveMap.bind( razerhydra, rh_pos1, RHPos1);
moveMap.bind( razerhydra, rh_rot1, RHRot1);
Torque 3D allows a Razer Hydra controller to be used like a gamepad thumb stick. Imagine that a thumb stick is coming out of the top of the controller and you move it by tilting the controller.
To activate these thumb stick input events we set the $RazerHydra::RotationAsAxisEvents
global TorqueScript variable to true
. With that variable set the following action map input events are available:
Left Controller
-
rh_rotaxisx0
- thumb stick like x-axis motion in the range of -1.0 to 1.0 -
rh_rotaxisy0
- thumb stick like y-axis motion in the range of -1.0 to 1.0
Right Controller
-
rh_rotaxisx1
- thumb stick like x-axis motion in the range of -1.0 to 1.0 -
rh_rotaxisy1
- thumb stick like y-axis motion in the range of -1.0 to 1.0
Internally, these x and y axis values are normalized to ensure the length of their vector is never more than 1, just like a real thumb stick.
In order to calculate the -1.0 to 1.0 range, the tilt of the controller with respect to a vector pointing straight up (technically this vector is normal to the plane of the Razer Hydra's base unit) is used. When this controller to up vector angle reaches the $RazerHydra::MaximumAxisAngle
global script variable value (the default is 25 degrees) then the virtual thumb stick is considered all the way over. Adjusting $RazerHydra::MaximumAxisAngle
for your application determines how far over the user must tilt their controller for a 100% value.
There may be a time when the provided Razer Hydra input events don't quite fit your needs. In these cases you may make use of the Razer Hydra whole frame input event that is available in Torque 3D. To activate this input event you set the $RazerHydra::GenerateWholeFrameEvents
global TorqueScript variable to true
. When active, you may then receive the rh_frame
input event.
The rh_frame
event is unique in that it provides a single value that is a SimObject ID to a RazerHydraFrame
class instance. You may then use this ID to call the instance's methods and retrieve the frame's data.
Each 'RazerHydraFrame' class instance is automatically stored within the RazerHydraFrameGroup
SimGroup. A maximum number of RazerHydraFrame
objects are kept at any time as determined by the $RazerHydra::MaximumFramesStored
global TorqueScript variable (the default is 30). When a new RazerHydraFrame
object is required, the oldest is removed from the RazerHydraFrameGroup
and recycled.
The RazerHydraFrame
instances are stored newest to oldest, with the newest at index 0 within the group. When you receive a rh_frame
event you may safely assume that the frame ID given in the frame's parameter is the first frame in the RazerHydraFrameGroup
. To manually retrieve the newest frame and the frame that came just before it (perhaps to perform a delta calculation between the two) you may use the following:
%newestFrame = RazerHydraFrameGroup.getObject(0);
%previousFrame = RazerHydraFrameGroup.getObject(1);
This may be done at any time that your application is running so long as you are collecting whole frames as set with the $RazerHydra::GenerateWholeFrameEvents
global variable.
You bind the Razer Hydra input events to an action map just like any other input event. Specifically, you tie the events to the razerhydra
device with the action map bind()
method. For example, the following TorqueScript code (placed in scripts/client/default.bind.cs
) performs an action against each frame received by the input event:
function RHFrame(%id)
{
// Output some information about this frame to the console
echo( "Frame " @ %id @ " time: " @ %id.getFrameRealTime() @ " left controller transform: " @ %id.getControllerTransform(0) );
}
$RazerHydra::GenerateWholeFrameEvents = true;
moveMap.bind( razerhydra, rh_frame, RHFrame);
The 'RazerHydraFrame' class has a large number of methods available for working with a frame's controller data. Please see the bottom of the source code file platform/input/razerHydra/razerHydraFrame.cpp for a complete list of the available methods.
The rh_docked0
and rh_docked1
(for left and right) input events are generated whenever a controller's docked status changes. A controller is docked when it is sitting in the Razer Hydra base station. This event can be useful for changing the application's state, such as pausing when nothing is being tracked by the Razer Hydra controller.
The rh_docked0
and rh_docked1
input events provides a single parameter that has a value of 1 when a controller is docked, and 0 when a controller has been picked up by the user. Here is an example of using this event:
function RHDocked0(%val)
{
echo("Left controller is docked: " @ %val);
}
// Set up for the left controller
moveMap.bind( razerhydra, rh_docked0, RHDocked0);
We may also check a controller's docked status at any time with the following TorqueScript function:
isRazerHydraControllerDocked( controller );
where the controller parameter is 0
or 1
for the left or right controller. This function returns true
if the requested controller is currently docked. As the rh_docked0
and rh_docked1
input events are only generated when a controller's docked status changes, the isRazerHydraControllerDocked()
function is useful when your application first starts up to detect a controller's current state.
The following is the order in which Razer Hydra input events may be received by the application:
For each controller, starting with the left one
- The
rh_docked
event. If a controller is docked and$RazerHydra::ProcessWhenDocked
is set tofalse
then the following controller events will be skipped. - If
$RazerHydra::SeparatePositionEvents
istrue
then all individual controller position events. - If
$RazerHydra::CombinedPositionEvents
istrue
then the combined controller position event. - The controller's rotation event.
- All standard gamepad input events.
- If
$RazerHydra::RotationAsAxisEvents
istrue
then the controller as thumb stick input events, but only if these values have changed this frame compared to the previous frame. This is the same behavior as with gamepad thumb sticks. When a controller is docked one last input event of this type is sent out with a value of0.0
. This returns the virtual thumb stick to a neutral position.
Following the controllers being processed
- If
$RazerHydra::GenerateWholeFrameEvents
istrue
then therh_frame
event.