package actions; import listeners.eventManagerListeners.OrientationChangedListener; import system.EventManager; import system.Setup; import android.hardware.SensorManager; import android.view.Surface; /** * Register it in the * {@link EventManager#addOnOrientationChangedAction(OrientationChangedListener)} * and you will get updates whenever the angles change * * @author Simon Heinen * */ public abstract class ActionUseCameraAngles2 implements OrientationChangedListener { private float[] mag; private float[] accel; private boolean sensorRead; float[] R = new float[16]; float[] outR = new float[16]; float[] I = new float[16]; private int screenRotation; public ActionUseCameraAngles2() { screenRotation = Setup.getScreenOrientation(); } @Override public boolean onMagnetChanged(float[] values) { mag = values; sensorRead = true; calcMatrix(); return true; } @Override public boolean onAccelChanged(float[] values) { accel = values; calcMatrix(); return true; } @Override public boolean onOrientationChanged(float[] values) { // TODO return true; } private void calcMatrix() { if (mag != null && accel != null && sensorRead) { sensorRead = false; SensorManager.getRotationMatrix(R, I, accel, mag); onRotationMatrixUpdated(R); } } /** * @return the correctly rotated matrix which can then be used in OpenGL * e.g. */ public float[] getRotateMatrixAccordingToDeviceOrientation() { if (EventManager.isTabletDevice) { /* * change accel sensor data according to http://code.google.com/p * /libgdx/source/browse/trunk/backends/gdx -backend-android/src/com * /badlogic/gdx/backends/android/AndroidInput.java */ SensorManager.remapCoordinateSystem(R, SensorManager.AXIS_X, SensorManager.AXIS_Y, outR); } else { /* * TODO do this for all 4 rotation possibilities! */ if (screenRotation == Surface.ROTATION_90) { // then rotate it according to the screen rotation: SensorManager.remapCoordinateSystem(R, SensorManager.AXIS_Y, SensorManager.AXIS_MINUS_X, outR); } else { outR = R; } } return outR; } private final float rad2deg = 180 / (float) Math.PI; private float[] o = new float[3]; /** * you can also use * {@link ActionUseCameraAngles2#getRotateMatrixAccordingToDeviceOrientation()} * here to rotate R correctly automatically. so this method body might look * like this: <br> * <br> * glCamera.setRotationMatrix(getRotateMatrixAccordingToDeviceOrientation(), * 0); * * @param updatedRotationMatrix */ public void onRotationMatrixUpdated(float[] updatedRotationMatrix) { SensorManager.getOrientation(updatedRotationMatrix, o); float magnet = o[0] * rad2deg + 90; if (magnet < 0) magnet += 360; onAnglesUpdated(o[1] * rad2deg, -o[2] * rad2deg, magnet); } /** * @param pitch * pitch is the rotation around the x axis. when the device would * be a steering wheel, this method would indicate how much it is * rotated. 0 means the car drives straight forward, positive * values (0 to 90) mean that the car turns left, negative values * mean that the car turns right * @param roll * the roll is the rotation around the y axis. if the device * would be your head 0 would mean you are looking on the ground, * 90 would mean you look in front of you and 180 would mean you * look in the sky. from 0 to 360. 0 means the camera targets the * ground, 180 the camera looks into the sky * @param compassAzimuth * 0=north 90=east 180=south 270=west */ public abstract void onAnglesUpdated(float pitch, float roll, float compassAzimuth); }