Let's enhance the viewing experience by rotating the model as the user rotates his head. The effect will be different than a "normal" virtual reality experience. Ordinarily, moving one's head in VR rotates the subjective view of the camera in the scene to look around in unison with your head movement. In this project, the head movement will be like an input control rotating the model. The model is at a fixed position in front of you at all times.
To implement this feature is quite simple. The RenderBox preDraw
interface method is called at the start of each frame. We'll get the current head angles and rotate the model accordingly, converting the head post-Euler angles into a Quaternion. (Combining multiple Euler angles can result in an unexpected final rotational orientation). We will also conjugate (that is, invert or reverse) the rotation, so that when you look up, you see the bottom of the object and so on. It feels more natural this way.
In MainActivity
, add the following code to preDraw
:
public void preDraw() { float[] hAngles = RenderBox.instance.headAngles; Quaternion rot = new Quaternion(); rot.setEulerAnglesRad(hAngles[0], hAngles[1], hAngles[2]); model.setLocalRotation(rot.conjugate()); }
In setup
, ensure that the setLocalPosition
method positions the teapot straight in front of the camera:
.setLocalPosition(0, 0, -3)
Try and run it. We're almost there! The model rotates with the head, but we're still looking around the VR space as well.
To lock the head position, we just need to disable head tracking in RenderBox
. If your version of RenderBox
(as built in Chapter 5, RenderBox Engine) does not yet have this feature, add it to your separate RenderBoxLib
lib project, as follows:
In the Camera.java
file, first add a new public variable for headTracking
:
public boolean headTracking = true;
Modify the onDrawEye
method to conditionally update the view transform, as follows:
if (headTracking) { // Apply the eye transformation to the camera. Matrix.multiplyMM(view, 0, eye.getEyeView(), 0, camera, 0); } else { // copy camera into view for (int i=0; i < camera.length; i++) { view[i] = camera[i]; } }
Make sure that you copy the updated .aar
file to the ModelViewer
project's RenderBox
module folder after you rebuild it.
Now, in the MainActivity
class's setup()
, add the following setting:
RenderBox.instance.mainCamera.headTracking = false;
Run it now, and as you move your head, the model remains relatively stationary but rotates as you turn your head. Neato! Much better.