• Welcome to PiBoSo Official Forum. Please login or sign up.
 
August 26, 2025, 10:53:42 AM

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Messages - Nihil

1
Support / VR head tracking off center - fisheye
July 18, 2024, 10:51:19 PM
Hi, I've been having this issue for over a year -
In VR it seems the perspective, FOV or tracking is not centered,
Everything looks like "Fisheye" camera, where screen center is ok but edges are stretched,
And head movement is very strange.

Everything was fine until Virtual Desktop switched to OpenVR a while back,
But!
Issue is same in both SteamVR and Oculus VR,
Using Virtual Desktop, AirLink and Oculus Link,
In Quest 2 and Quest Pro.

Tried re-installing, fresh demo profile, deleted all local files.. no bueno.

I thought an update of GP-bikes or Virtual Desktop will fix it, so I waited..
But still same issue.

Thanks for your help!
2
exactly right. I'll probably open new thread for "Rider assist" when I make progress.

Thanks a lot for all your help!
3
Yes, this stops here I believe.

Plugin and controller can not be mixed.
The UUID seems to be used to assign a bind to a controller.
If you give the plugin the same UUID as your gamepad in controls.txt - it will just take over it and you won't need to re-bind the controls by selecting each one and giving an input/moving the stick.

If you want to re-bind your input plugin, you can either attach it to a device that will feed real input and actually move a stick,

Or you could programatically send the input.
I had my input plugin send max value for X-Axis, so when I clicked on "lean" in settings it just assigned it because the stick was "pressed".

Thanks for the link to the docs, I will now move to pipe gamepad input through a proxy, and will probably need to disable it as you suggest.
4
Quote from: HornetMaX on March 03, 2022, 12:34:05 AM@Nihil: Just noticed: you must probably fill _psInfo and _psData, not assign a new address. I.e. something like "psInfo->m_iNumSliders = 0;" etc.

Oh hey! Good catch!!
I replaced my address assignment -
_psData = &mydata;With this (too lazy to assign member by member)-
(*_psData) = mydata;
And it works!
Guess the original _psData address is used elsewhere so can't re-assign new address or something?
I think using "psInfo->m_iNumSliders = 0;" will also work and allow setting a specific axis/slider/button instead of building the whole struct like I did.

Anyway, results -
As you remember I wanted to have this input plugin pretend to be the controller, so both it and the controller would be bound to lean or throttle and mix inputs.
So I gave my input plugin the same UUID as the gamepad.
That didn't work.

1. Plugin does not appear in calibration screen. even when working and transmitting data.

2. In-game controller name -
original binding, without plugin - gamepad name when bound to lean - "XInput X-Axis"
original binding, with plugin - gamepad name when bound to lean - "C0 X-Axis"
rebind, with plugin - plugin name when bound to lean - "C1 X-Axis"
rebind, with plugin - gamepad name when bound to lean - "Joy - X-Axis"

3. m_szName is ignored? I have it as "XInput" in my plugin but still shows as "C1".

So even if plugin uses the same UUID as the gamepad, they do not mix signals.
Not changing the binding from original (bound to gamepad), the plugin just "takes over" the UUID and original settings (even though the name changed to "C1").
Re-mapping the controls shows gamepad is now a new device.

So I guess the m_iID for the gamepad gets changed and I can't control that, and UUID is just responsible for binding, which is why existing binds are transferred to plugin.

Bottom line - no mixing. I'll probably go with extermal mixing and feeding to ViGEm.

Good stuff :)
5
Thanks @Vini, I'm thinking along the same lines -

I prefer the input plugin to mix controller inputs with emulated ones as it's a bit simpler and stand-alone GPB solution. Just a tool you can enable without external executables.

But as you suggested, my plan B is to pass the physical controller inputs through a MITM.
I've already started working on my own implementation of XInput to read the controller, now I can either feed the modified output to VJoy or ViGEm (looks interesting! thanks!) and bind that virt-controller in GPB,

Or I could include my XInput reader code in the input plugin directly (and probably will need to disable the GPB original xinput.dli or use HidHide).
BTW, in this approach, Update() will probably be where I read the controller inputs.

As for it being a cheat program - I'm also thinking that.
For me it's more of an experiment in developing rider assist tech that could maybe be used in the real world.
I know BMW were working on something similar. "Smart Bike" or something it was called.

I can justify it being used in gameplay by saying in reality riders get feedback from the front wheel and can maybe save a front slide, but in GPB we don't get those physical sensations.
But still, I don't know if I should release it or use it beyond research purposes.
6
Quote from: HornetMaX on February 28, 2022, 05:11:40 PMI'm not sure you're populating the fields m_aiButton and m_aiDial (in mydata) correctly: I suspect they should not be really "chars" ... I guess they are in fact integer numbers (as the prefix m_ai* indicates), for the status of each button.
Yes, I'm pretty sure these should be 0/1 ints, I was just lazy to create an array of 32 zeroes. I'll try correcting it and see if it works.

Quote from: HornetMaX on February 28, 2022, 05:11:40 PMIn myinfo m_szName is set to "XInput": bad idea. This should be the name you give to your custom controller (I think), so call it "MyOwnController" or something special.

Do you actually see your own controller in GPB settings page
Agreed. I tried naming it "XInput" to hijack my physical controller that's defined in GPB under that name, and make the input plugin write to the same controller.
That didn't work. And naming it anything else makes no difference-

I can not actually see it in GPB, not in selection dropdown, not in "calibrate" screen.
I can't really see the xbox controller either, but it's axis/buttons are shown once I bind them to something.
So maybe if I try binding lean/throttle to my pluin it will show, but I need the plugin to be able to send a key when I'm changing the settings. might try that.

Quote from: HornetMaX on February 28, 2022, 05:11:40 PM@PiBoSO: what's the intended usage of Update() and Reset() calls ?

I was wondering about the Update() func as well -
Should I read controller state/data values every frame in Update(),
Or should I read controller data only when GetControllerData() is called?
It's frequency doesn't seem very high.

And of course the main question - can an input plugin write data as a controller already connected, i.e "two controllers, acting as one"

Thanks for your help!!!
 
7
Quote from: HornetMaX on February 27, 2022, 09:18:58 PMI'm not sure of what you're trying to achieve here.

An input plugin is to send data from a device to GPB, not the other way around.
You don't need to create one for an XBox gamepad as GPB already supports gamepads.

I'm trying to write a "rider assist" plugin that will correct user input, like prevent 100% throttle at max lean,
Or will save the bike from crash like giving a steering command when the front wheel looses grip.

For that I want an input plugin that will override/inject inputs to GPB when a condition is met, otherwise allow the user to control the bike with his controller.

Quote from: HornetMaX on February 27, 2022, 09:18:58 PMI'd say no. In GetControllerInfo you declare myinfo as a local variable (hence allocated on the stack) but then you pass its address back to GPB: that address is garbage as soon as the execution leaves your function. I'd expect GPB to crash badly.

Same thing in GetControllerData. Plus, in GetControllerData you have twice a return statement, the first one being even before assigning _psData...

Oops, sorry about those brainfarts (it didn't crash though!).
I've corrected these issues, taking the struct population out of the function.
Still not working/not injecting input into GPB as the controller.

Added some debug prints -
/*
If compiled as C++, extern "C" must be added to declaration of functions to export
*/
#include <string.h>
#include <stdio.h>

typedef struct
{
 char m_szName[100];
 char m_szUUID[37]; /* universally unique identifier */
 int m_iID; /* internal unique ID */
 char m_iNumAxis; /* number of axis */
 short m_aaiAxisRange[6][3]; /* min, max and center value of each axis */
 char m_iNumSliders; /* number of sliders */
 short m_aiSliderRange[6]; /* max value of each slider */
 char m_iNumButtons; /* number of buttons */
 char m_iNumPOV; /* number of POVs */
 char m_iNumDials; /* number of dials */
 char m_aiDialRange[8]; /* max value of dials */
} SControllerInfo_t;

typedef struct
{
 short m_aiAxis[6];
 short m_aiSlider[6];
 char m_aiButton[32];
 unsigned short m_aiPOV[2];
 char m_aiDial[8];
} SControllerData_t;

 SControllerInfo_t myinfo = {
 "XInput",
 "47f219dc-2cb8-4afc-b670-56c637f64a5a",
 0,
 4,
 {
 {0, 32767, 16383},
 {0, 32767, 16383},
 {0, 32767, 16383},
 {0, 32767, 16383}
 },
 2,
 {32767,32767,0,0,0,0},
 6,
 2,
 2,
 {255,255,0,0,0,0,0,0}
 };

 SControllerData_t mydata = {
 {32767, 32767, 32767, 32767, 0, 0},
 {32767, 32767, 32767, 32767, 0, 0},
 "C_AXIS",
 {20, 20},
 "C_AXIS"
 };

__declspec(dllexport) int Version()
{
 return 3;
}

/* called when software is started. If return value is not 0, the plugin is disabled */
__declspec(dllexport) int Startup()
{
 FILE *fp;
 fp = fopen ("C:/Users/nihil/Desktop/testInput.txt", "w");
 fprintf(fp, "test \n");
 fclose(fp);
 return 0;
}

/* called when software is closed */
__declspec(dllexport) void Shutdown()
{
}

/* called every rendering frame. This function is optional */
__declspec(dllexport) void Update()
{

}

/* called when a control is queried */
__declspec(dllexport) void Reset()
{
}

/* called every few seconds to support hot plugging. The return value is the number of active controllers */
__declspec(dllexport) int GetNumControllers()
{
 //return 0;
 return 1;
}

/* _iIndex is the 0 based controller index. _psInfo must be filled with controller info */
__declspec(dllexport) int GetControllerInfo(int _iIndex,SControllerInfo_t *_psInfo)
{

 FILE *fp;
 fp = fopen ("C:/Users/nihil/Desktop/testInput.txt", "a");
 fprintf(fp, "iIndex = %d \n", _iIndex);
 fprintf(fp, "_psInfo.iID = %d \n", _psInfo->m_iID);

 _psInfo = &myinfo;

 fprintf(fp, "my _psInfoiID = %d \n", _psInfo->m_iID);
 fclose(fp);

 return 0;
}

/* _iID is the unique controller ID. _psData must be filled with controller data */
__declspec(dllexport) int GetControllerData(int _iID,SControllerData_t *_psData)
{


 FILE *fp;
 fp = fopen ("C:/Users/nihil/Desktop/testInput.txt", "a");
 fprintf(fp, "iID = %d \n", _iID);
 fprintf(fp, "_psData m_aiAxis = %d \n", _psData->m_aiAxis[0]);

 _psData = &mydata;

 fprintf(fp, "my _psData m_aiAxis = %d \n", _psData->m_aiAxis[0]);
 fclose(fp);

 return 0;
}

and the output log, you can see my input value "32767" is being set, at least inside the function
test
iIndex = 0
_psInfo.iID = 0
my _psInfoiID = 0
iID = 0
_psData m_aiAxis = 0
my _psData m_aiAxis = 32767
iID = 0
_psData m_aiAxis = 0
my _psData m_aiAxis = 32767
iID = 0
_psData m_aiAxis = 0
my _psData m_aiAxis = 32767
iID = 0
_psData m_aiAxis = 0
my _psData m_aiAxis = 32767
8
Plugins / Input plugin - inject to existing controller
February 27, 2022, 02:26:14 PM
Hi I'm trying to write an input plugin that would inject inputs to an existing controller (i.e Xbox gamepad).

I've created and compiled a DLI, setting the `SControllerInfo_t` m_szUUID to the existing external controller UUID taken from `controls.txt` in profile (Don't know where to take `m_iID` from),
And injecting max values in `GetControllerData`.


This doesn't seem to work though.
I think it's compiled correctly as `printf` statements work.

Is that even possible?

Also, am I using the data structures / populating _psData correctly?
What are _iID and _iIndex for? they seem to be always zero.

Thanks!

Here's my input file:
/*
If compiled as C++, extern "C" must be added to declaration of functions to export
*/
#include <string.h>
#include <stdio.h>

typedef struct
{
char m_szName[100];
char m_szUUID[37]; /* universally unique identifier */
int m_iID; /* internal unique ID */
char m_iNumAxis; /* number of axis */
short m_aaiAxisRange[6][3]; /* min, max and center value of each axis */
char m_iNumSliders; /* number of sliders */
short m_aiSliderRange[6]; /* max value of each slider */
char m_iNumButtons; /* number of buttons */
char m_iNumPOV; /* number of POVs */
char m_iNumDials; /* number of dials */
char m_aiDialRange[8]; /* max value of dials */
} SControllerInfo_t;

typedef struct
{
short m_aiAxis[6];
short m_aiSlider[6];
char m_aiButton[32];
unsigned short m_aiPOV[2];
char m_aiDial[8];
} SControllerData_t;

__declspec(dllexport) int Version()
{
return 3;
}

/* called when software is started. If return value is not 0, the plugin is disabled */
__declspec(dllexport) int Startup()
{
FILE *fp;
fp = fopen ("C:/Users/nihil/Desktop/testInput.txt", "w");
fprintf(fp, "test");
fclose(fp);
return 0;
}

/* called when software is closed */
__declspec(dllexport) void Shutdown()
{
}

/* called every rendering frame. This function is optional */
__declspec(dllexport) void Update()
{

}

/* called when a control is queried */
__declspec(dllexport) void Reset()
{
}

/* called every few seconds to support hot plugging. The return value is the number of active controllers */
__declspec(dllexport) int GetNumControllers()
{
//return 0;
return 1;
}

/* _iIndex is the 0 based controller index. _psInfo must be filled with controller info */
__declspec(dllexport) int GetControllerInfo(int _iIndex,SControllerInfo_t *_psInfo)
{
SControllerInfo_t myinfo = {
"myInput",
"47f219dc-2cb8-4afc-b670-56c637f64a5a",
0,
4,
{
{0, 32767, 16383},
{0, 32767, 16383},
{0, 32767, 16383},
{0, 32767, 16383}
},
2,
{32767,32767,0,0,0,0},
6,
2,
2,
{255,255,0,0,0,0,0,0}
};

FILE *fp;
fp = fopen ("C:/Users/nihil/Desktop/testInput.txt", "a");
fprintf(fp, "iIndex = %d", _iIndex);
fclose(fp);
return 0;

_psInfo = &myinfo;


return 0;
}

/* _iID is the unique controller ID. _psData must be filled with controller data */
__declspec(dllexport) int GetControllerData(int _iID,SControllerData_t *_psData)
{

SControllerData_t mydata = {
{32767, 32767, 32767, 32767, 0, 0},
{32767, 32767, 32767, 32767, 0, 0},
"BUTTONS",  // This is probably wrong, but not focusing on buttons at the moment
{20, 20},
"DIAL"   // This is probably wrong, but not focusing on dials at the moment
};

FILE *fp;
fp = fopen ("C:/Users/nihil/Desktop/testInput.txt", "a");
fprintf(fp, "iID = %d", _iID);
fclose(fp);
return 0;

_psData = &mydata;

return 0;
}
9
Virtual Reality / Re: Steam VR issues Major WTF
February 16, 2022, 12:53:38 AM
Quote from: Chispifumy on February 15, 2022, 08:36:50 PMis the world scale correct in your case using steam vr? Everything seems a little small to me.

Looks fine to me, but you can change it in SteamVR settings (either global or per-game, make sure you have advanced options showing)
10
Suggestions and wishlist / Look back to work in VR
February 15, 2022, 12:58:49 AM
I don't know if this is possible (or recommended), but perhaps look-back should work in VR?
At the moment it does not.

For me it's a bit difficult to rotate fully, and can't do the under-arm-upside-down look I used to do in real life because headset will fall off.

11
General Discussion / Re: Known bugs of Beta20
February 08, 2022, 02:30:47 PM
Quote from: Chispifumy on February 07, 2022, 12:21:49 AMIn VR (Oculus Quest 2), in the replays, the asphalt is not seen, there is a kind of "empty" texture and the steam vr background is seen in the background.

+1.
12
Virtual Reality / Re: game freezes when player connects
February 08, 2022, 02:28:48 PM
Quote from: fryy on December 23, 2021, 04:40:53 PMI'm moving all my mods over to an SSD to see if that will fix it. My theory is that when someone connects with a mod my game has to load off my D drive, it's freezing while loading the mod. Hopefully moving the mods all onto an SSD will help.

All my mods are on the same SSD as install folder. Still get these freezes so that probably won't help (but might shorten the freeze, I don't know how long it is for you).

I notices sometimes players connect with no freeze. my guess is that your right and when a player connects with a bike that's already used by someone there's no need to load the model, but if a new unused bike joins the model is loaded to memory.
13
Virtual Reality / Re: VR version resolution
February 08, 2022, 02:25:37 PM
I think you can also add to/create the file oculus.ini in GPB install folder:
[render]
pixel_density = 1.5


As for resolution - I'm using Virtual Desktop and SteamVR, and the resolution settings in both do not seem to effect GPB.
Or it does set an upscaled resolution, but any alterations do not have an effect.
14
Suggestions and wishlist / News and Events on home screen
February 08, 2022, 02:22:02 PM
Hi,

I think it would be nice to have an events section on the home screen,
Where we can update riders on upcoming races, championships etc.

This will increase engagement and help us schedule our riding times rather than randomly finding a race.
Especially for users that are not on the forum/discord.

Cheers
15
Support / Re: Debug and crash logs
January 17, 2022, 03:01:06 AM
I must fix it! used to race minitwins for a couple of seasons, I just have to throw it around Brands and Snet :)