com.jme3.input.vr.openvr.OpenVRInput Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jme3-vr Show documentation
Show all versions of jme3-vr Show documentation
jMonkeyEngine is a 3-D game engine for adventurous Java developers
package com.jme3.input.vr.openvr;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jme3.app.VREnvironment;
import com.jme3.input.vr.VRInputAPI;
import com.jme3.input.vr.VRInputType;
import com.jme3.input.vr.VRTrackedController;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
import com.jme3.scene.Spatial;
import com.jme3.system.jopenvr.JOpenVRLibrary;
import com.jme3.system.jopenvr.OpenVRUtil;
import com.jme3.system.jopenvr.VRControllerState_t;
import com.jme3.system.jopenvr.VR_IVRSystem_FnTable;
import com.jme3.util.VRUtil;
/*
make helper functions to pull the following easily from raw data (DONE)
trigger:
Controller#1, Axis#0 X: 0.0, Y: 0.0
Controller#1, Axis#1 X: 1.0, Y: 0.0
Controller#1, Axis#2 X: 0.0, Y: 0.0
Controller#1, Axis#3 X: 0.0, Y: 0.0
Controller#1, Axis#4 X: 0.0, Y: 0.0
Button press: 8589934592 (when full), touch: 8589934592
touchpad (upper left):
Controller#1, Axis#0 X: -0.6059755, Y: 0.2301706
Controller#1, Axis#1 X: 0.0, Y: 0.0
Controller#1, Axis#2 X: 0.0, Y: 0.0
Controller#1, Axis#3 X: 0.0, Y: 0.0
Controller#1, Axis#4 X: 0.0, Y: 0.0
Button press: 4294967296 (when pressed in), touch: 4294967296
grip:
Controller#1, Axis#0 X: 0.0, Y: 0.0
Controller#1, Axis#1 X: 0.0, Y: 0.0
Controller#1, Axis#2 X: 0.0, Y: 0.0
Controller#1, Axis#3 X: 0.0, Y: 0.0
Controller#1, Axis#4 X: 0.0, Y: 0.0
Button press: 4, touch: 4
thumb:
Controller#1, Axis#0 X: 0.0, Y: 0.0
Controller#1, Axis#1 X: 0.0, Y: 0.0
Controller#1, Axis#2 X: 0.0, Y: 0.0
Controller#1, Axis#3 X: 0.0, Y: 0.0
Controller#1, Axis#4 X: 0.0, Y: 0.0
Button press: 2, touch: 2
*/
/**
* A class that wraps an OpenVR input.
* null
values will be returned if no valid pose exists, or that input device isn't available
* user code should check for null
values.
* @author reden - phr00t - https://github.com/phr00t
* @author Julien Seinturier - COMEX SA - http://www.seinturier.fr
*/
public class OpenVRInput implements VRInputAPI {
private static final Logger logger = Logger.getLogger(OpenVRInput.class.getName());
private final VRControllerState_t[] cStates = new VRControllerState_t[JOpenVRLibrary.k_unMaxTrackedDeviceCount];
private final Quaternion[] rotStore = new Quaternion[JOpenVRLibrary.k_unMaxTrackedDeviceCount];
private final Vector3f[] posStore = new Vector3f[JOpenVRLibrary.k_unMaxTrackedDeviceCount];
private static final int[] controllerIndex = new int[JOpenVRLibrary.k_unMaxTrackedDeviceCount];
private int controllerCount = 0;
private final Vector2f tempAxis = new Vector2f(), temp2Axis = new Vector2f();
private final Vector2f lastCallAxis[] = new Vector2f[JOpenVRLibrary.k_unMaxTrackedDeviceCount];
private final boolean needsNewVelocity[] = new boolean[JOpenVRLibrary.k_unMaxTrackedDeviceCount];
private final boolean needsNewAngVelocity[] = new boolean[JOpenVRLibrary.k_unMaxTrackedDeviceCount];
private final boolean buttonDown[][] = new boolean[JOpenVRLibrary.k_unMaxTrackedDeviceCount][16];
private float axisMultiplier = 1f;
private final Vector3f tempVel = new Vector3f();
private final Quaternion tempQuaternion = new Quaternion();
private VREnvironment environment;
private List trackedControllers = null;
/**
* Create a new OpenVR input attached to the given VR environment.
* @param environment the VR environment to which the input is attached.
*/
public OpenVRInput(VREnvironment environment){
this.environment = environment;
}
@Override
public float getAxisMultiplier() {
return axisMultiplier;
}
@Override
public void setAxisMultiplier(float set) {
axisMultiplier = set;
}
@Override
public void swapHands() {
if( controllerCount != 2 ) return;
int temp = controllerIndex[0];
controllerIndex[0] = controllerIndex[1];
controllerIndex[1] = temp;
}
@Override
public boolean isButtonDown(int controllerIndex, VRInputType checkButton) {
VRControllerState_t cs = cStates[OpenVRInput.controllerIndex[controllerIndex]];
switch( checkButton ) {
default:
return false;
case ViveGripButton:
return (cs.ulButtonPressed & 4) != 0;
case ViveMenuButton:
return (cs.ulButtonPressed & 2) != 0;
case ViveTrackpadAxis:
return (cs.ulButtonPressed & 4294967296l) != 0;
case ViveTriggerAxis:
return (cs.ulButtonPressed & 8589934592l) != 0;
}
}
@Override
public boolean wasButtonPressedSinceLastCall(int controllerIndex, VRInputType checkButton) {
boolean buttonDownNow = isButtonDown(controllerIndex, checkButton);
int checkButtonValue = checkButton.getValue();
int cIndex = OpenVRInput.controllerIndex[controllerIndex];
boolean retval = buttonDownNow == true && buttonDown[cIndex][checkButtonValue] == false;
buttonDown[cIndex][checkButtonValue] = buttonDownNow;
return retval;
}
@Override
public void resetInputSinceLastCall() {
for(int i=0;i 0) && (index < trackedControllers.size())){
return trackedControllers.get(index);
}
}
return null;
}
@Override
public int getTrackedControllerCount() {
return controllerCount;
}
@Override
public VRControllerState_t getRawControllerState(int index) {
if( isInputDeviceTracking(index) == false ) return null;
return cStates[controllerIndex[index]];
}
//public Matrix4f getPoseForInputDevice(int index) {
// if( isInputDeviceTracking(index) == false ) return null;
// return OpenVR.poseMatrices[controllerIndex[index]];
//}
@Override
public boolean isInputFocused() {
if (environment != null){
return ((VR_IVRSystem_FnTable)environment.getVRHardware().getVRSystem()).IsInputAvailable.apply() == 0;
} else {
throw new IllegalStateException("VR input is not attached to a VR environment.");
}
}
@Override
public boolean isInputDeviceTracking(int index) {
if( index < 0 || index >= controllerCount ){
return false;
}
if (environment != null){
if (environment.getVRHardware() instanceof OpenVR){
return ((OpenVR)environment.getVRHardware()).hmdTrackedDevicePoses[controllerIndex[index]].bPoseIsValid != 0;
} else {
throw new IllegalStateException("VR hardware "+environment.getVRHardware().getClass().getSimpleName()+" is not a subclass of "+OpenVR.class.getSimpleName());
}
} else {
throw new IllegalStateException("VR input is not attached to a VR environment.");
}
}
@Override
public Quaternion getOrientation(int index) {
if( isInputDeviceTracking(index) == false ){
return null;
}
if (environment != null){
if (environment.getVRHardware() instanceof OpenVR){
index = controllerIndex[index];
VRUtil.convertMatrix4toQuat(((OpenVR)environment.getVRHardware()).poseMatrices[index], rotStore[index]);
return rotStore[index];
} else {
throw new IllegalStateException("VR hardware "+environment.getVRHardware().getClass().getSimpleName()+" is not a subclass of "+OpenVR.class.getSimpleName());
}
} else {
throw new IllegalStateException("VR input is not attached to a VR environment.");
}
}
@Override
public Vector3f getPosition(int index) {
if( isInputDeviceTracking(index) == false ){
return null;
}
if (environment != null){
if (environment.getVRHardware() instanceof OpenVR){
// the hmdPose comes in rotated funny, fix that here
index = controllerIndex[index];
((OpenVR)environment.getVRHardware()).poseMatrices[index].toTranslationVector(posStore[index]);
posStore[index].x = -posStore[index].x;
posStore[index].z = -posStore[index].z;
return posStore[index];
} else {
throw new IllegalStateException("VR hardware "+environment.getVRHardware().getClass().getSimpleName()+" is not a subclass of "+OpenVR.class.getSimpleName());
}
} else {
throw new IllegalStateException("VR input is not attached to a VR environment.");
}
}
@Override
public Quaternion getFinalObserverRotation(int index) {
if (environment != null){
OpenVRViewManager vrvm = (OpenVRViewManager)environment.getVRViewManager();
if (vrvm != null){
if(isInputDeviceTracking(index) == false ){
return null;
}
Object obs = environment.getObserver();
if( obs instanceof Camera ) {
tempQuaternion.set(((Camera)obs).getRotation());
} else {
tempQuaternion.set(((Spatial)obs).getWorldRotation());
}
return tempQuaternion.multLocal(getOrientation(index));
} else {
throw new IllegalStateException("VR environment has no valid view manager.");
}
} else {
throw new IllegalStateException("VR input is not attached to a VR environment.");
}
}
@Override
public Vector3f getFinalObserverPosition(int index) {
if (environment != null){
OpenVRViewManager vrvm = (OpenVRViewManager)environment.getVRViewManager();
if (vrvm != null){
if(isInputDeviceTracking(index) == false ){
return null;
}
Object obs = environment.getObserver();
Vector3f pos = getPosition(index);
if( obs instanceof Camera ) {
((Camera)obs).getRotation().mult(pos, pos);
return pos.addLocal(((Camera)obs).getLocation());
} else {
((Spatial)obs).getWorldRotation().mult(pos, pos);
return pos.addLocal(((Spatial)obs).getWorldTranslation());
}
} else {
throw new IllegalStateException("VR environment has no valid view manager.");
}
} else {
throw new IllegalStateException("VR input is not attached to a VR environment.");
}
}
@Override
public void triggerHapticPulse(int controllerIndex, float seconds) {
if( environment.isInVR() == false || isInputDeviceTracking(controllerIndex) == false ){
return;
}
// apparently only axis ID of 0 works
((VR_IVRSystem_FnTable)environment.getVRHardware().getVRSystem()).TriggerHapticPulse.apply(OpenVRInput.controllerIndex[controllerIndex],
0, (short)Math.round(3f * seconds / 1e-3f));
}
@Override
public void updateConnectedControllers() {
logger.config("Updating connected controllers.");
if (environment != null){
controllerCount = 0;
for(int i=0;i(JOpenVRLibrary.k_unMaxTrackedDeviceCount);
}
trackedControllers.add(new OpenVRTrackedController(i, this, controllerName, manufacturerName, environment));
// Send a Haptic pulse to the controller
triggerHapticPulse(controllerCount, 1.0f);
controllerCount++;
logger.config(" Tracked controller "+(i+1)+"/"+JOpenVRLibrary.k_unMaxTrackedDeviceCount+" "+controllerName+" ("+manufacturerName+") attached.");
} else {
logger.config(" Controller "+(i+1)+"/"+JOpenVRLibrary.k_unMaxTrackedDeviceCount+" ignored.");
}
}
} else {
throw new IllegalStateException("VR input is not attached to a VR environment.");
}
}
@Override
public void updateControllerStates() {
if (environment != null){
for(int i=0;i
© 2015 - 2024 Weber Informatics LLC | Privacy Policy