OpenVR 1.0.9 and Occulus Support (#779)
* Updated OpenVR implementation to 1.0.9 User can specify external OpenVR library to load with openvr.library.path system property. Usage: java -Dopenvr.library.name=my_path_to_library MyApp Removed reference to OCCULUS VR and OpenVR from VRAppstate as this class is generic and does not have to be linked to specific implementation. VRMouseManager can be buggous using OSVR or Occulus VR. Refactored VR implementation packages in order to separate all available implementation. Modifying or adding implementation should no more impact other ones. Renamed some classes in order to be uniformempirephoenix-patch-1
parent
96836de6e8
commit
58a9211879
@ -0,0 +1,107 @@ |
||||
package com.jme3.input.vr; |
||||
|
||||
import com.jme3.app.VREnvironment; |
||||
import com.jme3.input.controls.AnalogListener; |
||||
import com.jme3.math.Vector2f; |
||||
|
||||
/** |
||||
* A class dedicated to the handling of the mouse within VR environment. |
||||
* @author Julien Seinturier - COMEX SA - <a href="http://www.seinturier.fr">http://www.seinturier.fr</a>
|
||||
*/ |
||||
public interface VRMouseManager { |
||||
|
||||
|
||||
/** |
||||
* Initialize the VR mouse manager. |
||||
*/ |
||||
public void initialize(); |
||||
|
||||
/** |
||||
* Get the {@link VREnvironment VR Environment} to which this manager is attached. |
||||
* @return the {@link VREnvironment VR Environment} to which this manager is attached. |
||||
*/ |
||||
public VREnvironment getVREnvironment(); |
||||
|
||||
/** |
||||
* Set if the VR device controller is used within thumb stick mode. |
||||
* @param set <code>true</code> if the VR device controller is used within thumb stick mode and <code>false</code> otherwise. |
||||
*/ |
||||
public void setThumbstickMode(boolean set); |
||||
|
||||
/** |
||||
* Get if the VR device controller is used within thumb stick mode. |
||||
* @return <code>true</code> if the VR device controller is used within thumb stick mode and <code>false</code> otherwise. |
||||
*/ |
||||
public boolean isThumbstickMode(); |
||||
|
||||
/** |
||||
* Set the speed of the mouse. |
||||
* @param sensitivity the sensitivity of the mouse. |
||||
* @param acceleration the acceleration of the mouse. |
||||
* @see #getSpeedAcceleration() |
||||
* @see #getSpeedSensitivity() |
||||
*/ |
||||
public void setSpeed(float sensitivity, float acceleration); |
||||
|
||||
/** |
||||
* Get the sensitivity of the mouse. |
||||
* @return the sensitivity of the mouse. |
||||
* @see #setSpeed(float, float) |
||||
*/ |
||||
public float getSpeedSensitivity(); |
||||
|
||||
/** |
||||
* Get the acceleration of the mouse. |
||||
* @return the acceleration of the mouse. |
||||
* @see #setSpeed(float, float) |
||||
*/ |
||||
public float getSpeedAcceleration(); |
||||
|
||||
/** |
||||
* Get the move scale. |
||||
* return the move scale. |
||||
* @see #setMouseMoveScale(float) |
||||
*/ |
||||
public float getMouseMoveScale(); |
||||
|
||||
/** |
||||
* Set the mouse move scale. |
||||
* @param set the mouse move scale. |
||||
* @see #getMouseMoveScale() |
||||
*/ |
||||
public void setMouseMoveScale(float set); |
||||
|
||||
/** |
||||
* Set the image to use as mouse cursor. The given string describe an asset that the underlying application asset manager has to load. |
||||
* @param texture the image to use as mouse cursor. |
||||
*/ |
||||
public void setImage(String texture); |
||||
|
||||
/** |
||||
* Update analog controller as it was a mouse controller. |
||||
* @param inputIndex the index of the controller attached to the VR system. |
||||
* @param mouseListener the JMonkey mouse listener to trigger. |
||||
* @param mouseXName the mouseX identifier. |
||||
* @param mouseYName the mouseY identifier |
||||
* @param tpf the time per frame. |
||||
*/ |
||||
public void updateAnalogAsMouse(int inputIndex, AnalogListener mouseListener, String mouseXName, String mouseYName, float tpf); |
||||
|
||||
/** |
||||
* Get the actual cursor position. |
||||
* @return the actual cursor position. |
||||
*/ |
||||
public Vector2f getCursorPosition(); |
||||
|
||||
/** |
||||
* Center the mouse on the display. |
||||
*/ |
||||
public void centerMouse(); |
||||
|
||||
/** |
||||
* Update the mouse manager. This method should not be called manually. |
||||
* The standard behavior for this method is to be called from the {@link VRViewManager#update(float) update method} of the attached {@link VRViewManager VR view manager}. |
||||
* @param tpf the time per frame. |
||||
*/ |
||||
public void update(float tpf); |
||||
} |
@ -0,0 +1,108 @@ |
||||
package com.jme3.input.vr.oculus; |
||||
|
||||
import com.jme3.app.VREnvironment; |
||||
import com.jme3.input.controls.AnalogListener; |
||||
import com.jme3.input.vr.AbstractVRMouseManager; |
||||
import com.jme3.input.vr.VRInputType; |
||||
import com.jme3.math.Vector2f; |
||||
|
||||
/** |
||||
* A class dedicated to the mouse handling within Oculus Rift based VR experience. |
||||
* @author Julien Seinturier - COMEX SA - <a href="http://www.seinturier.fr">http://www.seinturier.fr</a>
|
||||
* |
||||
*/ |
||||
public class OculusMouseManager extends AbstractVRMouseManager { |
||||
|
||||
private final int AVERAGE_AMNT = 4; |
||||
|
||||
private int avgCounter; |
||||
|
||||
private final float[] lastXmv = new float[AVERAGE_AMNT]; |
||||
|
||||
private final float[] lastYmv = new float[AVERAGE_AMNT]; |
||||
|
||||
/** |
||||
* Create a new VR mouse manager within the given {@link VREnvironment VR environment}. |
||||
* @param environment the VR environment of the mouse manager. |
||||
*/ |
||||
public OculusMouseManager(VREnvironment environment){ |
||||
super(environment); |
||||
} |
||||
|
||||
@Override |
||||
public void updateAnalogAsMouse(int inputIndex, AnalogListener mouseListener, String mouseXName, String mouseYName, float tpf) { |
||||
|
||||
if (getVREnvironment() != null){ |
||||
if (getVREnvironment().getApplication() != null){ |
||||
// got a tracked controller to use as the "mouse"
|
||||
if( getVREnvironment().isInVR() == false || |
||||
getVREnvironment().getVRinput() == null || |
||||
getVREnvironment().getVRinput().isInputDeviceTracking(inputIndex) == false ){ |
||||
return; |
||||
} |
||||
|
||||
Vector2f tpDelta; |
||||
// TODO option to use Touch joysticks
|
||||
if( isThumbstickMode() ) { |
||||
tpDelta = getVREnvironment().getVRinput().getAxis(inputIndex, VRInputType.OculusThumbstickAxis); |
||||
} else { |
||||
tpDelta = getVREnvironment().getVRinput().getAxisDeltaSinceLastCall(inputIndex, VRInputType.OculusThumbstickAxis); |
||||
} |
||||
|
||||
float Xamount = (float)Math.pow(Math.abs(tpDelta.x) * getSpeedSensitivity(), getSpeedAcceleration()); |
||||
float Yamount = (float)Math.pow(Math.abs(tpDelta.y) * getSpeedSensitivity(), getSpeedAcceleration()); |
||||
|
||||
if( tpDelta.x < 0f ){ |
||||
Xamount = -Xamount; |
||||
} |
||||
|
||||
if( tpDelta.y < 0f ){ |
||||
Yamount = -Yamount; |
||||
} |
||||
|
||||
Xamount *= getMouseMoveScale(); |
||||
Yamount *= getMouseMoveScale(); |
||||
|
||||
if( mouseListener != null ) { |
||||
if( tpDelta.x != 0f && mouseXName != null ) mouseListener.onAnalog(mouseXName, Xamount * 0.2f, tpf); |
||||
if( tpDelta.y != 0f && mouseYName != null ) mouseListener.onAnalog(mouseYName, Yamount * 0.2f, tpf); |
||||
} |
||||
|
||||
if( getVREnvironment().getApplication().getInputManager().isCursorVisible() ) { |
||||
int index = (avgCounter+1) % AVERAGE_AMNT; |
||||
lastXmv[index] = Xamount * 133f; |
||||
lastYmv[index] = Yamount * 133f; |
||||
cursorPos.x -= avg(lastXmv); |
||||
cursorPos.y -= avg(lastYmv); |
||||
Vector2f maxsize = getVREnvironment().getVRGUIManager().getCanvasSize(); |
||||
|
||||
if( cursorPos.x > maxsize.x ){ |
||||
cursorPos.x = maxsize.x; |
||||
} |
||||
|
||||
if( cursorPos.x < 0f ){ |
||||
cursorPos.x = 0f; |
||||
} |
||||
|
||||
if( cursorPos.y > maxsize.y ){ |
||||
cursorPos.y = maxsize.y; |
||||
} |
||||
|
||||
if( cursorPos.y < 0f ){ |
||||
cursorPos.y = 0f; |
||||
} |
||||
} |
||||
} else { |
||||
throw new IllegalStateException("This VR environment is not attached to any application."); |
||||
} |
||||
} else { |
||||
throw new IllegalStateException("This VR view manager is not attached to any VR environment."); |
||||
} |
||||
} |
||||
|
||||
private float avg(float[] arr) { |
||||
float amt = 0f; |
||||
for(float f : arr) amt += f; |
||||
return amt / arr.length; |
||||
} |
||||
} |
@ -0,0 +1,59 @@ |
||||
package com.jme3.input.vr.openvr; |
||||
|
||||
import com.jme3.input.vr.VRBounds; |
||||
import com.jme3.math.Vector2f; |
||||
import com.jme3.system.jopenvr.JOpenVRLibrary; |
||||
import com.jme3.system.jopenvr.VR_IVRChaperone_FnTable; |
||||
import com.sun.jna.ptr.FloatByReference; |
||||
|
||||
import java.util.logging.Logger; |
||||
|
||||
/** |
||||
* A class that represents VR world bounds. |
||||
* @author reden - phr00t - https://github.com/phr00t
|
||||
* @author Julien Seinturier - COMEX SA - <a href="http://www.seinturier.fr">http://www.seinturier.fr</a>
|
||||
*/ |
||||
public class OpenVRBounds implements VRBounds { |
||||
|
||||
private static Logger logger = Logger.getLogger(OpenVRBounds.class.getName()); |
||||
|
||||
private VR_IVRChaperone_FnTable vrChaperone; |
||||
private Vector2f playSize; |
||||
|
||||
/** |
||||
* Initialize the VR bounds. |
||||
* @return <code>true</code> if the initialization is a success and <code>false</code> otherwise. |
||||
*/ |
||||
public boolean init(OpenVR api) { |
||||
|
||||
logger.config("Initialize VR bounds..."); |
||||
|
||||
if( vrChaperone == null ) { |
||||
vrChaperone = new VR_IVRChaperone_FnTable(JOpenVRLibrary.VR_GetGenericInterface(JOpenVRLibrary.IVRChaperone_Version, api.hmdErrorStore).getPointer()); |
||||
if( vrChaperone != null ) { |
||||
vrChaperone.setAutoSynch(false); |
||||
vrChaperone.read(); |
||||
FloatByReference fbX = new FloatByReference(); |
||||
FloatByReference fbZ = new FloatByReference(); |
||||
vrChaperone.GetPlayAreaSize.apply(fbX, fbZ); |
||||
playSize = new Vector2f(fbX.getValue(), fbZ.getValue()); |
||||
|
||||
logger.config("Initialize VR bounds [SUCCESS]"); |
||||
return true; // init success
|
||||
} |
||||
|
||||
logger.warning("Initialize VR bounds [FAILED]."); |
||||
return false; // failed to init
|
||||
} |
||||
|
||||
logger.config("Initialize VR bounds already done."); |
||||
return true; // already initialized
|
||||
} |
||||
|
||||
@Override |
||||
public Vector2f getPlaySize() { |
||||
return playSize; |
||||
} |
||||
|
||||
} |
||||
|
@ -0,0 +1,114 @@ |
||||
/* |
||||
* To change this license header, choose License Headers in Project Properties. |
||||
* To change this template file, choose Tools | Templates |
||||
* and open the template in the editor. |
||||
*/ |
||||
package com.jme3.input.vr.openvr; |
||||
|
||||
import com.jme3.app.VREnvironment; |
||||
import com.jme3.input.controls.AnalogListener; |
||||
import com.jme3.input.vr.AbstractVRMouseManager; |
||||
import com.jme3.input.vr.VRInputType; |
||||
import com.jme3.math.Vector2f; |
||||
|
||||
|
||||
/** |
||||
* A class dedicated to the handling of the mouse within VR environment. |
||||
* @author Julien Seinturier - COMEX SA - <a href="http://www.seinturier.fr">http://www.seinturier.fr</a>
|
||||
*/ |
||||
public class OpenVRMouseManager extends AbstractVRMouseManager { |
||||
|
||||
private final int AVERAGE_AMNT = 4; |
||||
|
||||
private int avgCounter; |
||||
|
||||
private final float[] lastXmv = new float[AVERAGE_AMNT]; |
||||
|
||||
private final float[] lastYmv = new float[AVERAGE_AMNT]; |
||||
|
||||
/** |
||||
* Create a new VR mouse manager within the given {@link VREnvironment VR environment}. |
||||
* @param environment the VR environment of the mouse manager. |
||||
*/ |
||||
public OpenVRMouseManager(VREnvironment environment){ |
||||
super(environment); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void updateAnalogAsMouse(int inputIndex, AnalogListener mouseListener, String mouseXName, String mouseYName, float tpf) { |
||||
|
||||
if (getVREnvironment() != null){ |
||||
if (getVREnvironment().getApplication() != null){ |
||||
// got a tracked controller to use as the "mouse"
|
||||
if( getVREnvironment().isInVR() == false || |
||||
getVREnvironment().getVRinput() == null || |
||||
getVREnvironment().getVRinput().isInputDeviceTracking(inputIndex) == false ){ |
||||
return; |
||||
} |
||||
|
||||
Vector2f tpDelta; |
||||
// TODO option to use Touch joysticks
|
||||
if( isThumbstickMode() ) { |
||||
tpDelta = getVREnvironment().getVRinput().getAxis(inputIndex, VRInputType.ViveTrackpadAxis); |
||||
} else { |
||||
tpDelta = getVREnvironment().getVRinput().getAxisDeltaSinceLastCall(inputIndex, VRInputType.ViveTrackpadAxis); |
||||
} |
||||
|
||||
float Xamount = (float)Math.pow(Math.abs(tpDelta.x) * getSpeedSensitivity(), getSpeedAcceleration()); |
||||
float Yamount = (float)Math.pow(Math.abs(tpDelta.y) * getSpeedSensitivity(), getSpeedAcceleration()); |
||||
|
||||
if( tpDelta.x < 0f ){ |
||||
Xamount = -Xamount; |
||||
} |
||||
|
||||
if( tpDelta.y < 0f ){ |
||||
Yamount = -Yamount; |
||||
} |
||||
|
||||
Xamount *= getMouseMoveScale(); |
||||
Yamount *= getMouseMoveScale(); |
||||
|
||||
if( mouseListener != null ) { |
||||
if( tpDelta.x != 0f && mouseXName != null ) mouseListener.onAnalog(mouseXName, Xamount * 0.2f, tpf); |
||||
if( tpDelta.y != 0f && mouseYName != null ) mouseListener.onAnalog(mouseYName, Yamount * 0.2f, tpf); |
||||
} |
||||
|
||||
if( getVREnvironment().getApplication().getInputManager().isCursorVisible() ) { |
||||
int index = (avgCounter+1) % AVERAGE_AMNT; |
||||
lastXmv[index] = Xamount * 133f; |
||||
lastYmv[index] = Yamount * 133f; |
||||
cursorPos.x -= avg(lastXmv); |
||||
cursorPos.y -= avg(lastYmv); |
||||
Vector2f maxsize = getVREnvironment().getVRGUIManager().getCanvasSize(); |
||||
|
||||
if( cursorPos.x > maxsize.x ){ |
||||
cursorPos.x = maxsize.x; |
||||
} |
||||
|
||||
if( cursorPos.x < 0f ){ |
||||
cursorPos.x = 0f; |
||||
} |
||||
|
||||
if( cursorPos.y > maxsize.y ){ |
||||
cursorPos.y = maxsize.y; |
||||
} |
||||
|
||||
if( cursorPos.y < 0f ){ |
||||
cursorPos.y = 0f; |
||||
} |
||||
} |
||||
} else { |
||||
throw new IllegalStateException("This VR environment is not attached to any application."); |
||||
} |
||||
} else { |
||||
throw new IllegalStateException("This VR view manager is not attached to any VR environment."); |
||||
} |
||||
} |
||||
|
||||
private float avg(float[] arr) { |
||||
float amt = 0f; |
||||
for(float f : arr) amt += f; |
||||
return amt / arr.length; |
||||
} |
||||
} |
@ -1,10 +1,16 @@ |
||||
package com.jme3.input.vr; |
||||
package com.jme3.input.vr.openvr; |
||||
|
||||
import com.jme3.app.VREnvironment; |
||||
import com.jme3.input.vr.VRTrackedController; |
||||
import com.jme3.math.Matrix4f; |
||||
import com.jme3.math.Quaternion; |
||||
import com.jme3.math.Vector3f; |
||||
|
||||
/** |
||||
* |
||||
* @author Julien Seinturier - COMEX SA - <a href="http://www.seinturier.fr">http://www.seinturier.fr</a>
|
||||
* |
||||
*/ |
||||
public class OpenVRTrackedController implements VRTrackedController{ |
||||
|
||||
/** |
@ -0,0 +1,108 @@ |
||||
package com.jme3.input.vr.osvr; |
||||
|
||||
import com.jme3.app.VREnvironment; |
||||
import com.jme3.input.controls.AnalogListener; |
||||
import com.jme3.input.vr.AbstractVRMouseManager; |
||||
import com.jme3.input.vr.VRInputType; |
||||
import com.jme3.math.Vector2f; |
||||
|
||||
/** |
||||
* A class dedicated to the mouse handling within OSVR based VR experience. |
||||
* @author Julien Seinturier - COMEX SA - <a href="http://www.seinturier.fr">http://www.seinturier.fr</a>
|
||||
*/ |
||||
public class OSVRMouseManager extends AbstractVRMouseManager { |
||||
|
||||
private final int AVERAGE_AMNT = 4; |
||||
|
||||
private int avgCounter; |
||||
|
||||
private final float[] lastXmv = new float[AVERAGE_AMNT]; |
||||
|
||||
private final float[] lastYmv = new float[AVERAGE_AMNT]; |
||||
|
||||
/** |
||||
* Create a new VR mouse manager within the given {@link VREnvironment VR environment}. |
||||
* @param environment the VR environment of the mouse manager. |
||||
*/ |
||||
public OSVRMouseManager(VREnvironment environment){ |
||||
super(environment); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void updateAnalogAsMouse(int inputIndex, AnalogListener mouseListener, String mouseXName, String mouseYName, float tpf) { |
||||
|
||||
if (getVREnvironment() != null){ |
||||
if (getVREnvironment().getApplication() != null){ |
||||
// got a tracked controller to use as the "mouse"
|
||||
if( getVREnvironment().isInVR() == false || |
||||
getVREnvironment().getVRinput() == null || |
||||
getVREnvironment().getVRinput().isInputDeviceTracking(inputIndex) == false ){ |
||||
return; |
||||
} |
||||
|
||||
Vector2f tpDelta; |
||||
// TODO option to use Touch joysticks
|
||||
if( isThumbstickMode() ) { |
||||
tpDelta = getVREnvironment().getVRinput().getAxis(inputIndex, VRInputType.ViveTrackpadAxis); |
||||
} else { |
||||
tpDelta = getVREnvironment().getVRinput().getAxisDeltaSinceLastCall(inputIndex, VRInputType.ViveTrackpadAxis); |
||||
} |
||||
|
||||
float Xamount = (float)Math.pow(Math.abs(tpDelta.x) * getSpeedSensitivity(), getSpeedAcceleration()); |
||||
float Yamount = (float)Math.pow(Math.abs(tpDelta.y) * getSpeedSensitivity(), getSpeedAcceleration()); |
||||
|
||||
if( tpDelta.x < 0f ){ |
||||
Xamount = -Xamount; |
||||
} |
||||
|
||||
if( tpDelta.y < 0f ){ |
||||
Yamount = -Yamount; |
||||
} |
||||
|
||||
Xamount *= getMouseMoveScale(); |
||||
Yamount *= getMouseMoveScale(); |
||||
|
||||
if( mouseListener != null ) { |
||||
if( tpDelta.x != 0f && mouseXName != null ) mouseListener.onAnalog(mouseXName, Xamount * 0.2f, tpf); |
||||
if( tpDelta.y != 0f && mouseYName != null ) mouseListener.onAnalog(mouseYName, Yamount * 0.2f, tpf); |
||||
} |
||||
|
||||
if( getVREnvironment().getApplication().getInputManager().isCursorVisible() ) { |
||||
int index = (avgCounter+1) % AVERAGE_AMNT; |
||||
lastXmv[index] = Xamount * 133f; |
||||
lastYmv[index] = Yamount * 133f; |
||||
cursorPos.x -= avg(lastXmv); |
||||
cursorPos.y -= avg(lastYmv); |
||||
Vector2f maxsize = getVREnvironment().getVRGUIManager().getCanvasSize(); |
||||
|
||||
if( cursorPos.x > maxsize.x ){ |
||||
cursorPos.x = maxsize.x; |
||||
} |
||||
|
||||
if( cursorPos.x < 0f ){ |
||||
cursorPos.x = 0f; |
||||
} |
||||
|
||||
if( cursorPos.y > maxsize.y ){ |
||||
cursorPos.y = maxsize.y; |
||||
} |
||||
|
||||
if( cursorPos.y < 0f ){ |
||||
cursorPos.y = 0f; |
||||
} |
||||
} |
||||
} else { |
||||
throw new IllegalStateException("This VR environment is not attached to any application."); |
||||
} |
||||
} else { |
||||
throw new IllegalStateException("This VR view manager is not attached to any VR environment."); |
||||
} |
||||
} |
||||
|
||||
private float avg(float[] arr) { |
||||
float amt = 0f; |
||||
for(float f : arr) amt += f; |
||||
return amt / arr.length; |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue