Oculus Rift Support

@HaihaoZhang, are you sure you are initializing the library in a static context outside of your app (e.g. in the main() function)? Take a look at the wiki on the SVN for more:

http://code.google.com/p/jmonkeyengine-oculus-rift/wiki/HowTo

The Oculus Rift SDK has been updated to 0.4.0 to support the DK2. However, there isn’t a Linux or Mac download available yet. @jherico did update JOVR to support this release:

https://developer.oculusvr.com/forums/viewtopic.php?f=20&t=11149&p=148068

… however, I"m going to wait until a Linux version becomes available (since I’m developing on Linux and can’t test anything anyway). There are also some promised updates coming to improve juddering & “true black smear” that should be in any SDK update.

My DK2 arrives today and I was really hoping to give it a go on a jmonkey project (on Windows). I’ll keep my fingers crossed that the Linux flavor arrives soon.

@phr00t said: @HaihaoZhang, are you sure you are initializing the library in a static context outside of your app (e.g. in the main() function)? Take a look at the wiki on the SVN for more:

http://code.google.com/p/jmonkeyengine-oculus-rift/wiki/HowTo

The Oculus Rift SDK has been updated to 0.4.0 to support the DK2. However, there isn’t a Linux or Mac download available yet. @jherico did update JOVR to support this release:

https://developer.oculusvr.com/forums/viewtopic.php?f=20&t=11149&p=148068

… however, I"m going to wait until a Linux version becomes available (since I’m developing on Linux and can’t test anything anyway). There are also some promised updates coming to improve juddering & “true black smear” that should be in any SDK update.

Hi

Thanks for your help,I am initializing the library in the main () function, but I don’t really understand what you mean by outside my app?
This is my main function.

public static void main(String args)
{
try
{

		// load logger configuration file
		PropertyConfigurator.configure("assets/JasperReports/log4j/log4j.properties");
		
		/*
		logger.debug("Sample debug message");
		logger.info("Sample info message");
		logger.warn("Sample warn message");
		logger.error("Sample error message");
		logger.fatal("Sample fatal message");
		*/
	
		// only show severe jme3-logs
		java.util.logging.Logger.getLogger("").setLevel(java.util.logging.Level.SEVERE);
		
    	Simulator sim = new Simulator();
	   // these two lines below are important before app starts
	    OculusRift.initialize();
	    sim.guiNode = new OculusGuiNode();
	    OVRAppState ovrAppState = new OVRAppState( (OculusGuiNode)sim.guiNode);
	    sim.stateManager.attach(ovrAppState);
	    Spatial observer = new Node("Observer");
	    observer.addControl(ovrAppState.getCameraControl());
	    sim.rootNode.attachChild(observer);
	    
	    OculusRift.getAppState().getGuiNode().setPositioningMode(POSITIONING_MODE.AUTO);
	    OculusRift.getAppState().getGuiNode().setGuiDistance(0.8f); 

    	if(args.length >= 1)
    	{
    		if(DrivingTask.isValidDrivingTask(new File(args[0])))
    		{
    			SimulationDefaults.drivingTaskFileName = args[0];
    			sim.drivingTaskGiven = true;
    		}
    	}

    	if(args.length >= 2)
    	{
    		SimulationDefaults.driverName = args[1];
    	}
		
    	AppSettings settings = new AppSettings(false);
        settings.setUseJoysticks(true);
        settings.setSettingsDialogImage("OpenDS.png");
        settings.setTitle("OpenDS");
        
        // set splash screen parameters
        /*
        settings.setFullscreen(false);
        settings.setResolution(1280, 720);
        settings.setSamples(4);
        settings.setBitsPerPixel(24);
        settings.setVSync(false);
        settings.setFrequency(60);
        */
        
		sim.setSettings(settings);

		// TODO show/hide splash screen
		//sim.setShowSettings(false);
		
		sim.setPauseOnLostFocus(false);
		
		sim.start();
	}
	catch(Exception e1)
	{
		logger.fatal("Could not run main method:", e1);
	}
}

[java]OVRAppState ovrAppState = new OVRAppState( (OculusGuiNode)sim.guiNode);
sim.stateManager.attach(ovrAppState);
Spatial observer = new Node(“Observer”);
observer.addControl(ovrAppState.getCameraControl());
sim.rootNode.attachChild(observer);

OculusRift.getAppState().getGuiNode().setPositioningMode(POSITIONING_MODE.AUTO);
OculusRift.getAppState().getGuiNode().setGuiDistance(0.8f);[/java]

… this stuff I wouldn’t do until after your application starts (e.g. inside simpleInitApp()). You should only do

[java]OculusRift.initialize();
sim.guiNode = new OculusGuiNode();[/java]

… before your sim.start(); call. This might be the problem… I’ll update the wiki.

@HaihaoZhang said: Hi

Thanks for your help,I am initializing the library in the main () function, but I don’t really understand what you mean by outside my app?
This is my main function.
[snip]

For future reference:

Paging @rickard, I could really use your help! I’m trying to push the FOV a bit using the SDK-side distortion filter, and I’m having trouble with the texture buffer size (which should be increasing with a larger FOV).

In this code,

[java]@Override
protected void initFilter(AssetManager manager, RenderManager renderManager, ViewPort vp, int w, int h) {
material = new Material(manager, “oculusvr/shaders/Oculus.j3md”);

    Matrix4f projMat = OculusRiftUtil.toMatrix4f(Hmd.getPerspectiveProjection(
            eyeRenderDesc.Fov, 0.1f, 1000000f, true));
    
    vp.getCamera().setProjectionMatrix(projMat);
    TextureHeader eth = eyeTexture.Header;        
    eth.TextureSize = hmd.getFovTextureSize(eyeIndex, eyeRenderDesc.Fov, 1.0f);
    
    eth.TextureSize.h = 1; // debug set to 1
    eth.TextureSize.w = 1; // debug set to 1
    
    eth.RenderViewport.Size = eth.TextureSize;
    eth.RenderViewport.Pos = new OvrVector2i(0, 0);
}[/java]

… I’m trying to set the texture size given a certain FoV passed to getFovTextureSize(…). However, the result of that function doesn’t seem to matter, since I set if I later set the width & height to 1 (as seen above), nothing changes. However, if I set it to 0, all that renders is a solid brown color. The values that come out of getFovTextureSize(…) is h: 2705, w: 1257, which is no different than h: 1 & w: 1. This matters, because as FoV goes up, the texture size to support that FoV should go up too. The center of the image gets fuzzy when the FOV gets increased, and @jherico suggested it is because the Texture buffer isn’t being sized up.

Here is the image showing the comparison of the normal FOV & the increased FOV:

I asked @jherico, and he suggested these two things:

  1. Take a look at the code where the framebuffer textures are allocated and make sure they’re respecting the depth values passed back by the texture size function
  2. Make sure that after you bind the framebuffer you’re calling glViewport with the appropriate size

… but I am getting in a little over my head. Any help by anyone would be appreciated!

@pspeed said: For future reference:

ok sure, thanks for the tip xD.

@phr00t said: [java]OVRAppState ovrAppState = new OVRAppState( (OculusGuiNode)sim.guiNode); sim.stateManager.attach(ovrAppState); Spatial observer = new Node(“Observer”); observer.addControl(ovrAppState.getCameraControl()); sim.rootNode.attachChild(observer);

OculusRift.getAppState().getGuiNode().setPositioningMode(POSITIONING_MODE.AUTO);
OculusRift.getAppState().getGuiNode().setGuiDistance(0.8f);[/java]

… this stuff I wouldn’t do until after your application starts (e.g. inside simpleInitApp()). You should only do

[java]OculusRift.initialize();
sim.guiNode = new OculusGuiNode();[/java]

… before your sim.start(); call. This might be the problem… I’ll update the wiki.

Thanks a lot for your help, I have placed all those code into simpleInitApp(), yet I still get the same error.
I have the simpleInitApp() method attached.

[java] @Override
public void simpleInitApp()
{

    OVRAppState ovrAppState = new OVRAppState( (OculusGuiNode)guiNode);
    stateManager.attach(ovrAppState);
    Spatial observer = new Node("Observer");
    observer.addControl(ovrAppState.getCameraControl());
    rootNode.attachChild(observer);
    
    
    OculusRift.getAppState().getGuiNode().setPositioningMode(POSITIONING_MODE.AUTO);
    OculusRift.getAppState().getGuiNode().setGuiDistance(0.8f); 
    
	showStats(false);
	
	if(drivingTaskGiven)
		simpleInitDrivingTask(SimulationDefaults.drivingTaskFileName, SimulationDefaults.driverName);
	else
		initDrivingTaskSelectionGUI();
}[/java] 

Any help would be much appreciated.
Thanks

@HaihaoZhang

This looks like it’s not running the postFilter function in the oculusvr,post.OculusFilter class. The most likely reason is that you’re not running nightly, the normal download of jme3 doesn’t have this method in com.jme3.post.Filter. I’m not sure why netbeans doesn’t throw an error with the @Override annotation there, but it seems to ignore it.

@wildcard0 said: @HaihaoZhang

This looks like it’s not running the postFilter function in the oculusvr,post.OculusFilter class. The most likely reason is that you’re not running nightly, the normal download of jme3 doesn’t have this method in com.jme3.post.Filter. I’m not sure why netbeans doesn’t throw an error with the @Override annotation there, but it seems to ignore it.

I have downloaded the .jar files that have been provided and I believe that method is in the JMonkeyOculusRift.jar if I’m not mistaken and I have added them to the build path.

But thanks for the help.

Hi guys

So what I have done was trying it on a different computer and I started getting a new error.
I have initialised the oculus rift in a static context and the rest of the code in simpleInitApp().

com.jme3.app.Application handleError
SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]
java.lang.Error: Invalid memory access
at com.sun.jna.Native.invokeInt(Native Method)
at com.sun.jna.Function.invoke(Function.java:374)
at com.sun.jna.Function.invoke(Function.java:315)
at com.sun.jna.Library$Handler.invoke(Library.java:212)
at sun.proxy.$Proxy0.ovrHmd_ConfigureRendering(Unknown Source)
at com.oculusvr.capi.Hmd.configureRendering(Hmd.java:126)
at oculusvr.util.OculusRiftUtil.configureRendering(OculusRiftUtil.java:41)
at oculusvr.input.OculusRift.initRendering(OculusRift.java:63)
at oculusvr.state.OVRAppState.initialize(OVRAppState.java:117)
at com.jme3.app.state.AppStateManager.initializePending(AppStateManager.java:251)
at com.jme3.app.state.AppStateManager.update(AppStateManager.java:281)
at com.jme3.app.SimpleApplication.update(SimpleApplication.java:239)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:151)
at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:185)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:228)
at java.lang.Thread.run(Unknown Source)

AL lib: (EE) alc_cleanup: 1 device not closed

Exception: java.lang.Error thrown from the UncaughtExceptionHandler in thread “LWJGL Renderer Thread”

Any help would be much appreciated.
Thank you

@phr00t said: Paging @rickard, I could really use your help! I'm trying to push the FOV a bit using the SDK-side distortion filter, and I'm having trouble with the texture buffer size (which should be increasing with a larger FOV).

Hi.

I’ve been out of town, so I haven’t had the opportunity to look at this. I’ll see if I have any ideas hopefully later today.

@HaihaoZhang said: I have downloaded the .jar files that have been provided and I believe that method is in the JMonkeyOculusRift.jar if I'm not mistaken and I have added them to the build path.

But thanks for the help.

Take a look at com.jme3.post.Filter and see if the postFilter method exists in that class.

@wildcard0 said: Take a look at com.jme3.post.Filter and see if the postFilter method exists in that class.

Hi I have just double checked and the postFilter method does exist in the class.

Thanks

@phr00t said: ... I'm trying to set the texture size given a certain FoV passed to getFovTextureSize(...). However, the result of that function doesn't seem to matter, since I set if I later set the width & height to 1 (as seen above), nothing changes. However, if I set it to 0, all that renders is a solid brown color. The values that come out of getFovTextureSize(...) is h: 2705, w: 1257, which is no different than h: 1 & w: 1. This matters, because as FoV goes up, the texture size to support that FoV should go up too. The center of the image gets fuzzy when the FOV gets increased, and @jherico suggested it is because the Texture buffer isn't being sized up.

I asked @jherico, and he suggested these two things:

  1. Take a look at the code where the framebuffer textures are allocated and make sure they’re respecting the depth values passed back by the texture size function
  2. Make sure that after you bind the framebuffer you’re calling glViewport with the appropriate size

… but I am getting in a little over my head. Any help by anyone would be appreciated!

Sorry for the late reply. I’m on vacation and haven’t spent much time with this.

Hmm, I’m a bit unsure of the flow you’re doing this in. But let’s discuss it to make sure we’re on the same page.

FOV is retrieved from the HMD in OculusRiftUtil in this method:

[java]public static EyeRenderDesc configureRendering(Hmd hmd, HmdDesc hmdDesc, int width, int height, int samples) {
EyeRenderDesc configureResult;

    FovPort fovPorts[] = (FovPort[]) new FovPort().toArray(2);
    fovPorts[0] = hmdDesc.DefaultEyeFov[0];
    fovPorts[1] = hmdDesc.DefaultEyeFov[1];[/java]

TextureHeader creates a link between the texture id between the application and hmd in the opengl context. It might be that the filter does not update the texture size post creation.

The problem you’re facing. Does it happen when changing fov in run time, or also when changin it during initialization?

Also, I’m not 100% sure the problem is with the texture size, it could also be the projection matrix.
It seems like an issue I had when creating the filter in the first place.

@HaihaoZhang said: Hi I have just double checked and the postFilter method does exist in the class.

Thanks

Have you run any of the tests? Do they work?

@rickard said: Have you run any of the tests? Do they work?

Thanks for the reply and yes I have run the tests but I get the same error.

Thank you
Haihao Zhang

@rickard said: Sorry for the late reply. I'm on vacation and haven't spent much time with this.

Hmm, I’m a bit unsure of the flow you’re doing this in. But let’s discuss it to make sure we’re on the same page.

FOV is retrieved from the HMD in OculusRiftUtil in this method:

[java]public static EyeRenderDesc configureRendering(Hmd hmd, HmdDesc hmdDesc, int width, int height, int samples) {
EyeRenderDesc configureResult;

    FovPort fovPorts[] = (FovPort[]) new FovPort().toArray(2);
    fovPorts[0] = hmdDesc.DefaultEyeFov[0];
    fovPorts[1] = hmdDesc.DefaultEyeFov[1];[/java]

TextureHeader creates a link between the texture id between the application and hmd in the opengl context. It might be that the filter does not update the texture size post creation.

The problem you’re facing. Does it happen when changing fov in run time, or also when changin it during initialization?

I’m changing the FOV during initialization. I notice there is some pixelation even at the default FOV settings. My guess at what is happening: the viewports are rendered at half of whatever the window size is (e.g. 512x768) since that is the normal behavior, and the SDK-side distortion filter operates on that texture and distorts it. However, it wants a much higher resolution original image to work with, so when it enlarges the center, the result is still clear. Somehow, we need to render a larger texture than the window, have it distorted by the post filter, then scale to fit the window size. Not sure how to go about this, though :-/

Still awaiting a Linux SDK release to update this library…

@phr00t said: I'm changing the FOV during initialization. I notice there is some pixelation even at the default FOV settings. My guess at what is happening: the viewports are rendered at half of whatever the window size is (e.g. 512x768) since that is the normal behavior, and the SDK-side distortion filter operates on that texture and distorts it. However, it wants a much higher resolution original image to work with, so when it enlarges the center, the result is still clear. Somehow, we need to render a larger texture than the window, have it distorted by the post filter, then scale to fit the window size. Not sure how to go about this, though :-/

Still awaiting a Linux SDK release to update this library…

Ok, I tested it myself and now I see the problem.
I’m pretty sure what we need to do is modify the projection matrix for the viewport:
[java]Matrix4f projMat = OculusRiftUtil.toMatrix4f(Hmd.getPerspectiveProjection(
eyeRenderDesc.Fov, 0.01f, 1000000f, true));[/java]

Processing…

No, I’m not sure of that anymore.