[英]Rajawali rotating camera with Sensor.TYPE_ROTATION_VECTOR strange behavior
我正在創建一個全景視圖,允許用戶通過旋轉智能手機環顧一下球形圖像。 我將Rajawali的Skybox與TYPE_ROTATION_VECTOR傳感器一起使用。
我得到了它的工作,但只有當我向前看時(它實際上是基於我的旋轉(偏航))
這是行為:
現在我確實有預感正在發生什么。 似乎“相機對象”一直看着相同的方向,即使它看起來不是這樣。 這意味着俯仰似乎與滾動相同,但是它仍然在俯仰,因為物體沒有旋轉。 我把它比作飛機上的四處看看。
我需要做些什么來解決這個問題?
我有一種感覺,我將不得不用lookAt()旋轉相機,但我不知道如何。
public class SkyboxFragment extends RajawaliFragment implements SensorEventListener {
public static final String TAG = "SkyBoxFragment";
private SensorManager mSensorManager;
private float[] orientationVals = new float[3];
private float[] mRotationMatrix = new float[16];
private Sensor mRotVectSensor;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
LinearLayout ll = new LinearLayout(getActivity());
ll.setOrientation(LinearLayout.VERTICAL);
ll.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.TOP);
mSensorManager = (SensorManager) getActivity().getSystemService(
Context.SENSOR_SERVICE);
mRotVectSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);
mLayout.addView(ll);
mSensorManager.registerListener(this,
mRotVectSensor,
10000);
return mLayout;
}
@Override
public AExampleRenderer createRenderer() {
mRenderer = new SkyboxRenderer(getActivity());
return ((SkyboxRenderer) mRenderer);
}
@Override
public void onClick(View v) {
}
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) {
SensorManager.getRotationMatrixFromVector(mRotationMatrix, event.values);
SensorManager.remapCoordinateSystem(mRotationMatrix, SensorManager.AXIS_X, SensorManager.AXIS_Z, mRotationMatrix);
SensorManager.getOrientation(mRotationMatrix, orientationVals);
orientationVals[0] = (float) Math.toDegrees(orientationVals[0]);
orientationVals[1] = (float) Math.toDegrees(orientationVals[1]) * -1;
orientationVals[2] = (float) Math.toDegrees(orientationVals[2]) * -1;
//Log.d(TAG, "YAW:" + orientationVals[0] + " PITCH:" + orientationVals[1] + "ROLL:" + orientationVals[2]);
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
private final class SkyboxRenderer extends AExampleRenderer implements View.OnClickListener {
private final Vector3 mAccValues;
boolean odd = true;
public SkyboxRenderer(Context context) {
super(context);
mAccValues = new Vector3();
}
@Override
protected void initScene() {
getCurrentCamera().setFarPlane(1000);
/**
* Skybox images by Emil Persson, aka Humus. http://www.humus.name humus@comhem.se
*/
try {
getCurrentScene().setSkybox(R.drawable.posx, R.drawable.negx,
R.drawable.posy, R.drawable.negy, R.drawable.posz, R.drawable.negz);
} catch (ATexture.TextureException e) {
e.printStackTrace();
}
}
@Override
protected void onRender(long ellapsedRealtime, double deltaTime) {
super.onRender(ellapsedRealtime, deltaTime);
getCurrentCamera().setRotation(orientationVals[2], orientationVals[0], orientationVals[1]);
}
@Override
public void onClick(View v) {
try {
if (odd) {
/**
* Skybox images by Emil Persson, aka Humus. http://www.humus.name humus@comhem.se
*/
getCurrentScene().updateSkybox(R.drawable.posx2, R.drawable.negx2,
R.drawable.posy2, R.drawable.negy2, R.drawable.posz2, R.drawable.negz2);
} else {
/**
* Skybox images by Emil Persson, aka Humus. http://www.humus.name humus@comhem.se
*/
getCurrentScene().updateSkybox(R.drawable.posx, R.drawable.negx,
R.drawable.posy, R.drawable.negy, R.drawable.posz, R.drawable.negz);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
odd = !odd;
}
}
public void setAccelerometerValues(float x, float y, float z) {
mAccValues.setAll(-x, -y, -z);
}
}
}
你有兩個問題。 首先是您要描述的問題,但另一個問題是TYPE_ROTATION_VECTOR
的傳感器會受到附近磁鐵的影響,例如手機外殼中的磁鐵。
解決方案可以是使用加速度計和陀螺儀的組合。 幸運的是, Google Cardboard SDK已經將其抽象化了。
您可以通過使用HeadTracker.createFromContext(this.getActivity())
實例化com.google.vrtoolkit.cardboard.sensors.HeadTracker
的實例並在其上調用startTracking()
來跟蹤當前輪換。
現在你不再需要onSensorChanged
了。 相反,在你的onRender
,你可以這樣做:
float[] R = new float[16];
headTracker.getLastHeadView(R, 0);
獲得旋轉矩陣。 這解決了您未說明的磁場問題。
使用此旋轉矩陣將攝像機指向正確方向的最簡單方法是將其轉換為org.rajawali3d.math.Quaternion
,然后調用getCurrentCamera().setCameraOrientation(quaternion);
從float[16]
到四元數的轉換可能很難正確,但Google Cardboard SDK再一次為您做到了。 在這種情況下,它位於不再使用的舊類的源代碼中: HeadTransform 。
您可以輕松地調整該代碼以return new Quaternion(w, x, y, z);
。
現在,如果沒有將orientationVals[1]
和orientationVals[2]
乘以-1
則會產生與當前代碼相同的問題。
然而,通過反轉旋轉矩陣可以很容易地解決該問題。 這將導致onRender
中的以下代碼(假設getQuaternion(R)
返回org.rajawali3d.math.Quaternion
):
@Override
protected void onRender(long ellapsedRealtime, double deltaTime) {
super.onRender(ellapsedRealtime, deltaTime);
float[] R = new float[16];
headTracker.getLastHeadView(R, 0);
android.opengl.Matrix.invertM(R, 0, R, 0);
Quaternion q = getQuaternion(R);
getCurrentCamera().setCameraOrientation(q);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.