javaandroidopengl-esgoogle-cardboardgoogle-vr

How to anchor an object using Cardboard Java SDK


I'm currently working on a project with the Cardboard SDK, and I'm relatively struck right now.

I want to display a cross in the center of the sight, like in a FPS, and keep it in the center of the sight when the user moves his head.

I know that in this code :

public void onNewFrame(HeadTransform headTransform) {
    float[] headView = new float[16];
    headTransform.getHeadView(headView, 0);
}

the headView param will contains the transformation matrix (rotation + translation) of the head (thanks to this SO : Android VR Toolkit - HeadTransform getHeadView matrix representation ).

I tried to do this :

private float[] mHeadView = new float[16];

public void onNewFrame(HeadTransform headTransform) {
    headTransform.getHeadView(mHeadView, 0);
}

public void onDrawEye(Eye eye) {
    float[] mvpMatrix = new float[16];
    float[] modelMatrix = new float[16];
    float[] mvMatrix = new float[16];
    float[] camera = new float[16];
    Matrix.setLookAt(camera, 0, 0, 0, -2, 0, 0, -1, 0, 1, 0);
    Matrix.multiplyMM(modelMatrix, 0, mHeadView, 0, camera, 0);
    Matrix.multiplyMM(mvMatrix, 0, eye.getEyeView(), 0, modelMatrix, 0);
    Matrix.multiplyMM(mvpMatrix, 0, eye.getEyePerspective(0.1, 100), 0, mvMatrix, 0);

    // Pass the mvpMatrix and vertices buffer to the vertex shader.
}

And here is my vertex shader :

uniform mat4 uMatrix;
attribute vec4 vPosition;
attribute vec4 vColors;
varying vec4 color;
void main() {
    color = vColors;
    gl_Position = uMatrix * vPosition;
}

But the cross is still anchored to its initial position and doesn't follow the head.

Am I missing something ? How can I make my cross follow my head and stay in the center of the sight ?

Thanks in advance for your answers :)

(PS : I don't want to use Unity because this project must only use the Java SDK).


Solution

  • tl;dr: For a head-locked crosshair, skip the multiplication by the mHeadView matrix.

    If you want a head locked object, you need to define it in head space, not in world space. Your current code defines the crosshair in world space. The mHeadView transform maps from world space to current head space, accounting for current head rotation. You don't need to multiply by this, it's only required for world-locked objects.