/*
* DemoGLField.java
*
* Copyright � 1998-2011 Research In Motion Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Note: For the sake of simplicity, this sample application may not leverage
* resource bundles and resource strings. However, it is STRONGLY recommended
* that application developers make use of the localization features available
* within the BlackBerry development platform to ensure a seamless application
* experience across a variety of languages and geographies. For more information
* on localizing your application, please refer to the BlackBerry Java Development
* Environment Development Guide associated with this release.
*/
package com.rim.samples.device.augmentedrealitydemo;
import javax.microedition.khronos.opengles.GL;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;
import net.rim.device.api.math.Matrix4f;
import net.rim.device.api.math.Vector3f;
import net.rim.device.api.opengles.GLField;
import net.rim.device.api.opengles.GLUtils;
import net.rim.device.api.system.AccelerometerData;
import net.rim.device.api.system.AccelerometerListener;
import net.rim.device.api.system.AccelerometerSensor;
import net.rim.device.api.system.AccelerometerSensor.Channel;
import net.rim.device.api.system.Application;
import net.rim.device.api.system.Bitmap;
/**
* A GLField implementation which renders a Cube object and changes the rotation
* axis based on accelerometer data.
*/
class DemoGLField extends GLField implements AccelerometerListener {
// Holds the number of radians to rotate per frame
private static final float RADIANS_PER_FRAME = (float) Math.toRadians(2.0f);
// Accelerometer orientation data channel
private Channel _orientChannel;
// Holds the screen's aspect ratio
private final float _aspect;
// Holds the transformations for the boxes
private Matrix4f _transform;
// Holds the axis of rotation
private final Vector3f _rotationAxis = new Vector3f(0, 1, 0);
// Holds the cube to be rendered
private Cube _cube;
private final int _width;
private final int _height;
/**
* Creates a new DemoGLField object
*
* @param width
* Width for the field
* @param height
* Height of the field
*/
DemoGLField(final int width, final int height) {
super(GLField.VERSION_1_1);
_width = width;
_height = height;
_aspect = (float) width / (float) height;
if (AccelerometerSensor.isSupported()) {
// Initialize Accelerometer data channel and listener
_orientChannel =
AccelerometerSensor.openOrientationDataChannel(Application
.getApplication());
_orientChannel.addAccelerometerListener(this);
}
}
/**
* @see net.rim.device.api.ui.Field#layout(int, int)
*/
protected void layout(final int width, final int height) {
setExtent(_width, _height);
}
/**
* @see net.rim.device.api.opengles.GLField#initialize(GL)
*/
public void initialize(final GL renderer) {
final GL11 gl = (GL11) renderer;
_transform = new Matrix4f();
_transform.translate(0, 0, -4.0f);
_transform.scale(1.5f);
// Create the cube for "instanced" rendering
_cube = new Cube(gl);
gl.glEnable(GL10.GL_TEXTURE_2D);
// Load the texture bitmap
final Bitmap bitmap = Bitmap.getBitmapResource("BlackBerry.png");
if (bitmap != null) {
final int[] textureIds = new int[1];
gl.glGenTextures(1, textureIds, 0);
final int _texture = textureIds[0];
gl.glBindTexture(GL10.GL_TEXTURE_2D, _texture);
GLUtils.glTexImage2D(gl, 0, GL10.GL_RGB,
GL10.GL_UNSIGNED_SHORT_5_6_5, bitmap, null);
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
GL10.GL_LINEAR);
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,
GL10.GL_LINEAR);
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,
GL10.GL_CLAMP_TO_EDGE);
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
GL10.GL_CLAMP_TO_EDGE);
}
// Setup GL state
gl.glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
gl.glDisable(GL10.GL_DITHER);
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
gl.glEnable(GL10.GL_CULL_FACE);
gl.glShadeModel(GL10.GL_SMOOTH);
gl.glEnable(GL10.GL_DEPTH_TEST);
initializeLights(gl);
}
/**
* Defines the lighting for the cube
*
* @param gl
* The GL11 object used for drawing
*/
private void initializeLights(final GL11 gl) {
// Set the ambient color for the entire scene
final float[] ambientColor = { 0.2f, 0.2f, 0.2f, 1.0f };
gl.glLightModelfv(GL10.GL_LIGHT_MODEL_AMBIENT, ambientColor, 0);
// Set up the position and color for light 0
final float[] position = { 5.0f, -2.0f, 20.0f, 0.0f };
final float[] color = { 0.75f, 0.75f, 0.75f, 1.0f };
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, position, 0);
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, color, 0);
gl.glEnable(GL10.GL_LIGHT0);
gl.glEnable(GL10.GL_LIGHTING);
}
/**
* @see AccelerometerListener#onData(AccelerometerData)
*/
public void onData(final AccelerometerData accData) {
// Adjust the rotation of the cube based on current orientation
switch (accData.getOrientation()) {
case AccelerometerSensor.ORIENTATION_TOP_UP:
_rotationAxis.set(0.0f, 1.0f, 0.0f);
break;
case AccelerometerSensor.ORIENTATION_BOTTOM_UP:
_rotationAxis.set(0.0f, 1.0f, 0.0f);
break;
case AccelerometerSensor.ORIENTATION_FRONT_UP:
_rotationAxis.set(0.0f, 0.0f, 1.0f);
break;
case AccelerometerSensor.ORIENTATION_BACK_UP:
_rotationAxis.set(0.0f, 0.0f, 1.0f);
break;
case AccelerometerSensor.ORIENTATION_LEFT_UP:
_rotationAxis.set(1.0f, 0.0f, 0.0f);
break;
case AccelerometerSensor.ORIENTATION_RIGHT_UP:
_rotationAxis.set(1.0f, 0.0f, 0.0f);
break;
}
}
/**
* @see net.rim.device.api.opengles.GLField#update()
*/
public void update() {
_rotationAxis.normalize();
_transform.rotate(_rotationAxis, RADIANS_PER_FRAME);
}
/**
* @see net.rim.device.api.opengles.GLField#render(GL)
*/
public void render(final GL renderer) {
final GL11 gl = (GL11) renderer;
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// Set up the perspective projection
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
GLUtils.gluPerspective(gl, 45.0f, _aspect, 0.15f, 1000.0f);
// Set up the local modelview transform and render it
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadMatrixf(_transform.getArray(), 0);
_cube.enableVertexAttrib();
_cube.enableNormalAttrib();
_cube.enableTexcoordAttrib();
_cube.render(gl);
}
/**
* Closes the Accelerometer's data channel
*/
public void cleanUp() {
if (_orientChannel != null) {
_orientChannel.close();
}
}
}