I have a cardboard and now tested JME on it. First I thought I have to port the Oculus rift code to get the stereo view but first I tried it with a very simple “2 synchronized cameras” app state which I now can switch on and off whenever the cardboard is detected by the magnometer of the device
Works fine so far, even with the 3d effect, here is the first version of the “stereo view app state”. I still have problems with the GUI cameras, I cant set the aspect ration of the GUI camera so I deactivated stereo GUI for now, perhaps someone of you has an idea about it:
[java]
public class AS_StereoCamSyncer extends AbstractAppState {
private static final String RIGHT_GUI_VIEW = "Right Gui";
private static final String RIGHT_EYE_VIEW = "RightEye";
private Camera left;
private Camera right;
private final RenderManager renderManager;
private final ViewPort guiViewPort;
private final Node rootNode;
private boolean use3d = true;
private float eyeDistance = 0.3f; // 30cm woot
/**
* @param guiViewPort
* @param renderManager
* @param rootNode
* @param guiNode
* @param leftCam
* will be the main camera
* @param rightCam
* will be controlled by the left camera
*/
public AS_StereoCamSyncer(RenderManager renderManager,
ViewPort guiViewPort, Node rootNode, Camera leftCam) {
left = leftCam;
this.renderManager = renderManager;
this.guiViewPort = guiViewPort;
this.rootNode = rootNode;
}
public void setLeftCamera(Camera left) {
this.left = left;
}
public void setUse3d(boolean use3d) {
this.use3d = use3d;
}
public void setEyeDistance(float eyeDistance) {
this.eyeDistance = eyeDistance;
}
@Override
public void stateAttached(AppStateManager stateManager) {
right = left.clone();
setupBothEyes(left, right);
}
@Override
public void stateDetached(AppStateManager stateManager) {
setupOneEye(left);
}
@Override
public void update(float tpf) {
super.update(tpf);
right.setRotation(left.getRotation());
if (use3d) {
right.setLocation(left.getLocation().add(
left.getLeft().normalize().multLocal(eyeDistance)));
} else {
right.setLocation(left.getLocation());
}
}
private void setupOneEye(Camera cam1) {
renderManager.removeMainView(RIGHT_EYE_VIEW);
cam1.setViewPort(0f, 1f, 0f, 1f);
JmeCameraController.updateAspectRatioOf(cam1);
setupGuiOneEye(guiViewPort.getCamera());
}
private void setupBothEyes(Camera cam1, Camera cam2) {
ViewPort view2 = renderManager.createMainView(RIGHT_EYE_VIEW, cam2);
view2.setClearFlags(true, true, true);
view2.attachScene(rootNode);
cam1.setViewPort(0f, 0.5f, 0f, 1f);
cam2.setViewPort(.5f, 1f, 0f, 1f);
// now the viewport is only half of its normal size for both cameras so
// update the aspect ratio:
updateAspectRatioOf(cam1);
updateAspectRatioOf(cam2);
// setupGuiBothEyes(guiViewPort.getCamera());
}
/**
* returns the FovY of the passed camera, can be used for
* {@link Camera#setFrustumPerspective(float, float, float, float)} e.g.
*
* @param c
* @return
*/
public static float getFovY(Camera c) {
/*
* just do the following formula from
* Camera#setFrustumPerspective(float, float, float, float) backwards:
*
* float h = FastMath.tan(fovY * FastMath.DEG_TO_RAD * .5f) * near;
*/
float fovY = FastMath.atan(c.getFrustumTop() / c.getFrustumNear())
/ (FastMath.DEG_TO_RAD * .5f);
return fovY;
}
/**
* update the aspect ratio (and leave the rest of the parameters like they
* are)
*
* @param c
*/
public static void updateAspectRatioOf(Camera c) {
c.setFrustumPerspective(getFovY(c), calcAspect(c), c.getFrustumNear(),
c.getFrustumFar());
}
public static float calcAspect(Camera c) {
return (c.getWidth() * (c.getViewPortRight() - c.getViewPortLeft()))
/ (c.getHeight() * (c.getViewPortTop() - c.getViewPortBottom()));
}
private void setupGuiOneEye(Camera guiCam1) {
renderManager.removePostView(RIGHT_GUI_VIEW);
guiCam1.setViewPort(0f, 1f, 0f, 1f);
}
/**
* mirroring the GUI does not work currently, the nifty ui is not cloned for
* both eyes and the aspect ratio of the gui camera is not correctly
* adjusted
*
* @param guiCam1
*/
@Deprecated
private void setupGuiBothEyes(Camera guiCam1) {
Camera guiCam2 = guiCam1.clone();
guiCam1.setViewPort(0f, 0.5f, 0f, 1f);
guiCam2.setViewPort(.5f, 1f, 0f, 1f);
ViewPort guiViewPort2 = renderManager.createPostView(RIGHT_GUI_VIEW,
guiCam2);
guiViewPort2.setClearFlags(false, false, false);
JmeCameraController.updateAspectRatioOf(guiCam1);
JmeCameraController.updateAspectRatioOf(guiCam2);
for (Spatial s : guiViewPort.getScenes()) {
Log.d("guiViewPort2 adding " + s);
guiViewPort2.attachScene(s);
}
for (SceneProcessor p : guiViewPort.getProcessors()) {
Log.d("guiViewPort2 adding " + p);
guiViewPort2.addProcessor(p);
}
}
}
[/java]