(Lactose, I don't have a card slot in my phone, and it's not a smart phone anyway.)
So, here's the status. First I'll display the code from the sixense.h file that corresponds to the DLL that I'm using, with my own comments explaining it as I see it. I don't use all the functions so there's no need to be overwhelmed:
// Standard definitions for exporting and stuff
#ifndef _SIXENSE_H_
#define _SIXENSE_H_
#if defined(WIN32)
#ifdef SIXENSE_STATIC_LIB
#define SIXENSE_EXPORT
#else
#ifdef SIXENSE_BUILDING_DLL
#define SIXENSE_EXPORT __declspec(dllexport)
#else
#define SIXENSE_EXPORT __declspec(dllimport)
#endif
#endif
#else
#define SIXENSE_EXPORT
#endif
// Flags for button states defined as bits within an int and some other constants
#define SIXENSE_BUTTON_BUMPER (0x01<<7)
#define SIXENSE_BUTTON_JOYSTICK (0x01<<8)
#define SIXENSE_BUTTON_1 (0x01<<5)
#define SIXENSE_BUTTON_2 (0x01<<6)
#define SIXENSE_BUTTON_3 (0x01<<3)
#define SIXENSE_BUTTON_4 (0x01<<4)
#define SIXENSE_BUTTON_START (0x01<<0)
#define SIXENSE_SUCCESS 0
#define SIXENSE_FAILURE -1
#define SIXENSE_MAX_CONTROLLERS 4
// The structure that holds all the data for the current state of the controller. This is what's giving me the most trouble!
typedef struct _sixenseControllerData
{
float pos[3];
float rot_mat[3][3];
float joystick_x;
float joystick_y;
float trigger;
unsigned int buttons;
unsigned char sequence_number;
float rot_quat[4];
unsigned short firmware_revision;
unsigned short hardware_revision;
unsigned short packet_type;
unsigned short magnetic_frequency;
int enabled;
int controller_index;
unsigned char is_docked;
unsigned char which_hand;
unsigned char hemi_tracking_enabled;
} sixenseControllerData;
// Extra structure to hold an array of controllers. It doesn't do me much good at the moment, so you can probably ignore it.
typedef struct _sixenseAllControllerData
{
sixenseControllerData controllers[4];
} sixenseAllControllerData;
// More standard definitions
#if defined(__LANGUAGE_C_PLUS_PLUS)||defined(__cplusplus)||defined(c_plusplus)
extern "C" {
#endif
// Function signatures
SIXENSE_EXPORT int sixenseInit( void );
SIXENSE_EXPORT int sixenseExit( void );
SIXENSE_EXPORT int sixenseGetMaxBases();
SIXENSE_EXPORT int sixenseSetActiveBase( int i );
SIXENSE_EXPORT int sixenseIsBaseConnected( int i );
SIXENSE_EXPORT int sixenseGetMaxControllers( void );
SIXENSE_EXPORT int sixenseIsControllerEnabled( int which );
SIXENSE_EXPORT int sixenseGetNumActiveControllers();
SIXENSE_EXPORT int sixenseGetHistorySize();
SIXENSE_EXPORT int sixenseGetData( int which, int index_back, sixenseControllerData * );
SIXENSE_EXPORT int sixenseGetAllData( int index_back, sixenseAllControllerData * );
SIXENSE_EXPORT int sixenseGetNewestData( int which, sixenseControllerData * );
SIXENSE_EXPORT int sixenseGetAllNewestData( sixenseAllControllerData * );
SIXENSE_EXPORT int sixenseSetHemisphereTrackingMode( int which_controller, int state );
SIXENSE_EXPORT int sixenseGetHemisphereTrackingMode( int which_controller, int *state );
SIXENSE_EXPORT int sixenseAutoEnableHemisphereTracking( int which_controller );
SIXENSE_EXPORT int sixenseSetHighPriorityBindingEnabled( int on_or_off );
SIXENSE_EXPORT int sixenseGetHighPriorityBindingEnabled( int *on_or_off );
SIXENSE_EXPORT int sixenseTriggerVibration( int controller_id, int duration_100ms, int pattern_id );
SIXENSE_EXPORT int sixenseSetFilterEnabled( int on_or_off );
SIXENSE_EXPORT int sixenseGetFilterEnabled( int *on_or_off );
SIXENSE_EXPORT int sixenseSetFilterParams( float near_range, float near_val, float far_range, float far_val );
SIXENSE_EXPORT int sixenseGetFilterParams( float *near_range, float *near_val, float *far_range, float *far_val );
SIXENSE_EXPORT int sixenseSetBaseColor( unsigned char red, unsigned char green, unsigned char blue );
SIXENSE_EXPORT int sixenseGetBaseColor( unsigned char *red, unsigned char *green, unsigned char *blue );
// Ending definitions
#if defined(__LANGUAGE_C_PLUS_PLUS)||defined(__cplusplus)||defined(c_plusplus)
}
#endif
#endif /* _SIXENSE_H_ */
Now for the fun part. Here's my code in C# (sorry the formatting and colors got messed up):
using System.Runtime.InteropServices;
namespace DLLImporter
{
public unsafe partial class Form1 : Form
{
//[StructLayout(LayoutKind.Sequential)]
unsafe struct controller
{
float X;
float Y;
float Z;
/*float mat00;
float mat01;
float mat02;
float mat03;
float mat10;
float mat11;
float mat12;
float mat13;
float mat20;
float mat21;
float mat22;
float mat23;
float mat30;
float mat31;
float mat32;
float mat33;*/
fixed float mat[16];
float joyX;
float joyY;
float trigger;
uint buttons;
char seqNum;
/*float quatX;
float quatY;
float quatZ;
float quatW;*/
fixed float quat[4];
ushort firmwareRev;
ushort hardwareRev;
ushort packetType;
ushort magFreq;
int enabled;
int index;
char docked;
char hand;
char trackingEnabled;
};
[DllImport("sixense.dll", CallingConvention = CallingConvention.Cdecl)]
static extern int sixenseInit();
[DllImport("sixense.dll", CallingConvention = CallingConvention.Cdecl)]
static extern int sixenseExit();
[DllImport("sixense.dll", CallingConvention = CallingConvention.Cdecl)]
static extern int sixenseGetMaxBases();
[DllImport("sixense.dll", CallingConvention = CallingConvention.Cdecl)]
static extern int sixenseSetActiveBase(int which);
[DllImport("sixense.dll", CallingConvention = CallingConvention.Cdecl)]
static extern int sixenseGetNumActiveControllers();
[DllImport("sixense.dll", CallingConvention = CallingConvention.Cdecl)]
static extern int sixenseIsControllerEnabled(int which);
[DllImport("sixense.dll", CallingConvention = CallingConvention.Cdecl)]
static extern int sixenseIsBaseConnected(int i);
[DllImport("sixense.dll", CallingConvention = CallingConvention.Cdecl)]
static extern int sixenseGetNewestData(int which, sixenseControllerData *data);
public Form1()
{
unsafe
{
InitializeComponent();
sixenseInit(); // Returns 0
int maxBases = sixenseGetMaxBases(); // Returns 4
sixenseSetActiveBase(1); // Returns 0
sixenseGetNumActiveControllers(); // Returns 0
sixenseIsBaseConnected(0); // Returns 0
sixenseControllerData data = new sixenseControllerData();
sixenseGetNewestData(0, &data); // Throws MarshalDirectiveException
sixenseExit();
}
}
}
}
As you can see, I tried to do the mat and quat as individual variables, and switched to making them fixed arrays, but it didn't have much effect (although the mat values changed I think, but they're still not right, and have lots of 0 values).
I've tried it with and without using the StructLayout attribute. It doesn't seem to have an effect.
I tried it with and without the unsafe block. Originally I was using the data variable in SixenseGetNewestData using a ref keyword instead of making it a pointer and using &. When I did it that way, it didn't throw an exception, but put bad values in the data variable. Now it throws an exception instead. More details are posted above.
If anyone could please solve this, I've been working on it for months now and I can feel that I'm so close, but something stupid keeps getting in my way somehow! Thank you very much!