Archive for the ‘Hydra support in UDK’ Category

Hey VR Heads!

Work and volunteering took up a lot of my time this week, but I managed to make some meager progress with Hydra integration in UDK. I used examples from a couple of places:

http://forums.epicgames.com/threads/937066-Razer-Hydra-Dll-Bind-Player-Input-and-Player-Controller-Ready-to-go/page2
Craig just keeps posting awesome things! I took the camera modes that he constructed from his latest release.

http://forums.epicgames.com/threads/734592-Making-a-Skeletal-Control-to-move-an-arm
This post by Comicaztaway is a tutorial for getting the arm of a skeletal mesh to move with the mouse, Little Big Planet style.

After a lot of experimentation and frustration, I arrived at what you see in the video. Nowhere close to where I want to be, but its progress nonetheless. I will make a tutorial video outlining what I did in the near future. In the mean time, here is the quick-and-dirty tutorial:

  • Make a copy of, and then edit CH_AnimHuman_Tree. Add b_RightWeapon and b_LeftWeapon to the AnimTree. Create 2 new SkelControl_CCD_IKs named RightArmIK and LeftArmIK.
  • Make the edits that Comicaztaway sugests in his post, then close and save the package.
  • Add the following code to your Pawn.uc:

var SkelControl_CCD_IK RightArmIK;
var SkelControl_CCD_IK LeftArmIK;

simulated event PostInitAnimTree(SkeletalMeshComponent SkelComp)
{
super.PostInitAnimTree(SkelComp);
RightArmIK = SkelControl_CCD_IK( mesh.FindSkelControl('RightArmIK') );
LeftArmIK = SkelControl_CCD_IK( mesh.FindSkelControl('LeftArmIK') );
}

defaultproperties
{
Begin Object class=SkeletalMeshComponent Name=SkeletalMeshComponent0
SkeletalMesh=SkeletalMesh'CH_IronGuard_MaleHG.Mesh.SK_CH_IronGuard_MaleA'
PhysicsAsset=PhysicsAsset'CH_AnimCorrupt.Mesh.SK_CH_Corrupt_Male_Physics'
Animsets(0)=AnimSet'CH_AnimHumanHG.Anims.K_AnimHuman_AimOffset'
Animsets(1)=AnimSet'CH_AnimHumanHG.Anims.K_AnimHuman_BaseMale'
AnimTreeTemplate=AnimTree'CH_AnimHuman_MyTree.AT_CH_Human'
End Object
Mesh=SkeletalMeshComponent0
Components.Add(SkeletalMeshComponent0)

Name="Default__HydraGamePawn"
}
  • Add the following code to your PlayerController.uc:

var vector RightArmLocation;
var vector LeftArmLocation;
var HydraGamePawn Utp;
var HydraGamePlayerInput Hgp;

// function for SkelControl movement.
function UpdateRotation(float DeltaTime)
{
Hgp = HydraGamePlayerInput(PlayerInput); // gives us access to the Hydra variables
Utp = HydraGamePawn(Pawn); // this simply gets our pawn so we can then point to our SkelControl

// assigns vector RightArmLocation to the position of the Right Hydra Wand.
RightArmLocation.Z = Pawn.Location.Z + Hgp.RightHandPosition.Z;
RightArmLocation.Y = Pawn.Location.Y - 200 - Hgp.RightHandPosition.Y;
RightArmLocation.X = Pawn.Location.X - 400 - Hgp.RightHandPosition.X;
Utp.RightArmIK.EffectorLocation = RightArmLocation;

// assigns vector LeftArmLocation to the position of the Left Hydra Wand.
LeftArmLocation.Z = Pawn.Location.Z + Hgp.LeftHandPosition.Z;
LeftArmLocation.Y = Pawn.Location.Y - 400 - Hgp.LeftHandPosition.Y;
LeftArmLocation.X = Pawn.Location.X - 400 - Hgp.LeftHandPosition.X;
Utp.LeftArmIK.EffectorLocation = LeftArmLocation;

// Optional log feed, so you can see the number values and decide how to tweak the assignments above.
`log("RightArmIK.EffectorLocation Value is :"$Utp.RightArmIK.EffectorLocation);

}

I have weird numbers in there to offset position based on how I have my Hydra situated on my desk. The base station is off to my right. This solution is brute force and is not at all flexible, but may serve as a jump-off point for someone out there.

I will post the full files to GitHub sometime tomorrow, for now I have to get some sleep.

Oh yeah, on other thing: my Rift is due to arrive tomorrow! Next week’s video will include impressions and direct feeds if I can swing it.

Excelsior,

–Bruce

Hey VR Heads!

So, this past week has been lots of random tutorials and reading the documentation in the newly opened Oculus Developer Center. Not a whole lot new to show off, but I definitely feel like I am making progress!

I got crouch working with the Hydra. Yet again, UDK is simpler that what I make it out to be. No need for Pawn.ShouldCrouch(bool bCrouch) or StartCrouch(float HeightOffset). Just use bDuck. Here’s the code from my HydraGamePlayerController.uc:

function LeftTriggerPress()
{	
if(bDuck==0) bDuck = 1;
}

function LeftTriggerRelease()
{	
if(bDuck==1) bDuck=0;
}

Also, I have been slowly but steadily learning more about the UDK editor. Kismet and Matinee are not terribly intuitive, but I am getting the hang of it.

Finally, after several recommendations, I ended up watching the anime series Sword Art Online on CrunchyRoll. It is a really cool show about gamers stuck in a VRMMO. The battle scenes and story were pretty fantastic.
I was impressed with how they presented the player UI in the show. It has a really clean design, and is gesture based. You can see an example here (skip ahead to 8:45):

Also in this vid (skip ahead to 5:52 and 18:45):

I began investigating how I would do such a thing in UDK. As it turns out, Scaleform has 3D UI functionality in UDK! Awesome! I have no idea how the layering of 2D objects will look in the Rift, but I am going to attempt to throw together a UI mock up that is similar to SAO.

Other than that, I am still working on binding the arms/hands of a Pawn to the position of the Hydra controllers. I have been slowly working through the info on this page: http://udn.epicgames.com/Three/UsingSkeletalControllers.html
Once I have that done, I will put together a comprehensive tutorial for adding Hydra support to UDK on a separate page, so future devs don’t have to go digging through blog posts.

Hoping to receive my dev kit this week!

Excelsior,

–Bruce

Hey VR Heads!

So most of this week was spent learning how to make static meshes in Blender. Blender is complex – definitely not the “jump in and push buttons” type of program. After poking around a bit, I found a great tutorial that was highly recommended:

Blender 3D: From Noob to Pro (wikibook)

I am in the beginning of Unit 2, and I was able to put together the stuff you see in the video above. Not bad. 😀

The UDK tutorials from The New Boston are also fantastic:

The New Boston’s UDK Tutorial playlist

A lot of great knowledge and step-by-step walkthrough for the UDK Editor, Kismet, and Matinee.

Finally, I was able to get some buttons on the Hydra linked to in game actions! If you are using Craig’s source that I posted in part 3.5, you simply need to add Pawn instance functions (or whatever else you want) within the PlayerController class. A list of Pawn instance fuctions is here:

UDK List of Pawn Instance Functions

Here are some examples I was able to get working:

function RightTriggerPress()
{
Pawn.StartFire(1);
}

function RightTriggerRelease()
{
Pawn.StopFire(1);
}

function RightBumperPress()
{
Pawn.StartFire(0);
}

function RightBumperRelease()
{
Pawn.StopFire(0);
}

function RightB1Press()
{
Pawn.DoJump(true);
}

StartFire and StopFire need a byte argument (number between 0-255). What firing type each number value corresponds to is up to the weapon. By default, 0 = primary fire and 1 = alternate fire.

Other than that, I changed the AimMode variable within PlayerInput to 2, which allows the movement of the right Hydra wand to control looking around. It feels pretty nice so far. I also slapped together a Pawn file that would silence the footsteps in game. Those footsteps are loud, and ruin my videos! XD

That about wraps it up. Look forward to the hallway getting fancier and fancier!

Excelsior,

–Bruce

Hello fellow VR heads!

Not a big update this week, still tooling around with some code but haven’t made progress worth posting. However, I found a good resource if you are a newcomer to UnrealScript:

Archived World of Design UnrealScript Tutorial

Also, in order to get around the issue of WordPress screwing up quotation marks in code, I took the time to set up and figure out GitHub. You can now download the source from previous blog entries here:

CymaticSoft GitHub VRDevTutorial_2

CymaticSoft GitHub CraigDeLancyHydraSource

From now on, complete source will be posted on GitHub. Simply click on the “ZIP” button to download it for yourself!

Frustratingly, I seem to be the only GitHub user working on the Hydra in UDK. On the up side, there are a few folks working on Hydra stuff in blender, OpenGL, and other environments. Search GitHub for “Razer Hydra” and you will see.

Okay! I am going to get back to tooling around with Craig’s code, see if I can get the Hydra fully functional in the default Unreal game and begin linking the Hydra to the skeletal movement of the pawn. Oh yeah, I pledged for an Oculus Rift on the first day of the Kickstarter, so I hope to receive my dev kit soon. I will be posting unboxing and first impression vids when I do!

Excelsior,

–Bruce

Okay, more progress has been made, thanks to a couple of things:

So at this point, I am able to move my pawn around with the Hydra joysticks, tweak that movement, and verify that I am reading button presses through the console. Its going slower than I would like, but its going. More soon! 

Okay, now UDK and Notepad++ are set up. The next step is to create and compile some scripts to get the Hydra integrated!

This section was pieced together from reading the Sixense UDK Dev Forums and a couple of posts from the Beyond Unreal forums.

First, we need to a script to bind the Sixense DLL to the UDK project. Within the ../Development/Src/HydraGame/Classes/ folder, create a file named Sixense.uc with the following code:

*Note: If copy/pasting any of the following code, you will receive an error because the ( ‘ ) and ( ” ) characters are screwed up by WordPress. You will need to be find/replace them in all of these source files. I am trying to find a solution for this issue.

Sixense.uc

class Sixense extends Object
DLLBind(sixense);

//layout of the basis vectors
//unreal space X axis = forward Y axis = Right Z axis = up
//sixense space X axis = Right Y axis = Up Z axis = back
// Sx2Un X = -Z Y = X Z = Y
//Un2Sx X = Y Y = Z Z = -X

// Bit masks. 0x01 >> 2^x = y
const SIXENSE_BUTTON_BUMPER = 128; //(0x01<<7)
const SIXENSE_BUTTON_JOYSTICK = 256; //(0x01<<8)
const SIXENSE_BUTTON_1 = 32; //(0x01<<5);
const SIXENSE_BUTTON_2 = 64; //(0x01<<6);
const SIXENSE_BUTTON_3 = 8; //(0x01<<3);
const SIXENSE_BUTTON_4 = 16; //(0x01<<4);
const SIXENSE_BUTTON_START = 1; //(0x01<<0);

// Not sure where this is used… log files?
const SIXENSE_SUCCESS = 0;
const SIXENSE_FAILURE = -1;

// 4 controllers at once? Wicked!
const SIXENSE_MAX_CONTROLLERS = 4;

// 3D position, rotation matrices, joystick, trigger, and button data
struct sixenseControllerData {
var float pos[3];
var float rot_mat[9];
var float joystick_x;
var float joystick_y;
var float trigger;
var int buttons;
var byte sequence_number;
var float rot_quat[4];
var byte firmware_revision[2];
var byte hardware_revision[2];
var byte packet_type[2];
var byte magnetic_frequency[2];
var int enabled;
var int controller_index;
var byte is_docked;
var byte which_hand;
var byte hemi_tracking_enabled;
};

//Sets up controller data for all controllers?
struct sixenseAllControllerData {
var sixenseControllerData controller[4];
};

// declares an object that you’ll use later when you want to display data in ClientMessage
var sixenseAllControllerData TheControllerData;

// importing functions from sixense.dll
dllimport final function int sixenseInit( );
dllimport final function int sixenseExit( );

dllimport final function int sixenseGetMaxBases();
dllimport final function int sixenseSetActiveBase( int i );
dllimport final function int sixenseIsBaseConnected( int i );

dllimport final function int sixenseGetMaxControllers( );
dllimport final function int sixenseIsControllerEnabled( int which );
dllimport final function int sixenseGetNumActiveControllers( );

dllimport final function int sixenseGetHistorySize();

dllimport final function int sixenseGetData( int which, int index_back, out sixenseControllerData data );
dllimport final function int sixenseGetAllData( int index_back, out sixenseAllControllerData data );
dllimport final function int sixenseGetNewestData( int which, out sixenseControllerData data );
dllimport final function int sixenseGetAllNewestData( out sixenseAllControllerData data );

dllimport final function int sixenseSetHemisphereTrackingMode( int which_controller, int state );
dllimport final function int sixenseGetHemisphereTrackingMode( int which_controller, out int state );

dllimport final function int sixenseAutoEnableHemisphereTracking( int which_controller );

dllimport final function int sixenseSetHighPriorityBindingEnabled( int on_or_off );
dllimport final function int sixenseGetHighPriorityBindingEnabled( out int on_or_off );

dllimport final function int sixenseTriggerVibration( int controller_id, int duration_100ms, int pattern_id );

dllimport final function int sixenseSetFilterEnabled( int on_or_off );
dllimport final function int sixenseGetFilterEnabled( out int on_or_off );

dllimport final function int sixenseSetFilterParams( float near_range, float near_val, float far_range, float far_val );
dllimport final function int sixenseGetFilterParams( out float near_range, out float near_val, out float far_range, out float far_val );

dllimport final function int sixenseSetBaseColor( byte red, byte green, byte blue );
dllimport final function int sixenseGetBaseColor( out byte red, out byte green, out byte blue );

/*NOTE
The C++ DLL stores it’s matrix data as a 2D Array but Unreal must address it with one index. Use the macro below to address it more naturally

EX: Memory layout of 3×3 rotation matrices
C++: rot_mat[0][0], rot_mat[0][1], rot_mat[0][2], rot_mat[1][0], rot_mat[1][1], rot_mat[1][2], rot_mat[2][0], rot_mat[2][1], rot_mat[2][2]
Unreal: 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8
******************/
// mathematical conversion: 3x + y = U
//macro for accessing a particular 3×3 matrix element using two indices
//column major
// what does ` do? It is the grave accent (the one below tilde)? Necessary for log output, other operations.
`define m33el(x, y) `y + `x * 3

In the same folder, create the game file scripts. “HydraGame” can be replaced with whatever the name of your game is. Filenames and code below!

HydraGame.uc

//standard bare bones “MyGame” file

class HydraGame extends FrameworkGame;

defaultproperties
{
PlayerControllerClass=class’HydraGamePlayerController’
bDelayedStart=false
}

HydraGamePlayerController.uc

class HydraGamePlayerController extends GamePlayerController;

var sixense TheSixense;

defaultproperties

{
InputClass=class’HydraGame.HydraGamePlayerInput’
}

simulated event PostBeginPlay()
{
super.PostBeginPlay();
TheSixense = new class’Sixense’;
TheSixense.sixenseInit();
TheSixense.sixenseGetAllNewestData(TheSixense.TheControllerData);
}

simulated event PlayerTick(float DeltaTime)
{
super.Tick(DeltaTime);
TheSixense.sixenseGetAllNewestData(TheSixense.TheControllerData);
}

HydraGamePlayerInput.uc

//setup in-game client messages that will verify Hydra input. Use ini to bind this function to “H”

class HydraGamePlayerInput extends PlayerInput within HydraGamePlayerController;

simulated exec function TestFunction1()
{
ClientMessage(“Sixense L button value: “$TheSixense.TheControllerData.controller[0].buttons);
ClientMessage(“Sixense L position 0: “$TheSixense.TheControllerData.controller[0].pos[0]);
ClientMessage(“Sixense L position 1: “$TheSixense.TheControllerData.controller[0].pos[1]);
ClientMessage(“Sixense L position 2: “$TheSixense.TheControllerData.controller[0].pos[2]);

}

Okay, basic script files are all done! A couple more things to do before compiling scripts and diving into the UDK Editor.

.ini file editing

Open ../UDKGame/Config/DefaultInput.ini, and add the following code to ‘Primary default bindings’

.Bindings=(Name=”H”,Command=”TestFunction1″)

Open ../UDKGame/Config/DefaultEngine.ini, and add the following code to the [UnrealEd.EditorEngine] section:

+EditPackages=HydraGame

Open ../UDKGame/Config/DefaultGame.ini, and add the following code to the [Engine.GameInfo] section:

DefaultGame=HydraGame.HydraGame
DefaultServerGame=UDKBase.SimpleGame
PlayerControllerClassName=HydraGame.HydraGamePlayerController
GameDifficulty=+1.0
MaxPlayers=32
DefaultGameType=”UTGame.UTDeathmatch”;
+DefaultMapPrefixes=(Prefix=”DM”,bUsesCommonPackage=FALSE,GameType=”UTGame.UTDeathmatch”)
+DefaultMapPrefixes=(Prefix=”CTF”,bUsesCommonPackage=FALSE,GameType=”UTGameContent.UTCTFGame_Content”)
+DefaultMapPrefixes=(Prefix=”VCTF”,bUsesCommonPackage=FALSE,GameType=”UTGameContent.UTVehicleCTFGame_Content”)
+DefaultMapPrefixes=(Prefix=”HG”,bUsesCommonPackage=FALSE,GameType=”HydraGame.HydraGame”)

Now “HydraGame” will be set up as a game type, map file names prefaced with “HG-” will be recognized as HydraGame maps, and pressing “H” during gameplay brings up some data about the Hydra.

Delete the files UDKGame.ini, UDKEngine.ini, and UDKInput.ini. They will be recreated when the UDKEditor is started up.

Compile Scripts, Open the Editor!

For easy access, I made desktop shortcuts for the UDKEditor and the UnrealFrontEnd – I end up opening and closing these two programs quite a bit. First we need UFE (UnrealFrontEnd.exe), which is located in the Binaries folder. Open it up, click on the Scripts icon and select “compile scripts.” F4 is the keyboard shortcut.

Once the scripts are compiled, we can finally get into the Editor!  Create a shortcut from ../Binaries/Win32/UDK.exe. Add “Editor -log” to the command line in the shortcut properties. Name the shortcut “HydraGame UDK Editor”. Open it.

As a test, save the default level as “HG-Level01.udk” to ../UDKGame/Content/HydraGame/Levels. Build the level (Build>Build All).

Finally, we need to make sure that the game type for the PIE (Play-In-Editor) is “HydraGame”. Gotta go to World Properties (View>World Properties) and expand the “Game Type” section. Change Game Type for PIE and Default Game Type to HydraGame.

Play the game in the editor (Alt+F8) and repeatedly press H to get data from the Hydra. I move the left controller around and press all the buttons… Success!

Now to learn more about the Editor and connect the Hydra to the UDK Pawn! I think I will continue with the tutorials from The New Boston, and peruse more posts from Nathaniel3W!

So, first things first. I downloaded some things:

UDK

Installed UDK. After installing, checked out the UDK folders. According to most tutorials, it is important to know which folder does what:

  • Binaries – contains the game executable, UnrealFrontEnd, and other important stuff. Won’t need to mess with this much.
  • Development – this folder is where your game source code will be. Get comfortable!
  • Engine – this folder is required by Unreal Engine 3. Won’t need to mess with this much either.
  • UDKGame – this is where the files and content for the game hang out. Several folders should be here, including Config, Content, Localization, Movies, Script, and Splash.

Now its time to make a few more folders that will hold the game content. I am naming this first effort “HydraGame”. Yeah, unique right? (forgive my use of the wrong slashes here)

  • Created folder “HydraGame” in ..UDKGame/Content. Created folders “Levels” and “UPK” within ..UDKGame/Content/HydraGame.
  • Created folder “HydraGame” in ../Development/Src. Created folder “Classes” within ../Development/Src/HydraGame.

Notepad++

Using UDK will involve writing source files in UnrealScript (these files have the extension .uc). There are a few ways to do this, (nFringe and Visual Studio?) but my preferred method is to use Notepad++. After you install the program, you will need to add the UnrealScript Plugin:

  • Place UnrealScript.xml into C:/Users/Username/AppData/Roaming/Notepad++/plugins
  • Place userDefineLang_UnrealScript into C:/Users/Username/AppData/Roaming/Notepad++, then rename it to userDefineLang.xml

Username refers to whatever your username is on your computer.

Now open up Notepad++, set the Language to UnrealScript. The window turns blue! Ready to create some .uc files!

Sixense SDK

Downloaded the SDK through Steam. UDK only needs the dll file from the SDK.

So I copied sixense.dll from ..Steam/steamapps/common/sixense sdk/SixenseSDK/bin/win32/release_dll to ../Binaries/Win32/UserCode.

 

So all the pieces are in place to begin integrating the Hydra and develop some stuff with UDK. More to come!