I just got a 3D Connexion SpaceNavigator which is a kind of 3D input device(mouse/stick). It is cool to use when 3D modeling content for JavaFX but I thought it would be even better if I could navigate my JavaFX 3D scenes using it. I managed to hack some quick code to get it working in JavaFX. Many thanks to the JInput project, they made it super easy. Its super fun so I recoded a little video to share with you.
SpaceNavigator with JavaFX from Jasper Potts on Vimeo.
The code really is very simple, I just have a AnimationTimer that every frame checks to get the current inputs from device and applies them to the camera transforms. The device via jinput provides 6 floats for each axis and 2 booleans for the buttons, so could not be easier to connect to your app. Below is complete 3D app with a simple cube. I will be working on getting the object importers out in open source for you to use very soon 🙂
public class InputTestBlog extends Application { private ControllerEnvironment controllerEnvironment; private Controller spaceNavigator; private Component[] components; private Translate translate; private Rotate rotateX,rotateY,rotateZ; @Override public void start(Stage stage) throws Exception { controllerEnvironment = ControllerEnvironment.getDefaultEnvironment(); Controller[] controllers = controllerEnvironment.getControllers(); for(Controller controller: controllers){ if ("SpaceNavigator".equalsIgnoreCase(controller.getName())){ spaceNavigator = controller; System.out.println("USING Device ["+controller.getName()+"] of type ["+controller.getType().toString()+"]"); components = spaceNavigator.getComponents(); } } Group root = new Group(); Scene scene = new Scene(root, 1024, 768, true); stage.setScene(scene); scene.setFill(Color.GRAY); // CAMERA final PerspectiveCamera camera = new PerspectiveCamera(true); scene.setCamera(camera); root.getChildren().add(camera); // BOX Box testBox = new Box(5,5,5); testBox.setMaterial(new PhongMaterial(Color.RED)); testBox.setDrawMode(DrawMode.LINE); root.getChildren().add(testBox); // MOVE CAMERA camera.getTransforms().addAll( rotateY = new Rotate(-20, Rotate.Y_AXIS), rotateX = new Rotate(-20, Rotate.X_AXIS), rotateZ = new Rotate(0, Rotate.Z_AXIS), translate = new Translate(5, -5, -15) ); // SHOW STAGE stage.show(); // CHECK FOR INPUT if (spaceNavigator != null) { new AnimationTimer() { @Override public void handle(long l) { if (spaceNavigator.poll()) { for(Component component: components) { switch(component.getName()) { case "x": translate.setX(translate.getX() + component.getPollData()); break; case "y": translate.setY(translate.getY()+component.getPollData()); break; case "z": translate.setZ(translate.getZ()+component.getPollData()); break; case "rx": rotateX.setAngle(rotateX.getAngle()+component.getPollData()); break; case "ry": rotateY.setAngle(rotateY.getAngle()+component.getPollData()); break; case "rz": rotateZ.setAngle(rotateZ.getAngle()+component.getPollData()); break; } } } } }.start(); } } public static void main(String[] args) { System.setProperty("net.java.games.input.librarypath", new File("lib").getAbsolutePath()); launch(args); } }
Interesting read, thank you.
It would be very good to integrate the JInput functionality into JavaFX.
The project was last updated 2 years ago I think and at least the Mac version has only one sporadic maintainer.
But for something like the 3D functionality of JavaFX the possibility of proper input by joysticks or your SpaceNavigator is essential.
When we are at it, Java is generally missing a standardized method of talking to USB ports.