Oculus Rift Support

Ok. Here’s my new theory:

The architecture should be changed so that the Oculus is using a SceneProcessor rather than a Post Filter.
This would give us more control and makes sense as well, since we want the distortion to happen as early as possible anyway.

@rickard said: since we want the distortion to happen as early as possible anyway.

Hi, i have to say that i have no clue at all how the oculus stuff works, but:

If you distort the scene before the postprocessing, wouldnt that cause all default filters to output ‘wrong’ data? Like some are depending on the original depthmap, or even the gaussian blur would not take the distortion into account…

@zzuegg said: Hi, i have to say that i have no clue at all how the oculus stuff works, but:

If you distort the scene before the postprocessing, wouldnt that cause all default filters to output ‘wrong’ data? Like some are depending on the original depthmap, or even the gaussian blur would not take the distortion into account…

Yeah, maybe I’m remembering it backwards. It’s been too long :frowning:

Back to the original problem:
When printing the resulting EyeRenderDesc coming from hmd.configureRendering (in OculusRiftUtil) it seems the results are always the same for some of the fields:

[java]OvrRecti DistortedViewport@14=OvrRecti(allocated@0x13f95554 (16 bytes) (shared from allocated@0x13f95540 (56 bytes) (shared from auto-allocated@0x13f95540 (112 bytes)))) {
OvrVector2i Pos@0=OvrVector2i(allocated@0x13f95554 (8 bytes) (shared from allocated@0x13f95554 (16 bytes) (shared from allocated@0x13f95540 (56 bytes) (shared from auto-allocated@0x13f95540 (112 bytes))))) {
int x@0=0
int y@4=0
}
OvrSizei Size@8=OvrSizei(allocated@0x13f9555c (8 bytes) (shared from allocated@0x13f95554 (16 bytes) (shared from allocated@0x13f95540 (56 bytes) (shared from auto-allocated@0x13f95540 (112 bytes))))) {
int w@0=280
int h@4=320
}
}
OvrVector2f PixelsPerTanAngleAtCenter@24=OvrVector2f(allocated@0x13f95564 (8 bytes) (shared from allocated@0x13f95540 (56 bytes) (shared from auto-allocated@0x13f95540 (112 bytes)))) {
float x@0=363.15085
float y@4=363.24783
}[/java]

No matter what values i set for the fov ports or RT size, these values remain the same. Might that be related?

Spent quite some time yesterday, trying to solve this. I really can’t find out what the problem is. Implementation looks OK when comparing with docs.
One thing i noticed: If you have a skybox, it isn’t affected in the same way as other items, ie, the texture doesn’t seem to be jagged or blurred(?)

@rickard said: Spent quite some time yesterday, trying to solve this. I really can't find out what the problem is. Implementation looks OK when comparing with docs. One thing i noticed: If you have a skybox, it isn't affected in the same way as other items, ie, the texture doesn't seem to be jagged or blurred(?)

I figured out the main problem with texture blurring:

… it is anisotropic filtering. Once you enable a sufficient amount of anisotropic filtering, the texture no longer gets blurred. We’ll have to tell developers that anisotropic filtering is a must.

However, there is still a decent amount of pixelation happening near the center. Notice the jagged line along the roof in the center, but no jagged edges on the smaller roof at the bottom. My guess is this is still happening because it is stretching the originally rendered scene at the window size when the scene needs to be rendered at a higher resolution before being stretched. I might be wrong, though…

Also, @rickard, maybe we need to create a new render pass at a higher resolution? Or, maybe we can just modify the existing rendering passes at a higher resolution? Here is an example of a filter with new passes and you can see the resolution being provided as arguments – maybe we need to pass the result of the Oculus Rift FoV texture size function as a new/existing pass width & height?

http://hub.jmonkeyengine.org/forum/topic/wip-basicssao-added-optional-smoothing/

EDIT: An additional pass seems inefficient… maybe another jMonkeyEngine pro would know how to increase the first pass’s texture size?

Just got word that my development kit is processing! I hope to receive it next week. Doesn’t look like this library will be ready to go for the DK2 in time, though :frowning: This is because Oculus has yet to release an SDK with Linux support, which is my development environment.

So, I tried modifying the jme-core to allow me to override the filter’s init() call, where it initializes “defaultPass”, which takes in a width and height. It appears the width and height values have no use, though. If I set it to 3x3 or 5000x5000, there is no change in the image.

[java]
@Override
protected void init(AssetManager manager, RenderManager renderManager, ViewPort vp, int w, int h) {
defaultPass = new Pass();
defaultPass.init(renderManager.getRenderer(), 5000, 5000, getDefaultPassTextureFormat(), getDefaultPassDepthFormat());
initFilter(manager, renderManager, vp, 5000, 5000);
}[/java]

… not sure why. I’ve also tried just re-initializing defaultPass in the initFilter (which doesn’t require changes to jme-core), and it doesn’t have any effect. If I set w = 0 & h = 0, I get an exception for bad arguments, at least…

I was hoping that I could pass the width & height provided by the FoV function to the defaultPass, but it doesn’t seem to work. Anyone with experience with filters have any suggestions? :S

@phr00t said: So, I tried modifying the jme-core to allow me to override the filter's init() call, where it initializes "defaultPass", which takes in a width and height. It appears the width and height values have no use, though. If I set it to 3x3 or 5000x5000, there is no change in the image.blockquote>

I was experimenting a bit with the material’s (of the filter) texture. No luck there either.
I have another idea about offscreen rendering, and then scaling it down, but it requires a bit more work (and time). I’ll try it out when I play with this the next time. :slight_smile:

Thanks for replying, but I’m pretty sure I figured out the root problem. The camera size is the culprit. The cameras need to be resized (or recreated at the right size) for it to stretch properly. I’m trying to polish the fix up & I should have a fix committed shortly!

It is SO BEAUTIFUL :smiley: :smiley:

Fix checked in, booya:

https://code.google.com/p/jmonkeyengine-oculus-rift/source/detail?r=100

It now resizes the cameras as needed, depending on what the underlying resolution needs to be.

I also added an OculusRiftUtil.useMaxEyeFov(boolean enable); function that will allow you to maximize the FOV rendered to the screen if its called before OVRAppState (now documented on the wiki).

Now we just need a linux SDK & my DK2!! @rickard, try it out & tell me what you think :slight_smile:

2 Likes
@phr00t said:

Now we just need a linux SDK & my DK2!! @rickard, try it out & tell me what you think :slight_smile:

I think it’s awesome!

Another fix checked in – the changes to the camera size made the GUI get offset. I now store the original resolution of the cameras so the GUI can be setup properly.

https://code.google.com/p/jmonkeyengine-oculus-rift/source/detail?r=103

1 Like

Great work!

I have a couple of things on my list which I’ll try to work on the next time I spend some time with the lib:

  • Loading the lib from static context. This really bugs me! I don’t think that there is much to do about it, but I want to bang my head against it a bit more.
  • Device not closed exception when shutting down the application. Might be related to above, but It might also be solvable. I’ve seen indications that this means that the device is not released from memory properly.
@rickard said: Great work!

I have a couple of things on my list which I’ll try to work on the next time I spend some time with the lib:

  • Loading the lib from static context. This really bugs me! I don’t think that there is much to do about it, but I want to bang my head against it a bit more.
  • Device not closed exception when shutting down the application. Might be related to above, but It might also be solvable. I’ve seen indications that this means that the device is not released from memory properly.

OK, sounds good. I just checked in another update that I can’t test without a Rift. I’m trying to use prediction based on the frame rate (previously it was just set to predict 0 seconds into the future – not very helpful). When you get the chance, can you fire up your DK1 and let me know if latency has improved at all? Might need to tweak the OculusRift.predictive(…) call argument in StereoCameraControl:setView(…) based on what works best.

@phr00t said: OK, sounds good. I just checked in another update that I can't test without a Rift. I'm trying to use prediction based on the frame rate (previously it was just set to predict 0 seconds into the future -- not very helpful). When you get the chance, can you fire up your DK1 and let me know if latency has improved at all? Might need to tweak the OculusRift.predictive(...) call argument in StereoCameraControl:setView(...) based on what works best.

I synced up your changes. I noticed that you moved the cam initialization to OVRAppState. Is there a particular reason for it? From the looks of it, it seems it could still be in the OculusFilter class since it has access to the camera through the view port. It would also get rid of the if-statement.
If it’s OK, I’d like to move it back to make the class a bit “lighter”. But maybe I’m missing something?

Edit: Maybe it has to happen before initializing the filter?

@rickard said: I synced up your changes. I noticed that you moved the cam initialization to OVRAppState. Is there a particular reason for it? From the looks of it, it seems it could still be in the OculusFilter class since it has access to the camera through the view port. It would also get rid of the if-statement. If it's OK, I'd like to move it back to make the class a bit "lighter". But maybe I'm missing something?

Edit: Maybe it has to happen before initializing the filter?

You probably can move it back into the filter, then just grab and resize the camera as needed via the viewport when the filter initializes. You can then probably get rid of the GUI original sizing stuff, since the cameras won’t be resized when the GUI gets setup. I forget what led to moving the camera initialization in there, honestly, so hopefully nothing breaks when you move things back :slight_smile:

EDIT: ACTUALLY, you might be right. There is a filter init call before initFilter() where “defaultPass” gets created, using the camera size. You can experiment moving things back, but it might not work 100%. In my opinion, I’d leave it as is (e.g. “don’t fix what isn’t broken”), hehe.

Finally got around to do the refactoring (before i read your EDIT).
You were right, it did not work due to the init method. I added a reshape call though, which fixed that. Now I don’t see any different behavior from before. Did some more minor reshuffling of the code in OVRAppState to increase readability, as well.

Is there no way to edit the first post in a thread anymore? I think it’s time to update that 15 months old screenshot (and the text as well).

try adding /edit to the address - it should allow editing first post.

http://hub.jmonkeyengine.org/forum/topic/oculus-rift-support/edit

1 Like
@abies said: try adding /edit to the address - it should allow editing first post.

http://hub.jmonkeyengine.org/forum/topic/oculus-rift-support/edit

Thanks, worked nicely.

Updated with phr00t’s latest screenshot.

1 Like