Creating a VRAppState
This commit is contained in:
parent
b9071513e7
commit
41bead60e3
@ -170,6 +170,60 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
||||
*/
|
||||
protected transient int refreshFlags = 0;
|
||||
|
||||
public void refreshFlagOr(int flag){
|
||||
refreshFlags |= flag;
|
||||
//logger.warning("Changing refresh flags for spatial " + getName()+", flags: "+getRefreshFlagsDescription());
|
||||
}
|
||||
|
||||
public void refreshFlagAnd(int flag){
|
||||
refreshFlags &= flag;
|
||||
//logger.warning("Changing refresh flags for spatial " + getName()+", flags: "+getRefreshFlagsDescription());
|
||||
}
|
||||
|
||||
public int refreshFlagGetAnd(int flag){
|
||||
return (refreshFlags & flag);
|
||||
}
|
||||
|
||||
public int getRefreshFlags(){
|
||||
return refreshFlags;
|
||||
}
|
||||
|
||||
public String getRefreshFlagsDescription(){
|
||||
String str = "";
|
||||
|
||||
if (refreshFlags == 0){
|
||||
str += "OK";
|
||||
} else {
|
||||
|
||||
// need light resort + combine transforms
|
||||
if ((refreshFlags & RF_TRANSFORM) == RF_TRANSFORM){
|
||||
str += "RF_TRANSFORM ";
|
||||
}
|
||||
|
||||
// need light resort + combine transforms
|
||||
if ((refreshFlags & RF_BOUND) == RF_BOUND){
|
||||
str += "RF_BOUND ";
|
||||
}
|
||||
|
||||
// changes in light lists
|
||||
if ((refreshFlags & RF_LIGHTLIST) == RF_LIGHTLIST){
|
||||
str += "RF_LIGHTLIST ";
|
||||
}
|
||||
|
||||
// some child need geometry update
|
||||
if ((refreshFlags & RF_CHILD_LIGHTLIST) == RF_CHILD_LIGHTLIST){
|
||||
str += "RF_CHILD_LIGHTLIST ";
|
||||
}
|
||||
|
||||
// some child need geometry update
|
||||
if ((refreshFlags & RF_MATPARAM_OVERRIDE) == RF_MATPARAM_OVERRIDE){
|
||||
str += "RF_MATPARAM_OVERRIDE ";
|
||||
}
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if a subclass requires updateLogicalState() even
|
||||
* if it doesn't have any controls. Defaults to true thus implementing
|
||||
@ -209,7 +263,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
||||
|
||||
localOverrides = new SafeArrayList<>(MatParamOverride.class);
|
||||
worldOverrides = new SafeArrayList<>(MatParamOverride.class);
|
||||
refreshFlags |= RF_BOUND;
|
||||
refreshFlagOr(RF_BOUND);
|
||||
}
|
||||
|
||||
public void setKey(AssetKey key) {
|
||||
@ -272,35 +326,35 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
||||
* a refresh is required.
|
||||
*/
|
||||
protected void setTransformRefresh() {
|
||||
refreshFlags |= RF_TRANSFORM;
|
||||
refreshFlagOr(RF_TRANSFORM);
|
||||
setBoundRefresh();
|
||||
}
|
||||
|
||||
protected void setLightListRefresh() {
|
||||
refreshFlags |= RF_LIGHTLIST;
|
||||
refreshFlagOr(RF_LIGHTLIST);
|
||||
// Make sure next updateGeometricState() visits this branch
|
||||
// to update lights.
|
||||
Spatial p = parent;
|
||||
while (p != null) {
|
||||
if ((p.refreshFlags & RF_CHILD_LIGHTLIST) != 0) {
|
||||
if ((p.refreshFlagGetAnd(RF_CHILD_LIGHTLIST)) != 0) {
|
||||
// The parent already has this flag,
|
||||
// so must all ancestors.
|
||||
return;
|
||||
}
|
||||
p.refreshFlags |= RF_CHILD_LIGHTLIST;
|
||||
p.refreshFlagOr(RF_CHILD_LIGHTLIST);
|
||||
p = p.parent;
|
||||
}
|
||||
}
|
||||
|
||||
protected void setMatParamOverrideRefresh() {
|
||||
refreshFlags |= RF_MATPARAM_OVERRIDE;
|
||||
refreshFlagOr(RF_MATPARAM_OVERRIDE);
|
||||
Spatial p = parent;
|
||||
while (p != null) {
|
||||
if ((p.refreshFlags & RF_MATPARAM_OVERRIDE) != 0) {
|
||||
if ((p.refreshFlagGetAnd(RF_MATPARAM_OVERRIDE)) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
p.refreshFlags |= RF_MATPARAM_OVERRIDE;
|
||||
p.refreshFlagOr(RF_MATPARAM_OVERRIDE);
|
||||
p = p.parent;
|
||||
}
|
||||
}
|
||||
@ -310,15 +364,15 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
||||
* a refresh is required.
|
||||
*/
|
||||
protected void setBoundRefresh() {
|
||||
refreshFlags |= RF_BOUND;
|
||||
refreshFlagOr(RF_BOUND);
|
||||
|
||||
Spatial p = parent;
|
||||
while (p != null) {
|
||||
if ((p.refreshFlags & RF_BOUND) != 0) {
|
||||
if ((p.refreshFlagGetAnd(RF_BOUND)) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
p.refreshFlags |= RF_BOUND;
|
||||
p.refreshFlagOr(RF_BOUND);
|
||||
p = p.parent;
|
||||
}
|
||||
}
|
||||
@ -353,11 +407,14 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
||||
* (should be rendered), false if outside.
|
||||
*/
|
||||
public boolean checkCulling(Camera cam) {
|
||||
if (refreshFlags != 0) {
|
||||
if (getRefreshFlags() != 0) {
|
||||
/*
|
||||
throw new IllegalStateException("Scene graph is not properly updated for rendering.\n"
|
||||
+ "State was changed after rootNode.updateGeometricState() call. \n"
|
||||
+ "Make sure you do not modify the scene from another thread!\n"
|
||||
+ "Problem spatial name: " + getName());
|
||||
+ "Problem spatial name: " + getName()+", flags: "+getRefreshFlagsDescription());
|
||||
*/
|
||||
logger.warning("Invalid refresh flags for spatial " + getName()+", flags: "+getRefreshFlagsDescription());
|
||||
}
|
||||
|
||||
CullHint cm = getCullHint();
|
||||
@ -571,28 +628,28 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
||||
// for a node, the world bound is a combination of all it's children
|
||||
// bounds
|
||||
// -> handled by subclass
|
||||
refreshFlags &= ~RF_BOUND;
|
||||
refreshFlagAnd(~RF_BOUND);
|
||||
}
|
||||
|
||||
protected void updateWorldLightList() {
|
||||
if (parent == null) {
|
||||
worldLights.update(localLights, null);
|
||||
refreshFlags &= ~RF_LIGHTLIST;
|
||||
refreshFlagAnd(~RF_LIGHTLIST);
|
||||
} else {
|
||||
assert (parent.refreshFlags & RF_LIGHTLIST) == 0;
|
||||
assert (parent.refreshFlagGetAnd(RF_LIGHTLIST)) == 0;
|
||||
worldLights.update(localLights, parent.worldLights);
|
||||
refreshFlags &= ~RF_LIGHTLIST;
|
||||
refreshFlagAnd(~RF_LIGHTLIST);
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateMatParamOverrides() {
|
||||
refreshFlags &= ~RF_MATPARAM_OVERRIDE;
|
||||
refreshFlagAnd(~RF_MATPARAM_OVERRIDE);
|
||||
|
||||
worldOverrides.clear();
|
||||
if (parent == null) {
|
||||
worldOverrides.addAll(localOverrides);
|
||||
} else {
|
||||
assert (parent.refreshFlags & RF_MATPARAM_OVERRIDE) == 0;
|
||||
assert (parent.refreshFlagGetAnd(RF_MATPARAM_OVERRIDE)) == 0;
|
||||
worldOverrides.addAll(parent.worldOverrides);
|
||||
worldOverrides.addAll(localOverrides);
|
||||
}
|
||||
@ -643,13 +700,13 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
||||
protected void updateWorldTransforms() {
|
||||
if (parent == null) {
|
||||
worldTransform.set(localTransform);
|
||||
refreshFlags &= ~RF_TRANSFORM;
|
||||
refreshFlagAnd(~RF_TRANSFORM);
|
||||
} else {
|
||||
// check if transform for parent is updated
|
||||
assert ((parent.refreshFlags & RF_TRANSFORM) == 0);
|
||||
assert ((parent.refreshFlagGetAnd(RF_TRANSFORM)) == 0);
|
||||
worldTransform.set(localTransform);
|
||||
worldTransform.combineWithParent(parent.worldTransform);
|
||||
refreshFlags &= ~RF_TRANSFORM;
|
||||
refreshFlagAnd(~RF_TRANSFORM);
|
||||
}
|
||||
}
|
||||
|
||||
@ -658,13 +715,13 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
||||
* efficient manner possible.
|
||||
*/
|
||||
void checkDoTransformUpdate() {
|
||||
if ((refreshFlags & RF_TRANSFORM) == 0) {
|
||||
if ((refreshFlagGetAnd(RF_TRANSFORM)) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (parent == null) {
|
||||
worldTransform.set(localTransform);
|
||||
refreshFlags &= ~RF_TRANSFORM;
|
||||
refreshFlagAnd(~RF_TRANSFORM);
|
||||
} else {
|
||||
TempVars vars = TempVars.get();
|
||||
|
||||
@ -675,14 +732,14 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
||||
Spatial hisParent = rootNode.parent;
|
||||
if (hisParent == null) {
|
||||
rootNode.worldTransform.set(rootNode.localTransform);
|
||||
rootNode.refreshFlags &= ~RF_TRANSFORM;
|
||||
rootNode.refreshFlagAnd(~RF_TRANSFORM);
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
|
||||
stack[i] = rootNode;
|
||||
|
||||
if ((hisParent.refreshFlags & RF_TRANSFORM) == 0) {
|
||||
if ((hisParent.refreshFlagGetAnd(RF_TRANSFORM)) == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
@ -707,7 +764,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
||||
* manner possible.
|
||||
*/
|
||||
void checkDoBoundUpdate() {
|
||||
if ((refreshFlags & RF_BOUND) == 0) {
|
||||
if ((refreshFlagGetAnd(RF_BOUND)) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -897,20 +954,20 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
||||
|
||||
// NOTE: Update world transforms first because
|
||||
// bound transform depends on them.
|
||||
if ((refreshFlags & RF_LIGHTLIST) != 0) {
|
||||
if ((refreshFlagGetAnd(RF_LIGHTLIST)) != 0) {
|
||||
updateWorldLightList();
|
||||
}
|
||||
if ((refreshFlags & RF_TRANSFORM) != 0) {
|
||||
if ((refreshFlagGetAnd(RF_TRANSFORM)) != 0) {
|
||||
updateWorldTransforms();
|
||||
}
|
||||
if ((refreshFlags & RF_BOUND) != 0) {
|
||||
if ((refreshFlagGetAnd(RF_BOUND)) != 0) {
|
||||
updateWorldBound();
|
||||
}
|
||||
if ((refreshFlags & RF_MATPARAM_OVERRIDE) != 0) {
|
||||
if ((refreshFlagGetAnd(RF_MATPARAM_OVERRIDE)) != 0) {
|
||||
updateMatParamOverrides();
|
||||
}
|
||||
|
||||
assert refreshFlags == 0;
|
||||
assert getRefreshFlags() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
843
jme3-vr/src/main/java/com/jme3/app/VRAppState.java
Normal file
843
jme3-vr/src/main/java/com/jme3/app/VRAppState.java
Normal file
@ -0,0 +1,843 @@
|
||||
package com.jme3.app;
|
||||
|
||||
|
||||
import com.jme3.app.Application;
|
||||
import com.jme3.app.state.AbstractAppState;
|
||||
import com.jme3.app.state.AppStateManager;
|
||||
import com.jme3.input.vr.OSVR;
|
||||
import com.jme3.input.vr.OpenVR;
|
||||
import com.jme3.input.vr.VRAPI;
|
||||
import com.jme3.input.vr.VRInputAPI;
|
||||
import com.jme3.math.ColorRGBA;
|
||||
import com.jme3.math.Quaternion;
|
||||
import com.jme3.math.Vector3f;
|
||||
import com.jme3.post.PreNormalCaching;
|
||||
import com.jme3.renderer.Camera;
|
||||
import com.jme3.renderer.RenderManager;
|
||||
import com.jme3.renderer.ViewPort;
|
||||
import com.jme3.scene.Spatial;
|
||||
import com.jme3.system.AppSettings;
|
||||
import com.jme3.system.jopenvr.JOpenVRLibrary;
|
||||
|
||||
import java.awt.GraphicsDevice;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import jmevr.util.VRGuiManager;
|
||||
import jmevr.util.VRMouseManager;
|
||||
import jmevr.util.VRViewManager;
|
||||
import jmevr.util.VRGuiManager.POSITIONING_MODE;
|
||||
|
||||
/**
|
||||
* A JMonkey app state dedicated to Virtual Reality.
|
||||
* An application that want to use VR devices (HTC vive, ...) has to use this app state.<br>
|
||||
* As this app state and the main {@link Application application} have to share {@link AppSettings application settings},
|
||||
* the common way to use this app state is:<br>
|
||||
* <ul>
|
||||
* <li>To create {@link AppSettings application settings} and set the VR related settings (see {@link VRConstants}).
|
||||
* <li>To instantiate this app state with the created settings.
|
||||
* <li>To instantiate the main {@link Application application} and to attach it to the created settings (with {@link Application#setSettings(AppSettings) setSettings(AppSettings)}).
|
||||
* <li>To start the main {@link Application application}.
|
||||
* </ul>
|
||||
* Attaching an instance of this app state to an already started application may cause crashes.
|
||||
* @author Julien Seinturier - JOrigin project - <a href="http://www.jorigin.org">http:/www.jorigin.org</a>
|
||||
*/
|
||||
public class VRAppState extends AbstractAppState {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(VRAppState.class.getName());
|
||||
|
||||
/**
|
||||
* The underlying system VR API. By default set to {@link VRConstants#SETTING_VRAPI_OPENVR_VALUE}.
|
||||
*/
|
||||
public int vrBinding = VRConstants.SETTING_VRAPI_OPENVR_VALUE;
|
||||
|
||||
/**
|
||||
* Is the application has not to start within VR mode (default is <code>false</code>).
|
||||
*/
|
||||
public boolean DISABLE_VR = false;
|
||||
|
||||
private VRAPI VRhardware = null;
|
||||
private VRGuiManager guiManager = null;
|
||||
private VRMouseManager mouseManager = null;
|
||||
private VRViewManager viewmanager = null;
|
||||
|
||||
private String OS;
|
||||
|
||||
private Camera dummyCam;
|
||||
|
||||
private Spatial observer = null;
|
||||
|
||||
private boolean VRSupportedOS;
|
||||
private boolean forceVR = false;;
|
||||
private boolean disableSwapBuffers = true;
|
||||
private boolean disableVR = false;
|
||||
private boolean seated;
|
||||
private boolean nogui;
|
||||
private boolean instanceVR = false;
|
||||
|
||||
private float defaultFOV = 108f;
|
||||
private float defaultAspect = 1f;
|
||||
|
||||
|
||||
|
||||
private float fFar = 1000f;
|
||||
private float fNear = 0.1f;
|
||||
private int xWin = 1920;
|
||||
private int yWin = 1080;
|
||||
|
||||
private float resMult = 1f;
|
||||
|
||||
private boolean useCompositor = true;
|
||||
private boolean compositorOS;
|
||||
|
||||
/*
|
||||
where is the headset pointing, after all rotations are combined?
|
||||
depends on observer rotation, if any
|
||||
*/
|
||||
private Quaternion tempq = new Quaternion();
|
||||
|
||||
private Application application = null;
|
||||
private AppStateManager stateManager = null;
|
||||
private AppSettings settings = null;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new default VR app state.
|
||||
*/
|
||||
public VRAppState() {
|
||||
super();
|
||||
|
||||
dummyCam = new Camera();
|
||||
|
||||
// Create the GUI manager.
|
||||
guiManager = new VRGuiManager();
|
||||
|
||||
// Create a new view manager.
|
||||
viewmanager = new VRViewManager();
|
||||
|
||||
// Create a new mouse manager.
|
||||
mouseManager = new VRMouseManager();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new VR app state with given settings.
|
||||
* @param settings the settings to use.
|
||||
*/
|
||||
public VRAppState(AppSettings settings){
|
||||
this();
|
||||
this.settings = settings;
|
||||
processSettings(settings);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Simple update of the app state, this method should contains any spatial updates.
|
||||
* This method is called by the {@link #update(float) update()} method and should not be called manually.
|
||||
* @param tpf the application time.
|
||||
*/
|
||||
public void simpleUpdate(float tpf) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rendering callback of the app state. This method is called by the {@link #update(float) update()} method and should not be called manually.
|
||||
* @param renderManager the {@link RenderManager render manager}.
|
||||
*/
|
||||
public void simpleRender(RenderManager renderManager) {
|
||||
PreNormalCaching.resetCache(isInVR());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the frustrum values for the application.
|
||||
* @param near the frustrum near value.
|
||||
* @param far the frustrum far value.
|
||||
*/
|
||||
public void setFrustrumNearFar(float near, float far) {
|
||||
fNear = near;
|
||||
fFar = far;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the mirror window size in pixel.
|
||||
* @param width the width of the mirror window in pixel.
|
||||
* @param height the height of the mirror window in pixel.
|
||||
*/
|
||||
public void setMirrorWindowSize(int width, int height) {
|
||||
xWin = width;
|
||||
yWin = height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the resolution multiplier.
|
||||
* @param val the resolution multiplier.
|
||||
*/
|
||||
public void setResolutionMultiplier(float val) {
|
||||
resMult = val;
|
||||
if( viewmanager != null ){
|
||||
viewmanager.setResolutionMultiplier(resMult);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the VR compositor is active.
|
||||
* @return <code>true</code> if the VR compositor is active and <code>false</code> otherwise.
|
||||
*/
|
||||
public boolean compositorAllowed() {
|
||||
return useCompositor && compositorOS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get if the system currently support VR.
|
||||
* @return <code>true</code> if the system currently support VR and <code>false</Code> otherwise.
|
||||
*/
|
||||
public boolean isVRSupported() {
|
||||
return VRSupportedOS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link Camera camera} attached to this application state.
|
||||
* If the VR mode is {@link #isInVR() active}, this method return a dummy camera, otherwise,
|
||||
* this method return the camera of the attached application.
|
||||
* @return the camera attached to this application state.
|
||||
*/
|
||||
public Camera getCamera() {
|
||||
if( isInVR() && viewmanager != null && viewmanager.getLeftCamera() != null ) {
|
||||
return dummyCam;
|
||||
}
|
||||
|
||||
return application.getCamera();
|
||||
}
|
||||
|
||||
/**
|
||||
* Can be used to change seated experience during runtime.
|
||||
* @param isSeated <code>true</code> if designed for sitting, <code>false</code> for standing/roomscale
|
||||
* @see #isSeatedExperience()
|
||||
*/
|
||||
public void setSeatedExperience(boolean isSeated) {
|
||||
seated = isSeated;
|
||||
if( VRhardware instanceof OpenVR ) {
|
||||
if( VRhardware.getCompositor() == null ) return;
|
||||
if( seated ) {
|
||||
((OpenVR)VRhardware).getCompositor().SetTrackingSpace.apply(JOpenVRLibrary.ETrackingUniverseOrigin.ETrackingUniverseOrigin_TrackingUniverseSeated);
|
||||
} else {
|
||||
((OpenVR)VRhardware).getCompositor().SetTrackingSpace.apply(JOpenVRLibrary.ETrackingUniverseOrigin.ETrackingUniverseOrigin_TrackingUniverseStanding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the application is configured as a seated experience.
|
||||
* @return <code>true</code> if the application is configured as a seated experience and <code>false</code> otherwise.
|
||||
* @see #setSeatedExperience(boolean)
|
||||
*/
|
||||
public boolean isSeatedExperience() {
|
||||
return seated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset headset pose if seating experience.
|
||||
*/
|
||||
public void resetSeatedPose(){
|
||||
if( VRSupportedOS == false || isSeatedExperience() == false ) return;
|
||||
VRhardware.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the rendering is instanced (see <a href="https://en.wikipedia.org/wiki/Geometry_instancing">Geometry instancing</a>).
|
||||
* @return <code>true</code> if the rendering is instanced and <code>false</code> otherwise.
|
||||
*/
|
||||
public boolean isInstanceVRRendering() {
|
||||
return instanceVR && isInVR();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the VR mode is enabled.
|
||||
* @return <code>true</code> if the VR mode is enabled and <code>false</code> otherwise.
|
||||
*/
|
||||
public boolean isInVR() {
|
||||
return DISABLE_VR == false && (forceVR || VRSupportedOS && VRhardware != null && VRhardware.isInitialized());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default Field Of View (FOV) value.
|
||||
* @return the default Field Of View (FOV) value.
|
||||
* @see #setDefaultFOV(float)
|
||||
*/
|
||||
public float getDefaultFOV() {
|
||||
return defaultFOV;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default Field Of View (FOV) value.
|
||||
* @param defaultFOV the default Field Of View (FOV) value.
|
||||
* @see #getDefaultFOV()
|
||||
*/
|
||||
public void setDefaultFOV(float defaultFOV) {
|
||||
this.defaultFOV = defaultFOV;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default aspect ratio.
|
||||
* @return the default aspect ratio.
|
||||
* @see #setDefaultAspect(float)
|
||||
*/
|
||||
public float getDefaultAspect() {
|
||||
return defaultAspect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default aspect ratio.
|
||||
* @param defaultAspect the default aspect ratio.
|
||||
* @see #getDefaultAspect()
|
||||
*/
|
||||
public void setDefaultAspect(float defaultAspect) {
|
||||
this.defaultAspect = defaultAspect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move filters from the main scene into the eye's.
|
||||
* This removes filters from the main scene.
|
||||
*/
|
||||
public void moveScreenProcessingToVR() {
|
||||
if( isInVR() ) {
|
||||
viewmanager.moveScreenProcessingToEyes();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the application has a GUI overlay attached.
|
||||
* @return <code>true</code> if the application has a GUI overlay attached and <code>false</code> otherwise.
|
||||
*/
|
||||
public boolean hasTraditionalGUIOverlay() {
|
||||
return !nogui;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the scene observer. If no observer has been set, this method return the application {@link #getCamera() camera}.
|
||||
* @return the scene observer.
|
||||
* @see #setObserver(Spatial)
|
||||
*/
|
||||
public Object getObserver() {
|
||||
if( observer == null ) {
|
||||
return getCamera();
|
||||
}
|
||||
return observer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the scene observer. The VR headset will be linked to it. If no observer is set, the VR headset is linked to the the application {@link #getCamera() camera}.
|
||||
* @param observer the scene observer.
|
||||
*/
|
||||
public void setObserver(Spatial observer) {
|
||||
this.observer = observer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the observer final rotation within the scene.
|
||||
* @return the observer final rotation within the scene.
|
||||
* @see #getFinalObserverPosition()
|
||||
*/
|
||||
public Quaternion getFinalObserverRotation() {
|
||||
if( viewmanager == null ) {
|
||||
if( observer == null ) {
|
||||
return getCamera().getRotation();
|
||||
} else return observer.getWorldRotation();
|
||||
}
|
||||
if( observer == null ) {
|
||||
tempq.set(dummyCam.getRotation());
|
||||
} else {
|
||||
tempq.set(observer.getWorldRotation());
|
||||
}
|
||||
return tempq.multLocal(VRhardware.getOrientation());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the observer final position within the scene.
|
||||
* @return the observer position.
|
||||
* @see #getFinalObserverRotation()
|
||||
*/
|
||||
public Vector3f getFinalObserverPosition() {
|
||||
if( viewmanager == null ) {
|
||||
if( observer == null ) {
|
||||
return getCamera().getLocation();
|
||||
} else return observer.getWorldTranslation();
|
||||
}
|
||||
Vector3f pos = VRhardware.getPosition();
|
||||
if( observer == null ) {
|
||||
dummyCam.getRotation().mult(pos, pos);
|
||||
return pos.addLocal(dummyCam.getLocation());
|
||||
} else {
|
||||
observer.getWorldRotation().mult(pos, pos);
|
||||
return pos.addLocal(observer.getWorldTranslation());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the VR headset height from the ground.
|
||||
* @param amount the VR headset height from the ground.
|
||||
* @see #getVRHeightAdjustment()
|
||||
*/
|
||||
public void setVRHeightAdjustment(float amount) {
|
||||
if( viewmanager != null ) viewmanager.setHeightAdjustment(amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the VR headset height from the ground.
|
||||
* @return the VR headset height from the ground.
|
||||
* @see #setVRHeightAdjustment(float)
|
||||
*/
|
||||
public float getVRHeightAdjustment() {
|
||||
if( viewmanager != null ){
|
||||
return viewmanager.getHeightAdjustment();
|
||||
}
|
||||
return 0f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the VR headset left viewport.
|
||||
* @return the VR headset left viewport.
|
||||
* @see #getRightViewPort()
|
||||
*/
|
||||
public ViewPort getLeftViewPort() {
|
||||
if( viewmanager == null ) return application.getViewPort();
|
||||
return viewmanager.getLeftViewport();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the VR headset right viewport.
|
||||
* @return the VR headset right viewport.
|
||||
* @see #getLeftViewPort()
|
||||
*/
|
||||
public ViewPort getRightViewPort() {
|
||||
if( viewmanager == null ) return application.getViewPort();
|
||||
return viewmanager.getRightViewport();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the background color for both left and right view ports.
|
||||
* @param clr the background color.
|
||||
*/
|
||||
public void setBackgroundColors(ColorRGBA clr) {
|
||||
if( viewmanager == null ) {
|
||||
application.getViewPort().setBackgroundColor(clr);
|
||||
} else if( viewmanager.getLeftViewport() != null ) {
|
||||
viewmanager.getLeftViewport().setBackgroundColor(clr);
|
||||
if( viewmanager.getRightViewport() != null ) viewmanager.getRightViewport().setBackgroundColor(clr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link Application} to which this app state is attached.
|
||||
* @return the {@link Application} to which this app state is attached.
|
||||
* @see #getStateManager()
|
||||
*/
|
||||
public Application getApplication(){
|
||||
return application;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link AppStateManager state manager} to which this app state is attached.
|
||||
* @return the {@link AppStateManager state manager} to which this app state is attached.
|
||||
* @see #getApplication()
|
||||
*/
|
||||
public AppStateManager getStateManager(){
|
||||
return stateManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the VR underlying hardware.
|
||||
* @return the VR underlying hardware.
|
||||
*/
|
||||
public VRAPI getVRHardware() {
|
||||
return VRhardware;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the VR dedicated input.
|
||||
* @return the VR dedicated input.
|
||||
*/
|
||||
public VRInputAPI getVRinput() {
|
||||
if( VRhardware == null ){
|
||||
return null;
|
||||
}
|
||||
|
||||
return VRhardware.getVRinput();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the VR view manager.
|
||||
* @return the VR view manager.
|
||||
*/
|
||||
public VRViewManager getVRViewManager() {
|
||||
return viewmanager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the GUI manager attached to this application.
|
||||
* @return the GUI manager attached to this application.
|
||||
*/
|
||||
public VRGuiManager getVRGUIManager(){
|
||||
return guiManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the VR mouse manager attached to this application.
|
||||
* @return the VR mouse manager attached to this application.
|
||||
*/
|
||||
public VRMouseManager getVRMouseManager(){
|
||||
return mouseManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link AppSettings settings} attached to this app state.
|
||||
* @return the {@link AppSettings settings} attached to this app state.
|
||||
* @see #setSettings(AppSettings)
|
||||
*/
|
||||
public AppSettings getSettings(){
|
||||
return settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link AppSettings settings} attached to this app state.
|
||||
* @param settings the {@link AppSettings settings} attached to this app state.
|
||||
* @see #getSettings()
|
||||
*/
|
||||
public void setSettings(AppSettings settings){
|
||||
this.settings = settings;
|
||||
processSettings(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(float tpf) {
|
||||
|
||||
// update VR pose & cameras
|
||||
if( viewmanager != null ) {
|
||||
viewmanager.update(tpf);
|
||||
} else if( observer != null ) {
|
||||
getCamera().setFrame(observer.getWorldTranslation(), observer.getWorldRotation());
|
||||
}
|
||||
|
||||
//FIXME: check if this code is necessary.
|
||||
// Updates scene and gui states.
|
||||
Iterator<Spatial> spatialIter = application.getViewPort().getScenes().iterator();
|
||||
Spatial spatial = null;
|
||||
while(spatialIter.hasNext()){
|
||||
spatial = spatialIter.next();
|
||||
spatial.updateLogicalState(tpf);
|
||||
spatial.updateGeometricState();
|
||||
}
|
||||
|
||||
if( isInVR() == false || guiManager.getPositioningMode() == POSITIONING_MODE.MANUAL ) {
|
||||
// only update geometric state here if GUI is in manual mode, or not in VR
|
||||
// it will get updated automatically in the viewmanager update otherwise
|
||||
spatialIter = application.getGuiViewPort().getScenes().iterator();
|
||||
spatial = null;
|
||||
while(spatialIter.hasNext()){
|
||||
spatial = spatialIter.next();
|
||||
spatial.updateGeometricState();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// use the analog control on the first tracked controller to push around the mouse
|
||||
getVRMouseManager().updateAnalogAsMouse(0, null, null, null, tpf);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postRender() {
|
||||
super.postRender();
|
||||
// update compositor?
|
||||
if( viewmanager != null ) {
|
||||
viewmanager.sendTextures();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(AppStateManager stateManager, Application app) {
|
||||
super.initialize(stateManager, app);
|
||||
|
||||
this.application = app;
|
||||
this.stateManager = stateManager;
|
||||
|
||||
// disable annoying warnings about GUI stuff being updated, which is normal behavior
|
||||
// for late GUI placement for VR purposes
|
||||
Logger.getLogger("com.jme3").setLevel(Level.SEVERE);
|
||||
|
||||
// VR module attch
|
||||
guiManager.attach(this, app);
|
||||
viewmanager.attach(this, app);
|
||||
mouseManager.attach(this, app);
|
||||
|
||||
app.getCamera().setFrustumFar(fFar);
|
||||
app.getCamera().setFrustumNear(fNear);
|
||||
dummyCam = app.getCamera().clone();
|
||||
|
||||
if( isInVR() ) {
|
||||
|
||||
logger.config("VR mode enabled.");
|
||||
|
||||
if( VRhardware != null ) {
|
||||
VRhardware.initVRCompositor(compositorAllowed());
|
||||
} else {
|
||||
logger.warning("No VR system found.");
|
||||
}
|
||||
|
||||
|
||||
viewmanager.setResolutionMultiplier(resMult);
|
||||
//inputManager.addMapping(RESET_HMD, new KeyTrigger(KeyInput.KEY_F9));
|
||||
//setLostFocusBehavior(LostFocusBehavior.Disabled);
|
||||
} else {
|
||||
logger.config("VR mode disabled.");
|
||||
//viewPort.attachScene(rootNode);
|
||||
//guiViewPort.attachScene(guiNode);
|
||||
}
|
||||
|
||||
if( viewmanager != null ) {
|
||||
viewmanager.initialize();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stateAttached(AppStateManager stateManager) {
|
||||
super.stateAttached(stateManager); //To change body of generated methods, choose Tools | Templates.
|
||||
|
||||
if (settings == null) {
|
||||
settings = new AppSettings(true);
|
||||
logger.config("Using default settings.");
|
||||
} else {
|
||||
logger.config("Using given settings.");
|
||||
}
|
||||
|
||||
// we are going to use OpenVR now, not the Oculus Rift
|
||||
// OpenVR does support the Rift
|
||||
OS = System.getProperty("os.name", "generic").toLowerCase(Locale.ENGLISH);
|
||||
VRSupportedOS = !OS.contains("nux") && System.getProperty("sun.arch.data.model").equalsIgnoreCase("64"); //for the moment, linux/unix causes crashes, 64-bit only
|
||||
compositorOS = OS.contains("indows");
|
||||
|
||||
if( VRSupportedOS && disableVR == false ) {
|
||||
if( vrBinding == VRConstants.SETTING_VRAPI_OSVR_VALUE ) {
|
||||
VRhardware = new OSVR(this);
|
||||
logger.config("Creating OSVR wrapper [SUCCESS]");
|
||||
} else if( vrBinding == VRConstants.SETTING_VRAPI_OPENVR_VALUE ) {
|
||||
VRhardware = new OpenVR(this);
|
||||
logger.config("Creating OpenVR wrapper [SUCCESS]");
|
||||
} else {
|
||||
logger.config("Cannot create VR binding: "+vrBinding+" [FAILED]");
|
||||
}
|
||||
|
||||
if( VRhardware.initialize() ) {
|
||||
logger.config("VR native wrapper initialized [SUCCESS]");
|
||||
} else {
|
||||
logger.warning("VR native wrapper initialized [FAILED]");
|
||||
}
|
||||
}
|
||||
|
||||
GraphicsDevice defDev = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
|
||||
|
||||
if( isInVR() && !compositorAllowed() ) {
|
||||
// "easy extended" mode
|
||||
// setup experimental JFrame on external device
|
||||
// first, find the VR device
|
||||
GraphicsDevice VRdev = null;
|
||||
GraphicsDevice[] devs = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices();
|
||||
// pick the display that isn't the default one
|
||||
for(GraphicsDevice gd : devs) {
|
||||
if( gd != defDev ) {
|
||||
VRdev = gd;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// did we get the VR device?
|
||||
if( VRdev != null ) {
|
||||
// set properties for VR acceleration
|
||||
try {
|
||||
java.awt.DisplayMode useDM = null;
|
||||
int max = 0;
|
||||
for(java.awt.DisplayMode dm : VRdev.getDisplayModes()) {
|
||||
int check = dm.getHeight() + dm.getWidth() + dm.getRefreshRate() + dm.getBitDepth();
|
||||
if( check > max ) {
|
||||
max = check;
|
||||
useDM = dm;
|
||||
}
|
||||
}
|
||||
|
||||
// create a window for the VR device
|
||||
settings.setWidth(useDM.getWidth());
|
||||
settings.setHeight(useDM.getHeight());
|
||||
settings.setBitsPerPixel(useDM.getBitDepth());
|
||||
settings.setFrequency(useDM.getRefreshRate());
|
||||
settings.setSwapBuffers(true);
|
||||
settings.setVSync(true); // allow vsync on this display
|
||||
stateManager.getApplication().setSettings(settings);
|
||||
logger.config("Updated underlying application settings.");
|
||||
|
||||
//VRdev.setFullScreenWindow(VRwindow);
|
||||
// make sure we are in the right display mode
|
||||
if( VRdev.getDisplayMode().equals(useDM) == false ) {
|
||||
VRdev.setDisplayMode(useDM);
|
||||
}
|
||||
|
||||
return;
|
||||
} catch(Exception e) {
|
||||
logger.log(Level.SEVERE, e.getMessage(), e);
|
||||
}
|
||||
} else {
|
||||
logger.config("Cannot access to external screen.");
|
||||
}
|
||||
} else {
|
||||
if (!isInVR()){
|
||||
logger.config("Cannot switch to VR mode (VR disabled by user).");
|
||||
} else if (!compositorAllowed()){
|
||||
logger.warning("Cannot switch to VR mode (VR not supported).");
|
||||
}
|
||||
}
|
||||
|
||||
if( !isInVR() ) {
|
||||
|
||||
//FIXME: Handling GLFW workaround on MacOS
|
||||
boolean macOs = false;
|
||||
if (macOs) {
|
||||
// GLFW workaround on macs
|
||||
settings.setFrequency(defDev.getDisplayMode().getRefreshRate());
|
||||
settings.setDepthBits(24);
|
||||
settings.setVSync(true);
|
||||
// try and read resolution from file in local dir
|
||||
File resfile = new File("resolution.txt");
|
||||
if( resfile.exists() ) {
|
||||
try {
|
||||
BufferedReader br = new BufferedReader(new FileReader(resfile));
|
||||
settings.setWidth(Integer.parseInt(br.readLine()));
|
||||
settings.setHeight(Integer.parseInt(br.readLine()));
|
||||
try {
|
||||
settings.setFullscreen(br.readLine().toLowerCase(Locale.ENGLISH).contains("full"));
|
||||
} catch(Exception e) {
|
||||
settings.setFullscreen(false);
|
||||
}
|
||||
br.close();
|
||||
} catch(Exception e) {
|
||||
settings.setWidth(1280);
|
||||
settings.setHeight(720);
|
||||
}
|
||||
} else {
|
||||
settings.setWidth(1280);
|
||||
settings.setHeight(720);
|
||||
settings.setFullscreen(false);
|
||||
}
|
||||
settings.setResizable(false);
|
||||
}
|
||||
settings.setSwapBuffers(true);
|
||||
} else {
|
||||
// use basic mirroring window, skip settings window
|
||||
settings.setSamples(1);
|
||||
settings.setWidth(xWin);
|
||||
settings.setHeight(yWin);
|
||||
settings.setBitsPerPixel(32);
|
||||
settings.setFrameRate(0);
|
||||
settings.setFrequency(VRhardware.getDisplayFrequency());
|
||||
settings.setFullscreen(false);
|
||||
settings.setVSync(false); // stop vsyncing on primary monitor!
|
||||
settings.setSwapBuffers(disableSwapBuffers);
|
||||
}
|
||||
|
||||
// Updating application settings
|
||||
stateManager.getApplication().setSettings(settings);
|
||||
logger.config("Updated underlying application settings.");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup() {
|
||||
if( VRhardware != null ) {
|
||||
VRhardware.destroy();
|
||||
VRhardware = null;
|
||||
}
|
||||
disableVR = true;
|
||||
|
||||
this.application = null;
|
||||
this.stateManager = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stateDetached(AppStateManager stateManager) {
|
||||
super.stateDetached(stateManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the attached settings and apply changes to this app state.
|
||||
* @param settings the app settings to process.
|
||||
*/
|
||||
protected void processSettings(AppSettings settings){
|
||||
if (settings != null){
|
||||
if (settings.get(VRConstants.SETTING_USE_COMPOSITOR) != null){
|
||||
useCompositor = settings.getBoolean(VRConstants.SETTING_USE_COMPOSITOR);
|
||||
if( useCompositor == false ){
|
||||
disableSwapBuffers = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.get(VRConstants.SETTING_VR_FORCE) != null){
|
||||
forceVR = settings.getBoolean(VRConstants.SETTING_VR_FORCE);
|
||||
}
|
||||
|
||||
if (settings.get(VRConstants.SETTING_FLIP_EYES) != null){
|
||||
if( VRhardware != null ){
|
||||
VRhardware._setFlipEyes(settings.getBoolean(VRConstants.SETTING_FLIP_EYES));
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.get(VRConstants.SETTING_GUI_OVERDRAW) != null){
|
||||
guiManager._enableGuiOverdraw(settings.getBoolean(VRConstants.SETTING_GUI_OVERDRAW));
|
||||
}
|
||||
|
||||
if (settings.get(VRConstants.SETTING_GUI_CURVED_SURFACE) != null){
|
||||
guiManager._enableCurvedSuface(settings.getBoolean(VRConstants.SETTING_GUI_CURVED_SURFACE));
|
||||
}
|
||||
|
||||
if (settings.get(VRConstants.SETTING_ENABLE_MIRROR_WINDOW) != null){
|
||||
if( useCompositor == false ) {
|
||||
disableSwapBuffers = false;
|
||||
} else {
|
||||
disableSwapBuffers = !settings.getBoolean(VRConstants.SETTING_ENABLE_MIRROR_WINDOW);
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.get(VRConstants.SETTING_DISABLE_VR) != null){
|
||||
DISABLE_VR = settings.getBoolean(VRConstants.SETTING_DISABLE_VR);
|
||||
}
|
||||
|
||||
if (settings.get(VRConstants.SETTING_SEATED_EXPERIENCE) != null){
|
||||
seated = settings.getBoolean(VRConstants.SETTING_SEATED_EXPERIENCE);
|
||||
}
|
||||
|
||||
if (settings.get(VRConstants.SETTING_NO_GUI) != null){
|
||||
nogui = settings.getBoolean(VRConstants.SETTING_NO_GUI);
|
||||
}
|
||||
|
||||
if (settings.get(VRConstants.SETTING_INSTANCE_RENDERING) != null){
|
||||
instanceVR = settings.getBoolean(VRConstants.SETTING_INSTANCE_RENDERING);
|
||||
}
|
||||
|
||||
if (settings.get(VRConstants.SETTING_DEFAULT_FOV) != null){
|
||||
defaultFOV = settings.getFloat(VRConstants.SETTING_DEFAULT_FOV);
|
||||
}
|
||||
|
||||
if (settings.get(VRConstants.SETTING_DEFAULT_ASPECT_RATIO) != null){
|
||||
defaultAspect = settings.getFloat(VRConstants.SETTING_DEFAULT_ASPECT_RATIO);
|
||||
}
|
||||
|
||||
if (settings.get(VRConstants.SETTING_VRAPI) != null){
|
||||
vrBinding = settings.getInteger(VRConstants.SETTING_VRAPI);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -255,13 +255,13 @@ public abstract class VRApplication implements Application, SystemListener {
|
||||
initStateManager();
|
||||
|
||||
// Create the GUI manager.
|
||||
guiManager = new VRGuiManager(this);
|
||||
guiManager = new VRGuiManager();
|
||||
|
||||
// Create a new view manager.
|
||||
viewmanager = new VRViewManager(this);
|
||||
viewmanager = new VRViewManager();
|
||||
|
||||
// Create a new mouse manager.
|
||||
mouseManager = new VRMouseManager(this);
|
||||
mouseManager = new VRMouseManager();
|
||||
|
||||
// we are going to use OpenVR now, not the Oculus Rift
|
||||
// OpenVR does support the Rift
|
||||
@ -275,10 +275,12 @@ public abstract class VRApplication implements Application, SystemListener {
|
||||
logger.warning("VR disabled via code.");
|
||||
} else if( VRSupportedOS && DISABLE_VR == false ) {
|
||||
if( CONSTRUCT_WITH_OSVR ) {
|
||||
VRhardware = new OSVR(this);
|
||||
//FIXME: WARNING !!
|
||||
VRhardware = new OSVR(null);
|
||||
logger.config("Creating OSVR wrapper [SUCCESS]");
|
||||
} else {
|
||||
VRhardware = new OpenVR(this);
|
||||
//FIXME: WARNING !!
|
||||
VRhardware = new OpenVR(null);
|
||||
logger.config("Creating OpenVR wrapper [SUCCESS]");
|
||||
}
|
||||
if( VRhardware.initialize() ) {
|
||||
@ -820,6 +822,16 @@ public abstract class VRApplication implements Application, SystemListener {
|
||||
context.create(waitFor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move filters from the main scene into the eye's.
|
||||
* This removes filters from the main scene.
|
||||
*/
|
||||
public void moveScreenProcessingToVR() {
|
||||
if( isInVR() ) {
|
||||
viewmanager.moveScreenProcessingToEyes();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set VR application {@link PreconfigParameter specific parameter}.
|
||||
* If making changes to default values, this must be called before the VRApplication starts
|
||||
@ -924,15 +936,6 @@ public abstract class VRApplication implements Application, SystemListener {
|
||||
return DISABLE_VR == false && (forceVR || VRSupportedOS && VRhardware != null && VRhardware.isInitialized());
|
||||
}
|
||||
|
||||
/**
|
||||
* Move filters from the main scene into the eye's.
|
||||
* This removes filters from the main scene.
|
||||
*/
|
||||
public void moveScreenProcessingToVR() {
|
||||
if( isInVR() ) {
|
||||
viewmanager.moveScreenProcessingToEyes();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the GUI node from the application.
|
||||
@ -1354,7 +1357,8 @@ public abstract class VRApplication implements Application, SystemListener {
|
||||
logger.warning("No VR system found.");
|
||||
}
|
||||
|
||||
viewmanager = new VRViewManager(this);
|
||||
//FIXME: WARNING !!
|
||||
viewmanager = new VRViewManager();
|
||||
viewmanager.setResolutionMultiplier(resMult);
|
||||
inputManager.addMapping(RESET_HMD, new KeyTrigger(KeyInput.KEY_F9));
|
||||
setLostFocusBehavior(LostFocusBehavior.Disabled);
|
||||
|
||||
147
jme3-vr/src/main/java/com/jme3/app/VRConstants.java
Normal file
147
jme3-vr/src/main/java/com/jme3/app/VRConstants.java
Normal file
@ -0,0 +1,147 @@
|
||||
package com.jme3.app;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import com.jme3.system.AppSettings;
|
||||
|
||||
/**
|
||||
* Some constants dedicated to the VR module.
|
||||
* @author Julien Seinturier - JOrigin project - <a href="http://www.jorigin.org">http:/www.jorigin.org</a>
|
||||
* @since 3.1.0
|
||||
*/
|
||||
public class VRConstants {
|
||||
|
||||
/**
|
||||
* An AppSettings parameter that set if the VR compositor has to be used.
|
||||
* <p>
|
||||
* <b>Type: </b><code>boolean</code><br>
|
||||
* <b>Usage: </b><code>{@link AppSettings appSettings}.{@link HashMap#put(Object, Object) put}(VRConstants.SETTING_USE_COMPOSITOR, value)</code>
|
||||
*/
|
||||
public static final String SETTING_USE_COMPOSITOR = "VRUseCompositor";
|
||||
|
||||
/**
|
||||
* An AppSettings parameter that set if the rendering has to use two eyes,
|
||||
* regardless of VR API detection (turning this setting on without a VR system should lead to errors).
|
||||
* <p>
|
||||
* <b>Type: </b><code>boolean</code><br>
|
||||
* <b>Usage: </b><code>{@link AppSettings appSettings}.{@link HashMap#put(Object, Object) put}(VRConstants.SETTING_VR_FORCE, value)</code>
|
||||
|
||||
*/
|
||||
public static final String SETTING_VR_FORCE = "VRForce";
|
||||
|
||||
/**
|
||||
* An AppSettings parameter that set to invert the eyes of the HMD.
|
||||
* <b>Type: </b><code>boolean</code><br>
|
||||
* <b>Usage: </b><code>{@link AppSettings appSettings}.{@link HashMap#put(Object, Object) put}(VRConstants.SETTING_FLIP_EYES, value)</code>
|
||||
*/
|
||||
public static final String SETTING_FLIP_EYES = "VRFlipEyes";
|
||||
|
||||
/**
|
||||
* An AppSettings parameter that set if the GUI has to be displayed even if it is behind objects.
|
||||
* <b>Type: </b><code>boolean</code><br>
|
||||
* <b>Usage: </b><code>{@link AppSettings appSettings}.{@link HashMap#put(Object, Object) put}(VRConstants.SETTING_GUI_OVERDRAW, value)</code>
|
||||
*
|
||||
*/
|
||||
public static final String SETTING_GUI_OVERDRAW = "VRGUIOverdraw";
|
||||
|
||||
/**
|
||||
* An AppSettings parameter that set if the GUI surface has to be curved.
|
||||
* <b>Type: </b><code>boolean</code><br>
|
||||
* <b>Usage: </b><code>{@link AppSettings appSettings}.{@link HashMap#put(Object, Object) put}(VRConstants.SETTING_GUI_CURVED_SURFACE, value)</code>
|
||||
*/
|
||||
public static final String SETTING_GUI_CURVED_SURFACE = "VRGUICurvedSurface";
|
||||
|
||||
/**
|
||||
* An AppSettings parameter that set if a mirror rendering has to be displayed on the screen.
|
||||
* Runs faster when set to <code>false</code>.
|
||||
* <b>Type: </b><code>boolean</code><br>
|
||||
* <b>Usage: </b><code>{@link AppSettings appSettings}.{@link HashMap#put(Object, Object) put}(VRConstants.SETTING_ENABLE_MIRROR_WINDOW, value)</code>
|
||||
*/
|
||||
public static final String SETTING_ENABLE_MIRROR_WINDOW = "VREnableMirrorWindow";
|
||||
|
||||
/**
|
||||
* An AppSettings parameter that set if the VR rendering has to be disabled,
|
||||
* regardless VR API and devices are presents.
|
||||
* <b>Type: </b><code>boolean</code><br>
|
||||
* <b>Usage: </b><code>{@link AppSettings appSettings}.{@link HashMap#put(Object, Object) put}(VRConstants.SETTING_DISABLE_VR, value)</code>
|
||||
*/
|
||||
public static final String SETTING_DISABLE_VR = "VRDisable";
|
||||
|
||||
|
||||
/**
|
||||
* An AppSettings parameter that set if the VR user is seated.
|
||||
* <b>Type: </b><code>boolean</code><br>
|
||||
* <b>Usage: </b><code>{@link AppSettings appSettings}.{@link HashMap#put(Object, Object) put}(VRConstants.SETTING_SEATED_EXPERIENCE, value)</code>
|
||||
*/
|
||||
public static final String SETTING_SEATED_EXPERIENCE = "VRSeatedExperience";
|
||||
|
||||
/**
|
||||
* An AppSettings parameter that set if the GUI has to be ignored.
|
||||
* <b>Type: </b><code>boolean</code><br>
|
||||
* <b>Usage: </b><code>{@link AppSettings appSettings}.{@link HashMap#put(Object, Object) put}(VRConstants.SETTING_NO_GUI, value)</code>
|
||||
*/
|
||||
public static final String SETTING_NO_GUI = "VRNoGUI";
|
||||
|
||||
/**
|
||||
* An AppSettings parameter that set if instance rendering has to be used.
|
||||
* This setting requires some vertex shader changes (see Common/MatDefs/VR/Unshaded.j3md).
|
||||
* <b>Type: </b><code>boolean</code><br>
|
||||
* <b>Usage: </b><code>{@link AppSettings appSettings}.{@link HashMap#put(Object, Object) put}(VRConstants.SETTING_INSTANCE_RENDERING, value)</code>
|
||||
*/
|
||||
public static final String SETTING_INSTANCE_RENDERING = "VRInstanceRendering";
|
||||
|
||||
/**
|
||||
* An AppSettings parameter that set if Multi Sample Anti Aliasing has to be enabled.
|
||||
* <b>Type: </b><code>boolean</code><br>
|
||||
* <b>Usage: </b><code>{@link AppSettings appSettings}.{@link HashMap#put(Object, Object) put}(VRConstants.SETTING_DISABLE_MSAA, value)</code>
|
||||
*/
|
||||
public static final String SETTING_DISABLE_MSAA = "VRDisableMSAA";
|
||||
|
||||
/**
|
||||
* An AppSettings parameter that set the default field of view (FOV) value.
|
||||
* <b>Type: </b><code>float</code><br>
|
||||
* <b>Usage: </b><code>{@link AppSettings appSettings}.{@link HashMap#put(Object, Object) put}(VRConstants.SETTING_DEFAULT_FOV, value)</code>
|
||||
*/
|
||||
public static final String SETTING_DEFAULT_FOV = "VRDefaultFOV";
|
||||
|
||||
/**
|
||||
* An AppSettings parameter that set the default aspect ratio.
|
||||
* <b>Type: </b><code>float</code><br>
|
||||
* <b>Usage: </b><code>{@link AppSettings appSettings}.{@link HashMap#put(Object, Object) put}(VRConstants.SETTING_DEFAULT_ASPECT_RATIO, value)</code>
|
||||
*/
|
||||
public static final String SETTING_DEFAULT_ASPECT_RATIO = "VRDefaultAspectRatio";
|
||||
|
||||
/**
|
||||
* An AppSettings parameter that specifies the underlying VR API. Possible values are:<br>
|
||||
* <ul>
|
||||
* <li>{@link VRConstants#SETTING_VRAPI_OPENVR_VALUE SETTING_VRAPI_OPENVR_VALUE}: Use OpenVR binding.
|
||||
* <li>{@link VRConstants#SETTING_VRAPI_OSVR_VALUE SETTING_VRAPI_OSVR_VALUE}: Use OSVR binding.
|
||||
* <li>{@link VRConstants#SETTING_VRAPI_OPENVR_LWJGL_VALUE SETTING_VRAPI_OPENVR_LWJGL_VALUE}: Use OpenVR binding from LWJGL.
|
||||
* </ul>
|
||||
* <b>Type: </b><code>int</code><br>
|
||||
* <b>Usage: </b><code>{@link AppSettings appSettings}.{@link HashMap#put(Object, Object) put}(VRConstants.SETTING_VRAPI, value)</code>
|
||||
|
||||
*/
|
||||
public static final String SETTING_VRAPI = "VRAPI";
|
||||
|
||||
/**
|
||||
* The identifier of the OpenVR system.
|
||||
* @see #SETTING_VRAPI
|
||||
*/
|
||||
public static final int SETTING_VRAPI_OPENVR_VALUE = 1;
|
||||
|
||||
/**
|
||||
* The identifier of the OSVR system.
|
||||
* @see #SETTING_VRAPI
|
||||
*/
|
||||
public static final int SETTING_VRAPI_OSVR_VALUE = 2;
|
||||
|
||||
/**
|
||||
* The identifier of the OpenVR from LWJGL system.
|
||||
* @see #SETTING_VRAPI
|
||||
*/
|
||||
public static final int SETTING_VRAPI_OPENVR_LWJGL_VALUE = 3;
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -9,6 +9,7 @@ https://github.com/sensics/OSVR-RenderManager/blob/master/examples/RenderManager
|
||||
*/
|
||||
package com.jme3.input.vr;
|
||||
|
||||
import com.jme3.app.VRAppState;
|
||||
import com.jme3.app.VRApplication;
|
||||
import com.jme3.math.Matrix4f;
|
||||
import com.jme3.math.Quaternion;
|
||||
@ -110,14 +111,14 @@ public class OSVR implements VRAPI {
|
||||
boolean initSuccess = false;
|
||||
boolean flipEyes = false;
|
||||
|
||||
private VRApplication application = null;
|
||||
private VRAppState app = null;
|
||||
|
||||
/**
|
||||
* Create a new <a href="http://www.osvr.org/">OSVR</a> system attached to the given application.
|
||||
* @param application the application to which the input is attached.
|
||||
* Create a new <a href="http://www.osvr.org/">OSVR</a> system attached to the given {@link VRAppState app state}.
|
||||
* @param app the app state to which the input is attached.
|
||||
*/
|
||||
public OSVR(VRApplication application){
|
||||
this.application = application;
|
||||
public OSVR(VRAppState app){
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -149,7 +150,7 @@ public class OSVR implements VRAPI {
|
||||
|
||||
hmdPose.setAutoSynch(false);
|
||||
context = OsvrClientKitLibrary.osvrClientInit(defaultJString, 0);
|
||||
VRinput = new OSVRInput(application);
|
||||
VRinput = new OSVRInput(app);
|
||||
initSuccess = context != null && VRinput.init();
|
||||
if( initSuccess ) {
|
||||
PointerByReference grabDisplay = new PointerByReference();
|
||||
@ -462,8 +463,8 @@ public class OSVR implements VRAPI {
|
||||
}
|
||||
|
||||
@Override
|
||||
public VRApplication getApplication() {
|
||||
return application;
|
||||
public VRAppState getVRAppState() {
|
||||
return app;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@ package com.jme3.input.vr;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.jme3.app.VRAppState;
|
||||
import com.jme3.app.VRApplication;
|
||||
import com.jme3.math.Quaternion;
|
||||
import com.jme3.math.Vector2f;
|
||||
@ -63,7 +64,7 @@ public class OSVRInput implements VRInputAPI {
|
||||
private static final Vector2f lastCallAxis[] = new Vector2f[16];
|
||||
private static float axisMultiplier = 1f;
|
||||
|
||||
private VRApplication application = null;
|
||||
private VRAppState app = null;
|
||||
|
||||
/**
|
||||
* Get the system String that identifies a controller.
|
||||
@ -90,11 +91,11 @@ public class OSVRInput implements VRInputAPI {
|
||||
|
||||
|
||||
/**
|
||||
* Create a new <a href="http://www.osvr.org/">OSVR</a> input attached to the given application.
|
||||
* @param application the application to which the input is attached.
|
||||
* Create a new <a href="http://www.osvr.org/">OSVR</a> input attached to the given {@link VRAppState app state}.
|
||||
* @param app the app state to which the input is attached.
|
||||
*/
|
||||
public OSVRInput(VRApplication application){
|
||||
this.application = application;
|
||||
public OSVRInput(VRAppState app){
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
|
||||
@ -166,7 +167,7 @@ public class OSVRInput implements VRInputAPI {
|
||||
|
||||
private OSVR_ClientInterface getInterface(byte[] str) {
|
||||
PointerByReference pbr = new PointerByReference();
|
||||
OsvrClientKitLibrary.osvrClientGetInterface((OsvrClientKitLibrary.OSVR_ClientContext)application.getVRHardware().getVRSystem(), str, pbr);
|
||||
OsvrClientKitLibrary.osvrClientGetInterface((OsvrClientKitLibrary.OSVR_ClientContext)app.getVRHardware().getVRSystem(), str, pbr);
|
||||
return new OSVR_ClientInterface(pbr.getValue());
|
||||
}
|
||||
|
||||
@ -302,9 +303,9 @@ public class OSVRInput implements VRInputAPI {
|
||||
|
||||
@Override
|
||||
public Quaternion getFinalObserverRotation(int index) {
|
||||
VRViewManager vrvm = application.getVRViewManager();
|
||||
VRViewManager vrvm = app.getVRViewManager();
|
||||
if( vrvm == null || isInputDeviceTracking(index) == false ) return null;
|
||||
Object obs = application.getObserver();
|
||||
Object obs = app.getObserver();
|
||||
if( obs instanceof Camera ) {
|
||||
tempq.set(((Camera)obs).getRotation());
|
||||
} else {
|
||||
@ -315,9 +316,9 @@ public class OSVRInput implements VRInputAPI {
|
||||
|
||||
@Override
|
||||
public Vector3f getFinalObserverPosition(int index) {
|
||||
VRViewManager vrvm = application.getVRViewManager();
|
||||
VRViewManager vrvm = app.getVRViewManager();
|
||||
if( vrvm == null || isInputDeviceTracking(index) == false ) return null;
|
||||
Object obs = application.getObserver();
|
||||
Object obs = app.getObserver();
|
||||
Vector3f pos = getPosition(index);
|
||||
if( obs instanceof Camera ) {
|
||||
((Camera)obs).getRotation().mult(pos, pos);
|
||||
@ -350,8 +351,8 @@ public class OSVRInput implements VRInputAPI {
|
||||
|
||||
|
||||
@Override
|
||||
public VRApplication getApplication() {
|
||||
return application;
|
||||
public VRAppState getVRAppState() {
|
||||
return app;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
*/
|
||||
package com.jme3.input.vr;
|
||||
|
||||
import com.jme3.app.VRAppState;
|
||||
import com.jme3.app.VRApplication;
|
||||
import com.jme3.math.Matrix4f;
|
||||
import com.jme3.math.Quaternion;
|
||||
@ -83,14 +84,15 @@ public class OpenVR implements VRAPI {
|
||||
private static long frameCount;
|
||||
private static OpenVRInput VRinput;
|
||||
|
||||
private VRApplication application = null;
|
||||
private VRAppState app = null;
|
||||
|
||||
/**
|
||||
* Create a new <a href="https://github.com/ValveSoftware/openvr/wiki/API-Documentation">OpenVR</a> system attached to the given application.
|
||||
* @param application the application to which the input is attached.
|
||||
* Create a new <a href="https://github.com/ValveSoftware/openvr/wiki/API-Documentation">OpenVR</a> system
|
||||
* attached to the given {@link VRAppState VR app state}.
|
||||
* @param appState the VR app state to which the api is attached.
|
||||
*/
|
||||
public OpenVR(VRApplication application){
|
||||
this.application = application;
|
||||
public OpenVR(VRAppState appState){
|
||||
this.app = appState;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -178,7 +180,7 @@ public class OpenVR implements VRAPI {
|
||||
}
|
||||
|
||||
// init controllers for the first time
|
||||
VRinput = new OpenVRInput(application);
|
||||
VRinput = new OpenVRInput(app);
|
||||
VRinput.init();
|
||||
VRinput.updateConnectedControllers();
|
||||
|
||||
@ -204,7 +206,7 @@ public class OpenVR implements VRAPI {
|
||||
if(compositorFunctions != null && hmdErrorStore.getValue() == 0 ){
|
||||
compositorFunctions.setAutoSynch(false);
|
||||
compositorFunctions.read();
|
||||
if( application.isSeatedExperience() ) {
|
||||
if( app.isSeatedExperience() ) {
|
||||
compositorFunctions.SetTrackingSpace.apply(JOpenVRLibrary.ETrackingUniverseOrigin.ETrackingUniverseOrigin_TrackingUniverseSeated);
|
||||
} else {
|
||||
compositorFunctions.SetTrackingSpace.apply(JOpenVRLibrary.ETrackingUniverseOrigin.ETrackingUniverseOrigin_TrackingUniverseStanding);
|
||||
@ -354,7 +356,7 @@ public class OpenVR implements VRAPI {
|
||||
frameCount = nowCount;
|
||||
|
||||
vrsystemFunctions.GetDeviceToAbsoluteTrackingPose.apply(
|
||||
application.isSeatedExperience()?JOpenVRLibrary.ETrackingUniverseOrigin.ETrackingUniverseOrigin_TrackingUniverseSeated:
|
||||
app.isSeatedExperience()?JOpenVRLibrary.ETrackingUniverseOrigin.ETrackingUniverseOrigin_TrackingUniverseSeated:
|
||||
JOpenVRLibrary.ETrackingUniverseOrigin.ETrackingUniverseOrigin_TrackingUniverseStanding,
|
||||
fSecondsUntilPhotons, hmdTrackedDevicePoseReference, JOpenVRLibrary.k_unMaxTrackedDeviceCount);
|
||||
}
|
||||
@ -371,7 +373,7 @@ public class OpenVR implements VRAPI {
|
||||
VRInput._updateConnectedControllers();
|
||||
}*/
|
||||
//update controllers pose information
|
||||
application.getVRinput().updateControllerStates();
|
||||
app.getVRinput().updateControllerStates();
|
||||
|
||||
// read pose data from native
|
||||
for (int nDevice = 0; nDevice < JOpenVRLibrary.k_unMaxTrackedDeviceCount; ++nDevice ){
|
||||
@ -445,7 +447,7 @@ public class OpenVR implements VRAPI {
|
||||
|
||||
@Override
|
||||
public Vector3f getSeatedToAbsolutePosition() {
|
||||
if( application.isSeatedExperience() == false ) return Vector3f.ZERO;
|
||||
if( app.isSeatedExperience() == false ) return Vector3f.ZERO;
|
||||
if( hmdSeatToStand == null ) {
|
||||
hmdSeatToStand = new Vector3f();
|
||||
HmdMatrix34_t mat = vrsystemFunctions.GetSeatedZeroPoseToStandingAbsoluteTrackingPose.apply();
|
||||
@ -524,8 +526,8 @@ public class OpenVR implements VRAPI {
|
||||
}
|
||||
|
||||
@Override
|
||||
public VRApplication getApplication() {
|
||||
return application;
|
||||
public VRAppState getVRAppState() {
|
||||
return app;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.jme3.app.VRAppState;
|
||||
import com.jme3.app.VRApplication;
|
||||
import com.jme3.math.Quaternion;
|
||||
import com.jme3.math.Vector2f;
|
||||
@ -97,7 +98,7 @@ public class OpenVRInput implements VRInputAPI {
|
||||
|
||||
private final Quaternion tempq = new Quaternion();
|
||||
|
||||
private VRApplication application;
|
||||
private VRAppState app;
|
||||
|
||||
private List<VRTrackedController> trackedControllers = null;
|
||||
|
||||
@ -105,8 +106,8 @@ public class OpenVRInput implements VRInputAPI {
|
||||
* Create a new <a href="https://github.com/ValveSoftware/openvr/wiki/API-Documentation">OpenVR</a> input attached to the given application.
|
||||
* @param application the application to which the input is attached.
|
||||
*/
|
||||
public OpenVRInput(VRApplication application){
|
||||
this.application = application;
|
||||
public OpenVRInput(VRAppState appState){
|
||||
this.app = appState;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -296,7 +297,7 @@ public class OpenVRInput implements VRInputAPI {
|
||||
|
||||
@Override
|
||||
public boolean isInputFocused() {
|
||||
return ((VR_IVRSystem_FnTable)application.getVRHardware().getVRSystem()).IsInputFocusCapturedByAnotherProcess.apply() == 0;
|
||||
return ((VR_IVRSystem_FnTable)app.getVRHardware().getVRSystem()).IsInputFocusCapturedByAnotherProcess.apply() == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -326,9 +327,9 @@ public class OpenVRInput implements VRInputAPI {
|
||||
|
||||
@Override
|
||||
public Quaternion getFinalObserverRotation(int index) {
|
||||
VRViewManager vrvm = application.getVRViewManager();
|
||||
VRViewManager vrvm = app.getVRViewManager();
|
||||
if( vrvm == null || isInputDeviceTracking(index) == false ) return null;
|
||||
Object obs = application.getObserver();
|
||||
Object obs = app.getObserver();
|
||||
if( obs instanceof Camera ) {
|
||||
tempq.set(((Camera)obs).getRotation());
|
||||
} else {
|
||||
@ -339,9 +340,9 @@ public class OpenVRInput implements VRInputAPI {
|
||||
|
||||
@Override
|
||||
public Vector3f getFinalObserverPosition(int index) {
|
||||
VRViewManager vrvm = application.getVRViewManager();
|
||||
VRViewManager vrvm = app.getVRViewManager();
|
||||
if( vrvm == null || isInputDeviceTracking(index) == false ) return null;
|
||||
Object obs = application.getObserver();
|
||||
Object obs = app.getObserver();
|
||||
Vector3f pos = getPosition(index);
|
||||
if( obs instanceof Camera ) {
|
||||
((Camera)obs).getRotation().mult(pos, pos);
|
||||
@ -354,9 +355,9 @@ public class OpenVRInput implements VRInputAPI {
|
||||
|
||||
@Override
|
||||
public void triggerHapticPulse(int controllerIndex, float seconds) {
|
||||
if( application.isInVR() == false || isInputDeviceTracking(controllerIndex) == false ) return;
|
||||
if( app.isInVR() == false || isInputDeviceTracking(controllerIndex) == false ) return;
|
||||
// apparently only axis ID of 0 works
|
||||
((VR_IVRSystem_FnTable)application.getVRHardware().getVRSystem()).TriggerHapticPulse.apply(OpenVRInput.controllerIndex[controllerIndex],
|
||||
((VR_IVRSystem_FnTable)app.getVRHardware().getVRSystem()).TriggerHapticPulse.apply(OpenVRInput.controllerIndex[controllerIndex],
|
||||
0, (short)Math.round(3f * seconds / 1e-3f));
|
||||
}
|
||||
|
||||
@ -365,13 +366,13 @@ public class OpenVRInput implements VRInputAPI {
|
||||
logger.config("Updating connected controllers.");
|
||||
controllerCount = 0;
|
||||
for(int i=0;i<JOpenVRLibrary.k_unMaxTrackedDeviceCount;i++) {
|
||||
if( ((OpenVR)application.getVRHardware()).getVRSystem().GetTrackedDeviceClass.apply(i) == JOpenVRLibrary.ETrackedDeviceClass.ETrackedDeviceClass_TrackedDeviceClass_Controller ) {
|
||||
if( ((OpenVR)app.getVRHardware()).getVRSystem().GetTrackedDeviceClass.apply(i) == JOpenVRLibrary.ETrackedDeviceClass.ETrackedDeviceClass_TrackedDeviceClass_Controller ) {
|
||||
|
||||
String controllerName = "Unknown";
|
||||
String manufacturerName = "Unknown";
|
||||
try {
|
||||
controllerName = OpenVRUtil.getTrackedDeviceStringProperty(((OpenVR)application.getVRHardware()).getVRSystem(), i, JOpenVRLibrary.ETrackedDeviceProperty.ETrackedDeviceProperty_Prop_TrackingSystemName_String);
|
||||
manufacturerName = OpenVRUtil.getTrackedDeviceStringProperty(((OpenVR)application.getVRHardware()).getVRSystem(), i, JOpenVRLibrary.ETrackedDeviceProperty.ETrackedDeviceProperty_Prop_ManufacturerName_String);
|
||||
controllerName = OpenVRUtil.getTrackedDeviceStringProperty(((OpenVR)app.getVRHardware()).getVRSystem(), i, JOpenVRLibrary.ETrackedDeviceProperty.ETrackedDeviceProperty_Prop_TrackingSystemName_String);
|
||||
manufacturerName = OpenVRUtil.getTrackedDeviceStringProperty(((OpenVR)app.getVRHardware()).getVRSystem(), i, JOpenVRLibrary.ETrackedDeviceProperty.ETrackedDeviceProperty_Prop_ManufacturerName_String);
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.WARNING, e.getMessage(), e);
|
||||
}
|
||||
@ -393,7 +394,7 @@ public class OpenVRInput implements VRInputAPI {
|
||||
public void updateControllerStates() {
|
||||
for(int i=0;i<controllerCount;i++) {
|
||||
int index = controllerIndex[i];
|
||||
((OpenVR)application.getVRHardware()).getVRSystem().GetControllerState.apply(index, cStates[index], 5);
|
||||
((OpenVR)app.getVRHardware()).getVRSystem().GetControllerState.apply(index, cStates[index], 5);
|
||||
cStates[index].readField("ulButtonPressed");
|
||||
cStates[index].readField("rAxis");
|
||||
needsNewVelocity[index] = true;
|
||||
@ -402,8 +403,8 @@ public class OpenVRInput implements VRInputAPI {
|
||||
}
|
||||
|
||||
@Override
|
||||
public VRApplication getApplication() {
|
||||
return application;
|
||||
public VRAppState getVRAppState() {
|
||||
return app;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
*/
|
||||
package com.jme3.input.vr;
|
||||
|
||||
import com.jme3.app.VRApplication;
|
||||
import com.jme3.app.VRAppState;
|
||||
import com.jme3.math.Matrix4f;
|
||||
import com.jme3.math.Quaternion;
|
||||
import com.jme3.math.Vector2f;
|
||||
@ -33,10 +33,10 @@ public interface VRAPI {
|
||||
public boolean initVRCompositor(boolean allowed);
|
||||
|
||||
/**
|
||||
* Get the VR application to which this input is attached.
|
||||
* @return the VR application to which this input is attached.
|
||||
* Get the {@link VRAppState VR app state} to which this api is attached.
|
||||
* @return the VR app state to which this input is attached.
|
||||
*/
|
||||
public VRApplication getApplication();
|
||||
public VRAppState getVRAppState();
|
||||
|
||||
/**
|
||||
* Get the object that wraps natively the VR system.
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
*/
|
||||
package com.jme3.input.vr;
|
||||
|
||||
import com.jme3.app.VRAppState;
|
||||
import com.jme3.app.VRApplication;
|
||||
import com.jme3.math.Quaternion;
|
||||
import com.jme3.math.Vector2f;
|
||||
@ -197,8 +198,8 @@ public interface VRInputAPI {
|
||||
public void triggerHapticPulse(int controllerIndex, float seconds);
|
||||
|
||||
/**
|
||||
* Get the VR application to which this input is attached.
|
||||
* @return the VR application to which this input is attached.
|
||||
* Get the {@link VRAppState VR app state} to which this api is attached.
|
||||
* @return the VR app state to which this input is attached.
|
||||
*/
|
||||
public VRApplication getApplication();
|
||||
public VRAppState getVRAppState();
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
package jmevr.util;
|
||||
|
||||
import com.jme3.app.VRApplication;
|
||||
import com.jme3.input.vr.VRAPI;
|
||||
import com.jme3.scene.Mesh;
|
||||
import com.jme3.scene.VertexBuffer;
|
||||
import com.jme3.system.jopenvr.DistortionCoordinates_t;
|
||||
@ -17,7 +18,7 @@ import com.jme3.system.jopenvr.VR_IVRSystem_FnTable;
|
||||
*/
|
||||
public class MeshUtil {
|
||||
|
||||
public static Mesh setupDistortionMesh(int eye, VRApplication application) {
|
||||
public static Mesh setupDistortionMesh(int eye, VRAPI api) {
|
||||
Mesh distortionMesh = new Mesh();
|
||||
float m_iLensGridSegmentCountH = 43, m_iLensGridSegmentCountV = 43;
|
||||
|
||||
@ -45,7 +46,7 @@ public class MeshUtil {
|
||||
vertPos += 3;
|
||||
|
||||
DistortionCoordinates_t dc0 = new DistortionCoordinates_t();
|
||||
if( application.getVRHardware().getVRSystem() == null ) {
|
||||
if( api.getVRSystem() == null ) {
|
||||
// default to no distortion
|
||||
texcoordR[coordPos] = u;
|
||||
texcoordR[coordPos + 1] = 1 - v;
|
||||
@ -54,7 +55,7 @@ public class MeshUtil {
|
||||
texcoordB[coordPos] = u;
|
||||
texcoordB[coordPos + 1] = 1 - v;
|
||||
} else {
|
||||
((VR_IVRSystem_FnTable)application.getVRHardware().getVRSystem()).ComputeDistortion.apply(eye, u, v, dc0);
|
||||
((VR_IVRSystem_FnTable)api.getVRSystem()).ComputeDistortion.apply(eye, u, v, dc0);
|
||||
|
||||
texcoordR[coordPos] = dc0.rfRed[0];
|
||||
texcoordR[coordPos + 1] = 1 - dc0.rfRed[1];
|
||||
|
||||
@ -4,7 +4,10 @@
|
||||
*/
|
||||
package jmevr.util;
|
||||
|
||||
import com.jme3.app.Application;
|
||||
import com.jme3.app.VRAppState;
|
||||
import com.jme3.app.VRApplication;
|
||||
import com.jme3.app.state.AppState;
|
||||
import com.jme3.material.Material;
|
||||
import com.jme3.material.RenderState.BlendMode;
|
||||
import com.jme3.math.ColorRGBA;
|
||||
@ -24,6 +27,7 @@ import com.jme3.texture.Image.Format;
|
||||
import com.jme3.texture.Texture;
|
||||
import com.jme3.texture.Texture2D;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -44,22 +48,35 @@ public class VRGuiManager {
|
||||
private Vector2f screenSize;
|
||||
protected boolean wantsReposition;
|
||||
|
||||
private VRApplication application = null;
|
||||
private VRAppState app = null;
|
||||
private Application application = null;
|
||||
|
||||
/**
|
||||
* Create a new GUI manager attached to the given application.
|
||||
* @param application the VR application that this manager is attached to.
|
||||
* Create a new GUI manager attached to the given app state.
|
||||
* @param app the VR app state that this manager is attached to.
|
||||
*/
|
||||
public VRGuiManager(VRApplication application){
|
||||
this.application = application;
|
||||
public VRGuiManager(){
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the VR application to which this GUI manager is attached.
|
||||
* @return the VR application to which this GUI manager is attached.
|
||||
* Get the VR app state to which this GUI manager is attached.
|
||||
* @return the VR app state to which this GUI manager is attached.
|
||||
*/
|
||||
public VRApplication getApplication(){
|
||||
return application;
|
||||
public VRAppState getVRAppState(){
|
||||
return app;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach the GUI manager to an app state and an Application.
|
||||
* The application has to be the one that the app state is attached.
|
||||
* This method should be called from the {@link AppState#initialize(com.jme3.app.state.AppStateManager, Application) initialize}
|
||||
* method of the {@link AppState} instance.
|
||||
* @param app the VR app state that this manager is attached to.
|
||||
* @param application the application to whitch the app state is attcached.
|
||||
*/
|
||||
public void attach(VRAppState app, Application application){
|
||||
this.app = app;
|
||||
this.application = application;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -84,10 +101,10 @@ public class VRGuiManager {
|
||||
|
||||
public Vector2f getCanvasSize() {
|
||||
if( screenSize == null ) {
|
||||
if( application.isInVR() && application.getVRHardware() != null ) {
|
||||
if( app.isInVR() && app.getVRHardware() != null ) {
|
||||
screenSize = new Vector2f();
|
||||
application.getVRHardware().getRenderSize(screenSize);
|
||||
screenSize.multLocal(application.getVRViewManager().getResolutionMuliplier());
|
||||
app.getVRHardware().getRenderSize(screenSize);
|
||||
screenSize.multLocal(app.getVRViewManager().getResolutionMuliplier());
|
||||
} else {
|
||||
AppSettings as = application.getContext().getSettings();
|
||||
screenSize = new Vector2f(as.getWidth(), as.getHeight());
|
||||
@ -127,7 +144,7 @@ public class VRGuiManager {
|
||||
guiPos.set(0f, 0f, guiDistance);
|
||||
dir.mult(guiPos, guiPos);
|
||||
guiPos.x += pos.x;
|
||||
guiPos.y += pos.y + application.getVRHeightAdjustment();
|
||||
guiPos.y += pos.y + app.getVRHeightAdjustment();
|
||||
guiPos.z += pos.z;
|
||||
if( guiPositioningElastic > 0f && posMode != POSITIONING_MODE.MANUAL ) {
|
||||
// mix pos & dir with current pos & dir
|
||||
@ -142,7 +159,7 @@ public class VRGuiManager {
|
||||
|
||||
protected void positionGuiNow(float tpf) {
|
||||
wantsReposition = false;
|
||||
if( application.isInVR() == false ) return;
|
||||
if( app.isInVR() == false ) return;
|
||||
guiQuadNode.setLocalScale(guiDistance * guiScale * 4f, 4f * guiDistance * guiScale, 1f);
|
||||
|
||||
switch( posMode ) {
|
||||
@ -158,7 +175,7 @@ public class VRGuiManager {
|
||||
|
||||
break;
|
||||
case AUTO_OBSERVER_POS_CAM_ROTATION:
|
||||
Object obs = application.getObserver();
|
||||
Object obs = app.getObserver();
|
||||
if( obs != null ) {
|
||||
if( obs instanceof Camera ) {
|
||||
positionTo(((Camera)obs).getLocation(), camLeft.getRotation(), tpf);
|
||||
@ -171,7 +188,7 @@ public class VRGuiManager {
|
||||
break;
|
||||
case AUTO_OBSERVER_ALL:
|
||||
case AUTO_OBSERVER_ALL_CAMHEIGHT:
|
||||
obs = application.getObserver();
|
||||
obs = app.getObserver();
|
||||
if( obs != null ) {
|
||||
Quaternion q;
|
||||
if( obs instanceof Camera ) {
|
||||
@ -230,7 +247,7 @@ public class VRGuiManager {
|
||||
}
|
||||
|
||||
protected void setupGui(Camera leftcam, Camera rightcam, ViewPort left, ViewPort right) {
|
||||
if( application.hasTraditionalGUIOverlay() ) {
|
||||
if( app.hasTraditionalGUIOverlay() ) {
|
||||
camLeft = leftcam;
|
||||
camRight = rightcam;
|
||||
Spatial guiScene = getGuiQuad(camLeft);
|
||||
@ -259,6 +276,7 @@ public class VRGuiManager {
|
||||
private Node guiQuadNode;
|
||||
private ViewPort offView;
|
||||
private Texture2D guiTexture;
|
||||
|
||||
private Spatial getGuiQuad(Camera sourceCam){
|
||||
if( guiQuadNode == null ) {
|
||||
Vector2f guiCanvasSize = getCanvasSize();
|
||||
@ -287,7 +305,11 @@ public class VRGuiManager {
|
||||
offView.setOutputFrameBuffer(offBuffer);
|
||||
|
||||
// setup framebuffer's scene
|
||||
offView.attachScene(application.getGuiNode());
|
||||
Iterator<Spatial> spatialIter = application.getGuiViewPort().getScenes().iterator();
|
||||
while(spatialIter.hasNext()){
|
||||
offView.attachScene(spatialIter.next());
|
||||
}
|
||||
|
||||
|
||||
if( useCurvedSurface ) {
|
||||
guiQuad = (Geometry)application.getAssetManager().loadModel("Common/Util/gui_mesh.j3o");
|
||||
|
||||
@ -5,9 +5,15 @@
|
||||
*/
|
||||
package jmevr.util;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import com.jme3.app.Application;
|
||||
import com.jme3.app.VRAppState;
|
||||
import com.jme3.app.VRApplication;
|
||||
import com.jme3.app.state.AppState;
|
||||
import com.jme3.input.MouseInput;
|
||||
import com.jme3.input.controls.AnalogListener;
|
||||
import com.jme3.input.lwjgl.GlfwMouseInputVR;
|
||||
@ -16,6 +22,7 @@ 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.system.lwjgl.LwjglWindowVR;
|
||||
import com.jme3.texture.Texture;
|
||||
import com.jme3.texture.Texture2D;
|
||||
@ -29,8 +36,9 @@ public class VRMouseManager {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(VRMouseManager.class.getName());
|
||||
|
||||
private VRApplication application = null;
|
||||
|
||||
private Application application = null;
|
||||
private VRAppState app = null;
|
||||
|
||||
private final int AVERAGE_AMNT = 4;
|
||||
private int avgCounter;
|
||||
|
||||
@ -48,16 +56,20 @@ public class VRMouseManager {
|
||||
return amt / arr.length;
|
||||
}
|
||||
|
||||
public VRMouseManager(VRApplication application){
|
||||
this.application = application;
|
||||
public VRMouseManager(){
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the VR application to which this mouse manager is attached.
|
||||
* @return the VR application to which this mouse manager is attached.
|
||||
* Attach the mouse manager to an app state and an Application.
|
||||
* The application has to be the one that the app state is attached.
|
||||
* This method should be called from the {@link AppState#initialize(com.jme3.app.state.AppStateManager, Application) initialize}
|
||||
* method of the {@link AppState} instance.
|
||||
* @param app the VR app state that this manager is attached to.
|
||||
* @param application the application to whitch the app state is attcached.
|
||||
*/
|
||||
public VRApplication getApplication(){
|
||||
return application;
|
||||
public void attach(VRAppState app, Application application){
|
||||
this.app = app;
|
||||
this.application = application;
|
||||
}
|
||||
|
||||
protected void init() {
|
||||
@ -73,6 +85,8 @@ public class VRMouseManager {
|
||||
((GlfwMouseInputVR)mi).hideActiveCursor();
|
||||
}
|
||||
centerMouse();
|
||||
|
||||
logger.config("Initialized VR mouse manager [SUCCESS]");
|
||||
}
|
||||
|
||||
public void setThumbstickMode(boolean set) {
|
||||
@ -101,7 +115,7 @@ public class VRMouseManager {
|
||||
}
|
||||
|
||||
public void setImage(String texture) {
|
||||
if( application.isInVR() == false ){
|
||||
if( app.isInVR() == false ){
|
||||
Texture tex = application.getAssetManager().loadTexture(texture);
|
||||
mouseImage.setTexture(application.getAssetManager(), (Texture2D)tex, true);
|
||||
ySize = tex.getImage().getHeight();
|
||||
@ -123,14 +137,14 @@ public class VRMouseManager {
|
||||
|
||||
public void updateAnalogAsMouse(int inputIndex, AnalogListener mouseListener, String mouseXName, String mouseYName, float tpf) {
|
||||
// got a tracked controller to use as the "mouse"
|
||||
if( application.isInVR() == false ||
|
||||
application.getVRinput() == null ||
|
||||
application.getVRinput().isInputDeviceTracking(inputIndex) == false ) return;
|
||||
if( app.isInVR() == false ||
|
||||
app.getVRinput() == null ||
|
||||
app.getVRinput().isInputDeviceTracking(inputIndex) == false ) return;
|
||||
Vector2f tpDelta;
|
||||
if( thumbstickMode ) {
|
||||
tpDelta = application.getVRinput().getAxis(inputIndex, VRInputType.ViveTrackpadAxis);
|
||||
tpDelta = app.getVRinput().getAxis(inputIndex, VRInputType.ViveTrackpadAxis);
|
||||
} else {
|
||||
tpDelta = application.getVRinput().getAxisDeltaSinceLastCall(inputIndex, VRInputType.ViveTrackpadAxis);
|
||||
tpDelta = app.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);
|
||||
@ -147,7 +161,7 @@ public class VRMouseManager {
|
||||
lastYmv[index] = Yamount * 133f;
|
||||
cursorPos.x -= avg(lastXmv);
|
||||
cursorPos.y -= avg(lastYmv);
|
||||
Vector2f maxsize = application.getVRGUIManager().getCanvasSize();
|
||||
Vector2f maxsize = app.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;
|
||||
@ -156,7 +170,7 @@ public class VRMouseManager {
|
||||
}
|
||||
|
||||
public Vector2f getCursorPosition() {
|
||||
if( application.isInVR() ) {
|
||||
if( app.isInVR() ) {
|
||||
return cursorPos;
|
||||
}
|
||||
return application.getInputManager().getCursorPosition();
|
||||
@ -164,11 +178,11 @@ public class VRMouseManager {
|
||||
|
||||
public void centerMouse() {
|
||||
// set mouse in center of the screen if newly added
|
||||
Vector2f size = application.getVRGUIManager().getCanvasSize();
|
||||
Vector2f size = app.getVRGUIManager().getCanvasSize();
|
||||
MouseInput mi = application.getContext().getMouseInput();
|
||||
AppSettings as = application.getContext().getSettings();
|
||||
if( mi instanceof GlfwMouseInputVR ) ((GlfwMouseInputVR)mi).setCursorPosition((int)(as.getWidth() / 2f), (int)(as.getHeight() / 2f));
|
||||
if( application.isInVR() ) {
|
||||
if( app.isInVR() ) {
|
||||
cursorPos.x = size.x / 2f;
|
||||
cursorPos.y = size.y / 2f;
|
||||
recentCenterCount = 2;
|
||||
@ -180,11 +194,13 @@ public class VRMouseManager {
|
||||
|
||||
if( application.getInputManager().isCursorVisible() ) {
|
||||
if( mouseImage.getParent() == null ) {
|
||||
application.getGuiNode().attachChild(mouseImage);
|
||||
|
||||
application.getGuiViewPort().attachScene(mouseImage);
|
||||
centerMouse();
|
||||
// the "real" mouse pointer should stay hidden
|
||||
org.lwjgl.glfw.GLFW.glfwSetInputMode(((LwjglWindowVR)application.getContext()).getWindowHandle(),
|
||||
org.lwjgl.glfw.GLFW.GLFW_CURSOR, org.lwjgl.glfw.GLFW.GLFW_CURSOR_DISABLED);
|
||||
if (application.getContext() instanceof LwjglWindow){
|
||||
GLFW.glfwSetInputMode(((LwjglWindow)application.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 = application.getContext().getMouseInput();
|
||||
@ -195,21 +211,24 @@ public class VRMouseManager {
|
||||
cursorPos.y += ((GlfwMouseInputVR)mi).getLastDeltaY();// * winratio.y;
|
||||
if( cursorPos.x < 0f ) cursorPos.x = 0f;
|
||||
if( cursorPos.y < 0f ) cursorPos.y = 0f;
|
||||
if( cursorPos.x > application.getVRGUIManager().getCanvasSize().x ) cursorPos.x = application.getVRGUIManager().getCanvasSize().x;
|
||||
if( cursorPos.y > application.getVRGUIManager().getCanvasSize().y ) cursorPos.y = application.getVRGUIManager().getCanvasSize().y;
|
||||
if( cursorPos.x > app.getVRGUIManager().getCanvasSize().x ) cursorPos.x = app.getVRGUIManager().getCanvasSize().x;
|
||||
if( cursorPos.y > app.getVRGUIManager().getCanvasSize().y ) cursorPos.y = app.getVRGUIManager().getCanvasSize().y;
|
||||
} else recentCenterCount--;
|
||||
((GlfwMouseInputVR)mi).clearDeltas();
|
||||
}
|
||||
// ok, update the cursor graphic position
|
||||
Vector2f currentPos = getCursorPosition();
|
||||
mouseImage.setLocalTranslation(currentPos.x, currentPos.y - ySize, application.getVRGUIManager().getGuiDistance() + 1f);
|
||||
mouseImage.setLocalTranslation(currentPos.x, currentPos.y - ySize, app.getVRGUIManager().getGuiDistance() + 1f);
|
||||
|
||||
mouseImage.updateGeometricState();
|
||||
mouseImage.getParent().updateGeometricState();
|
||||
|
||||
} else if( mouseImage.getParent() != null ) {
|
||||
Node n = mouseImage.getParent();
|
||||
mouseImage.removeFromParent();
|
||||
n.updateGeometricState();
|
||||
|
||||
if (n != null){
|
||||
n.updateGeometricState();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user