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
@ -1,335 +1,228 @@ |
|||||||
/* |
package com.jme3.input.vr; |
||||||
* To change this license header, choose License Headers in Project Properties. |
|
||||||
* To change this template file, choose Tools | Templates |
import java.util.logging.Logger; |
||||||
* and open the template in the editor. |
|
||||||
*/ |
import org.lwjgl.glfw.GLFW; |
||||||
package com.jme3.util; |
|
||||||
|
import com.jme3.app.VREnvironment; |
||||||
import java.util.logging.Logger; |
import com.jme3.input.MouseInput; |
||||||
|
import com.jme3.input.lwjgl.GlfwMouseInputVR; |
||||||
import org.lwjgl.glfw.GLFW; |
import com.jme3.material.RenderState.BlendMode; |
||||||
|
import com.jme3.math.Vector2f; |
||||||
import com.jme3.app.VREnvironment; |
import com.jme3.scene.Node; |
||||||
import com.jme3.input.MouseInput; |
import com.jme3.system.AppSettings; |
||||||
import com.jme3.input.controls.AnalogListener; |
import com.jme3.system.lwjgl.LwjglWindow; |
||||||
import com.jme3.input.lwjgl.GlfwMouseInputVR; |
import com.jme3.texture.Texture; |
||||||
import com.jme3.input.vr.VRInputType; |
import com.jme3.texture.Texture2D; |
||||||
import com.jme3.material.RenderState.BlendMode; |
import com.jme3.ui.Picture; |
||||||
import com.jme3.math.Vector2f; |
|
||||||
import com.jme3.scene.Node; |
/** |
||||||
import com.jme3.system.AppSettings; |
* An abstract implementation of a {@link VRMouseManager}. This class should be overrided by specific hardware implementation of VR devices. |
||||||
import com.jme3.system.lwjgl.LwjglWindow; |
* @author Julien Seinturier - COMEX SA - <a href="http://www.seinturier.fr">http://www.seinturier.fr</a>
|
||||||
import com.jme3.texture.Texture; |
* |
||||||
import com.jme3.texture.Texture2D; |
*/ |
||||||
import com.jme3.ui.Picture; |
public abstract class AbstractVRMouseManager implements VRMouseManager { |
||||||
|
|
||||||
/** |
private static final Logger logger = Logger.getLogger(AbstractVRMouseManager.class.getName()); |
||||||
* A class dedicated to the handling of the mouse within VR environment. |
|
||||||
* @author Julien Seinturier - (c) 2016 - JOrigin project - <a href="http://www.jorigin.org">http:/www.jorigin.org</a> |
private VREnvironment environment = null; |
||||||
* |
|
||||||
*/ |
|
||||||
public class VRMouseManager { |
|
||||||
|
private Picture mouseImage; |
||||||
private static final Logger logger = Logger.getLogger(VRMouseManager.class.getName()); |
private int recentCenterCount = 0; |
||||||
|
|
||||||
|
protected final Vector2f cursorPos = new Vector2f(); |
||||||
private VREnvironment environment = null; |
|
||||||
|
private float ySize, sensitivity = 8f, acceleration = 2f; |
||||||
private final int AVERAGE_AMNT = 4; |
|
||||||
private int avgCounter; |
private boolean thumbstickMode; |
||||||
|
private float moveScale = 1f; |
||||||
private Picture mouseImage; |
|
||||||
private int recentCenterCount = 0; |
/** |
||||||
private final Vector2f cursorPos = new Vector2f(); |
* Create a new AbstractVRMouseManager attached to the given {@link VREnvironment VR environment}. |
||||||
private float ySize, sensitivity = 8f, acceleration = 2f; |
* @param environment the {@link VREnvironment VR environment} that this manager is attached to. |
||||||
private final float[] lastXmv = new float[AVERAGE_AMNT], lastYmv = new float[AVERAGE_AMNT]; |
*/ |
||||||
private boolean thumbstickMode; |
public AbstractVRMouseManager(VREnvironment environment) { |
||||||
private float moveScale = 1f; |
this.environment = environment; |
||||||
|
} |
||||||
private float avg(float[] arr) { |
|
||||||
float amt = 0f; |
@Override |
||||||
for(float f : arr) amt += f; |
public void initialize() { |
||||||
return amt / arr.length; |
|
||||||
} |
logger.config("Initializing VR mouse manager."); |
||||||
|
|
||||||
/** |
// load default mouseimage
|
||||||
* Create a new VR mouse manager within the given {@link VREnvironment VR environment}. |
mouseImage = new Picture("mouse"); |
||||||
* @param environment the VR environment of the mouse manager. |
setImage("Common/Util/mouse.png"); |
||||||
*/ |
// hide default cursor by making it invisible
|
||||||
public VRMouseManager(VREnvironment environment){ |
|
||||||
this.environment = environment; |
MouseInput mi = environment.getApplication().getContext().getMouseInput(); |
||||||
} |
if( mi instanceof GlfwMouseInputVR ){ |
||||||
|
((GlfwMouseInputVR)mi).hideActiveCursor(); |
||||||
/** |
} |
||||||
* Initialize the VR mouse manager. |
centerMouse(); |
||||||
*/ |
|
||||||
protected void initialize() { |
logger.config("Initialized VR mouse manager [SUCCESS]"); |
||||||
|
} |
||||||
logger.config("Initializing VR mouse manager."); |
|
||||||
|
@Override |
||||||
// load default mouseimage
|
public VREnvironment getVREnvironment() { |
||||||
mouseImage = new Picture("mouse"); |
return environment; |
||||||
setImage("Common/Util/mouse.png"); |
} |
||||||
// hide default cursor by making it invisible
|
|
||||||
|
@Override |
||||||
MouseInput mi = environment.getApplication().getContext().getMouseInput(); |
public void setThumbstickMode(boolean set) { |
||||||
if( mi instanceof GlfwMouseInputVR ){ |
thumbstickMode = set; |
||||||
((GlfwMouseInputVR)mi).hideActiveCursor(); |
} |
||||||
} |
|
||||||
centerMouse(); |
@Override |
||||||
|
public boolean isThumbstickMode() { |
||||||
logger.config("Initialized VR mouse manager [SUCCESS]"); |
return thumbstickMode; |
||||||
} |
} |
||||||
|
|
||||||
public void setThumbstickMode(boolean set) { |
@Override |
||||||
thumbstickMode = set; |
public void setSpeed(float sensitivity, float acceleration) { |
||||||
} |
this.sensitivity = sensitivity; |
||||||
|
this.acceleration = acceleration; |
||||||
public boolean isThumbstickMode() { |
} |
||||||
return thumbstickMode; |
|
||||||
} |
@Override |
||||||
|
public float getSpeedSensitivity() { |
||||||
/** |
return sensitivity; |
||||||
* Set the speed of the mouse. |
} |
||||||
* @param sensitivity the sensitivity of the mouse. |
|
||||||
* @param acceleration the acceleration of the mouse. |
@Override |
||||||
* @see #getSpeedAcceleration() |
public float getSpeedAcceleration() { |
||||||
* @see #getSpeedSensitivity() |
return acceleration; |
||||||
*/ |
} |
||||||
public void setSpeed(float sensitivity, float acceleration) { |
|
||||||
this.sensitivity = sensitivity; |
@Override |
||||||
this.acceleration = acceleration; |
public float getMouseMoveScale() { |
||||||
} |
return moveScale; |
||||||
|
} |
||||||
/** |
|
||||||
* Get the sensitivity of the mouse. |
@Override |
||||||
* @return the sensitivity of the mouse. |
public void setMouseMoveScale(float set) { |
||||||
* @see #setSpeed(float, float) |
moveScale = set; |
||||||
*/ |
} |
||||||
public float getSpeedSensitivity() { |
|
||||||
return sensitivity; |
@Override |
||||||
} |
public void setImage(String texture) { |
||||||
|
|
||||||
/** |
if (environment != null){ |
||||||
* Get the acceleration of the mouse. |
|
||||||
* @return the acceleration of the mouse. |
if (environment.getApplication() != null){ |
||||||
* @see #setSpeed(float, float) |
if( environment.isInVR() == false ){ |
||||||
*/ |
Texture tex = environment.getApplication().getAssetManager().loadTexture(texture); |
||||||
public float getSpeedAcceleration() { |
mouseImage.setTexture(environment.getApplication().getAssetManager(), (Texture2D)tex, true); |
||||||
return acceleration; |
ySize = tex.getImage().getHeight(); |
||||||
} |
mouseImage.setHeight(ySize); |
||||||
|
mouseImage.setWidth(tex.getImage().getWidth()); |
||||||
/** |
mouseImage.getMaterial().getAdditionalRenderState().setBlendMode(BlendMode.Alpha); |
||||||
* Set the mouse move scale. |
mouseImage.getMaterial().getAdditionalRenderState().setDepthWrite(false); |
||||||
* @param set the mouse move scale. |
} else { |
||||||
*/ |
Texture tex = environment.getApplication().getAssetManager().loadTexture(texture); |
||||||
public void setMouseMoveScale(float set) { |
mouseImage.setTexture(environment.getApplication().getAssetManager(), (Texture2D)tex, true); |
||||||
moveScale = set; |
ySize = tex.getImage().getHeight(); |
||||||
} |
mouseImage.setHeight(ySize); |
||||||
|
mouseImage.setWidth(tex.getImage().getWidth()); |
||||||
/** |
mouseImage.getMaterial().getAdditionalRenderState().setBlendMode(BlendMode.Alpha); |
||||||
* Set the image to use as mouse cursor. The given string describe an asset that the underlying application asset manager has to load. |
mouseImage.getMaterial().getAdditionalRenderState().setDepthWrite(false); |
||||||
* @param texture the image to use as mouse cursor. |
} |
||||||
*/ |
} else { |
||||||
public void setImage(String texture) { |
throw new IllegalStateException("This VR environment is not attached to any application."); |
||||||
|
} |
||||||
if (environment != null){ |
|
||||||
|
} else { |
||||||
if (environment.getApplication() != null){ |
throw new IllegalStateException("This VR view manager is not attached to any VR environment."); |
||||||
if( environment.isInVR() == false ){ |
} |
||||||
Texture tex = environment.getApplication().getAssetManager().loadTexture(texture); |
} |
||||||
mouseImage.setTexture(environment.getApplication().getAssetManager(), (Texture2D)tex, true); |
|
||||||
ySize = tex.getImage().getHeight(); |
|
||||||
mouseImage.setHeight(ySize); |
@Override |
||||||
mouseImage.setWidth(tex.getImage().getWidth()); |
public Vector2f getCursorPosition() { |
||||||
mouseImage.getMaterial().getAdditionalRenderState().setBlendMode(BlendMode.Alpha); |
|
||||||
mouseImage.getMaterial().getAdditionalRenderState().setDepthWrite(false); |
if (environment != null){ |
||||||
} else { |
if (environment.getApplication() != null){ |
||||||
Texture tex = environment.getApplication().getAssetManager().loadTexture(texture); |
if( environment.isInVR() ) { |
||||||
mouseImage.setTexture(environment.getApplication().getAssetManager(), (Texture2D)tex, true); |
return cursorPos; |
||||||
ySize = tex.getImage().getHeight(); |
} |
||||||
mouseImage.setHeight(ySize); |
|
||||||
mouseImage.setWidth(tex.getImage().getWidth()); |
return environment.getApplication().getInputManager().getCursorPosition(); |
||||||
mouseImage.getMaterial().getAdditionalRenderState().setBlendMode(BlendMode.Alpha); |
} else { |
||||||
mouseImage.getMaterial().getAdditionalRenderState().setDepthWrite(false); |
throw new IllegalStateException("This VR environment is not attached to any application."); |
||||||
} |
} |
||||||
} else { |
} else { |
||||||
throw new IllegalStateException("This VR environment is not attached to any application."); |
throw new IllegalStateException("This VR view manager is not attached to any VR environment."); |
||||||
} |
} |
||||||
|
} |
||||||
} else { |
|
||||||
throw new IllegalStateException("This VR view manager is not attached to any VR environment."); |
@Override |
||||||
} |
public void centerMouse() { |
||||||
} |
|
||||||
|
if (environment != null){ |
||||||
/** |
if (environment.getApplication() != null){ |
||||||
* Update analog controller as it was a mouse controller. |
// set mouse in center of the screen if newly added
|
||||||
* @param inputIndex the index of the controller attached to the VR system. |
Vector2f size = environment.getVRGUIManager().getCanvasSize(); |
||||||
* @param mouseListener the JMonkey mouse listener to trigger. |
MouseInput mi = environment.getApplication().getContext().getMouseInput(); |
||||||
* @param mouseXName the mouseX identifier. |
AppSettings as = environment.getApplication().getContext().getSettings(); |
||||||
* @param mouseYName the mouseY identifier |
if( mi instanceof GlfwMouseInputVR ) ((GlfwMouseInputVR)mi).setCursorPosition((int)(as.getWidth() / 2f), (int)(as.getHeight() / 2f)); |
||||||
* @param tpf the time per frame. |
if( environment.isInVR() ) { |
||||||
*/ |
cursorPos.x = size.x / 2f; |
||||||
public void updateAnalogAsMouse(int inputIndex, AnalogListener mouseListener, String mouseXName, String mouseYName, float tpf) { |
cursorPos.y = size.y / 2f; |
||||||
|
recentCenterCount = 2; |
||||||
if (environment != null){ |
} |
||||||
if (environment.getApplication() != null){ |
} else { |
||||||
// got a tracked controller to use as the "mouse"
|
throw new IllegalStateException("This VR environment is not attached to any application."); |
||||||
if( environment.isInVR() == false || |
} |
||||||
environment.getVRinput() == null || |
} else { |
||||||
environment.getVRinput().isInputDeviceTracking(inputIndex) == false ){ |
throw new IllegalStateException("This VR view manager is not attached to any VR environment."); |
||||||
return; |
} |
||||||
} |
|
||||||
|
} |
||||||
Vector2f tpDelta; |
|
||||||
// TODO option to use Touch joysticks
|
@Override |
||||||
if( thumbstickMode ) { |
public void update(float tpf) { |
||||||
tpDelta = environment.getVRinput().getAxis(inputIndex, VRInputType.ViveTrackpadAxis); |
// if we are showing the cursor, add our picture as it
|
||||||
} else { |
|
||||||
tpDelta = environment.getVRinput().getAxisDeltaSinceLastCall(inputIndex, VRInputType.ViveTrackpadAxis); |
if( environment.getApplication().getInputManager().isCursorVisible() ) { |
||||||
} |
if( mouseImage.getParent() == null ) { |
||||||
|
|
||||||
float Xamount = (float)Math.pow(Math.abs(tpDelta.x) * sensitivity, acceleration); |
environment.getApplication().getGuiViewPort().attachScene(mouseImage); |
||||||
float Yamount = (float)Math.pow(Math.abs(tpDelta.y) * sensitivity, acceleration); |
centerMouse(); |
||||||
|
// the "real" mouse pointer should stay hidden
|
||||||
if( tpDelta.x < 0f ){ |
if (environment.getApplication().getContext() instanceof LwjglWindow){ |
||||||
Xamount = -Xamount; |
GLFW.glfwSetInputMode(((LwjglWindow)environment.getApplication().getContext()).getWindowHandle(), GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_DISABLED); |
||||||
} |
} |
||||||
|
} |
||||||
if( tpDelta.y < 0f ){ |
// handle mouse movements, which may be in addition to (or exclusive from) tracked movement
|
||||||
Yamount = -Yamount; |
MouseInput mi = environment.getApplication().getContext().getMouseInput(); |
||||||
} |
if( mi instanceof GlfwMouseInputVR ) { |
||||||
|
if( recentCenterCount <= 0 ) { |
||||||
Xamount *= moveScale; Yamount *= moveScale; |
//Vector2f winratio = VRGuiManager.getCanvasToWindowRatio();
|
||||||
if( mouseListener != null ) { |
cursorPos.x += ((GlfwMouseInputVR)mi).getLastDeltaX();// * winratio.x;
|
||||||
if( tpDelta.x != 0f && mouseXName != null ) mouseListener.onAnalog(mouseXName, Xamount * 0.2f, tpf); |
cursorPos.y += ((GlfwMouseInputVR)mi).getLastDeltaY();// * winratio.y;
|
||||||
if( tpDelta.y != 0f && mouseYName != null ) mouseListener.onAnalog(mouseYName, Yamount * 0.2f, tpf); |
if( cursorPos.x < 0f ) cursorPos.x = 0f; |
||||||
} |
if( cursorPos.y < 0f ) cursorPos.y = 0f; |
||||||
|
if( cursorPos.x > environment.getVRGUIManager().getCanvasSize().x ) cursorPos.x = environment.getVRGUIManager().getCanvasSize().x; |
||||||
if( environment.getApplication().getInputManager().isCursorVisible() ) { |
if( cursorPos.y > environment.getVRGUIManager().getCanvasSize().y ) cursorPos.y = environment.getVRGUIManager().getCanvasSize().y; |
||||||
int index = (avgCounter+1) % AVERAGE_AMNT; |
} else recentCenterCount--; |
||||||
lastXmv[index] = Xamount * 133f; |
((GlfwMouseInputVR)mi).clearDeltas(); |
||||||
lastYmv[index] = Yamount * 133f; |
} |
||||||
cursorPos.x -= avg(lastXmv); |
// ok, update the cursor graphic position
|
||||||
cursorPos.y -= avg(lastYmv); |
Vector2f currentPos = getCursorPosition(); |
||||||
Vector2f maxsize = environment.getVRGUIManager().getCanvasSize(); |
mouseImage.setLocalTranslation(currentPos.x, currentPos.y - ySize, environment.getVRGUIManager().getGuiDistance() + 1f); |
||||||
|
|
||||||
if( cursorPos.x > maxsize.x ){ |
mouseImage.updateGeometricState(); |
||||||
cursorPos.x = maxsize.x; |
|
||||||
} |
} else if( mouseImage.getParent() != null ) { |
||||||
|
Node n = mouseImage.getParent(); |
||||||
if( cursorPos.x < 0f ){ |
mouseImage.removeFromParent(); |
||||||
cursorPos.x = 0f; |
|
||||||
} |
if (n != null){ |
||||||
|
n.updateGeometricState(); |
||||||
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."); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Get the actual cursor position. |
|
||||||
* @return the actual cursor position. |
|
||||||
*/ |
|
||||||
public Vector2f getCursorPosition() { |
|
||||||
|
|
||||||
if (environment != null){ |
|
||||||
if (environment.getApplication() != null){ |
|
||||||
if( environment.isInVR() ) { |
|
||||||
return cursorPos; |
|
||||||
} |
|
||||||
|
|
||||||
return environment.getApplication().getInputManager().getCursorPosition(); |
|
||||||
} 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."); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Center the mouse on the display. |
|
||||||
*/ |
|
||||||
public void centerMouse() { |
|
||||||
|
|
||||||
if (environment != null){ |
|
||||||
if (environment.getApplication() != null){ |
|
||||||
// set mouse in center of the screen if newly added
|
|
||||||
Vector2f size = environment.getVRGUIManager().getCanvasSize(); |
|
||||||
MouseInput mi = environment.getApplication().getContext().getMouseInput(); |
|
||||||
AppSettings as = environment.getApplication().getContext().getSettings(); |
|
||||||
if( mi instanceof GlfwMouseInputVR ) ((GlfwMouseInputVR)mi).setCursorPosition((int)(as.getWidth() / 2f), (int)(as.getHeight() / 2f)); |
|
||||||
if( environment.isInVR() ) { |
|
||||||
cursorPos.x = size.x / 2f; |
|
||||||
cursorPos.y = size.y / 2f; |
|
||||||
recentCenterCount = 2; |
|
||||||
} |
|
||||||
} 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."); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 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. |
|
||||||
*/ |
|
||||||
protected void update(float tpf) { |
|
||||||
// if we are showing the cursor, add our picture as it
|
|
||||||
|
|
||||||
if( environment.getApplication().getInputManager().isCursorVisible() ) { |
|
||||||
if( mouseImage.getParent() == null ) { |
|
||||||
|
|
||||||
environment.getApplication().getGuiViewPort().attachScene(mouseImage); |
|
||||||
centerMouse(); |
|
||||||
// the "real" mouse pointer should stay hidden
|
|
||||||
if (environment.getApplication().getContext() instanceof LwjglWindow){ |
|
||||||
GLFW.glfwSetInputMode(((LwjglWindow)environment.getApplication().getContext()).getWindowHandle(), GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_DISABLED); |
|
||||||
} |
|
||||||
} |
|
||||||
// handle mouse movements, which may be in addition to (or exclusive from) tracked movement
|
|
||||||
MouseInput mi = environment.getApplication().getContext().getMouseInput(); |
|
||||||
if( mi instanceof GlfwMouseInputVR ) { |
|
||||||
if( recentCenterCount <= 0 ) { |
|
||||||
//Vector2f winratio = VRGuiManager.getCanvasToWindowRatio();
|
|
||||||
cursorPos.x += ((GlfwMouseInputVR)mi).getLastDeltaX();// * winratio.x;
|
|
||||||
cursorPos.y += ((GlfwMouseInputVR)mi).getLastDeltaY();// * winratio.y;
|
|
||||||
if( cursorPos.x < 0f ) cursorPos.x = 0f; |
|
||||||
if( cursorPos.y < 0f ) cursorPos.y = 0f; |
|
||||||
if( cursorPos.x > environment.getVRGUIManager().getCanvasSize().x ) cursorPos.x = environment.getVRGUIManager().getCanvasSize().x; |
|
||||||
if( cursorPos.y > environment.getVRGUIManager().getCanvasSize().y ) cursorPos.y = environment.getVRGUIManager().getCanvasSize().y; |
|
||||||
} else recentCenterCount--; |
|
||||||
((GlfwMouseInputVR)mi).clearDeltas(); |
|
||||||
} |
|
||||||
// ok, update the cursor graphic position
|
|
||||||
Vector2f currentPos = getCursorPosition(); |
|
||||||
mouseImage.setLocalTranslation(currentPos.x, currentPos.y - ySize, environment.getVRGUIManager().getGuiDistance() + 1f); |
|
||||||
|
|
||||||
mouseImage.updateGeometricState(); |
|
||||||
|
|
||||||
} else if( mouseImage.getParent() != null ) { |
|
||||||
Node n = mouseImage.getParent(); |
|
||||||
mouseImage.removeFromParent(); |
|
||||||
|
|
||||||
if (n != null){ |
|
||||||
n.updateGeometricState(); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,61 +1,17 @@ |
|||||||
package com.jme3.input.vr; |
package com.jme3.input.vr; |
||||||
|
|
||||||
import com.jme3.math.Vector2f; |
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; |
* This interface describe the VR playground bounds. |
||||||
|
* @author Julien Seinturier - COMEX SA - <a href="http://www.seinturier.fr">http://www.seinturier.fr</a>
|
||||||
import java.util.logging.Logger; |
* |
||||||
|
*/ |
||||||
/** |
public interface VRBounds { |
||||||
* A class that represents VR world bounds. |
|
||||||
* @author reden - phr00t - https://github.com/phr00t
|
/** |
||||||
* @author Julien Seinturier - (c) 2016 - JOrigin project - <a href="http://www.jorigin.org">http:/www.jorigin.org</a> |
* Get the size of the VR playground. |
||||||
*/ |
* @return the size of the VR playground. |
||||||
public class VRBounds { |
*/ |
||||||
|
public Vector2f getPlaySize(); |
||||||
private static Logger logger = Logger.getLogger(VRBounds.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
|
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Get the size of the VR world. |
|
||||||
* @return the size of the VR world. |
|
||||||
*/ |
|
||||||
public Vector2f getPlaySize() { |
|
||||||
return playSize; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
|
@ -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.app.VREnvironment; |
||||||
|
import com.jme3.input.vr.VRTrackedController; |
||||||
import com.jme3.math.Matrix4f; |
import com.jme3.math.Matrix4f; |
||||||
import com.jme3.math.Quaternion; |
import com.jme3.math.Quaternion; |
||||||
import com.jme3.math.Vector3f; |
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{ |
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