SpaceNavigator and Java

Post questions, comments and feedback to our 3Dconnexion Windows Development Team.

Moderator: Moderators

Post Reply
mm_911
Posts: 2
Joined: Tue Jul 17, 2007 7:05 am

SpaceNavigator and Java

Post by mm_911 »

Hi,

I'm a german student and bought a SpaceNavigator for my project. I programmed a 3D visualization in Java (but instead of Java3d I used JOGL (Java OpenGL Binding)). Now I want to use the SpaceNavigator in my visualization.

I already found the JNIsiapp.zip here. viewtopic.php?t=672&highlight=java

I can start the JNIsiappThread without any exception. But I don't receive any action of the SpaceNavigator. The method call

Code: Select all

siapp.SiWaitForEvent();

in line 32 in JNIsiappThread.java doesn't work, because the thread doesn't wait there.

I don't know what to do. Maybe I forgot a link or something else, but why is there no error or exception? I need help!

PS:
1, Can anybody explain me what this method call is for

Code: Select all

siapp.SiOpenWinInit("JNIsiappThread","eventCallback");
2, I use eclipse 3.2 maybe there is a trick to get the SpaceNavigator working
jwick
Moderator
Moderator
Posts: 3339
Joined: Wed Dec 20, 2006 2:25 pm
Location: USA
Contact:

Post by jwick »

Hello mm_911,

Do the Java demos work off the ftp site?

Please read this thread: viewtopic.php?p=3702#3702

The first argument of SiOpenWinInit must be the name of the window the driver will use to send events to your Java thread. If you aren't getting events, it is probably because the name is wrong.

We ship the source code for the JNI library. Feel free to trace through that at runtime to see what is happening.

Jim
3Dx Software Development
rlishere
Posts: 3
Joined: Wed Sep 12, 2007 12:47 pm
Location: Solingen, Germany

Post by rlishere »

Wow, a ndof-input-device at that price. :D
Great, I thought.
I ordered my Space-navigator, then the first tests.
What a google-feeling. 8) Ok, other Programs worked, too.
But what's about JAVA, - poor. :(
There is not a lot to find on the web for the moment.

I found that

http://www.edparrish.com/cis160/06s/sup ... amePad.pdf

as a very good introduction to use jinput as an interface for JAVA.

Everything starts here

http://fivedots.coe.psu.ac.th/~ad/jg2/ch11/index.html

the original sources are here

http://fivedots.coe.psu.ac.th/~ad/jg2/ch11/gp.zip

So I modified those sources to interface my Space-navigator.
All 6 channels and both buttons.

This is a good start for a test.

In the hope that this can be helpfull to others,

rl
ngomes
Moderator
Moderator
Posts: 3333
Joined: Mon Nov 27, 2006 7:22 am
Contact:

Post by ngomes »

Great stuff, rlishere. Thanks for reporting in the Forum.

We will be reviewing your code and we may want to make it available from our SDK page. To do that, we will need your permission.
Nuno Gomes
rlishere
Posts: 3
Joined: Wed Sep 12, 2007 12:47 pm
Location: Solingen, Germany

Post by rlishere »

Hi ngomes,
ngomes wrote:Great stuff, rlishere. Thanks for reporting in the Forum.

We will be reviewing your code and we may want to make it available from our SDK page. To do that, we will need your permission.
to clarify that,
the links in my above post are not pointing to MY code,
it is the starting point of my changings to use it for the SpaceNavigator.

The changings were not difficult and I'm not a professional Java-coder.

If useful, i will give MY changings to you, but I don't know how to handle the copyrights of the source.
So, if you find a way out...

rl :?
ngomes
Moderator
Moderator
Posts: 3333
Joined: Mon Nov 27, 2006 7:22 am
Contact:

Post by ngomes »

Hi rlishere,
he links in my above post are not pointing to MY code,
it is the starting point of my changings to use it for the SpaceNavigator.
Thanks for clarifying that. Like I said it is very useful information and we will be reviewing it. We will considering redistributing the code when we know more about the terms of its license.
brupbacher
Posts: 13
Joined: Tue Oct 02, 2007 1:35 pm

a working Java Example

Post by brupbacher »

Hi all, after a little hacking and reading the news groupe, I finally got a valid result to use my USB 3Dconnexion space mouse :-).
The solution and code I offer here is based on readings in this forum and the follwoing two links which were also
mentionned in this forum. Some people allready had solutions for themselves but for legal reasons did not publish it.

http://fivedots.coe.psu.ac.th/~ad/jg2/ch11/index.html (Andrew Davison's Java Gaming and 3D Book)
https://jinput.dev.java.net/


So here it is:

Solution Overview:
1: Download, Install and understand the jinput api (read also stuff from Andrew Davison's Java 3D stuff it helps to understand)
2: implement a Class which defines your SpaceNavigator (3DConnexion in our case) see the implementaton bellow (see Code 2)
3: use the SpaceNavigator class in your code (see Code 1)

I think this is fairly simple thanks to the effort made by the jinput community (big thanks) and


Code 1: Use the SpaceNavigator

...

private static final int DELAY = 40;
private Timer pollTimer;
private SpaceNavigatorController spaceNavigatorController;


public static void main (String[] args) {

spaceNavigatorController = new SpaceNavigatorController();
addWindowListener(new WindowAdapter() {
public void windowClosing (WindowEvent e) {
pollTimer.stop(); // stop the timer
System.exit(0);
}
});
startPolling();
}

private void startPolling () {
ActionListener pollPerformer = new ActionListener() {
public void actionPerformed (ActionEvent e) {
spaceNavigatorController.poll();
}
};
pollTimer = new Timer(DELAY, pollPerformer);
pollTimer.start();
}

...


Code 2: SpaceNavigatorController Class

package nacked;

import net.java.games.input.Component;
import net.java.games.input.Controller;
import net.java.games.input.ControllerEnvironment;

/**
* Details for: SpaceNavigator, Stick, Unknown
* Components: (8)
* 0. Z Axis, z, relative, analog, 0.0
* 1. Y Axis, y, relative, analog, 0.0
* 2. X Axis, x, relative, analog, 0.0
* 3. Z Rotation, rz, relative, analog, 0.0
* 4. Y Rotation, ry, relative, analog, 0.0
* 5. X Rotation, rx, relative, analog, 0.0
* 6. Button 0, 0, absolute, digital, 0.0
* 7. Button 1, 1, absolute, digital, 0.0
* No Rumblers
* No subcontrollers
*/

public class SpaceNavigatorController {

public static final int NUM_BUTTONS = 2;

public static final int ZAXIS = 0;
public static final int YAXIS = 1;
public static final int XAXIS = 2;
public static final int ZROTATION = 3;
public static final int YROTATION = 4; // default value
public static final int XROTATION = 5;
public static final int BUTTON0 = 6;
public static final int BUTTON1 = 7;

// values returnd by the device during poll (may not be correct)
private static final float MAX_ROTATION = 1560.0f;
private static final float MAX_TRANSLATION = 1613.0f;

private int xAxisIdx, yAxisIdx, zAxisIdx, rxAxisIdx, ryAxisIdx, rzAxisIdx;
private int buttonsIdx[];

private Controller controller;
private Component[] comps;

public SpaceNavigatorController () {

ControllerEnvironment ce = ControllerEnvironment.getDefaultEnvironment();
Controller[] cs = ce.getControllers();
if (cs.length == 0) {
System.out.println("No controllers found");
System.exit(0);
} else System.out.println("Num. controllers: " + cs.length);

controller = findSpaceNavigator(cs);
System.out.println("Space Navigator controller: " + controller.getName() + ", " + controller.getType());

findCompIndices(controller);
}


private Controller findSpaceNavigator (Controller[] cs) {
Controller.Type type;
int i = 0;
while (i < cs.length) {
type = cs.getType();
if ((type == Controller.Type.STICK)) break;
i++;
}

if (i == cs.length) {
System.out.println("No Space Navigator found");
System.exit(0);
} else System.out.println("No Space Navigator index: " + i);

return cs;
}

private void findCompIndices (Controller controller)
/* Store the indices for the analog sticks axes
(x,y) and (z,rz), POV hat, and
button components of the controller.
*/ {
comps = controller.getComponents();
if (comps.length == 0) {
System.out.println("No Components found");
System.exit(0);
} else System.out.println("Num. Components: " + comps.length);

// get the indices for the axes of the analog sticks: (x,y) and (z,rz)
xAxisIdx = findCompIndex(comps, Component.Identifier.Axis.X, "x");
yAxisIdx = findCompIndex(comps, Component.Identifier.Axis.Y, "y");
zAxisIdx = findCompIndex(comps, Component.Identifier.Axis.Z, "y");

rxAxisIdx = findCompIndex(comps, Component.Identifier.Axis.RZ, "rx");
ryAxisIdx = findCompIndex(comps, Component.Identifier.Axis.RZ, "ry");
rzAxisIdx = findCompIndex(comps, Component.Identifier.Axis.RZ, "rz");

findButtons(comps);
}

private int findCompIndex (Component[] comps, Component.Identifier id, String nm) {
Component c;
for (int i = 0; i < comps.length; i++) {
c = comps;
if ((c.getIdentifier() == id)) {
System.out.println("Found " + c.getName() + "; index: " + i);
return i;
}
}

System.out.println("No " + nm + " component found");
return -1;
}

/**
* Search through comps[] for NUM_BUTTONS buttons, storing
* their indices in buttonsIdx[]. Ignore excessive buttons.
* If there aren't enough buttons, then fill the empty spots in
* buttonsIdx[] with -1's.
*/
private void findButtons (Component[] comps) {
buttonsIdx = new int[NUM_BUTTONS];
int numButtons = 0;
Component c;

for (int i = 0; i < comps.length; i++) {
c = comps;
if (isButton(c)) { // deal with a button
if (numButtons == NUM_BUTTONS) // already enough buttons
System.out.println("Found an extra button; index: " + i + ". Ignoring it");
else {
buttonsIdx[numButtons] = i; // store button index
System.out.println("Found " + c.getName() + "; index: " + i);
numButtons++;
}
}
}

// fill empty spots in buttonsIdx[] with -1's
if (numButtons < NUM_BUTTONS) {
System.out.println("Too few buttons (" + numButtons + "); expecting " + NUM_BUTTONS);
while (numButtons < NUM_BUTTONS) {
buttonsIdx[numButtons] = -1;
numButtons++;
}
}
} // end of findButtons()

/**
* Return true if the component is a digital/absolute button, and
* its identifier name ends with "Button" (i.e. the
* identifier class is Component.Identifier.Button).
*/
private boolean isButton (Component c) {
if (!c.isAnalog() && !c.isRelative()) { // digital and absolute
String className = c.getIdentifier().getClass().getName();
// System.out.println(c.getName() + " identifier: " + className);
if (className.endsWith("Button")) return true;
}
return false;
}

/**
* Return all the buttons in a single array. Each button value is
* a boolean.
*/
public boolean[] getButtons () {
boolean[] buttons = new boolean[NUM_BUTTONS];
float value;
for (int i = 0; i < NUM_BUTTONS; i++) {
value = comps[buttonsIdx].getPollData();
buttons = ((value == 0.0f) ? false : true);
}
return buttons;
} // end of getButtons()


public boolean isButtonPressed (int pos)
/* Return the button value (a boolean) for button number 'pos'.
pos is in the range 1-NUM_BUTTONS to match the game pad
button labels.
*/ {
if ((pos <1> NUM_BUTTONS)) {
System.out.println("Button position out of range (1-" + NUM_BUTTONS + "): " + pos);
return false;
}

if (buttonsIdx[pos - 1] == -1) // no button found at that pos
return false;

float value = comps[buttonsIdx[pos - 1]].getPollData();
// array range is 0-NUM_BUTTONS-1
return ((value == 0.0f) ? false : true);
} // end of isButtonPressed()

public void poll () {
controller.poll();
}


/**
* X Translation
*
* @return float value between 1613 and -1613
* <p>
* Note: the returned value my not be very logic and correct, I just measured them during pooling
*/
public float getTX () {
return comps[xAxisIdx].getPollData();
}

/**
* Y Translation
*
* @return float value between 1613 and -1613
* <p>
* Note: the returned value my not be very logic and correct, I just measured them during pooling
*/
public float getTY () {
return comps[yAxisIdx].getPollData();
}

/**
* Z Translation
*
* @return float value between 1613 and -1613
* <p>
* Note: the returned value my not be very logic and correct, I just measured them during pooling
*/
public float getTZ () {
return comps[zAxisIdx].getPollData();
}


/**
* X Rotation
*
* @return float value between 1560 and -1560
* <p>
* Note: the returned value my not be very logic and correct, I just measured them during pooling
*/
public float getRX () {
return comps[rxAxisIdx].getPollData();
}

/**
* Y Rotation
*
* @return float value between 1560 and -1560
* <p>
* Note: the returned value my not be very logic and correct, I just measured them during pooling
*/
public float getRY () {
return comps[ryAxisIdx].getPollData();
}

/**
* Z Rotation
*
* @return float value between 1560 and -1560
* <p>
* Note: the returned value my not be very logic and correct, I just measured them during pooling
*/
public float getRZ () {
return comps[rzAxisIdx].getPollData();
}
}
jwick
Moderator
Moderator
Posts: 3339
Joined: Wed Dec 20, 2006 2:25 pm
Location: USA
Contact:

Post by jwick »

See related thread: Example in JAVA
Post Reply