您的位置:首页 > 移动开发 > Android开发

根据Android 传感器控制3D模型方向

2016-03-14 17:34 555 查看

目标

根据传感器信息, 平滑的控制3D模型方向.

实现

1. 注册传感器

@Override
protected void onResume() {
super.onResume();

mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
// 初始化加速度传感器
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
// 初始化地磁场传感器
mMagnetic = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);

if (mSensorManager != null) {
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME);
mSensorManager.registerListener(this, mMagnetic, SensorManager.SENSOR_DELAY_GAME);
}

}


2. 反注册

protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(this);
}


3. 采样,计算旋转矩阵,再转换为四元数。

<span style="white-space:pre">	</span>float[] accelerometerValues = new float[3];
float[] magneticFieldValues = new float[3];

float getMat3(float[] m, int x, int y){
return m[x + y * 3];
}
void matToQuat(float[]mat, float[]q)
{
float		trace;
float		s;
float		t;
int     	i;
int			j;
int			k;

int 	next[] = { 1, 2, 0 };

trace = mat[0] + mat[4] + mat[8];

if ( trace > 0.0f )
{
t = trace + 1.0f;
s = 0.5f / (float)Math.sqrt(t);
q[3] = s * t;
q[0] = ( getMat3(mat,  2 , 1 ) - getMat3(mat,  1 , 2 ) ) * s;
q[1] = ( getMat3(mat,  0 , 2 ) - getMat3(mat,  2 , 0 ) ) * s;
q[2] = ( getMat3(mat,  1 , 0 ) - getMat3(mat,  0 , 1 ) ) * s;

} else {
i = 0;
if ( getMat3(mat, 1 , 1 ) > getMat3(mat, 0 , 0 ) ) {
i = 1;
}
if ( getMat3(mat, 2 , 2 )> getMat3(mat, i , i ) ) {
i = 2;
}
j = next[ i ];
k = next[ j ];
t = ( getMat3(mat, i, i ) - ( getMat3(mat, j , j ) + getMat3(mat, k , k ) ) ) + 1.0f;
s = 0.5f / (float)Math.sqrt(t);
q[i] = s * t;
q[3] = ( getMat3(mat, k , j ) - getMat3(mat, j ,k ) ) * s;
q[j] = ( getMat3(mat, j , i ) + getMat3(mat, i , j ) ) * s;
q[k] = ( getMat3(mat, k , i ) + getMat3(mat, i , k ) ) * s;
}
}

float rotMat[] = new float[9];
float quat[] = new float[4];
@Override
public void onSensorChanged(SensorEvent event) {

// TODO Auto-generated method stub
boolean needComputer = false;
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
//Log.e("ACCELEROMETER","onSensorChanged:TYPE_ACCELEROMETER " + String.format("%f %f %f", event.values[0],event.values[1],event.values[2]));

if(true)
{
accelerometerValues[0] = -event.values[1];
accelerometerValues[1] = event.values[0];
accelerometerValues[2] = event.values[2];
needComputer = true;
}
}
if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {

if(true)
{
magneticFieldValues[0] = -event.values[1];
magneticFieldValues[1] = event.values[0];
magneticFieldValues[2] = event.values[2];
needComputer = true;
}
}

if(needComputer == true){
SensorManager.getRotationMatrix(rotMat, null, accelerometerValues,
magneticFieldValues);

matToQuat(rotMat, mQuat);

}

}

4. 计算将几何模型坐标变换到手机世界坐标矩阵, 将上一部得到的四元数与当前四元数插值再转换为矩阵,计算视点变换矩阵
void normalizeQuat(float[] q){
float temp=(float)Math.sqrt(q[0]*q[0]+q[1]*q[1]+q[2]*q[2]+q[3]*q[3]);
temp=(float)1.0/temp;
q[0]*=temp;
q[1]*=temp;
q[2]*=temp;
q[3]*=temp;
}

void quatSlerp(float[] q, float[]q0,float[] q1,float t) {
float k0,k1,cosomega = q0[0] * q1[0] + q0[1] * q1[1] + q0[2] * q1[2] + q0[3] * q1[3];
if(cosomega < 0.0) {
cosomega = -cosomega;
q[0] = -q1[0];
q[1] = -q1[1];
q[2] = -q1[2];
q[3] = -q1[3];
} else {
q[0] = q1[0];
q[1] = q1[1];
q[2] = q1[2];
q[3] = q1[3];
}
if(1.0 - cosomega > 1e-6) {
float omega = (float)Math.acos(cosomega);
float sinomega = (float)Math.sin(omega);
k0 = (float)Math.sin((1.0f - t) * omega) / sinomega;
k1 = (float)Math.sin(t * omega) / sinomega;
} else {
k0 = 1.0f - t;
k1 = t;
}
q[0] = q0[0] * k0 + q[0] * k1;
q[1] = q0[1] * k0 + q[1] * k1;
q[2] = q0[2] * k0 + q[2] * k1;
q[3] = q0[3] * k0 + q[3] * k1;

normalizeQuat(q);
}

void quatToMat(float[] ret, float[]q) {
float x = q[0];
float y = q[1];
float z = q[2];
float w = q[3];

float x2 = x + x;
float y2 = y + y;
float z2 = z + z;
float xx = x * x2;
float yy = y * y2;
float zz = z * z2;
float xy = x * y2;
float yz = y * z2;
float xz = z * x2;
float wx = w * x2;
float wy = w * y2;
float wz = w * z2;
ret[0] = 1.0f - (yy + zz); ret[4] = xy - wz;          ret[8] = xz + wy;           ret[12]=0.0f;
ret[1] = xy + wz;          ret[5] = 1.0f - (xx + zz); ret[9] = yz - wx;           ret[13]=0.0f;
ret[2] = xz - wy;          ret[6] = yz + wx;          ret[10]= 1.0f - (xx + yy);  ret[14]=0.0f;
ret[3] = 0.0f;              ret[7]=  0.0f;              ret[11]= 0.0f;               ret[15]=1.0f;
}

float[] mCurQuat = new float[4];
float[] mPreQuat = {0f, 0, 0, 1};
float[] mRotMat = new float[16];

public void draw() {
...................................

temp[0] = 1.f;	temp[4] = 0.f;	temp[8] = 0.f;	temp[12] = 0.f;
temp[1] = 0.f;	temp[5] = 0.f;	temp[9] = -1.f;	temp[13] = 0.f;
temp[2] = 0.f;	temp[6] = 1.f;	temp[10] = 0.f;	temp[14] = 0.f;
temp[3] = 0.f;	temp[7] = 0.f;	temp[11] = 0.f;	temp[15] = 1.f;

quatSlerp(mCurQuat, mPreQuat, rotMat, rotMat[4]);

mPreQuat[0] = mCurQuat[0];
mPreQuat[1] = mCurQuat[1];
mPreQuat[2] = mCurQuat[2];
mPreQuat[3] = mCurQuat[3];
quatToMat(mRotMat, mCurQuat);

Matrix.multiplyMM(mWorld, 0, mRotMat, 0, temp, 0);

..............................................
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: