Tamarin 2
I’ve just release a new version of Tamarin (2.0.0) that replaces the OpenVR of Tamarin 1 / jme3-vr with OpenXR. OpenXR is the new industry standard for Virtual and Augmented reality so applications running with OpenXR should have better support and a longer life.
Thank you to @starcommander for kicking off the OpenXR effort and to @zzuegg for helping me with a more efficient OpenGL render (apparently saving 700Mb of copying textures around per second)
It’s obviously filled with breaking changes from Tamarin 1 but the API is very similar so while it’s breaking it should be relatively obvious how to migrate an application. In particular the 3 main AppStates map like this
Tamarin 1 | Tamarin 2 | Purpose |
---|---|---|
VrAppState (from JMonkey) | XrAppState (from Tamarin) | The eyes and overall system boot up |
ActionBasedOpenVrState | OpenXrActionState | Low level calls to get actions (aka button presses and hand positions |
VRHandsAppState | VRHandsAppState | Optionated hand model binding and high level APIs (barely changed from Tamarin 1) |
Some of the hand coordinate systems are a little different (I took the opportunity to standardise them a bit)
Tamarin 2 completely replaces jme3-vr so that should not be included in build.gradle. Instead jme3-desktop (and other standard jme3 dependencies) should be included.
Minimal Example
public class Main extends SimpleApplication{
public static void main(String[] args) {
AppSettings settings = new AppSettings(true);
settings.put("Renderer", AppSettings.LWJGL_OPENGL45); // OpenXR only supports relatively modern OpenGL
settings.setTitle("Tamarin OpenXR Example");
settings.setVSync(false); // don't want to VSync to the monitor refresh rate, we want to sync to the headset refresh rate
Main app = new Main();
app.setSettings(settings);
app.start();
}
@Override
public void simpleInitApp(){
getStateManager().attach(new XrAppState());
//optionally add OpenXrActionState and VRHandsAppState
}
}
A more extensive example can be found in TamarinTestBed
What does Tamarin 2 / OpenXR have over OpenVR
VR & AR
OpenXR supports both VR (i.e. fully immersive) and Augmented reality (virtual objects layered over the real world). I don’t have a headset that supports it so I haven’t tested it but I think enabling AR should be as easy as:
-
Making sure the viewports background is transparent
-
Setting Tamarin to boot in AR mode
XrSettings xrSettings = new XrSettings(); xrSettings.setXrVrMode(XrVrMode.ENVIRONMENT_BLEND_MODE_ALPHA_BLEND); getStateManager().attach(new XrAppState(xrSettings));
Go into and out of VR at will
Unlike jme3-vr; Tamarin 2 adopts the running OpenGL context and does not need to be running before JME starts, this means that an application can start as a desktop application and then move over into VR when the XrAppState
is added. Additionally its possible to remove and re-add the state at will, with VR binding and unbinding (This is experimental, it works but I want to smooth it out a bit. The test bed has an example of doing this). This is something that was requested previously by @RaffaeleRagni .
Similarly, by default it adopts the main camera (makes the desktop view track the VR view) but it can be configured to not do that and leave the main view alone.
Nicer action manifest
In OpenXR the action manifest was defined in XML (and that XML could not be packed with the application, it had to be a raw file just lying about), in OpenXR it can be provided by code which means I can provide a nice API for it
Action openHandMenu = Action.builder()
.actionHandle(ActionHandles.OPEN_HAND_MENU)
.translatedName("Open Hand Menu")
.actionType(ActionType.BOOLEAN)
.withSuggestedBinding(OculusTouchController.PROFILE, OculusTouchController.pathBuilder().leftHand().thumbStickClick())
.withSuggestedBinding(OculusTouchController.PROFILE, OculusTouchController.pathBuilder().rightHand().thumbStickClick())
// other controllers suggested bindings
.build();
return ActionManifest.builder()
.withActionSet(ActionSet
.builder()
.name("main")
.translatedName("Main Actions")
.priority(1)
.withAction(openHandMenu)
// other actions
.build()
).build();
Gamma correction
As a side effect of adopting the existing OpenGL context rather than spinning up my own I believe that Tamarin 2 doesn’t have the long standing no gamma correction bug as reported by @marcelfalliere
Xr Extensions
OpenXR is made of a bunch of extensions, a small number of which are used in Tamarin. Tamarin makes it possible to request more if you require them
XrSettings xrSettings = new XrSettings();
xrSettings.addRequiredXrExtension("XR_EXT_DPAD_BINDING_EXTENSION_NAME");
getStateManager().attach(new XrAppState(xrSettings));
But of course that will probably mean you’ll need to write direct calls to LWJGL to exercise those extensions.
The observer
No one seemed to like the observer from jme3-vr. It still exists in Tamarin 2 (because it’s actually an essential concept; to map the VR world to the real world) but its prominence is much reduced; you can ask Tamarin to move the player’s feet to a location or turn them to face something and Tamarin will figure out what that actually means for the observer
DPads?
So often you want to treat a thumbpad as a DPad (i.e. left is a “button”, right is a “button” etc). That is supported in OpenXR but requires LWJGL 3.3.3 while JMonkeyEngine is on 3.3.1. In the meantime Tamarin includes a class SyntheticDPad
that can give the same functionality (albeit in a less clean and configurable way)
What about OpenVR
If your current project uses Tamarin 1 and/or pure JME3-vr then it isn’t super urgent to move. OpenVR continues to be well supported (and steam have recently committed to continuing support - although I can’t find where I read that) so “don’t panic” but in my opinion new projects probably should be targeting OpenXR.
Hand models
Hand models are unfortunately completely incompatible between OpenXR and OpenVR. This is because the bones have changed (OpenVR has bones parented naturally, OpenXR has them all as independent). Tamarin 2 comes with a new set of hands so if you were using Tamarin default hands before just use them, if not you’ll need to update your bones.
Testing
I have only tested this on one system with one OS and one graphics card. If anyone else is able to test (the TamarinTestBed is great for that) and let me know if it either does or doesn’t work for you that would be most appreciated.
I tested this on:
Windows 10, Oculus Quest 2 (SteamVR via Virtual Desktop), NVIDIA GeForce RTX 3070