Archive for February, 2013

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!