I've tried solving this problem in bit simplier way, using accelerometer values only.

In activity class, onSensorChanged method:

` `

@Override

public void onSensorChanged(SensorEvent event) {

if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER)

return;

/*

* record the accelerometer data, the event's timestamp as well as

* the current time. The latter is needed so we can calculate the

* "present" time during rendering. In this application, we need to

* take into account how the screen is rotated with respect to the

* sensors (which always return data in a coordinate space aligned

* to with the screen in its native orientation).

*/

switch (mDisplay.getRotation()) {

case Surface.ROTATION_0:

mSensorX = event.values[0];

mSensorY = event.values[1];

break;

case Surface.ROTATION_90:

mSensorX = -event.values[1];

mSensorY = event.values[0];

break;

case Surface.ROTATION_180:

mSensorX = -event.values[0];

mSensorY = -event.values[1];

break;

case Surface.ROTATION_270:

mSensorX = event.values[1];

mSensorY = -event.values[0];

break;

}

if (gameManager != null)

gameManager.handleSensor(mSensorX, mSensorY);

}

This method is mostly copied from Android sample ball game

gameManager is the instance of my game's class, which handles user input, game loop, creating game objects etc. gameManager.handleSensor(mSensorX, mSensorY) can be be replaced with your method handling accelerometer values.

Then goes GameManager class:

final int TICKS_PER_SECOND = 50;

final int SKIP_TICKS = 1000 / TICKS_PER_SECOND;

/**

* Game loop thread

* @author 32kda

*/

protected class GameLoop extends Thread {

public GameLoop() {

super("GameLoop");

}

@Override

public void run() {

long ticks = System.currentTimeMillis();

while (!isPaused()) {

long current = System.currentTimeMillis();

if (current - ticks < SKIP_TICKS) {

try {

sleep(SKIP_TICKS - (current - ticks));

} catch (InterruptedException e) {

e.printStackTrace();

}

}

updateGame(System.currentTimeMillis() - ticks); //Call update game method with some time interval

ticks = current;

}

super.run();

}

public boolean isPaused () {

return false;

}

}

...

final SimpleVector initialVectorUp = new SimpleVector(0f,-1f,0f); //Initial vector pointing up

SimpleVector vectorUp = new SimpleVector(0f,-1f,0f); //Camera's up vector. We reinit & rotate it any time we change camera orientation to set camera up/down angle with it

private float sensorX; //Accelerometer X & Y values

private float sensorY;

private float initialY = Float.MIN_VALUE; //field for storing initial y accelerometer value

private SimpleVector cameraVector = new SimpleVector(0f,0f,1f); //Camera horizontal orientation/azimuth vector

private SimpleVector orthoVector = new SimpleVector(); //Vector for rotating camera up/down. should be orthogonal to cameraVector when rotating

private Matrix cameraMatrix = new Matrix(); //Camera up vector rotation matrix

private float angle = 0; //Camera up/down rotation angle

/**

*handleSensor method. Simply remember sensorX / sensorY val for future use

*/

public void handleSensor(float mSensorX, float mSensorY) {

this.sensorX = mSensorX;

this.sensorY = mSensorY;

}

/**

*This method is called from game loop & used to update our world, camera, etc.

*/

protected void updateGame(long delta) {

if (Math.abs(sensorX) > 0.3) { //If x accelerometer value is greater than some threshold - rotate camera direction vector according to it

cameraVector.rotateY(-sensorX / 150);

}

Camera camera = world.getCamera();

if (initialY == Float.MIN_VALUE || initialY == 0.0) //Because it's not convenient to play with device placed strictly horizontally, I use some "initial" value

initialY = sensorY; //for vertical angle, and use it as position corresponding to zero vertical angle for camera

float yDiff = sensorY - initialY; //Calc the differnce

if (Math.abs(yDiff) > 0.3) {

angle -= yDiff / 200;

if (angle > 0.40f) //Limit vertical angle

angle = 0.40f;

if (angle < -0.40f)

angle = -0.40f;

}

vectorUp.set(initialVectorUp); //Re-init camera up-vector before rotating it to necessary angle

orthoVector.x = cameraVector.z; //Calculate vector orthogonal to camera vector (camera up/down riotation vector)

orthoVector.z = -cameraVector.x;

calcRotMatrix(cameraMatrix,orthoVector,angle); //Calculate rotation matrix

vectorUp.rotate(cameraMatrix); //rotate camera up vector

camera.setOrientation(cameraVector,vectorUp); //Set camera orientation

}

/**

* Calculates rotation matrix for arbitrary axis

* @param matrix Matrix to fill

* @param rotVector Arbitrary rotation axis vector

* @param angle Rotation angle

* Calculation algorythm got from the Internet & it works. Can't explain in details how(

*/

protected void calcRotMatrix(Matrix matrix, SimpleVector rotVector, float angle) {

matrix.setColumn(3,0,0,0,1);

matrix.setRow(3,0,0,0,1);

double sin = Math.sin(angle);

double cos = Math.cos(angle);

double subcos = 1 - cos;

float x = rotVector.x;

float y = rotVector.y;

float z = rotVector.z;

matrix.set(0,0,(float) (cos + subcos*x*x));

matrix.set(0,1,(float) (subcos*x*y - sin*z));

matrix.set(0,2,(float) (subcos*x*z + sin*y));

matrix.set(1,0,(float) (subcos*y*x + sin*z));

matrix.set(1,1,(float) (cos + subcos*y*y));

matrix.set(1,2,(float) (subcos*y*z - sin*x));

matrix.set(2,0,(float) (subcos*z*x - sin*y));

matrix.set(2,1,(float) (subcos*z*y + sin*x));

matrix.set(2,2,(float) (cos + subcos*z*z));

}