Skip to content

Getting started (Desktop)

oneMillionWorlds edited this page Nov 29, 2025 · 3 revisions

Dependencies

In your project you will need at least the following dependencies

  • org.jmonkeyengine:jme3-core
  • org.jmonkeyengine:jme3-lwjgl3
  • org.jmonkeyengine:jme3-desktop
  • com.onemillionworlds:tamarin

You may optionally want the following (for 3D GUIs)

  • com.simsilica:lemur
  • com.simsilica:lemur-proto

Do not include the jme3-vr dependency, that is an alternative older OpenVR implementation that Tamarin wholly replaces.

Tamarin itself is available on maven central so can be added as a dependency in gradle, maven or any other compatible build system. For example in gradle it would be includes as:

dependencies {
    implementation 'com.onemillionworlds:tamarin:3.?.?'
}

Check maven central for the most recent version

Code

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 XrActionAppState and VRHandsAppState here as well for extended functionality
    }
}

Actions (aka button presses, hand positions and skeletons) can be accessed by binding the OpenXrActionState

@Override
public void simpleInitApp(){
    ...
    getStateManager().attach(new XrActionAppState(manifest());
    ...
}

The manifest should be specified in Java to define your actions (button presses etc) and what physical buttons they map to on controllers

public static ActionManifest manifest(){
    Action openHandMenu = Action.builder()
            .actionHandle(ActionHandles.OPEN_HAND_MENU)
            .translatedName("Open Hand Menu")
            .actionType(ActionType.BOOLEAN)
            .withSuggestedBinding(OculusTouchController.PROFILE, OculusTouchController.pathBuilder().leftHand().thumbStickClick())
            //other suggested bindings
            .build();

    //other actions

    return ActionManifest.builder()
            .withActionSet(ActionSet
                    .builder()
                    .name("main")
                    .translatedName("Main Actions")
                    .priority(1)
                    .withAction(grip)
                    //other actions
                    .build()
            ).build();
}

These actions states can later be obtained with methods in the XrActionAppState

Finally Tamarin provides a mechanism to bind the players hands (as reported via a pose action in the manifest) to a hand model (as well as additional Grabbing and Picking actions)

@Override
public void simpleInitApp(){
    ...
    getStateManager().attach( new VRHandsAppState( handSpec() ) );
    ...
}

public static HandSpec handSpec(){
    return HandSpec.builder(
                    ActionHandles.HAND_POSE,
                    ActionHandles.HAND_POSE)
            .build();

}

Tamarin/Models/basicHands_left.j3o and Tamarin/Models/basicHands_right.j3o are built in hand models, each with a reference texture. These hand models can be used freely, or you can start with the blender files to create your own. If you do create your own you can specify them in the hand spec

public static HandSpec handSpec(){
    return HandSpec.builder(
                    ActionHandles.HAND_POSE,
                    ActionHandles.HAND_POSE)
            .leftHandModel("pathToLeftHandInResourcesFolder")
            .rightHandModel("pathToRightHandInResourcesFolder")
            .applyMaterialToLeftHand((hand, assetManager) -> {
                Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
                mat.setTexture("ColorMap", assetManager.loadTexture("path to your texture"));
                hand.setMaterial(mat);
            })
            .applyMaterialToRightHand((hand, assetManager) -> {
                Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
                mat.setTexture("ColorMap", assetManager.loadTexture("path to your texture"));
                hand.setMaterial(mat);
            })
            .build();
}

Complete Example

A complete simple test project can be found at https://github.com/oneMillionWorlds/TamarinTestBed

Clone this wiki locally