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 @@ |
||||
/* |
||||
* 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.util; |
||||
|
||||
import java.util.logging.Logger; |
||||
|
||||
import org.lwjgl.glfw.GLFW; |
||||
|
||||
import com.jme3.app.VREnvironment; |
||||
import com.jme3.input.MouseInput; |
||||
import com.jme3.input.controls.AnalogListener; |
||||
import com.jme3.input.lwjgl.GlfwMouseInputVR; |
||||
import com.jme3.input.vr.VRInputType; |
||||
import com.jme3.material.RenderState.BlendMode; |
||||
import com.jme3.math.Vector2f; |
||||
import com.jme3.scene.Node; |
||||
import com.jme3.system.AppSettings; |
||||
import com.jme3.system.lwjgl.LwjglWindow; |
||||
import com.jme3.texture.Texture; |
||||
import com.jme3.texture.Texture2D; |
||||
import com.jme3.ui.Picture; |
||||
|
||||
/** |
||||
* 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> |
||||
* |
||||
*/ |
||||
public class VRMouseManager { |
||||
|
||||
private static final Logger logger = Logger.getLogger(VRMouseManager.class.getName()); |
||||
|
||||
|
||||
private VREnvironment environment = null; |
||||
|
||||
private final int AVERAGE_AMNT = 4; |
||||
private int avgCounter; |
||||
|
||||
private Picture mouseImage; |
||||
private int recentCenterCount = 0; |
||||
private final Vector2f cursorPos = new Vector2f(); |
||||
private float ySize, sensitivity = 8f, acceleration = 2f; |
||||
private final float[] lastXmv = new float[AVERAGE_AMNT], lastYmv = new float[AVERAGE_AMNT]; |
||||
private boolean thumbstickMode; |
||||
private float moveScale = 1f; |
||||
|
||||
private float avg(float[] arr) { |
||||
float amt = 0f; |
||||
for(float f : arr) amt += f; |
||||
return amt / arr.length; |
||||
} |
||||
|
||||
/** |
||||
* Create a new VR mouse manager within the given {@link VREnvironment VR environment}. |
||||
* @param environment the VR environment of the mouse manager. |
||||
*/ |
||||
public VRMouseManager(VREnvironment environment){ |
||||
this.environment = environment; |
||||
} |
||||
|
||||
/** |
||||
* Initialize the VR mouse manager. |
||||
*/ |
||||
protected void initialize() { |
||||
|
||||
logger.config("Initializing VR mouse manager."); |
||||
|
||||
// load default mouseimage
|
||||
mouseImage = new Picture("mouse"); |
||||
setImage("Common/Util/mouse.png"); |
||||
// hide default cursor by making it invisible
|
||||
|
||||
MouseInput mi = environment.getApplication().getContext().getMouseInput(); |
||||
if( mi instanceof GlfwMouseInputVR ){ |
||||
((GlfwMouseInputVR)mi).hideActiveCursor(); |
||||
} |
||||
centerMouse(); |
||||
|
||||
logger.config("Initialized VR mouse manager [SUCCESS]"); |
||||
} |
||||
|
||||
public void setThumbstickMode(boolean set) { |
||||
thumbstickMode = set; |
||||
} |
||||
|
||||
public boolean isThumbstickMode() { |
||||
return thumbstickMode; |
||||
} |
||||
|
||||
/** |
||||
* 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) { |
||||
this.sensitivity = sensitivity; |
||||
this.acceleration = acceleration; |
||||
} |
||||
|
||||
/** |
||||
* Get the sensitivity of the mouse. |
||||
* @return the sensitivity of the mouse. |
||||
* @see #setSpeed(float, float) |
||||
*/ |
||||
public float getSpeedSensitivity() { |
||||
return sensitivity; |
||||
} |
||||
|
||||
/** |
||||
* Get the acceleration of the mouse. |
||||
* @return the acceleration of the mouse. |
||||
* @see #setSpeed(float, float) |
||||
*/ |
||||
public float getSpeedAcceleration() { |
||||
return acceleration; |
||||
} |
||||
|
||||
/** |
||||
* Set the mouse move scale. |
||||
* @param set the mouse move scale. |
||||
*/ |
||||
public void setMouseMoveScale(float set) { |
||||
moveScale = 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) { |
||||
|
||||
if (environment != null){ |
||||
|
||||
if (environment.getApplication() != null){ |
||||
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); |
||||
mouseImage.setWidth(tex.getImage().getWidth()); |
||||
mouseImage.getMaterial().getAdditionalRenderState().setBlendMode(BlendMode.Alpha); |
||||
mouseImage.getMaterial().getAdditionalRenderState().setDepthWrite(false); |
||||
} else { |
||||
Texture tex = environment.getApplication().getAssetManager().loadTexture(texture); |
||||
mouseImage.setTexture(environment.getApplication().getAssetManager(), (Texture2D)tex, true); |
||||
ySize = tex.getImage().getHeight(); |
||||
mouseImage.setHeight(ySize); |
||||
mouseImage.setWidth(tex.getImage().getWidth()); |
||||
mouseImage.getMaterial().getAdditionalRenderState().setBlendMode(BlendMode.Alpha); |
||||
mouseImage.getMaterial().getAdditionalRenderState().setDepthWrite(false); |
||||
} |
||||
} 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 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) { |
||||
|
||||
if (environment != null){ |
||||
if (environment.getApplication() != null){ |
||||
// got a tracked controller to use as the "mouse"
|
||||
if( environment.isInVR() == false || |
||||
environment.getVRinput() == null || |
||||
environment.getVRinput().isInputDeviceTracking(inputIndex) == false ){ |
||||
return; |
||||
} |
||||
|
||||
Vector2f tpDelta; |
||||
// TODO option to use Touch joysticks
|
||||
if( thumbstickMode ) { |
||||
tpDelta = environment.getVRinput().getAxis(inputIndex, VRInputType.ViveTrackpadAxis); |
||||
} else { |
||||
tpDelta = environment.getVRinput().getAxisDeltaSinceLastCall(inputIndex, VRInputType.ViveTrackpadAxis); |
||||
} |
||||
|
||||
float Xamount = (float)Math.pow(Math.abs(tpDelta.x) * sensitivity, acceleration); |
||||
float Yamount = (float)Math.pow(Math.abs(tpDelta.y) * sensitivity, acceleration); |
||||
|
||||
if( tpDelta.x < 0f ){ |
||||
Xamount = -Xamount; |
||||
} |
||||
|
||||
if( tpDelta.y < 0f ){ |
||||
Yamount = -Yamount; |
||||
} |
||||
|
||||
Xamount *= moveScale; Yamount *= moveScale; |
||||
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( environment.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 = environment.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."); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 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(); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
package com.jme3.input.vr; |
||||
|
||||
import java.util.logging.Logger; |
||||
|
||||
import org.lwjgl.glfw.GLFW; |
||||
|
||||
import com.jme3.app.VREnvironment; |
||||
import com.jme3.input.MouseInput; |
||||
import com.jme3.input.lwjgl.GlfwMouseInputVR; |
||||
import com.jme3.material.RenderState.BlendMode; |
||||
import com.jme3.math.Vector2f; |
||||
import com.jme3.scene.Node; |
||||
import com.jme3.system.AppSettings; |
||||
import com.jme3.system.lwjgl.LwjglWindow; |
||||
import com.jme3.texture.Texture; |
||||
import com.jme3.texture.Texture2D; |
||||
import com.jme3.ui.Picture; |
||||
|
||||
/** |
||||
* An abstract implementation of a {@link VRMouseManager}. This class should be overrided by specific hardware implementation of VR devices. |
||||
* @author Julien Seinturier - COMEX SA - <a href="http://www.seinturier.fr">http://www.seinturier.fr</a>
|
||||
* |
||||
*/ |
||||
public abstract class AbstractVRMouseManager implements VRMouseManager { |
||||
|
||||
private static final Logger logger = Logger.getLogger(AbstractVRMouseManager.class.getName()); |
||||
|
||||
private VREnvironment environment = null; |
||||
|
||||
|
||||
|
||||
private Picture mouseImage; |
||||
private int recentCenterCount = 0; |
||||
|
||||
protected final Vector2f cursorPos = new Vector2f(); |
||||
|
||||
private float ySize, sensitivity = 8f, acceleration = 2f; |
||||
|
||||
private boolean thumbstickMode; |
||||
private float moveScale = 1f; |
||||
|
||||
/** |
||||
* Create a new AbstractVRMouseManager attached to the given {@link VREnvironment VR environment}. |
||||
* @param environment the {@link VREnvironment VR environment} that this manager is attached to. |
||||
*/ |
||||
public AbstractVRMouseManager(VREnvironment environment) { |
||||
this.environment = environment; |
||||
} |
||||
|
||||
@Override |
||||
public void initialize() { |
||||
|
||||
logger.config("Initializing VR mouse manager."); |
||||
|
||||
// load default mouseimage
|
||||
mouseImage = new Picture("mouse"); |
||||
setImage("Common/Util/mouse.png"); |
||||
// hide default cursor by making it invisible
|
||||
|
||||
MouseInput mi = environment.getApplication().getContext().getMouseInput(); |
||||
if( mi instanceof GlfwMouseInputVR ){ |
||||
((GlfwMouseInputVR)mi).hideActiveCursor(); |
||||
} |
||||
centerMouse(); |
||||
|
||||
logger.config("Initialized VR mouse manager [SUCCESS]"); |
||||
} |
||||
|
||||
@Override |
||||
public VREnvironment getVREnvironment() { |
||||
return environment; |
||||
} |
||||
|
||||
@Override |
||||
public void setThumbstickMode(boolean set) { |
||||
thumbstickMode = set; |
||||
} |
||||
|
||||
@Override |
||||
public boolean isThumbstickMode() { |
||||
return thumbstickMode; |
||||
} |
||||
|
||||
@Override |
||||
public void setSpeed(float sensitivity, float acceleration) { |
||||
this.sensitivity = sensitivity; |
||||
this.acceleration = acceleration; |
||||
} |
||||
|
||||
@Override |
||||
public float getSpeedSensitivity() { |
||||
return sensitivity; |
||||
} |
||||
|
||||
@Override |
||||
public float getSpeedAcceleration() { |
||||
return acceleration; |
||||
} |
||||
|
||||
@Override |
||||
public float getMouseMoveScale() { |
||||
return moveScale; |
||||
} |
||||
|
||||
@Override |
||||
public void setMouseMoveScale(float set) { |
||||
moveScale = set; |
||||
} |
||||
|
||||
@Override |
||||
public void setImage(String texture) { |
||||
|
||||
if (environment != null){ |
||||
|
||||
if (environment.getApplication() != null){ |
||||
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); |
||||
mouseImage.setWidth(tex.getImage().getWidth()); |
||||
mouseImage.getMaterial().getAdditionalRenderState().setBlendMode(BlendMode.Alpha); |
||||
mouseImage.getMaterial().getAdditionalRenderState().setDepthWrite(false); |
||||
} else { |
||||
Texture tex = environment.getApplication().getAssetManager().loadTexture(texture); |
||||
mouseImage.setTexture(environment.getApplication().getAssetManager(), (Texture2D)tex, true); |
||||
ySize = tex.getImage().getHeight(); |
||||
mouseImage.setHeight(ySize); |
||||
mouseImage.setWidth(tex.getImage().getWidth()); |
||||
mouseImage.getMaterial().getAdditionalRenderState().setBlendMode(BlendMode.Alpha); |
||||
mouseImage.getMaterial().getAdditionalRenderState().setDepthWrite(false); |
||||
} |
||||
} 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."); |
||||
} |
||||
} |
||||
|
||||
|
||||
@Override |
||||
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."); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
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."); |
||||
} |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public 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; |
||||
|
||||
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 - (c) 2016 - JOrigin project - <a href="http://www.jorigin.org">http:/www.jorigin.org</a> |
||||
*/ |
||||
public class VRBounds { |
||||
|
||||
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; |
||||
} |
||||
|
||||
} |
||||
|
||||
package com.jme3.input.vr; |
||||
|
||||
import com.jme3.math.Vector2f; |
||||
|
||||
/** |
||||
* This interface describe the VR playground bounds. |
||||
* @author Julien Seinturier - COMEX SA - <a href="http://www.seinturier.fr">http://www.seinturier.fr</a>
|
||||
* |
||||
*/ |
||||
public interface VRBounds { |
||||
|
||||
/** |
||||
* Get the size of the VR playground. |
||||
* @return the size of the VR playground. |
||||
*/ |
||||
public Vector2f getPlaySize(); |
||||
} |
||||
|
@ -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