Visit this GitHub repository for a complete, working project with the code presented in this article.

Preface

The Google Cardboard and other virtual reality headsets have become pretty popular in the virtual reality community and the general public.

As any consumer level hardware platform, virtual reality headsets live and die with applications that they can be used with - imagine a console like the PlayStation 4 or the Xbox One that supports only a handful of games. Pretty boring, right? So it’s a good thing that Google is working on the Cardboard SDK for Android and for Unity enabling developers all over the world to create exciting applications.

This article is using the Cardboard SDK for Android, version 0.6.0.

The Cardboard SDK works with many virtual reality headsets like the DSCVR by I AM CARDBOARD, which was inspired by the Google Cardboard. To adjust the scene to your specific headset, you can scan a QR-code that is placed on the headset.

The Idea

We are going to draw a cube with random colors for every face! Even though it is a simple example, we are still getting familiar with the different components and concepts needed to draw an interesting scene with the Cardboard SDK. And for endless entertainment, we can even recolor the cube by using the Cardboard trigger. Awesome!

We will work with the following components:

MainActivity: Extending the CardboardActivity, it is responsible for the integration with the Cardboard itself. It also hosts the renderer drawing the actual scene.

Extending the CardboardActivity, it is responsible for the integration with the Cardboard itself. It also hosts the renderer drawing the actual scene. SceneRenderer: Implementing the CardboardView.StereoRenderer, it is responsible for drawing the actual scene. The renderer hosts and initializes the cube that we will later see in the scene.

Implementing the CardboardView.StereoRenderer, it is responsible for drawing the actual scene. The renderer hosts and initializes the cube that we will later see in the scene. Cube: A custom shape that manages six faces and places them correctly to form a cube. One face is represented by a plane.

A custom shape that manages six faces and places them correctly to form a cube. One face is represented by a plane. Plane: Another custom shape that is responsible for most of the OpenGL work.

The Implementation

We are starting by creating a new blank project in Android Studio. Adding the Cardboard SDK is as simple as copying the cardboard.jar into the app/libs folder of our project. You can find it here.

Note: Prior to version 0.6.0, the libprotobuf-java-2.6-nano.jar had to be copied over to app/libs as well. Since version 0.6.0 this is not needed anymore and will actually cause compile errors.

Now we can implement the MainActivity:

Most of the work here is done by the Cardboard SDK, we only have to connect the components with each other. We are simply setting up the cardboard view with our renderer after inflating the layout defined in common_ui.xml:

In the onCardboardTrigger() method we can react to the user pressing the cardboard trigger or actually clicking the phone screen. In this case, we are going to assign a new random color to each plane - let it be colorful! As another way to give feedback to the user, we let the phone vibrate.

Note: This is a good time to talk about permissions: we’re going to need some special permissions - like VIBRATE, INTERNET, NFC and others - to fully work with the Cardboard SDK. Check the AndroidManifest.xml in the example project to see the necessary permissions and other useful or necessary configurations for our application and our activity. If you’re using the Cardboard App (which you should, as it is required for adjusting the view by scanning your VR Headset’s QR Code) you can let your app appear there by adding the CARDBOARD category to your activity which is pretty neat.

Let’s head right into the code for the SceneRenderer, where we can finally be a bit more creative:

The scene renderer implements the CardboardView.StereoRenderer interface defined by the Cardboard SDK which enables us to draw the characteristic two-screen view. The renderer draws a cube and recolors it when the trigger() method is called.

If you are familiar with OpenGL ES 2.0 for Android, you might remember some of the methods here. Let’s quickly go through the methods we need to actually implement:

onSurfaceCreated(): This method is called exactly once for every visit to the MainActivity. Here, we are initializing our cube. Note that we cannot do that in the constructor, as we need the OpenGL context to initialize the cube. The context is only available in the onSurfaceCreated method or after.

onNewFrame(): Here, we can place code related to drawing that independent of the eye perspective. In our case, we are setting the camera to look into the direction of the z-axis using the Matrix.setLookAtM() method.

onDrawEye(): As our scene is the same for both eyes, we don’t have to differ between the two cases. First, we are multiplying the camera-matrix with the eye’s view matrix. Then we obtain the model-view-projection-matrix by multiplying the eye’s perspective matrix. Finally, we are actually drawing the cube. The eye object is provided by the SDK.

Note: If you want to draw a separate scene for each eye, you can use the Eye.Type of the eye object like this:

if (eye.getType() == Eye.Type.LEFT) {

// draw something

} else if (eye.getType() == Eye.Type.RIGHT) {

// draw something else

} else {

// eye.getType() is MONOCULAR - VR-Mode is disabled!

}

I won’t go into detail for the Cube and Plane classes - the cube is responsible for managing six planes and computes the correct transformation matrix for each face while a plane handles all the OpenGL stuff. We represent a plane as a rectangle consisting of two triangles. A plane gets a random color on creation that can be changed later. For the sake of completeness, you can find these classes here. Again, you can find the complete project at GitHub!

Conclusion

The Google Cardboard SDK is a neat library that helps with all the things surrounding a virtual reality application, like a two-screen layout that is automatically adjusting its view when the user is moving their head or the QR-code mechanic that allows to optimize the view to the specific headset in use.

Using a virtual reality headset is completely different from just hearing about it — try it out!

Plugging in your own code is pretty easy and you can start by simply adding the library’s jar to your project - no frustrating hassle before even writing a single line of code!

At the end though, even with all the great tools given to us, it is now our turn to actually create awesome virtual reality applications. Hopefully, this article helps you in achieving just that!

See also