PatHightree / SpaceNavigator

SpaceNavigator driver for Unity3D
MIT License
170 stars 55 forks source link

Unify layouts #37

Open krisrok opened 2 years ago

krisrok commented 2 years ago

Let's try to identify layouts (omitting buttons):

I've named them using report count (1/2) and if both parts are swapped (SS) or just one (S).

Interestingly, other implemenations do not have such distinctions regarding axis order, e.g. in FreeGLUT nor in FreeCAD.

PatHightree commented 2 years ago

As this data is going to to be subject to change, I think it might be better to put it on a wiki page instead

krisrok commented 2 years ago

Valid point. Another layout (like a table) would be great too, but for now: https://github.com/PatHightree/SpaceNavigator/wiki/Layout-differences

Could you please add your IDs and what you've tested?

Let's keep it this issue here for now as we need some place to discuss going forward. What really baffles me is the other applications' implementations. They are so straightforward. I wonder how they behave with all those different devices though.

PatHightree commented 2 years ago

I had no knowledge of those implementations, it looks like those are full applications, not plugins. That means they have access to the windows message pump, which is another (more conventional) mechanism for 3dconnexion to deliver its navigation data to apps. This probably means that the device differences are abstracted away.

krisrok commented 2 years ago

At least the GLUT one uses HID input as well. I stumbled upon this implementation via this project's wiki. Also, dropping the VIDs and PIDs into google yields some results :)

About the resource I just linked i wanted to add: At least the SpaceMouse Compact info there seems to be incorrect, i have the exact same one (judging by VID and PID) but I receive 2 reports not just the 1 containing both translation and rotation. So, as usual, you have to use this info gathered on this wiki with a grain of salt but it has some great pointers.

krisrok commented 2 years ago

This python implementation also uses the same layout for all supported devices: Translation XYZ, Rotation XZY (Pitch Roll Yaw)... Even for models that have different layouts in our codebase. But again, I wonder how that works out in reality. Maybe there is some mapping in another layer on top of that (like a config).

krisrok commented 2 years ago

Thanks for reworking the wiki page.

I've added a separate section for the Universal Receiver because it might be a special beast. Please see open questions.

We just need more input about the devices from different sources. @JiapengChi please chime in :)

PatHightree commented 2 years ago

I made a post on the 3dconnexion forum, asking outright for the HID details of the different hardware variations The post is waiting for review (I lost my old login) I'll link it here when it gets posted.

PatHightree commented 2 years ago

Here's the thread https://forum.3dconnexion.com/viewtopic.php?f=19&t=40919

Got a very interesting reply, it might very well be possible to read the data layout from the device at runtime and interpret the data accordingly. A sample implementation is forthcoming.

krisrok commented 2 years ago

Wow, ok. That's interesting indeed!

Just had a longer look at InputDevice.description.capabilities and it seems to contain everything we need. Why didn't we notice before?! The capabilities even get displayed nicely formatted through InputDebugger->Device->HID Descriptor. There you can see the correct usages, e.g. Element 2's usage is "0x32 (Z)", so this is Translation.Z. Great! This in turn means InputSystem comes with a HIDParser and such to decipher the usages etc, see here: InputSystem\Plugins\HID\HIDParser.cs

Those classes are internal though, but we could copy the bits we need or try and use reflection to get a nicely parsed HID descriptor object.

krisrok commented 2 years ago

Ok I guess it works all without internal APIs. Here's a quick test adopted from HIDDescriptorWindow:

var descriptor = HIDDeviceDescriptor.FromJson(device.description.capabilities);
foreach(var element in descriptor.elements)
{
    string usagePageString = HID.UsagePageToString(element.usagePage);
    string usageString = HID.UsageToString(element.usagePage, element.usage);

    Debug.Log(string.Format("Usage Page: 0x{0:X} ({1})", (uint)element.usagePage, usagePageString));
    if (usageString != null)
        Debug.Log(string.Format("Usage: 0x{0:X} ({1})", element.usage, usageString));
    else
        Debug.Log(string.Format("Usage: 0x{0:X}", element.usage));
}

The usage combined with other element info about reportId, offset and size should be enough to piece a layout together at runtime I think.

JiapengChi commented 2 years ago

@krisrok Sorry for replying late.

The SpaceMouses I am using are the following: SpaceMouse Wireless and SpaceMouse Enterprise

The Enterprise one can only work with wire, and the wireless one comes with a receiver, which I am not sure is a universal receiver or not.

The pull request #34 is to fix the bugs with the two devices above, I am not sure that it can work well with the previous generation products. What kind of SpaceMouse you are using?

For the Y axis, could you point out that which part of the code you have questions about?

Thanks!

JiapengChi commented 2 years ago

Thanks for reworking the wiki page.

I've added a separate section for the Universal Receiver because it might be a special beast. Please see open questions.

We just need more input about the devices from different sources. @JiapengChi please chime in :)

I will add the information later.

PatHightree commented 2 years ago

@JiapengChi Thanks, it would be great if you can you add your device info to the table on this page https://docs.unity3d.com/Packages/com.unity.inputsystem@1.0/manual/Layouts.html#layout-builders

@krisrok Great work! It's a shame that I used the attributes approach to configure the data layout in the driver, which is totally non-flexible. I think the solution is to use the LayoutBuilder api to create the data layout by script. As described over here https://docs.unity3d.com/Packages/com.unity.inputsystem@1.0/manual/Layouts.html#layout-builders

krisrok commented 2 years ago

I think the solution is to use the LayoutBuilder api to create the data layout by script.

Yep, I just finished reading up on that, too! 👍

krisrok commented 2 years ago

Here‘s outlined what should work for us: https://docs.unity3d.com/Packages/com.unity.inputsystem@1.0/api/UnityEngine.InputSystem.InputSystem.html#UnityEngine_InputSystem_InputSystem_onFindLayoutForDevice

Be sure to read the whole thing though, it has some caveats.

krisrok commented 2 years ago

"Some caveats" does not do justice at all. I've tried to implement this beast but one blocker follows the next. Here's an outline of it so far: https://forum.unity.com/threads/onfindlayoutfordevice-for-auto-assigned-layouts.1161377/

PatHightree commented 2 years ago

One of the mods at 3dconnexion forum sent me a c++ example of how HID api can be used to interpret the HID descriptor. Might come in handy if the layout builder is too uncooperative. HIDTest_descriptor_reader.zip