Sonifying UDK Skeletal Mesh Components with UDKOSC and Supercollider

3. Conditioning our Input Data

Since our Actor will be moving and rotating around our environment, keep in mind that we’ll be positioning our CCD_IK Effectors in Local Space (around our Pawn), then subsequently converting their location to World Space. This allows us to simply think of our target point for each Effector in relation to our current Pawn position and rotation, rather than in the vast wasteland that is World Space.

Now that we know what we want to control (the EffectorLocation of our bone’s attached CCD_IK Skeletal Controller), we need to figure out how to actually control it. Again, the control system we’re using here maps the 2 analog stick controllers from a stock XBox wired game pad to the rotation of each wing. To do so we’ll take advantage of the default mappings of those stick controllers in our DefaultInput.ini.

In DefaultInput.ini, the mappings between XBox joystick and in-game value are mapped out pretty clearly, once you know what to look for. As with many UDK-standard mappings in the input.ini’s, these are first bound to a generic function, which itself is then subsequently bound to one or more control schemata. The binding functions themselves are:

.Bindings=(Name="GBA_TurnLeft_Gamepad",Command="Axis aTurn Speed=1.0 DeadZone=0.2")
.Bindings=(Name="GBA_StrafeLeft_Gamepad",Command="Axis aStrafe Speed=1.0 DeadZone=0.2")
.Bindings=(Name="GBA_Look_Gamepad",Command="Axis aLookup Speed=1.0 DeadZone=0.2")
.Bindings=(Name="GBA_MoveForward_Gamepad",Command="Axis aBaseY Speed=1.0 DeadZone=0.2")

The secondary control mappings from gamepad to function are then:


Since these are the default XBox controller mappings for a game type that inherits from Epic’s UTGame type, data from the controller is already mapped into a place our PlayerController can access. These basic control signals for turning, strafing looking and the Y-axis motion are already exposed in Unrealscript, either by the conditioned float variables aTurn, aStrafe, aLookup and aBaseY or in raw form in PlayerInput.RawJoyLookRight, PlayerInput.RawJoyLookUp, PlayerInput.RawJoyUp, and PlayerInput.RawJoyRight.

In my custom Posing state, I don’t allow the player to move the Pawn around so I can just tap into these values while overwriting the UpdateRotation() method. If you wanted to preserve movement with manual control over your actor, you’ll need to tweak UpdateRotation to allow some other input source to rotate and move your Pawn around.

As we mentioned earlier, it’s in the PlayerController’s UpdateRotation() method that the real magic happens, namely mapping these controller stick values to World Coordinates for our CCD_IK EffectorLocations. Since the CCD_IK’s are already connected to our Skeletal Mesh Components, all we need to do to move the wings is to set a location for each EffectorLocation. We would do that by first grabbing an instance of our current Pawn (making sure to cast it as our subclassed OSCPawn type), and set the EffectorLocation vector for each of those CCD_IK’s we declared and instantiated in section (1) above.


Since the RawJoy input is float data ranging from -1.0 to 1.0, we’ll need to scale that range to something more useful. Given the default size of a UDK human-like Pawn is ~96 UU we’ll need to increase that a fair amount.

I’m using a pretty basic scaling function for X and Z of each EffectorLocation with maximum and minimum values of +300.0 and -300.0 UU, something along the lines of:

function float scaleWingRotation(float currentValue) {
  local float a, b, min, max, rValue;
  b = gWingRotationMin;  // -300.0 in defaultproperties
  a = gWingRotationMax;  // +300.0 in defaultproperties
  min = -1.0;
  max = 1.0;

  rValue = ( ((b - a)*(currentValue - min) ) / (max - min) ) + a;
  return rValue;

To keep things simple, we can just effectively ignore the Y coordinate of the EffectorLocation; for now I’m just setting it to a hard offset, pushing it out to the side of my pawn slightly. Then, X and Y for each wing’s Effector Location are just mapped to the scaled Raw Joystick data. I’m padding that a bit with a global offset value I added in there to set the default “untouched” wing position to a nice “non-0,0,0” location.

tempVectorLeft.X = scaleWingRotation(PlayerInput.RawJoyRight) + leftXOffset;
tempVectorLeft.Y = leftYOffset;
tempVectorLeft.Z = scaleWingRotation(PlayerInput.RawJoyUp) + leftZOffset;
tempVectorRight.X = scaleWingRotation(PlayerInput.RawJoyLookRight) + rightXOffset;
tempVectorRight.Y = rightYOffset;
tempVectorRight.Z = scaleWingRotation(PlayerInput.RawJoyLookUp) + rightZOffset;

The last step is then translating our chosen coordinates from Local Space to World space. Again, by conceptualizing the Effector’s position in Local Space, we can always think of it in relation to our Pawn, wherever that pawn may be in the environment.

tempVectorLeft = tempVectorLeft >> Pawn.Rotation;
tempVectorRight = tempVectorRight >> Pawn.Rotation;	

During this entire process, it’s easier to debug and tweak your Effector positioning if you can actually see where the Effector is being placed in-game. To visualize the EffectorLocation in space, we can take one of the UDK debug methods, DrawDebugSphere() and draw a simple sphere around our Effector Locations.

DrawDebugSphere(EffectorLocation_left, 10, 10, 255, 255, 0, false);
DrawDebugSphere(EffectorLocation_right, 10, 10, 0, 255, 0, false);

And that’s about it. Now, we can control our Right and Left Valkordia wings with our 2 analog XBox controller sticks.

After the Break: Bone tracking in UDKOSC…

Tagged with: ,
Posted in UDKOSC

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: