A Camera
class is another type of Component
, positioned in space like other component objects. The camera is special because through the camera's eyes, we render the scene. For VR, we render it twice, once for each eye.
Let's create the Camera
class, and then see how it works. Create it in the renderbox/components
folder and define it as follows:
public class Camera extends Component { private static final String TAG = "renderbox.Camera"; private static final float Z_NEAR = .1f; public static final float Z_FAR = 1000f; private final float[] camera = new float[16]; private final float[] view = new float[16]; public Transform getTransform(){return transform;} public Camera(){ //The camera breaks pattern and creates its own Transform transform = new Transform(); } public void onNewFrame(){ // Build the camera matrix and apply it to the ModelView. Vector3 position = transform.getPosition(); Matrix.setLookAtM(camera, 0, position.x, position.y, position.z + Z_NEAR, position.x, position.y, position.z, 0.0f, 1.0f, 0.0f); RenderBox.checkGLError("onNewFrame"); } public void onDrawEye(Eye eye) { GLES20.glEnable(GLES20.GL_DEPTH_TEST); GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); RenderBox.checkGLError("glClear"); // Apply the eye transformation to the camera. Matrix.multiplyMM(view, 0, eye.getEyeView(), 0, camera, 0); // Build the ModelView and ModelViewProjection matrices float[] perspective = eye.getPerspective(Z_NEAR, Z_FAR); for(RenderObject obj : RenderBox.instance.renderObjects) { obj.draw(view, perspective); } RenderBox.checkGLError("Drawing complete"); } }
The Camera
class implements two methods: onNewFrame
and onDrawEye
, which will be delegated from the RenderBox
class (which, in turn, is delegated from MainActivity
).
As the name implies, onNewFrame
is called on each new frame update. It is passed the current Cardboard SDK's HeadTransform
, which describes the user's head orientation. Our camera actually doesn't need the headTransform
value, because Eye.getEyeView()
, which is combined with the camera matrix, also contains rotation information. Instead, we just need to define its position and initial direction using Matrix.setLookAtM
(refer to http://developer.android.com/reference/android/opengl/Matrix.html).
The onDrawEye
method is called by the Cardboard SDK once for each eye view. Given a Cardboard SDK eye view, the method begins to render the scene. It clears the surface, including the depth buffer (used to determine visible pixels), applies the eye transformation to the camera (including perspective), and then draws each RenderObject
object in the scene.