Notice (8): Undefined index: HTTP_ACCEPT_LANGUAGE [APP/Controller/AppController.php, line 43]
ByteBites - JInput with 3DConnexion Space Pilot Pro controller

JInput and 3DConnexion Space Pilot Pro

Using 3DConnexion controllers in Java language

Introduction

In order to facilitate navigation in three-dimensional space there are several hardware solutions. One of them is quite popular equipment from 3DConnexion. These devices are: Space Navigator Space Mouse and Space Pilot/Pro. The devices have the main 3D controller and depending on the model, from a few to several programmable buttons.

dimmer dimmer

Fig. 3D Connexion controllers: Space Mouse and Space Pilot Pro

On Windows, Mac OSX and Linux there are proper device drivers and exist support for several popular 3D applications.

What interests us most is the ability to integrate the device in our own software solutions. After signing the NDA document, you can get the software SDK that allows you to integrate the device in your software. In this article I refer to the Linux platform, which I mostly work on. Delivered software (C/C++ source code) allow you to connect and get data from the running in the background 3Dconnexion daemon. Unfortunately, there are no examples for Java nor any JNI wrapper for the supplied code. You need to search for other solutions. And here to help comes JInput library.

JInput

The library was founded as a generic library for handling different game controllers. As it turns out, it also supports the 3Dconnexion devices as multimedia controllers. Unfortunately the library it now not very active supported. The last commit on the official repository (link below) was long time ago.

In addition, as it turns out, after downloading the source code and its compilation I have encountered problems with the Space Pilot Pro controller. The problem happened because this controller is identified by the JInput library as two separate controllers: STICK and MOUSE. The library code has an area in which it optimizes detected controllers and merge when they are the same type. Here happens to be the problem, because the designers did not expect (?) that one controller can be both mouse and joystick. I fixed the code, did a small patch in order to compile the code and put it on my own fork on bitbucket (link below). After compilation you should get jar library and a wrapper for native code compatible with the environment, in which it was compiled.

Using the library

Below you can find an example implementation of Space Pilot Pro controller support and data retrival. Function poll() should be executed according to your own application visualization cycles.

            public class SpaceNavigatorController {

                private final ControllerEnvironment controllerEnvironment;
                private Controller spaceNavigator;
                private Component[] components;

                public SpaceNavigatorController() {

                    controllerEnvironment = ControllerEnvironment.getDefaultEnvironment();
                    Controller[] controllers = controllerEnvironment.getControllers();
                    for (Controller controller : controllers) {
                        System.out.println("Controller: " + controller.getName());
                        if (controller.getName().contains("3Dconnexion") && controller.getType() == Controller.Type.STICK) {
                            spaceNavigator = controller;
                            System.out.println("USING Device [" + controller.getName() + "] of type [" + controller.getType().toString() + "]");
                            components = spaceNavigator.getComponents();
                        }
                    }
                }

                /** poll periodically in order to get data */
                public void poll() {
                    /** movement */
                    float x, y, z;
                    /** rotation */
                    float rx, ry, rz;

                    if (spaceNavigator != null) {
                        if (spaceNavigator.poll()) {                            
                            for (Component component : components) {
                                if (component.getName().equals("x")) {
                                    x = component.getPollData();
                                } else if (component.getName().equals("y")) {
                                    y = component.getPollData();
                                } else if (component.getName().equals("z")) {
                                    z = component.getPollData();
                                } else if (component.getName().equals("rx")) {
                                    rx = component.getPollData();
                                } else if (component.getName().equals("ry")) {
                                    ry = component.getPollData();
                                } else if (component.getName().equals("rz")) {
                                    rz = component.getPollData();
                                } 
                            }
                        }
                    }
                }
            }
            

Links